/**************************************************************************//**
  * \file     Sys_Tick.c
  * \brief    System tick timer driver file
  * \details
  * \author   Zhang Xuan
  * \version  V1.0.0
  * \date     19-Jul-2018
  * \par      History:
  *           V1.0.0 Initial release
  * \par      Copyright:
  *           (c) Heilongjiang TYW Electronics co., LTD
******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stdlib.h"
#include "r_typedefs.h"
#include "dr7f701441.dvf.h"
#include "r_dev_api.h"
#include "Sys_Tick.h"
#include "BGLInterface.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
    uint32_t  u32MainCnt;
    uint32_t  u32DstVal1ms;
    uint32_t  u32DstVal100ms;
} Sys_Tick_Timer_st_t;

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define   CLK_AWOTCLK_FREQ_Hz               (8000000UL)

/* Private variables ---------------------------------------------------------*/
void (*pfnSysTickCallBack[SYS_TICK_CALL_BACK_TYPE_NUM])(void);
Sys_Tick_Timer_st_t   g_stSysTickTimer;
volatile uint16_t     g_u16SysRollingCounter50us;
volatile uint16_t     g_u16SysRollingCounter1ms;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**************************************************************************//**
  * \brief      Start tick timer
  * \retval     None
******************************************************************************/
void Sys_Tick_Timer_Start(void)
{
    g_stSysTickTimer.u32MainCnt      = 0U;
    g_stSysTickTimer.u32DstVal1ms    =   1000UL / SYS_TICK_INT_INTERVAL;
    g_stSysTickTimer.u32DstVal100ms  = 100000UL / SYS_TICK_INT_INTERVAL;

    g_u16SysRollingCounter50us       = 0U;
    g_u16SysRollingCounter1ms        = 0U;

    AWOT0CTL = 0x00U;                         /* Disable AWOT before configuration */
    AWOT0TOE = 0x00U;                         /* Disable output of AWOTOUT pin */
    AWOT0EMU = 0x00U;                         /* Debug enable */
    AWOT0CCR = SYS_TICK_INT_INTERVAL * CLK_AWOTCLK_FREQ_Hz / 1000000UL;

    R_DEV_IntEnable(R_DEV_INT_AWOTM0, 1U);    /* Enable interrupt */

    AWOT0CTL = 0x80U;                         /* Start AWOT */
}

/**************************************************************************//**
  * \brief      GPIO initialization for sleep mode
  * \retval     None
******************************************************************************/
void Sys_Tick_Timer_Stop(void)
{
    R_DEV_IntEnable(R_DEV_INT_AWOTM0, 0U);    /* Disable interrupt */
    AWOT0CTL = 0x00U;                         /* Disable AWOT  */
}

void Sys_Tick_Timer_Call_Back_Reg(Sys_Tick_Call_Back_Type_en_t enType, void (*pfnIsr)(void))
{
    if (enType < SYS_TICK_CALL_BACK_TYPE_NUM)
    {
        pfnSysTickCallBack[enType] = pfnIsr;
    }
}

/**************************************************************************//**
  * \brief      Tick timer interrupt service routines
  * \retval     None
******************************************************************************/
void Sys_Tick_Timer_ISR(void)
{
    uint16_t u16Counter;
    
    if (pfnSysTickCallBack[SYS_TICK_50us_CB] != NULL )
    {
        pfnSysTickCallBack[SYS_TICK_50us_CB]();
    }

    g_stSysTickTimer.u32MainCnt++;

    if (g_stSysTickTimer.u32MainCnt >= g_stSysTickTimer.u32DstVal1ms)
    {
        if (pfnSysTickCallBack[SYS_TICK_1ms_CB] != NULL )
        {
            pfnSysTickCallBack[SYS_TICK_1ms_CB]();
        }
        
        u16Counter                    = g_u16SysRollingCounter1ms;
        g_u16SysRollingCounter1ms     = u16Counter + 1U;
        g_stSysTickTimer.u32DstVal1ms = g_stSysTickTimer.u32MainCnt + (1000UL / SYS_TICK_INT_INTERVAL);
    }

    if (g_stSysTickTimer.u32MainCnt >= g_stSysTickTimer.u32DstVal100ms)
    {
        if (pfnSysTickCallBack[SYS_TICK_100ms_CB] != NULL )
        {
            pfnSysTickCallBack[SYS_TICK_100ms_CB]();
        }
        
        g_stSysTickTimer.u32DstVal100ms  = g_stSysTickTimer.u32MainCnt + (100000UL / SYS_TICK_INT_INTERVAL);
    }

    if (g_stSysTickTimer.u32MainCnt & 0xFFFF0000UL)
    {
        g_stSysTickTimer.u32MainCnt     &= 0x0000FFFFUL;
        g_stSysTickTimer.u32DstVal1ms   &= 0x0000FFFFUL;
        g_stSysTickTimer.u32DstVal100ms &= 0x0000FFFFUL;
    }

    g_u16SysRollingCounter50us = (uint16_t)g_stSysTickTimer.u32MainCnt;

    R_DEV_IntClearFlag(R_DEV_INT_AWOTM0);
}
