#include "platform.h"
#include "hal_headfile.h"
#include "system.h"
#include "debug.h"
#include "config.h"
#include "power.h"

void gpio_int_callback(void *param);

volatile uint8_t Flag_system_hib = 0;
volatile uint8_t Flag_system_wfi = 0;
volatile uint8_t wfi_control_pin = 0;

void power_control_init(void)
{
    if(user_param.power_contrl == BY_GPIO0)
    {
        wfi_control_pin = GPIO0;
        wfi_gpio_init(wfi_control_pin);
    }
    Flag_system_hib = 0;
}

void wfi_gpio_init(gpio_pin_t pin)
{
    gpio_interrupt_config_type_t  gpio_interrupt_config;
    gpio_interrupt_config.ic = GPIO_IC0;
    gpio_interrupt_config.pin = pin;
    gpio_interrupt_config.event = RISING_EDGE;
    hal_gpio_interrput_config(&gpio_interrupt_config);
    hal_gpio_set_direction(pin, GPIO_DIRECTION_INPUT);
    hal_gpio_set_pull(pin, GPIO_PULL_UP);
    hal_gpio_pinmux_set_function(pin, GPIO_MUXSEL_GPIO);
    hal_gpio_interrupt_set_pin(pin, GPIO_IC0);
    hal_gpio_interrupt_set_callback(GPIO_IC0, gpio_int_callback, (void *)pin);
    hal_gpio_interrupt_init();
    hal_gpio_interrupt_clear_interrupt_pending(GPIO_IC0);
    hal_set_gpio_interrupt_enable(GPIO_IC0);
}

void gpio_int_callback(void *param)
{
    if (hal_gpio_read((uint32_t)param))
    {
        debug("high level\r\n");
    }
    else
    {
        debug("low level\r\n");
    }
}

/**
* @brief        WFI初始化
* @details
* @param[in]    none
* @return       none
* @note         none
*/
void wfi_init(void)
{
    wfi_mask0_config(IRQ_SOURCE_GPIO0, ENABLE);
}

/**
* @brief        进入空闲状态
* @details      使用wfi指令进入空闲状态
* @param[in]    none
* @return       none
* @note         none
*/

extern void denoise_lowpower_callback(uint8_t en);

__ILM void pmu_enter_wfi(void)
{
    uint32_t cmu_sysclk = DEV_CMU->SYSCLK;
    uint32_t core_pll_ctl = AON_PLL->CORE_CTL;
    time0_lowper_callback(DISABLE);
    denoise_lowpower_callback(DISABLE);
    wfi_mask1_config(WFI_MASK1_GPIO0, ENABLE);
    //切换CPU时钟到低频时钟
    DEV_CMU->SYSCLK =
        DEV_CMU_SYSCLK_CORE_DIV_1   |
        DEV_CMU_SYSCLK_SYS_DIV_1    |
        DEV_CMU_SYSCLK_CORE_SEL_OSC_ADC;
    AON_PLL->CORE_CTL_f.EN = 0;
    //逐渐减小DVDD供电
    pmu_dvdd_voltage_config(PMU_DVDD_VOL_1_1V);
    pmu_dvdd_voltage_config(PMU_DVDD_VOL_1_0V);
    pmu_dvdd_voltage_config(PMU_DVDD_VOL_0_9V);
    __asm("wfi");
    //逐渐增加DVDD供电
    pmu_dvdd_voltage_config(PMU_DVDD_VOL_1_0V);
    pmu_dvdd_voltage_config(PMU_DVDD_VOL_1_1V);
    pmu_dvdd_voltage_config(PMU_DVDD_VOL_1_2V);
    AON_PLL->CORE_CTL = core_pll_ctl;

    while (!AON_PLL->LOCK_STAT_f.PLL_CORE_LOCK);

    // //恢复CPU时钟
    DEV_CMU->SYSCLK = cmu_sysclk;
    time0_lowper_callback(ENABLE);
    denoise_lowpower_callback(ENABLE);
    system_reboot();
    debug("quit wfi\r\n");
}

/**
* @brief        进入掉电状态
* @details      进入掉电状态
* @param[in]    none
* @return       none
* @note         进入掉电状态后，只能被ONOFF唤醒。唤醒后，程序会复位
*/
void pmu_enter_hibernate(void)
{
    pmu_clear_interrupt_pending(PMU_ONOFF_SHORT_PENDING);
    pmu_wakeup_config(PMU_WAKEUP_ONOFF_SHORT, ENABLE);
    pmu_state_config(PMU_STATE_HIBERNATE);

    while (1);  //hold cpu
}

void system_pmu_process(void)
{
    static uint8_t pin_time_cnt;

    if (Flag_system_hib) //进入hibernate
    {
        if ((AON_PMU->ONOFF & 0x05) == 0x05) //ONOFF已经抬起
        {
            Flag_system_hib = 0;
            /*写svdd_global是为了区分是ONOFF唤醒还是RESET复位*/
            pmu_enter_hibernate();
        }
    }

    if (Flag_system_wfi)/*进入wfi*/
    {
        Flag_system_wfi = 0;
        pmu_enter_wfi();
    }

    if(user_param.power_contrl != BY_GPIO0)
    {
       return;
    }
    if (!hal_gpio_read(wfi_control_pin)) /*低电平关闭降噪*/
    {
        if (pin_time_cnt < 250)
        {
            pin_time_cnt++;
        }

        if (pin_time_cnt == 10)
        {
            Flag_system_wfi = 1;
        }
    }
    else  /*高电平开启降噪*/
    {
        pin_time_cnt = 0;
    }
}

void system_wakeup_process(void)
{
    onoff_pin_init();
    if (AON_PMU->ONOFF & 0x02) //上电唤醒
    {
        //直接进主程序
        pmu_clear_interrupt_pending(PMU_IT_ONOFF_SHORT);
        pmu_clear_interrupt_pending(PMU_IT_ONOFF_LONG);
        pmu_clear_interrupt_pending(PMU_IT_ONOFF_ULONG);
        pmu_interrupt_enable_config(PMU_IT_ONOFF_SHORT);
        pmu_interrupt_enable_config(PMU_IT_ONOFF_LONG);
        pmu_interrupt_enable_config(PMU_IT_ONOFF_ULONG);
        return;
    }

    while ((AON_PMU->ONOFF & 0x05) != 0x05) //onoff唤醒的,必须要等待抬起
    {
        //debug("wakeup3:%x\r\n",AON_PMU->ONOFF & 0x05);
        if (pmu_is_interrupt_pending(PMU_ONOFF_LONG_PENDING)) //长按生效
        {
            pmu_clear_interrupt_pending(PMU_IT_ONOFF_SHORT);
            pmu_clear_interrupt_pending(PMU_IT_ONOFF_LONG);
            pmu_clear_interrupt_pending(PMU_IT_ONOFF_ULONG);
            pmu_interrupt_enable_config(PMU_IT_ONOFF_SHORT);
            pmu_interrupt_enable_config(PMU_IT_ONOFF_LONG);
            pmu_interrupt_enable_config(PMU_IT_ONOFF_ULONG);
            return;
        }
    }

    /*短按唤醒*/
    {
        pmu_clear_interrupt_pending(PMU_IT_ONOFF_SHORT);
        pmu_clear_interrupt_pending(PMU_IT_ONOFF_LONG);
        pmu_clear_interrupt_pending(PMU_IT_ONOFF_ULONG);
        pmu_interrupt_enable_config(PMU_IT_ONOFF_SHORT);
        pmu_interrupt_enable_config(PMU_IT_ONOFF_LONG);
        pmu_interrupt_enable_config(PMU_IT_ONOFF_ULONG);
        return;
    }
    //debug("wakeup5\r\n");
    pmu_clear_interrupt_pending(PMU_ONOFF_SHORT_PENDING);
    pmu_wakeup_config(PMU_WAKEUP_ONOFF_SHORT, ENABLE);
    pmu_state_config(PMU_STATE_HIBERNATE);

    while (1);  //hold cpu
}

/**
* @brief        onoff_pin_init(void)
* @details      onoff短按、长按、超长按初始化
* @param[in]    none
* @return       none
* @note         debounce_time<短按事件<short_time<长按事件<long_time<超长按事件<ulong_time
*/
void onoff_pin_init(void)
{
    pmu_onoff_edge_config(PMU_ONOFF_EDGE_FALL);
    pmu_onoff_debounce_time_config(PMU_ONOFF_DEB_TIME_25MS);
    pmu_onoff_short_time_config(PMU_ONOFF_SHORT_TIME_2S);
    pmu_onoff_long_time_config(PMU_ONOFF_LONG_TIME_8S);
    pmu_onoff_ulong_time_config(PMU_ONOFF_ULONG_TIME_12S);
    pmu_clear_interrupt_pending(PMU_IT_ONOFF_SHORT);
    pmu_clear_interrupt_pending(PMU_IT_ONOFF_LONG);
    pmu_clear_interrupt_pending(PMU_IT_ONOFF_ULONG);
}

/**
* @brief        软件重启系统
* @details      通过写SYS_REBOOT寄存器对系统重启
* @param[in]    none
* @return       none
* @note         none
*/
void system_reboot(void)
{
    DEV_RMU->BOOT_f.RE_BOOT = 1;
    while (1)
    {
        ;/* code */
    }
}


/**
* @brief        onoff_irq_handler(void)
* @details      onoff 中断服务函数
* @param[in]    none
* @return       none
* @note         onoff中断服务函数
*/
void onoff_irq_handler(void)
{
    if (pmu_is_interrupt_pending(PMU_ONOFF_SHORT_PENDING))
    {
        pmu_clear_interrupt_pending(PMU_ONOFF_SHORT_PENDING);
        power_bug("onoff_short_irq_handler\r\n");
        if(user_param.power_contrl == BY_ONOFF)
        {
            Flag_system_hib = 1;
        }
    }
    else if (pmu_is_interrupt_pending(PMU_ONOFF_LONG_PENDING))
    {
        pmu_clear_interrupt_pending(PMU_ONOFF_LONG_PENDING);
        power_bug("onoff_long_irq_handler\r\n");
    }
    else if (pmu_is_interrupt_pending(PMU_ONOFF_ULONG_PENDING))
    {
        pmu_clear_interrupt_pending(PMU_ONOFF_ULONG_PENDING);
        power_bug("onoff_ulong_irq_handler\r\n");
    }
}