/**
 * @file        GenDelay.c
 * @brief       通用延时函数
 * @details     通用延时函数
 * @author      赵建智
 * @date        2022.5.4
 * @version     V1.0
 * @copyright   赵建智
 */
#include "GenDelay.h"

static volatile Delaylib_uint32_t s_osif_tick_cnt = 0u;

static Delaylib_uint32_t Gendelay_GetCurrentTickCount(void);
static Delaylib_uint32_t MSEC_TO_TICK(Delaylib_uint32_t msec, Delaylib_uint32_t TimBase);

FeedDog pFunc;
/**
 * @brief 延时函数初始化
 * @param[in] pfunction 看门狗喂狗函数
 * @warning 先于Gen_TimeDelay调用,越早初始化越好
 *
 * 示例
 @code
     GenDelay_Init(WDT_Clear);
 @endcode
 *
 * @since 1.0.0
 */
void GenDelay_Init(FeedDog pfunction)
{
    pFunc = pfunction;
}
/**
 * @brief 延时计时,至于中断中
 * @warning None
 *
 * 示例
 @code
     GenDelay_Tick();
 @endcode
 *
 * @since 1.0.0
 */
void GenDelay_Tick(void)
{
    s_osif_tick_cnt++;
}

static Delaylib_uint32_t Gendelay_GetCurrentTickCount(void)
{
    return s_osif_tick_cnt;
}

static Delaylib_uint32_t MSEC_TO_TICK(Delaylib_uint32_t msec, Delaylib_uint32_t TimBase)
{
    Delaylib_uint32_t Ret;
    if ( TimBase != 0u )
    {
        Ret = msec / TimBase;
    }
    else
    {
        Ret = msec;
    }

    return Ret;
}

/**
 * @brief 延时指定时间
 * @param[in] delay 延时函数时间基准,单位us.
 * @param[in] TickBase 延时时间数值,单位us.
 * @warning  要在初始化之后调用
 *
 * 示例
 @code
     Gen_TimeDelay(25000ul,50ul);//延时25ms. GenDelay_Tick 函数在50us中断内
     Gen_TimeDelay(25000ul,64ul);//延时25ms. GenDelay_Tick 函数在64us中断内
 @endcode
 *
 * @since 1.0.0
 */
void Gen_TimeDelay(const Delaylib_uint32_t delay, const Delaylib_uint32_t TickBase)
{

    Delaylib_uint32_t Tickstart;
    Delaylib_uint32_t crt_ticks;
    Delaylib_uint32_t delta;
    Delaylib_uint32_t delay_ticks;
    s_osif_tick_cnt = 0u;
    Tickstart       = Gendelay_GetCurrentTickCount( );
    crt_ticks       = Gendelay_GetCurrentTickCount( );
    delta           = crt_ticks - Tickstart;
    delay_ticks     = MSEC_TO_TICK(delay, TickBase);

    while ( delta < delay_ticks )
    {
        crt_ticks = Gendelay_GetCurrentTickCount( );
        delta     = crt_ticks - Tickstart;
        if ( pFunc != (( void * )0) )
        {
            pFunc( );
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : OSIF_GetMilliseconds
 * Description   : This function returns the number of miliseconds elapsed since
 *                  starting the internal timer. To initialize the internal timer
 *                  (Systick) in bare-metal, call either OSIF_TimeDelay or
 *                  OSIF_SemaWait functions. Calling OSIF_TimeDelay(0) will initialize
 *                  the timer without any side-effects (no delay).
 *
 * Implements : OSIF_GetMilliseconds_baremetal_Activity
 *END**************************************************************************/
Delaylib_uint32_t OSIF_GetMilliseconds(const Delaylib_uint32_t TickBase)
{
    /*
     * Please make sure the timer is initialized before calling this function.
     * For example, calling OSIF_TimeDelay(0) ensures that the timer is initialized
     * without any other side-effects. If OSIF_TimeDelay or OSIF_SemaWait functions
     * have been called, the timer is already initialized.
     */
    Delaylib_uint32_t Ret;
    Ret = Gendelay_GetCurrentTickCount( );
    return ( Delaylib_uint32_t )(Ret * TickBase); /* This assumes that 1 tick = 1 millisecond */
}