/*******************************************************************************
 * @note      Copyright (C) 2019 Shanghai Panchip Microelectronics Co., Ltd.
 *            All rights reserved.
 * @file      user_lp.c
 * @brief     Low Power test
 * @history - V1.0, 2019-3-21, zhangzhao, first implementation.
*******************************************************************************/
#include "pan271x.h"
#include "lp_common.h"


static void LP_SetStandbyMode1Config_test(PMU_T *pmu,
							uint32_t wkMode,
							uint8_t stdy_mode)
{
	LP_EnableInt(pmu,ENABLE);
	if (stdy_mode == LP_STANDBY_M1_MODE1){
		pmu->ANA_LPLDO |= ANA_LPLDO_PMU_LPLDOL_EN_AON_Msk;
		LP_SetAnalogConfig(pmu, LP_CTRL0_PMU_ISOLATE_EN_Msk, ENABLE);
		LP_SetAnalogConfig(pmu, LP_CTRL0_SW0_LP_CTRL_Msk | LP_CTRL0_SW1_LP_CTRL_Msk, DISABLE);
	} else if (stdy_mode == LP_STANDBY_M1_MODE2){
		pmu->ANA_LPLDO &= ~ANA_LPLDO_PMU_LPLDOL_EN_AON_Msk;
		LP_SetAnalogConfig(pmu, LP_CTRL0_PMU_ISOLATE_EN_Msk | LP_CTRL0_SW1_LP_CTRL_Msk, ENABLE);
		LP_SetAnalogConfig(pmu, LP_CTRL0_SW0_LP_CTRL_Msk, DISABLE);
	}
	
	LP_SetSleepMode(pmu, LP_MODE_SEL_STANDBY_M1_MODE);
	if((LP_WKUP_MODE_SEL_EXT_GPIO != wkMode)&&(LP_WKUP_MODE_SEL_GPIO != wkMode)){
		LP_SetAnalogConfig(pmu, LP_CTRL0_SLOW_CLK_LP_CTRL_Msk, ENABLE);
	} else {
		LP_SetAnalogConfig(pmu, LP_CTRL0_SLOW_CLK_LP_CTRL_Msk, DISABLE);
    }
	
	LP_SetOtpConfig(pmu, OTP_MODE_PSD_CE_REEN_DIS);
	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
	Wfi_With_Recover();
}

static void LP_RestoreAfterStandbyWake(void)
{
//	Peri_Init();
//	SYS_TEST("restore\n");
	NVIC_EnableIRQ(GPIO1_IRQn);
	NVIC_EnableIRQ(SLPTMR_IRQn);
//	SYS_delay_10nop(10000);
}

uint32_t LP_ContinuesStdbyWakeByGpioClk32k(void)
{
	char ldol[4], ldoh[4];
	uint32_t tmp_reg;
	uint32_t wkupMode = LP_WKUP_MODE_SEL_32K;
	uint32_t stdbyMode = LP_STANDBY_M1_MODE1;

	//set test pin
	GPIO_WritePin(1, 7, 0);
	SYS_SET_MFP(P1,7,GPIO);
	GPIO_SetMode(P1, BIT7, GPIO_MODE_OUTPUT);
	
	GPIO_WritePin(2, 0, 0);
	SYS_SET_MFP(P2,0,GPIO);
	GPIO_SetMode(P2, BIT0, GPIO_MODE_OUTPUT);
	
	special_case_test = true;
	NVIC_DisableIRQ(LP_IRQn);
//	NVIC_DisableIRQ(SLPTMR_IRQn);

	SYS_TEST("Input 'A' mode1 selected\n");
	SYS_TEST("Input 'B' mode2 selected\n");
	char mode;
	mode = getchar();
	if ((mode == 'A') || (mode == 'a'))
		stdbyMode = LP_STANDBY_M1_MODE1;
	else
		stdbyMode = LP_STANDBY_M1_MODE2;
	SYS_delay_10nop(1000);
	uint32_t lpldo1;
	uint32_t lpldoh;
	SYS_TEST("Input lpldol trim\n");
	gets(ldol);
	lpldo1 = atoi(ldol);
	SYS_TEST("lpldol = %x\n", lpldo1);
	SYS_delay_10nop(1000);
	SYS_TEST("Input lpldoh trim\n");
	gets(ldoh);
	lpldoh = atoi(ldoh);
	SYS_TEST("lpldoh = %x\n", lpldoh);
	SYS_delay_10nop(1000);

	tmp_reg = PMU->ANA_LPLDO;
	tmp_reg &= ~ANA_LPLDO_PMU_LPLDOH_VSEL_AON_Msk;
	tmp_reg = (tmp_reg & ~(0xf << 20)) | (lpldoh << 20);
	PMU->ANA_LPLDO = tmp_reg;
	tmp_reg = PMU->ANA_RESERVED;
	tmp_reg &= ~ANA_RESERVED_PMU_LPLDOL_VSEL_AON_Msk;
	tmp_reg = (tmp_reg & ~(0xf<<17)) | (lpldo1 << 17);
	PMU->ANA_RESERVED = tmp_reg;

	tmp_reg = PMU->CPU_ADDR_REMAP_CTRL;
	memcpy((void*)vec_remap_adr, (void*)(0x0), 256);
	tmp_reg &= ~CPU_ADDR_REMAP_CTRL_CPU_REMAP_ADDR_Msk;
	tmp_reg |= ((vec_remap_adr >> 8) & CPU_ADDR_REMAP_CTRL_CPU_REMAP_ADDR_Msk);
	tmp_reg |= CPU_ADDR_REMAP_CTRL_CPU_ADDR_REMAP_EN_Msk;
	PMU->CPU_ADDR_REMAP_CTRL = tmp_reg;
	
	GPIO_DisableDigitalPath(P0,0x03);
	GPIO_DisablePullupPath(P0,0x03);

	GPIO_ClrAllIntFlag(P1);
	__NVIC_ClearPendingIRQ(GPIO1_IRQn);	
	GPIO_DisableInt(P1,2);

	SYS_TEST("\r\nwake up by gpio P12 & 32k \r\n");
	SYS_delay_10nop(10000);
	SYS_SET_MFP(P1, 2, GPIO);
	GPIO_SetDebounceTime(GPIO_DBCTL_DBCLKSRC_RCL, GPIO_DBCTL_DBCLKSEL_1);
	GPIO_SetMode(P1,BIT2,GPIO_MODE_INPUT);
	GPIO_EnableDigitalPath(P1,BIT2);
	GPIO_EnablePulldownPath(P1,BIT2);
	GPIO_EnableInt(P1,2,GPIO_INT_RISING);
	GPIO_ClrAllIntFlag(P1);
	__NVIC_ClearPendingIRQ(GPIO1_IRQn);
	NVIC_EnableIRQ(GPIO1_IRQn);
	
	LP_SetSleepTimerConfig(PMU, SLPTMR_CTRL_SLPTMR_EN_Msk | SLPTMR_CTRL_SLPTMR_INT_EN_Msk
								| SLPTMR_CTRL_SLPTMR_CMP0_EN_Msk | SLPTMR_CTRL_SLPTMR_WK_EN_Msk,
								ENABLE);
	LP_SetUsrSleepTimer(32000 * 2, 0);
	//set cpu retention
	PMU->LP_CTRL0 |= LP_CTRL0_CPU_LP_RET_EN_Msk;
	
	GPIO_DisableDigitalPath(P0,BIT6);
	LP_SetStandbyMode1Config_test(PMU, wkupMode, stdbyMode);
	LP_RestoreAfterStandbyWake();
	while (1) {
		GPIO_WritePin(1, 7, 0);
		GPIO_WritePin(2, 0, 0);
		if (rcl32k_wakeup) {
			LP_SetUsrSleepTimer(32000 * 2, 0);
		}
		rcl32k_wakeup = false;
		LP_ClearWakeFlag(PMU,LP_FLAG_CTRL_STANDBY_M1_FLG_Msk);
		
		Wfi_With_Recover();
		LP_RestoreAfterStandbyWake();
	}
}

