/*******************************************************************************
 * @note      Copyright (C) 2019 Shanghai Panchip Microelectronics Co., Ltd.
 *            All rights reserved.
 * @file      main.c
 * @brief     Use FMC driver to performe flash operations and IAP feature.
 *            Flash operation include erasing, writting and reading
 *            IAP feature include running to LDROM without reset
 * @history - V1.0, 2019-3-20, lujiabo, first implementation.
*******************************************************************************/
#include "pan271x.h"

/*---------------------------------------------------------------------------------------------------------*/
/* Define functions prototype                                                                              */
/*---------------------------------------------------------------------------------------------------------*/

void Clock_Init(void)
{
	PMU->SYS_CLK_CTRL |= SYS_CLK_CTRL_OTP_READ_MODE_SEL_Msk;
	PMU->SYS_CLK_CTRL &= ~(SYS_CLK_CTRL_OTP_CLK_HIGH_CYCLE_Msk | SYS_CLK_CTRL_OTP_CLK_LOW_CYCLE_Msk);
	PMU->SYS_CLK_CTRL |= ((0x1 << SYS_CLK_CTRL_OTP_CLK_HIGH_CYCLE_Pos) | (0x0 << SYS_CLK_CTRL_OTP_CLK_LOW_CYCLE_Pos));
	PMU->SYS_CLK_CTRL |= SYS_CLK_CTRL_OTP_SW_UP_CYCLE_EN_Msk;

	PMU->ANA_ANALDO |= ANA_ANALDO_EN_LDO_FSYN_AON_Msk;
    //MCU
	CLK_XthStartupConfig();
	PMU->XTH_CTRL |= XTH_CTRL_FSYNXO_BUFEN_AON_Msk;
    PMU->XTH_CTRL |= XTH_CTRL_FSYNXO_EN_AON_Msk;
	CLK_WaitClockReady(CLK_SYS_SRCSEL_XTH);

	CLK_HCLKConfig(0);

	CLK_SYSCLKConfig(CLK_DPLL_REF_CLKSEL_XTH,CLK_DPLL_OUT_48M); 
	CLK_RefClkSrcConfig(CLK_SYS_SRCSEL_DPLL_1);

	CLK_AHBPeriphClockCmd(CLK_AHBPeriph_All,ENABLE);
	CLK_APB1PeriphClockCmd(CLK_APB1Periph_All,ENABLE);
}


void Peri_Init(void)
{
    SYS_UnlockReg();

    /* Init I/O Multi-function  */
	SYS_SET_MFP(P0,6,UART0_RX);
	SYS_SET_MFP(P0,5,UART0_TX);
	GPIO_EnableDigitalPath(P0,BIT6);

	UART_Init(UART0, 115200);
	
	SYS_SET_MFP(P1, 7, PWM_CH1);
    SYS_LockReg();
}

void platform_init()
{	
    Clock_Init();
    Peri_Init();
}

void print_status_info(void)
{
	SYS_TEST("+--------------------------------+ \r\n");
	SYS_TEST("reset flag reg RSTSTS[0] --> CHIP0RF \n");
	SYS_TEST("reset flag reg RSTSTS[1] --> PINRF   \n");
	SYS_TEST("reset flag reg RSTSTS[2] --> WDTRF   \n");
	SYS_TEST("reset flag reg RSTSTS[3] --> LVRRF   \n");
	SYS_TEST("reset flag reg RSTSTS[4] --> BODRF   \n");
	SYS_TEST("reset flag reg RSTSTS[5] --> SYSRF   \n");
	SYS_TEST("reset flag reg RSTSTS[6] --> PORRF   \n");
	SYS_TEST("reset flag reg RSTSTS[7] --> CPURF   \n");
	SYS_TEST("reset flag reg RSTSTS[8] --> CHIP1RF \n");
	SYS_TEST("\n");
}

void read_reset_status(void)
{
	SYS_TEST("Initial reset state is 0x%08x\n", CLK->RSTSTS);
	SYS_TEST("Start clear all reset status\n");
	CLK->RSTSTS |= 0xffffffff;
	SYS_TEST("reset state is 0x%08x\n", CLK->RSTSTS);
}

void chip0_reset(void)
{
	SYS_UnlockReg();
	CLK->IPRST0 |= IPRST0_CHIPRST_Msk;
    while (1) {}
}

void chip1_reset(void)
{
	SYS_UnlockReg();
	CLK->IPRST0 |= IPRST0_CHIP1RST_Msk;
    while (1) {}
}

void pin_reset(void)
{
	SYS_TEST("Wait for reset pad pressed \n");
    while (1) {}
}

void wdt_reset(void)
{
	SYS_UnlockReg();
	WDT_Open(WDT_TIMEOUT_2POW15, WDT_RESET_DELAY_2CLK, TRUE, FALSE);
    while (1) {}
}

void lvr_reset(void)
{
	CLK_EnableLVR();
    while (1) {}
}

void bod_reset(void)
{
	SYS_UnlockReg();
	CLK_ConfigureBOD(CLK_BODCTL_BOD_RST_EN, CLK_BODCTL_BODSEL_2_75V);
    while (1) {}
}

void system_reset(void)
{
	__NVIC_SystemReset();
    while (1) {}
}

void cpu_reset(void)
{
	SYS_UnlockReg();
	CLK->IPRST0 |= IPRST0_CPURST_Msk;
    while (1) {}
}
/**
 * @brief      print sample project information
 * @param[in]  none
 * @return     none
 * @history  - V1.0, 2019-3-20, first implementation.
 */ 
void LP_PrintSampleInfo()
{
    SYS_TEST("\n");
    SYS_TEST("+-------------------------------------------------------+ \r\n");
    SYS_TEST("|                      PAN271x Reset Sample Code.       | \r\n");
    SYS_TEST("+-------------------------------------------------------+ \r\n");
    SYS_TEST("|    press key to start test                            | \r\n");
    SYS_TEST("|    Input'0'   chip0_reset();                          | \r\n");
    SYS_TEST("|    Input'1'   pin_reset();                            | \r\n");
    SYS_TEST("|    Input'2'   wdt_reset();                            | \r\n");
	SYS_TEST("|    Input'3'   lvr_reset();                            | \r\n");
	SYS_TEST("|    Input'4'   bod_reset();                            | \r\n");
	SYS_TEST("|    Input'5'   system_reset();                         | \r\n");
    SYS_TEST("|    Input'6'   cpu_reset();                            | \r\n");
	SYS_TEST("|    Input'7'   chip1_reset();                          | \r\n");
    SYS_TEST("+-------------------------------------------------------+ \r\n");
}

int main(void)
{
    char cmd;

	#ifndef LP_DEBUG
	/*here set delay time prevent the soc unable to download after entering an abnormal state*/
	SYS_delay_10nop(10000);
	#endif

	CLK->IPRST0 |= IPRST0_USBRST_Msk;
	CLK->IPRST1 |= IPRST1_UART0RST_Msk;
	CLK->IPRST1 &= ~IPRST1_UART0RST_Msk;

    platform_init();

	print_status_info();
	read_reset_status();

    LP_PrintSampleInfo();

	cmd = getchar();
    while(cmd)
    {
        SYS_TEST("\r\n");
        switch(cmd)
        {
            case '0': chip0_reset(); break;
            case '1': pin_reset();   break;
            case '2': wdt_reset();   break;
            case '3': lvr_reset();   break;
            case '4': bod_reset();   break;
			case '5': system_reset();break;
			case '6': cpu_reset();   break;
			case '7': chip1_reset(); break;
			default: break;
        }
        LP_PrintSampleInfo();
        cmd = getchar();
    }
    while(1);
}
