#include "low_power_app.h"
#include "Cpu.h"
#include "Can_BusOff.h"
#include "app_encoder.h"
#include "CanNm.h"
#include "can_app.h"
#include "Com_Cfg.h"
#include "led_app.h"
#include "main.h"
#include "Can_Pl.h"
#include "CanIf.h"
#include "pwm_manage.h"
#include "can_app.h"
#include "WheelHeat.h"
#include "SimpleOs_Time.h"
#define LOW_POWER_TASK_PERIOD_TIME  10u

#define GOTO_SLEEP_TIMEOUT  (5000u / LOW_POWER_TASK_PERIOD_TIME)
#define LOW_POWER_PRE_WAKEUP_DELAY_2S   (2000u / LOW_POWER_TASK_PERIOD_TIME)

#define LOW_POWER_APP_ENTER_CRITICAL()		System_DisableIrqGlobal()
#define LOW_POWER_APP_EXIT_CRITICAL()  		System_EnableIrqGlobal()


uint8_t lp_tim16_wakeup_flag = 0;
uint8_t gpio_wakeup_flag = 0;
uint16_t goto_sleep_timer = 0;

uint8_t u8LowPowerPreWakeUpDelay = 0u;
uint8_t u8LowPower4BFMsgWakeUpFlag = 0u;
void lp_tim16_wakeup_flag_set(void)
{
    lp_tim16_wakeup_flag = 1;
}

void lp_tim16_wakeup_flag_clear(void)
{
    lp_tim16_wakeup_flag = 0;
}

uint8_t lp_tim16_wakeup_flag_get(void)
{
    return (lp_tim16_wakeup_flag);
}

void LowPower4BFMsgWakeUpFlag_Set(void)
{
    u8LowPower4BFMsgWakeUpFlag = 1u;
}
void LowPower4BFMsgWakeUpFlag_Clear(void)
{
    u8LowPower4BFMsgWakeUpFlag = 0u;
}

void gpio_wakeup_flag_set(void)
{
    gpio_wakeup_flag = 1;
}

void gpio_wakeup_flag_clear(void)
{
    gpio_wakeup_flag = 0;
}

uint8_t gpio_wakeup_flag_get(void)
{
    return gpio_wakeup_flag;
}

/**
	* @brief  Sleep
	* @param  void
	* @retval void
	*/
void Sleep(void)
{

	FL_PMU_SleepInitTypeDef LPM_InitStruct;

	//  FL_CMU_RCLF_Enable();               /* 暂开启RCLF */
	FL_RMU_PDR_Enable(RMU);                 /* 打开PDR */
	FL_RMU_BOR_Disable(RMU);                /* 关闭BOR 2uA */

	FL_VREF_Disable(VREF);                  /* 关闭VREF1p2 */

	LPM_InitStruct.deepSleep            = FL_PMU_SLEEP_MODE_NORMAL;
	LPM_InitStruct.powerMode            = FL_PMU_POWER_MODE_SLEEP_OR_DEEPSLEEP;
	LPM_InitStruct.wakeupFrequency      = FL_PMU_RCHF_WAKEUP_FREQ_8MHZ;
	LPM_InitStruct.wakeupDelay          = FL_PMU_WAKEUP_DELAY_2US;
	LPM_InitStruct.LDOLowPowerMode      = FL_PMU_LDO_LPM_DISABLE;
	LPM_InitStruct.coreVoltageScaling   = FL_DISABLE;
	FL_PMU_Sleep_Init(PMU, &LPM_InitStruct);
	/* 使能BOR */
	FL_RMU_BOR_Enable(RMU);
	/* 睡眠电源模式*/
	FL_PMU_SetLowPowerMode(PMU, FL_PMU_POWER_MODE_SLEEP_OR_DEEPSLEEP);
	/* 休眠 */
	__WFI();
	/* 使能VREF1p2 */
	FL_VREF_Enable(VREF);
}



void low_power_goto_sleep(void)
{
    LOW_POWER_APP_ENTER_CRITICAL();
    (void)Led_EnterSleepMode();
    (void)tim_de_init();
    (void)adc_de_init();
    (void)CanTrcv_Disable();
    (void)gpio_goto_sleep();
    (void)pwm_manage_deinit();
    (void)lptim16_init();
    
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    LOW_POWER_APP_EXIT_CRITICAL();
}


uint8_t low_power_pre_wakeup_Process(void)
{
    logic_timer_s logic_delay_100ms;
    uint8_t time_out;
    uint8_t power_gear;
    uint8_t ret;
    uint8_t time_100ms_cnt;

    (void)clk_init();
    (void)tim_init();
    (void)gpio_goto_wakeup();
    (void)Can_Init();
    (void)CanIf_SetControllerMode(0,CANIF_CS_STARTED);
    (void)Com_RxStart();
    (void)logic_timer_start((logic_timer_s*)&logic_delay_100ms, (void*)NULL_POINT , 100);
    time_100ms_cnt = 0;
    for(;;)
    {
        
        can_app_receive_signal(COM_RXSIGBCM1_POWER_GEAR, &power_gear);
        if(power_gear == POWER_GEAR_ON)
        {
            ret = true;
            break;
        }
        if( CanNm_RxIndFlg[0] == TRUE )
        {
            CanNm_RxIndFlg[0] = FALSE;
            ret = true;
            break;
        }
        time_out = logic_timer_out((logic_timer_s*)&logic_delay_100ms);
        if(time_out)
        {
            (void)logic_timer_start((logic_timer_s*)&logic_delay_100ms, (void*)NULL_POINT , 100);
            wdog_task();
            time_100ms_cnt ++;
            if(time_100ms_cnt >= 20u)
            {
                ret = false;
                break;
            }

        }
    }

    return ret;
}



void low_power_goto_wakeup(void)
{
    LOW_POWER_APP_ENTER_CRITICAL();   

	clk_init();
	gpio_init();
	adc_init();
	tim_init();
	system_voltage_manage_init();
	(void)app_encoder_init();
	stack_check_init();
	CanTrcv_Init();
	(void)Can_Init();
	CanIf_Init();
	(void)CanIf_SetControllerMode(0,CANIF_CS_STARTED);
	Com_Init();
	//Com_TxStart();
	Com_RxStart();
	CanTp_Init(((void *) 0));
	CAN_BusOff_Init();
	Dcm_Init(((void *) 0));
	key_app_init();
	(void)key_encoder_driver_init();
	cal_did_init();
	boot_app_init();
	random_init();
	service_27_init();
	dem_task_init();
    WheelHeat_Init();
    (void)CanApp_WakeupProcess();
   // CanNm_PassiveStartUp(0);
    FL_LPTIM16_DeInit(LPTIM16);
    SimpleOsTime_Init();
    goto_sleep_timer = 0;
    u8LowPowerPreWakeUpDelay = LOW_POWER_PRE_WAKEUP_DELAY_2S;
    u8LowPower4BFMsgWakeUpFlag = 0;
    LOW_POWER_APP_EXIT_CRITICAL(); 
}
void low_power_process(void)
{
    for(;;)
    {   
        wdog_task();
        
        (void)lp_tim16_wakeup_flag_clear();
        (void)gpio_wakeup_flag_clear();
        (void)low_power_goto_sleep();
        (void)CanTrcv_Disable();
        Sleep();
        if(gpio_wakeup_flag_get() != 0u)
        {
            low_power_goto_wakeup();
            break;
        }
      }
}

void LowPowerPreWakeUpDelay_Start(void)
{
    u8LowPowerPreWakeUpDelay = LOW_POWER_PRE_WAKEUP_DELAY_2S;
}

uint8_t Is_LowPowerPreWakeUpDelay_Empty(void)
{
    uint8_t Ret;

    if(u8LowPowerPreWakeUpDelay != 0U)
    {
        Ret = FALSE;
    }
    else
    {
        Ret = TRUE;
    }
    return Ret;
}


void low_power_app_task(void)
{
    Nm_StateType can_nm_state;
    Nm_ModeType  can_nm_mode;
    uint8_t power_gear;
    uint8_t led_app_allow_sleep;

   CanNm_GetState(0 ,(Nm_StateType *)(&can_nm_state),(Nm_ModeType *)(&can_nm_mode));
   can_app_receive_signal(COM_RXSIGBCM1_POWER_GEAR, &power_gear);

    switch(can_nm_state)
    {
        case NM_STATE_UNINIT:
            while(1);
            break;
        case NM_STATE_BUS_SLEEP:
            if(u8LowPowerPreWakeUpDelay)
            {
                u8LowPowerPreWakeUpDelay --;
                if((power_gear != POWER_GEAR_OFF) || (u8LowPower4BFMsgWakeUpFlag != 0u))
                {
                    u8LowPowerPreWakeUpDelay = 0;
                    CanNm_PassiveStartUp(0);
                    break;
                }                 
            }
            else
            {
                led_app_allow_sleep = is_led_app_allow_sleep();
                goto_sleep_timer ++;
                if((led_app_allow_sleep == true) || (goto_sleep_timer >= GOTO_SLEEP_TIMEOUT))
                {
                    low_power_process();
                }   
            }
   
            break;
        case NM_STATE_PREPARE_BUS_SLEEP:
            goto_sleep_timer = 0;
            if((power_gear != POWER_GEAR_OFF))
            {
                CanNm_PassiveStartUp(0);
            }
            break;
        case NM_STATE_READY_SLEEP:
            goto_sleep_timer = 0;
            if((power_gear != POWER_GEAR_OFF))
            {
                CanNm_NetworkRequest(0);
            }
            break;
        case NM_STATE_REPEAT_MESSAGE:
            goto_sleep_timer = 0;
            if((power_gear != POWER_GEAR_OFF))
            {
                CanNm_NetworkRequest(0);
            }
            else
            {
                CanNm_NetworkRelease(0);
            }
            break;
        case NM_STATE_NORMAL_OPERATION:
        case NM_STATE_SYNCHRONIZE:
        case NM_STATE_WAIT_CHECK_ACTIVATION:
        case NM_STATE_WAIT_NETWORK_STARTUP:
            goto_sleep_timer = 0;
            if((power_gear == POWER_GEAR_OFF))
            {
                CanNm_NetworkRelease(0);
            }
            break;
        default:
            while(1);
            break;
        
    }
    
}








