/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: 	Sino
Version: 	V0.0
Date: 		2020/04/26
History:
	V2.0	2020/04/26		 Preliminary
********************************************************************************/
#include "Main.h"


BOOL bSleepFlg;                                             //系统进入IDLE标志
BOOL bPDFlg;
BOOL bWakeupFlg;
BOOL bPCEnterPDFlg;                                         //PC通知系统进入SLEEP标志
U8  xdata ucSleepTimerCnt;
U8  xdata ucPDTimerCnt;
U8  xdata ucResetFlag;

/*************************************************************************************************
* 函数名: WakeUpProcess
* 参  数: 无
* 返回值: 无
* 描  述: 从Sleep模式唤醒，可通过电流检测和按键唤醒
*************************************************************************************************/
void WakeUpProcess(void)
{
	if(bWakeupFlg)
	{
		bWakeupFlg = 0;
		if(bSleepFlg)
		{
			McuClockSet(MCU_CLK_24MHz);
            IrqEn();
            
			bSleepFlg = 0;
			ucSleepTimerCnt = 0;
			Delay1ms(1);
			
			#if	(UART0_DEFINE != 0)			
			IrqUart0En();						       		//开启uart0中断						        
			#endif	
			IrqTimer3En();                                  //开启Timer3中断
			McuTwiEn();                                     //开启MCU Twi模块
				
			AfeAlarmDis(AFE_ALARM_SC | AFE_ALARM_OV | AFE_ALARM_CD);
			AfeTempADCEn();							//开启AFE温度采集
			AfeWDTEn();                                    //开启AFE WDT
		}
		ucSleepTimerCnt = 0;
		ucPDTimerCnt = 0;
		ucUart0TimeoutCnt = 0;
		ucUart1TimeoutCnt = 0;
		ucUart2TimeoutCnt = 0;
	}
}


/*************************************************************************************************
* 函数名: SystemIntoPD
* 参  数: 无
* 返回值: 无
* 描  述: 系统进入掉电模式
*************************************************************************************************/
void SystemIntoPD(void)
{
	while(1)
    {
        McuWDTClear();                                      //清除看门狗
        
        IrqDis();                                           //关闭中断源
//        LEDAllOff();                                        //关闭LED显示
        BlueToothPowerDis();                                //关闭蓝牙模块
        AFEMosCtl(0);                                       //关闭MOS驱动
        
        AFEEnterPD();                                       //关闭3.3V电源
    }
}


/*************************************************************************************************
* 函数名: SystemIntoSleep
* 参  数: 无
* 返回值: 无
* 描  述: 低功耗处理，进入IDLE或者PD
*************************************************************************************************/
void SystemIntoSleep(void)    
{	
//	LEDAllOff();                                            //关闭LED显示
	BlueToothPowerDis();                                    //关闭蓝牙模块
	bLedDisBleFlg = 0;

	AfeWDTDis();                                            //关闭AFE WDT
	AfeTempADCDis();									//关闭AFE温度采集
	AfeAlarmEn(AFE_ALARM_SC | AFE_ALARM_OV | AFE_ALARM_CD);	//开启SC,OV,CD的Alarm功能
	McuTwiDis();                                            //关闭MCU Twi模块降低功耗
	McuPWM2Dis();                                           //关闭MCU PWM模块
	if(bDSGMOS)                                             //DSG开启时，直接输出高电平
	{
		IO_DSG_PWM = 1;
	}
	else
	{
		IO_DSG_PWM = 0;
	}
	Delay1ms(1);

	IrqDis();                                               //关闭总中断源
	#if	(UART0_DEFINE != 0)	
	IrqUart0Dis();
	#endif
	#if	(UART1_DEFINE != 0)
	IrqUart1Dis();
	#endif
	#if	(UART2_DEFINE != 0)
	IrqUart2Dis();
	#endif
	IrqTimer3Dis();                                         //关闭Timer3中断
	IrqINT4FlgClr();                                        //保留外部中断4，清标志
    McuClockSet(MCU_CLK_128KHz);                            //设置系统时钟为128KHz
	IrqEn();
	
	McuIntoPD();                                            //MCU进入PD，可通过外部按键或ALARM唤醒。由于在系统进sleep后可能没有关DSG MOS，可能因为持续的小电流而将电芯耗空，但是，AFE内部预留FUSE，在VDD电压低于4V时会关闭LDO，使V33断电。
}
	



/*************************************************************************************************
* 函数名: LowPowerCheck
* 参  数: 无
* 返回值: 无
* 描  述: 检测是否进入IDLE或者PD
*************************************************************************************************/
void LowPowerCheck(void)
{
	if(bPCEnterPDFlg && (bUart0SndAckFlg||bUart1SndAckFlg||bUart2SndAckFlg))                     //上位机发送名字强制进入PD
	{
		bPCEnterPDFlg = 0;
		bPDFlg = 1;
	}
    else if(bCTO)                                           //发生断线后，延时进入PD
    {
		if(++ucPDTimerCnt >= E2ucLowPowerDeley)
		{
			ucPDTimerCnt = E2ucLowPowerDeley;
			bPDFlg = 1;
		}
    }
	else if(!bLedDisFlg)                                    //LED显示关闭后开始检测进入低功耗
	{
		if(!bCHGING && !bDSGING)                            //非充非放状态
		{
			if(bUV)                                         //发生欠压保护后，延时进入PD
			{
				if(++ucPDTimerCnt >= E2ucLowPowerDeley)
				{
					ucPDTimerCnt = E2ucLowPowerDeley;
					bPDFlg = 1;
				}
			}
			else                                            //未发生欠压保护，且未发生其他保护，则延时进入IDLE
			{
                ucPDTimerCnt = 0;
                if(!(bOTC | bUTC | bOV | bOCC | bOTD | bUTD | bUV | bOCD1 | bOCD2 | bAFE_SC | bLedDisBleFlg))
                {
    				if(++ucSleepTimerCnt >= E2ucLowPowerDeley)
    				{
    					ucSleepTimerCnt = E2ucLowPowerDeley;
    					bSleepFlg = 1;
    				}
                }
                else
                {
                    ucSleepTimerCnt = 0;
                }
			}
		}
		else
		{
			ucSleepTimerCnt = 0;
			ucPDTimerCnt = 0;
		}
	}
	else
	{
		ucSleepTimerCnt = 0;
		ucPDTimerCnt = 0;
	}
}


/*************************************************************************************************
* 函数名: LowPowerProcess
* 参  数: 无
* 返回值: 无
* 描  述: 低功耗处理，进入IDLE或者PD
*************************************************************************************************/
void LowPowerProcess(void)
{
	if(!bSleepFlg && !bPDFlg)
	{
		IrqDis();
		if(!(bKeyFlg | bCaliFlg | bMcuFlashWrFlg | bWakeupFlg | bISPFlg | bTimer50msFlg | bTimer1sFlg) && (ucResetFlag!=0x12))
		{
			IrqEn();
			McuIntoIdle();
		}
		IrqEn();
	}
	else if(bPDFlg)
	{
		bMcuFlashWrFlg = 1;
		McuFlashProcess();
		SystemIntoPD();
	}
	else if(bSleepFlg)
	{
		SystemIntoSleep();
	}
	
	WakeUpProcess();                                        //系统从低功耗唤醒
}


