/*!
 * @文件名 logic_power.c
 *
 * @功能描述
 *  1.通过检测主机控制的FCD_EN信号,控制系统的上下电
 *	2.通过检测948的LVDS Lock信号,控制屏幕的显示与关闭
 *	3.通过硬件机制,保证系统可执行自断电操作,从而不需要进入stop模式
 */
#include "logic_public.h"

#define PERIOD_CHECK_WAKEUP		10		//检测FCD_EN信号的周期,10ms
#define PERIOD_CHECK_LVDS_LOCK	10		//检测LVDS lock信号的周期,10ms

static eNotifyEvent g_BattStatus = EN_NOTIFY_VOLTAGE_NORMAL;		//电源状态
static bool g_bPowerDown = true;		//false[已上电] 				true[已下电]
static bool g_bWakeUp = false;			//false[系统未唤醒]			true[系统已唤醒]
static bool bWakeUpStatusOld = false;
static bool bLockStatusOld = false;

extern task_t s_bist_check_task;		//bist任务
task_t s_logic_check_lvds;				//周期检测LVDS lock信号的任务句柄
task_t s_logic_check_wakeup;			//周期检测Wakup信号的任务句柄(即主机FCD_EN信号)


/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_up_step1
 * Description   : 检测到FCD_EN信号时,先给948等外围器件 供电,以便与解串器实现信号LOCK
 *
 * 供电关系说明:
 * 1.FCD_EN信号->SW_3V3_EN[H]->SW_3V3[H]: AD上拉有了,器件3.3v供电有了,948,max25512,pmic供上电
 * 2.
 *
 *END**************************************************************************/
static void logic_power_up_step1(void)
{
	//1.检测到FCD_EN信号->SW_3V3_EN[H]->SW_3V3[H]: AD上拉有了,器件3.3v供电有了,948,max25512,pmic供上电

	//2.拉高PON_HOLD自锁接管电源
	fml_gpio_write(OUT_PON_HOLD,true);

	//3.拉高LDO_1V2_EN,使能1.2v电压输出,948有用到1.2v
	fml_gpio_write(OUT_LDO_1V2_EN,true);

	//4.拉高3V3_TFT_EN,使能TFT_VDD输出,给TDDI供电
	fml_gpio_write(OUT_3V3_TFT_EN,true);

	//5.使能948 LVDS输出
	fml_gpio_write(OUT_LVDS_PDB,true);

	//6.拉低TP_RST,将TDDI TP触摸复位
	fml_gpio_write(OUT_TP_RST,false);

	//7.拉低TFT_RST,将TDDI DP显示复位
	fml_gpio_write(OUT_TFT_RST,false);
	logWrite("logic_power_up_step1\r\n");
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_up_step2
 * Description   : 检测到LVDS Lock信号时,输出TFT相关电压,打开背光
 *
 *END**************************************************************************/
void logic_power_up_step2(void)
{
	//1.拉高TP_RST
	fml_gpio_write(OUT_TP_RST,true);

	//2.拉高TFT_RST
	fml_gpio_write(OUT_TFT_RST,true);

	//3.拉高TFT_SHLR,左右镜像控制
	fml_gpio_write(OUT_TFT_SHLR,true);

	//4.拉高TFT_SYBYB,TDDI退出Standby模式
	fml_gpio_write(OUT_TFT_SYBYB,true);

	//5.拉高TFT_DISP,使能显示
	fml_gpio_write(OUT_TFT_DISP,true);

	//6.拉低TFT_BIST,退出BIST测试模式
	fml_gpio_write(OUT_TFT_BIST,false);

	//7.拉高PMIC_EN,使能屏电压输出,具体输出还要写寄存器
	fml_gpio_write(OUT_PMIC_EN,true);

	//8.拉高BL_EN,使能MAX25512背光输出,具体输出还要写寄存器
	fml_gpio_write(OUT_BL_EN,true);

	//10.找到master i2c这路设备
	fml_tft_init();
	cola_delay_ms(10);//必须加延时,否则后面i2c写入会出现失败情况!

	//11.按TFT规格书,i2c配置pmic输出电压:PAVDD,NAVDD,VGH,VGL
	fml_pmic_init();

	//12.i2c配置max25512背光输出
	fml_max25512_init();

	//13.输出PWM背光控制(pwm输出放在最后,可避免闪屏!!)
	fml_pwm_init();

	fml_pwm_adjust(false);
	logWrite("logic_power_up_step2\r\n");
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_down
 * Description   : 屏端系统下电函数
 *
 *END**************************************************************************/
static void logic_power_down(void)
{
	//1.关闭pwm输出
	fml_pwm_change_duty(0);
	fml_pwm_deinit();

	//6.拉低TFT_SYBYB,TDDI进入Standby模式
	fml_gpio_write(OUT_TFT_SYBYB,false);

	cola_delay_ms(50);

	//5.拉低TFT_DISP,关闭显示
	fml_gpio_write(OUT_TFT_DISP,false);

	cola_delay_ms(16);

	//2.拉低BL_EN,关闭MAX25512背光输出
	fml_gpio_write(OUT_BL_EN,false);

	//3.拉低PMIC_EN,关闭PMIC给屏的相关供电
	fml_gpio_write(OUT_PMIC_EN,false);

	//4.拉低TFT_BIST,退出BIST测试模式
	fml_gpio_write(OUT_TFT_BIST,false);

	//7.拉低TFT_RST,复位DP
	fml_gpio_write(OUT_TFT_RST,false);

	//8.拉低TP_RST,复位TP
	fml_gpio_write(OUT_TP_RST,false);

	//9.关闭948 LVDS输出
	fml_gpio_write(OUT_LVDS_PDB,false);

	//10.拉低3V3_TFT_EN,关闭TFT_VDD输出,给TDDI断电
	fml_gpio_write(OUT_3V3_TFT_EN,false);

	//11.拉低LDO_1V2_EN,关闭1.2v电压输出
	fml_gpio_write(OUT_LDO_1V2_EN,false);

	//12.拉低PON_HOLD,MCU关闭整个系统电源,包括自身供电[但电源异常时不能关闭电源]
	if(g_BattStatus == EN_NOTIFY_VOLTAGE_NORMAL)
		fml_gpio_write(OUT_PON_HOLD,false);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_task_check_lvds_lock
 * Description   : 周期检测948 LVDS Lock信号,控制TFT的显示与关闭
 *
 *END**************************************************************************/
static void logic_task_check_lvds_lock(void *arg, uint32_t event)
{
	(void)arg;
	(void)event;
	static int iDlyCnt = 0;
	if(g_bWakeUp == false)
		return;
	if(g_BattStatus != EN_NOTIFY_VOLTAGE_NORMAL)
		return;
	bool bLockStatus = fml_gpio_read(IN_LVDS_UNLOCK);
	if(bLockStatusOld != bLockStatus)
	{
		iDlyCnt = 10;
#if 0
		if(bLockStatus)
			logWrite("detect bLockStatus = %d,signal match\r\n",bLockStatus);
		else
			logWrite("detect bLockStatus = %d,signal lost\r\n",bLockStatus);
#endif
		bLockStatusOld = bLockStatus;
	}
	if(iDlyCnt > 0)
	{
		iDlyCnt--;
		if(0 == iDlyCnt)
		{
			if(bLockStatus)
			{//检测lvds锁信号生效
				if(g_bPowerDown)
				{
					g_bPowerDown = false;
					logic_power_up_step2();
					logWrite("first lock, power on tft\r\n");
					if(cola_get_ticker() > 15000)
					{//用于解决上电没有接lvds线,后面再接上不亮屏的情况
						logWrite("tft self make bk light on\r\n");
						fml_max25512_set_bklight_on(true);
					}
				}
				else
				{
					logWrite("lock signal match,enable backlight\r\n");
					fml_max25512_set_bklight_on(true);
				}
			}
			else
			{//检测lvds锁信号丢失
				//fml_max25512_set_bklight_on(false);
				//logWrite("lock signal lost,disable backlight\r\n");
			}
		}
	}
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_task_check_wakeup_signal
 * Description   : 周期检测主机给过来的FCD_EN信号,控制系统的上下电
 *
 *END**************************************************************************/
static void logic_task_check_wakeup_signal(void *arg, uint32_t event)
{
	(void)arg;
	(void)event;
	static int iDlyCnt = 0;
	bool bWakeUpStatus = fml_gpio_read(IN_WAKEUP);
	bool bEnable = false;
	if(bWakeUpStatusOld != bWakeUpStatus)
	{
		iDlyCnt = 10;
		bWakeUpStatusOld = bWakeUpStatus;
	}
	if(iDlyCnt > 0)
	{
		iDlyCnt--;
		if(0 == iDlyCnt)
		{
			bEnable = true;
			logWrite("detect fcd_en=%d:",bWakeUpStatus);
		}
	}
	if(event > 0)
	{
		if((event & EN_NOTIFY_VOLTAGE_LOW) == EN_NOTIFY_VOLTAGE_LOW)
		{
			bEnable = true;
			logWrite("detect bat low:");
		}
		if((event & EN_NOTIFY_VOLTAGE_HIGH) == EN_NOTIFY_VOLTAGE_HIGH)
		{
			bEnable = true;
			logWrite("detect bat high:");
		}
		if((event & EN_NOTIFY_VOLTAGE_NORMAL) == EN_NOTIFY_VOLTAGE_NORMAL)
		{
			bEnable = true;
			logWrite("detect bat normal:");
		}
	}

	if(bEnable)
	{
		if(g_bWakeUp == false)
		{//上电
			logWrite("power up\r\n");
			g_bWakeUp = true;
			bLockStatusOld = false;
			logic_power_up_step1();
			cola_timer_create(&s_logic_check_lvds, logic_task_check_lvds_lock, NULL);
			cola_timer_start(&s_logic_check_lvds, EN_COLA_TIMER_ALWAYS, PERIOD_CHECK_LVDS_LOCK);
			cola_set_event(&s_bist_check_task,EN_NOTIFY_SYS_POWER_UP);
		}
		else if(g_bWakeUp == true)
		{//下电
			logWrite("power down\r\n");
			cola_set_event(&s_bist_check_task,EN_NOTIFY_SYS_POWER_DOWN);
			cola_timer_stop(&s_logic_check_lvds);
			cola_timer_delete(&s_logic_check_lvds);
			g_bWakeUp = false;
			g_bPowerDown = true;
			logic_power_down();
			cola_delay_ms(200);
		}
	}
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_init
 * Description   : 初始化电源管理检测任务
 *
 *END**************************************************************************/
void logic_power_init(void)
{
	logWrite("getSoftwareVersion:%s\r\n",getSoftwareVersion());
	bWakeUpStatusOld = !fml_gpio_read(IN_WAKEUP);
	cola_timer_create(&s_logic_check_wakeup, logic_task_check_wakeup_signal, NULL);
	cola_timer_start(&s_logic_check_wakeup, EN_COLA_TIMER_ALWAYS, PERIOD_CHECK_WAKEUP);
}
