#include "r_typedefs.h"
#include "dr7f701441.dvf.h"
#include "r_dev_clk_types.h"
#include "r_dev_api.h"
#include "Clock.h"
#include "GPIO.h"
#include "Watchdog.h"
#include "TYW_FLASH.h"
#include "RTC.h"
#include "rh850_macros.h"

extern uint32_t TestBackupRam;

#define CLOCK_PROTECTED_WRITE(preg, pstatus, reg, value) \
	do                                                   \
	{                                                    \
		(preg) = 0xA5U;                                  \
		(reg) = (value);                                 \
		(reg) = ~(value);                                \
		(reg) = (value);                                 \
	} while ((pstatus) == 1U)

static const r_dev_ClkGenConfig_t g_stClockGenCfg =
	{
		/*mainosc*/
		{
			/* FrequencyHz */ R_DEV_MOSC_FRQ_HZ,
			/* StabiTimeNs */ 400000UL,
			/* Gain        */ 3U,
			/* Running     */ 1U,
			/* StpReqMsk   */ 1U,
		},

		/*subosc*/
		{
			/* FrequencyHz */ 32768UL,
			/* Running     */ 0U,
			/* StpReqMsk   */ 0U,
		},

		/* PLL */
		{
			/*PLL0*/
			{
				/* Mode        */ R_DEV_PLL_SSCG,
				/* DithMode    */ R_DEV_PLL_DITH_DOWN,
				/* DithRange   */ 3U,
				/* ModFreq     */ 50UL,
				/* FrequencyHz */ 480UL * 1000UL * 1000UL,
				/* StabiTimeNs */ 40000UL,
				/* StpReqMsk   */ 0U,
			},

			/*PLL1*/
			{
				/* Mode        */ R_DEV_PLL_ON,
				/* DithMode    */ R_DEV_PLL_DITH_FIXED,
				/* DithRange   */ 0U,
				/* ModFreq     */ 0UL,
				/* FrequencyHz */ 480UL * 1000UL * 1000UL,
				/* StabiTimeNs */ 40000UL,
				/* StpReqMsk   */ 0U,
			},

			/*PLL2*/
			{
				/* Mode        */ R_DEV_PLL_OFF,
				/* DithMode    */ R_DEV_PLL_DITH_FIXED,
				/* DithRange   */ 0U,
				/* ModFreq     */ 0UL,
				/* FrequencyHz */ 0UL,
				/* StabiTimeNs */ 0UL,
				/* StpReqMsk   */ 0U,
			},
		},

		/* ROSC */
		/* RoscStpReqMsk */ 1U,

		/* BusEnable */
		{
			/* R_DEV_CLK_PLL0    */ 1U,
			/* R_DEV_CLK_PLL1    */ 1U,
			/* R_DEV_CLK_PLL2    */ 0U,
			/* R_DEV_CLK_PLL0PIX */ 1U,
			/* R_DEV_CLK_SDRB    */ 1U,
			/* R_DEV_CLK_ETNBP   */ 1U,
			/* R_DEV_CLK_MLBP    */ 1U,
			/* R_DEV_CLK_RSCANP  */ 1U,
			/* R_DEV_CLK_XCC     */ 1U,
			/* R_DEV_CLK_ETNBXCC */ 1U,
			/* R_DEV_CLK_MLBXCC  */ 1U,
		},
};

static const r_dev_ClkSelConfig_t g_stClkSelectionCfg[] =
	/*   Cks                   SrcId                Div  StpReqMsk      */
	{
		/* {R_DEV_CKS_RSCAN, R_DEV_CKS_SRC_PLLFIX, } */
		{R_DEV_CKS_RSCANXIN, R_DEV_CKS_SRC_MOSC, 1, 0u},
		{R_DEV_CKS_WDT0, R_DEV_CKS_SRC_LRNG, 256, 0u},
		{R_DEV_CKS_RTC, R_DEV_CKS_SRC_MOSC, 2, 0u},
		{R_DEV_CKS_OSTM, R_DEV_CKS_SRC_MOSC, 2, 0u},
		{R_DEV_CKS_CLKJIT, R_DEV_CKS_SRC_DIV, 6, 0u},
		{R_DEV_CKS_PLLFIX, R_DEV_CKS_SRC_PLL1, 1, 0u},
		{R_DEV_CKS_CLKFIX, R_DEV_CKS_SRC_DIV, 6, 0u},
		{R_DEV_CKS_CPU, R_DEV_CKS_SRC_PLL0, 2, 0u},
		{R_DEV_CKS_SFMA, R_DEV_CKS_SRC_PLL0, 3, 0u},
		{R_DEV_CKS_SSIF, R_DEV_CKS_SRC_PLLFIX, 156, 0u},

		/* delimiter - do not remove */
		{R_DEV_CKS_LAST, R_DEV_CKS_SRC_MOSC, 2, 0u},
};

void Clock_Pre_Init(void)
{
	/* use the config, call Clock Gen Init */
	R_DEV_ClkGenInit((r_dev_ClkGenConfig_t *)(&g_stClockGenCfg), g_stClkSelectionCfg);

	/* use the config, store settings (needs to be repeated after low init */
	R_DEV_ClkGenInitStore((r_dev_ClkGenConfig_t *)(&g_stClockGenCfg));
}

void Clock_Init(void)
{
	/* use the config, store settings */
	R_DEV_ClkGenInitStore((r_dev_ClkGenConfig_t *)(&g_stClockGenCfg));
}

/*Clock monitor initialization*/
static void Clock_Monitor_A_Init(void)
{
	/*only open monitor2 ,Monitor main clock*/
	CLMA2CMPH = 652U; /*+-10%*/

	CLMA2CMPL = 435U; /*+-10%*/

	CLOCK_PROTECTED_WRITE(CLMA2PCMD, CLMA2PS, CLMA2CTL0, 0x01U);
}

/*Stop all of the modules before Call the following function,except RTC*/
/*falling edge detection*/
void Clock_Enter_Sleep_Mode(void)
{
	/*Stop  modules*/
	/*port buffer  into hold state*/
	/*Disable  interrupt*/
	/*Clear the interrupt flag*/
	/*config interrupt , mask or unmask*/
	/*Clear  wake-up  flag*/
	/*Config wake-up factors*/
	/*You can choose more than one PIN*/
	/*(Except in D1M1A and D1M1-V2) ,Change CPU clock to EMCLK*/
	CLOCK_PROTECTED_WRITE(SYSPROTCMD1, SYSPROTS1, SYSCKSC_ICPUCLKS_CTL, 0x01U); /*select EMCLK*/

	/*Config clock domains . It's already set up in the initialization function  */
	/*MainOsc continues operation in DEEPSTOP mode*/
	SYSMOSCSTPM = 0x03U;
	/*High Speed IntOsc stops operation in DEEPSTOP mode.*/
	// SYSROSCSTPM = 0x02U;
	R_DEV_SetGenStopMask(R_DEV_HS_RING, 0U);
	/*Clock domain C_AWO_AWOT is stopped in DEEPSTOP mode*/
	SYSCKSC_AAWOTD_STPM = 0x02U;
	/*Clock domain C_AWO_RTCA is not stopped in DEEPSTOP mode*/
	SYSCKSC_ARTCAD_STPM = 0X03U;
	/*Clock domain C_AWO_FOUT is stopped in DEEPSTOP mode*/
	SYSCKSC_AFOUTS_STPM = 0X02U;

	/*Stop all active PLLs*/
	// CLOCK_PROTECTED_WRITE(SYSPROTCMD1, SYSPROTS1, SYSPLL0E, 0x02U); /*Stop the PLL0*/
	// CLOCK_PROTECTED_WRITE(SYSPROTCMD1, SYSPROTS1, SYSPLL1E, 0x02U); /*Stop the PLL1*/
	R_DEV_ClkGenStop(R_DEV_PLL0);
	R_DEV_ClkGenStop(R_DEV_PLL1);
	/*Clear the RESF register*/
	/*start DEEPSTOP mode*/
	/*wait for the transition to the DEEPSTOP mode by the unconditional loop*/
}
#pragma ghs section bss = ".absinitarea"

uint32_t u32ResetFlag;
uint32_t u32ResetSource;
#pragma ghs section bss = default

Clock_Startup_Mode_en_t Clock_Get_Startup_Mode(void)
{
	Clock_Startup_Mode_en_t enClockMode;

	uint32_t u32ResetRESFValue = 0U;
	uint32_t u32ResetRESFRValue = 0U;

	/* Read reset factor */
	u32ResetRESFValue = SYSRESF;
	u32ResetRESFRValue = SYSRESFR;

	u32ResetSource = SYSRESF;

	/* Clear reset factor */
	SYSRESFC = 0xC70FU;
	SYSRESFCR = 0xC70FU;

	if (u32ResetRESFValue & 0x0000C30FU)
	{
		enClockMode = CLOCK_STARTUP_PWR_ON;
	}
	else
	{
		enClockMode = CLOCK_STARTUP_WAKE_UP;
	}

	return enClockMode;
}

void Sys_Enter_Sleep_Mode(void)
{
	WDT_Clear();
	CLOCK_PROTECTED_WRITE(SYSPROTCMD0, SYSPROTS0, SYSCKSC_AWDTA0D_CTL, 0x06U); /*  看门狗时钟2048分频*/

	GPIO_Init(GPIO_SLEEP_MODE);

	__DI();
	SYSWUFC0 = 0x7FFFFU;
	/*---------------------------------------------*/
	GPIO_Wakeup_PIN_Set(GPIO_WAKEUP_PIN_P0_5, GPIO_WAKEUP_FALLING_EDGE);
	GPIO_Wakeup_PIN_Set(GPIO_WAKEUP_PIN_P0_0, GPIO_WAKEUP_RISING_EDGE);
	/*----------------------------------------------*/
	SYSWUFMSK0 &= 0x7FFFEU;

	Clock_Enter_Sleep_Mode();

	SYSRESFC = 0xC70FU;

	CLOCK_PROTECTED_WRITE(SYSPROTCMD0, SYSPROTS0, SYSSTBC0PSC, 0x02U);

	RTC_Backup_Time();
	TestBackupRam = 0xaabbccddu;
	hardware_reset();
}