/**************************************************************************************************
*******
**************************************************************************************************/
#include "clock.h"
#include "gpio.h"
#include "global_config.h"
#include "error.h"

extern uint32_t hclk,pclk;
extern uint32_t osal_sys_tick;

void hal_clk_gate_enable(MODULE_e module)
{
    if(module < MOD_CP_CPU)
    {
        AP_PCR->SW_CLK |= BIT(module);
    }
    else if(module < MOD_PCLK_CACHE)
    {
        AP_PCR->SW_CLK1 |= BIT(module-MOD_CP_CPU);
    }
    else if(module < MOD_USR0)
    {
        AP_PCR->CACHE_CLOCK_GATE |= BIT(module-MOD_PCLK_CACHE);
    }
}

void hal_clk_gate_disable(MODULE_e module)
{
    if(module < MOD_CP_CPU)
    {
        AP_PCR->SW_CLK &= ~(BIT(module));
    }
    else if(module < MOD_PCLK_CACHE)
    {
        AP_PCR->SW_CLK1 &= ~(BIT(module-MOD_CP_CPU));
    }
    else if(module < MOD_USR0)
    {
        AP_PCR->CACHE_CLOCK_GATE &= ~(BIT(module-MOD_PCLK_CACHE));
    }
}

int hal_clk_gate_get(MODULE_e module)
{
    if(module < MOD_CP_CPU)
    {
        return (AP_PCR->SW_CLK & BIT(module));
    }
    else if(module < MOD_PCLK_CACHE)
    {
        return (AP_PCR->SW_CLK1 & BIT(module-MOD_CP_CPU));
    }
    //else if(module < MOD_USR0)
    else
    {
        return (AP_PCR->CACHE_CLOCK_GATE & BIT(module-MOD_PCLK_CACHE));
    }
}

void hal_clk_get_modules_state(uint32_t* buff)
{
    *buff     = AP_PCR->SW_CLK;
    *(buff+1) = AP_PCR->SW_CLK1;
    *(buff+2) = AP_PCR->CACHE_CLOCK_GATE;
}

void hal_clk_reset(MODULE_e module)
{
    if(module < MOD_CP_CPU)
    {
        if((module >= MOD_TIMER5) &&(module <= MOD_TIMER6))
        {
            AP_PCR->SW_RESET0 &= ~BIT(5);
            AP_PCR->SW_RESET0 |= BIT(5);
        }
        else
        {
            AP_PCR->SW_RESET0 &= ~BIT(module);
            AP_PCR->SW_RESET0 |= BIT(module);
        }
    }
    else if(module < MOD_PCLK_CACHE)
    {
        if((module >= MOD_TIMER1) &&(module <= MOD_TIMER4))
        {
            AP_PCR->SW_RESET2 &= ~BIT(4);
            AP_PCR->SW_RESET2 |= BIT(4);
        }
        else
        {
            AP_PCR->SW_RESET2 &= ~BIT(module-MOD_CP_CPU);
            AP_PCR->SW_RESET2 |= BIT(module-MOD_CP_CPU);
        }
    }
    else if(module < MOD_USR0)
    {
        AP_PCR->CACHE_RST &= ~BIT(1-(module-MOD_HCLK_CACHE));
        AP_PCR->CACHE_RST |= BIT(1-(module-MOD_HCLK_CACHE));
    }
}


void hal_rtc_clock_config(CLK32K_e clk32Mode)
{
    if(clk32Mode == CLK_32K_RCOSC)
    {
        subWriteReg(&(AP_AON->PMCTL0),31,27,0x05);
        subWriteReg(&(AP_AON->PMCTL2_0),16,7,0x3fb);
        subWriteReg(&(AP_AON->PMCTL2_0),6,6,0x01);
        //pGlobal_config[LL_SWITCH]|=RC32_TRACKINK_ALLOW|LL_RC32K_SEL;
    }
    else if(clk32Mode == CLK_32K_XTAL)
    {
        // P16 P17 for 32K XTAL input
        hal_gpio_pull_set(P16,FLOATING);
        hal_gpio_pull_set(P17,FLOATING);
        subWriteReg(&(AP_AON->PMCTL2_0),9,8,0x03);   //software control 32k_clk
        subWriteReg(&(AP_AON->PMCTL2_0),6,6,0x00);   //disable software control
        subWriteReg(&(AP_AON->PMCTL0),31,27,0x16);
        //pGlobal_config[LL_SWITCH]&=0xffffffee;
    }

    //ZQ 20200812 for rc32k wakeup
    subWriteReg(&(AP_AON->PMCTL0),28,28,0x1);//turn on 32kxtal
    subWriteReg(&(AP_AON->PMCTL1),18,17,0x0);// reduce 32kxtl bias current
}



uint32_t hal_systick(void)
{
    return osal_sys_tick;
}

uint32_t hal_ms_intv(uint32_t tick)
{
    uint32_t diff = 0;

    if(osal_sys_tick < tick)
    {
        diff = 0xffffffff- tick;
        diff = osal_sys_tick + diff;
    }
    else
    {
        diff = osal_sys_tick - tick;
    }

    return diff*625/1000;
}

/**************************************************************************************
    @fn          WaitMs

    @brief       This function process for wait program msecond,use RTC

    input parameters

    @param       uint32_t msecond: the msecond value

    output parameters

    @param       None.

    @return      None.
 **************************************************************************************/

void WaitMs(uint32_t msecond)
{
    WaitRTCCount((msecond<<15)/1000);
}

void WaitUs(uint32_t wtTime)
{
    uint32_t T0,currTick,deltTick;
    //T0 = read_current_time();
    T0 =(TIME_BASE - ((AP_TIM3->CurrentCount) >> 2));

    while(1)
    {
        currTick = (TIME_BASE - ((AP_TIM3->CurrentCount) >> 2));
        deltTick = TIME_DELTA(currTick,T0);

        if(deltTick>wtTime)
            break;
    }
}

void hal_system_soft_reset(void)
{
    HAL_ENTER_CRITICAL_SECTION();
    AP_PCR->SW_RESET1 = 0;

    while(1);
}

