/********************************************************* * 
@file		:spi_common.c 
@brief  	:common interface source file,store some common interface functions 
@author 	:zhongfeng
@version	:v1.0 
@date 		:19/10/31
Copyright (C) 2019 Panchip Technology Corp. All rights reserved. 
***********************************************************/
#include "pan271x.h"
#include "lp_common.h"

uint32_t cycleCnt = 10;
bool special_case_test = false, rcl32k_wakeup = false;


typedef struct {
	uint32_t r8;
	uint32_t r9;
	uint32_t r10;
	uint32_t r11;
	uint32_t r12;
//uint32_t msp;//recover by hardware
//uint32_t lr; //didn't need to recover
//uint32_t pc; //recover by hardware
//uint32_t psp;//recover by hardware
} COREREG;
volatile COREREG reg;
__ASM void Wfi_With_Recover(void)
{
	//backup r0~r7
	PUSH {R0-R7, LR}
	
	//backup r8~r12
	LDR R1, =__cpp(&reg)
	MOV R0, R8
	STR R0, [R1, #0]
	MOV R0, R9
	STR R0, [R1, #4]
	MOV R0, R10
	STR R0, [R1, #8]
	MOV R0, R11
	STR R0, [R1, #12]
	MOV R0, R12
	STR R0, [R1, #16]
	
	//goto sleep
	WFI
	
	//restore r8~r12
	LDR R1, =__cpp(&reg)
	LDR R0, [R1, #0]
	MOV R8, R0
	LDR R0, [R1, #4]
	MOV R9, R0
	LDR R0, [R1, #8]
	MOV R10, R0
	LDR R0, [R1, #12]
	MOV R11, R0
	LDR R0, [R1, #16]
	MOV R12, R0	

	//restore r0~r7
  POP {R0-R7, PC}
	//pad to clear warning
	NOP
}


uint32_t (*LP_TestEntry[])(void) =
{
    LP_SleepModeTest,
	LP_DeepSleepPwmOutTest,
	LP_ContinuesSleepWakeByGpioClk32k,
	LP_StandbyModeTest,
	LP_ContinuesStdbyWakeByGpioClk32k
};

void LP_TestFunctionEnter(uint16_t Idx)
{
    (LP_TestEntry[Idx])();
}


void Delay_1us(uint32_t us)
{
	uint32_t i,j;

	for(j = 0; j < us;j++)
		for(i = 0; i < 10;i++);
}

void FillBuffer(uint8_t *pBuffer, uint32_t size)
{
    uint32_t idx = 0;
    
    for(idx = 0; idx < size; idx++)
    {
        pBuffer[idx] = (uint8_t)(idx % 0x100);
    }
}

void LP_SetUsrSleepTimer(uint32_t sleepTime, uint8_t idx)
{
	uint32_t cur_slptmr_cnt;
	uint64_t tmp_cnt;

	cur_slptmr_cnt = LP_GetCurrentSleepTimerCnt(PMU);
	tmp_cnt = sleepTime + cur_slptmr_cnt;
	if (tmp_cnt > 0xffffffff) {
		sleepTime = tmp_cnt - 0xffffffff;
	} else {
		sleepTime = tmp_cnt;
	}
	LP_SetSleepTime(PMU,sleepTime,idx);
}


void SLPTMR1_IRQHandler(void)
{
	LP_ClearWakeFlag(PMU,LP_FLAG_CTRL_SLPTMR_FLG1_Msk);
	rcl32k_wakeup = true;
	SYS_TEST("slptmr1 int\n");
}

void SLPTMR_IRQHandler(void)
{
	GPIO_WritePin(2, 0, 1);
	LP_ClearWakeFlag(PMU,LP_FLAG_CTRL_SLPTMR_FLG0_Msk);
	rcl32k_wakeup = true;
	if (!special_case_test) {
		SYS_TEST("slptmr int\n");
		SYS_delay_10nop(1000);
	}
}

void TMR0_IRQHandler(void)
{
    if (TIMER_GetTFFlag(TIMER0))
    {
        // Clear Timer interrupt flag
		TIMER_ClearTFFlag(TIMER0, TIMER_CTL_TIMER_FLAG_Msk);
//		SYS_TEST("timer0 interrupt \r\n");
	}
}

void WDT_IRQHandler(void)
{
	SYS_TEST("WDT interrupt \r\n");
	if(WDT_GetTimeoutIntFlag())
	{
		WDT_ClearTimeoutIntFlag();
		WDT_ClearTimeoutFlag();
		WDT_ClearTimeoutWakeupFlag();
	}
	NVIC_DisableIRQ(WDT_IRQn);
	WDT_Close();
}

void GPIO1_IRQHandler(void)
{
	GPIO_DB->DBCTL &= ~GP_DBCTL_DBCLKSRC_Msk;
	GPIO_WritePin(1, 7, 1);
	if (!special_case_test) {
		NVIC_DisableIRQ(GPIO1_IRQn);
	}
	GPIO_ClrAllIntFlag(P1);
	GPIO_DB->DBCTL |= GP_DBCTL_DBCLKSRC_Msk;

	if (!special_case_test) {
		SYS_TEST("p1 interrupt \r\n");
	}
}

void GPIO2_IRQHandler(void)
{
	GPIO_DB->DBCTL &= ~GP_DBCTL_DBCLKSRC_Msk;
	GPIO_WritePin(1, 7, 1);
	if (!special_case_test) {
		NVIC_DisableIRQ(GPIO2_IRQn);
	}
	GPIO_ClrAllIntFlag(P2);
	GPIO_DB->DBCTL |= GP_DBCTL_DBCLKSRC_Msk;

	if (!special_case_test) {
		SYS_TEST("p2 interrupt \r\n");
	}
}

void LP_IRQHandler(void)
{
	if(cycleCnt){
		cycleCnt--;
	}else{
		SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
	}

	if (!special_case_test) {
		if(PMU->LP_FLAG_CTRL & LP_FLAG_CTRL_DEEPSLEEP_FLG_Msk){
			SYS_TEST("Deepsleep \r\n");
		}else if(PMU->LP_FLAG_CTRL & LP_FLAG_CTRL_STANDBY_M1_FLG_Msk){
			SYS_TEST("Standby M1\r\n");
		} else if(PMU->LP_FLAG_CTRL & LP_FLAG_CTRL_STANDBY_M0_FLG_Msk){
			SYS_TEST("Standby M0\r\n");
		} else {
			SYS_TEST("sleep\r\n");
		}
	}
	LP_ClearWakeFlag(PMU,LP_FLAG_CTRL_DEEPSLEEP_FLG_Msk|LP_FLAG_CTRL_STANDBY_M1_FLG_Msk|LP_FLAG_CTRL_STANDBY_M0_FLG_Msk);
}

void BOD_IRQHandler(void)
{
	printf("bod isr\n");
	PMU->BLD_CTRL &= ~BLD_CTRL_PMU_BOD_EN_AON_Msk;
	NVIC_DisableIRQ(BOD_IRQn);
//	while(!(PMU->LP_FLAG_CTRL & LP_FLAG_CTRL_BODOUT_Msk));
	CLK_ClearBODIntFlag();
}
