/***********************************************************************
 * Copyright (c)  2017 - 2022, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : rtc.c
 * Description : rtc driver source file
 * Author(s)   : Mason
 * version     : V1.0
 * Modify date : 2022-08-04
 ***********************************************************************/
#include "rtc.h"

void (*rtc_callback)(void) = NULL;

/************************************************************************
 * Function     : RTC_IRQHandler
 * Description  : RTC IRQ Handler
 * Input        : none
 * Output		: none
 * Return       : none
 ************************************************************************/
void RTC_IRQHandler(void)
{
	uint32_t temp;
	temp = REG_RTC_RTCIF;
	
	if(temp & RTC_RTCIF_SEC_IF)				//秒中断
	{
		if(rtc_callback != NULL)
		{
			((void(*)())(rtc_callback))();
		}
		REG_RTC_RTCIF = RTC_RTCIF_SEC_IF;	//清标志
	}
	else
	{
		REG_RTC_RTCIF = 0x1FF;				//清除其他中断
	}

}

/************************************************************************
 * Function     : rtc_irq_init
 * Description  : rtc irq init
 * Input        : uint8_t irq_enable：interrupt enable/disable
 *                void (*rtc_int)(): interrupt callback function 
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_irq_init(uint8_t irq_enable, void (*rtc_int)())
{
	if(irq_enable == RTC_IRQ_ENABLE)
	{
		NVIC_ClearPendingIRQ(RTC_IRQn);
		NVIC_EnableIRQ(RTC_IRQn);
		
		REG_RTC_RTCIE = 0;						//清零中断使能
		REG_RTC_RTCIE |= RTC_RTCIE_SEC_IE;		//使能秒中断
		
		rtc_callback = rtc_int;
	}
	else
	{
		REG_RTC_RTCIE &= ~RTC_RTCIE_SEC_IE;		//关闭秒中断
		rtc_callback = NULL;
	}
	
}

/************************************************************************
 * Function     : rtc_enable
 * Description  : rtc clock enable
 * Input        : none
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_enable(void)
{
	REG_SCU_PERIRESET  |= ((uint32_t)0x01<<13);      //释放rtc复位 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<13);       // 使能rtc时钟 
}

/************************************************************************
 * Function     : rtc_disable
 * Description  : rtc disable
 * Input        : none
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_disable(void)
{
	REG_SCU_PERIRESET  &= ~((uint32_t)0x01<<13);      //rtc复位 
	REG_SCU_PERICLKEN &= ~((uint32_t)0x01<<13);       //关闭rtc时钟 
}

/************************************************************************
 * Function     : rtc_calendar_set
 * Description  : rtc calendar set
 * Input        : uint8_t year, uint8_t month, uint8_t day,uint8_t week, uint8_t hour, uint8_t min, uint8_t sec
 *                请写入十六进制的BCD码，如2019年11月18日星期三15时52分30秒：（0x19,0x11,0x18,0x3,0x52,0x30）
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_calendar_set(uint8_t year, uint8_t month, uint8_t day,uint8_t week, uint8_t hour, uint8_t min, uint8_t sec)   
{
	REG_RTC_RTCWE = 0xACACACAC;  
	REG_RTC_BCDYEAR = year;
	REG_RTC_BCDMONTH = month;
	REG_RTC_BCDDATE = day;
	REG_RTC_BCDWEEK = week;
	REG_RTC_BCDHOUR = hour;
	REG_RTC_BCDMIN = min;
	REG_RTC_BCDSEC = sec;
	REG_RTC_RTCWE = 0xFFFFFFFF;
}

/************************************************************************
 * Function     : rtc_calendar_get
 * Description  : rtc calendar get
 * Input        : *year, *month, *day, *week, *hour, *min, *sec
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_calendar_get(uint8_t *year, uint8_t *month, uint8_t *day,uint8_t *week, uint8_t *hour, uint8_t *min, uint8_t *sec)   
{
	*year = REG_RTC_BCDYEAR;
	*month = REG_RTC_BCDMONTH;
	*day = REG_RTC_BCDDATE;
	*week = REG_RTC_BCDWEEK;
	*hour = REG_RTC_BCDHOUR;
	*min = REG_RTC_BCDMIN;
	*sec = REG_RTC_BCDSEC;
}

/************************************************************************
 * Function     : rtc_alarm_set
 * Description  : rtc alarm set
 * Input        : uint8_t hour, uint8_t min, uint8_t sec
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_alarm_set(uint8_t hour, uint8_t min, uint8_t sec)
{
	REG_RTC_ALARM = 0x00000000;
	REG_RTC_ALARM |= ((uint32_t)hour<<16);
	REG_RTC_ALARM |= ((uint32_t)min<<8);
	REG_RTC_ALARM |= ((uint32_t)sec<<0);
	
}

/************************************************************************
 * Function     : rtc_fout_init
 * Description  : rtc fout init
 * Input        : none
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_fout_init(void)  //RTC FOUT输出功能
{
	REG_SCU_PERIRESET |= ((uint32_t)0x01<<13);              //释放rtc复位 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<13);              //使能rtc时钟 
	
	REG_SCU_CTRLPROTECT = 0xa5a55a5a;
	REG_SCU_CTRL0 &= ~(7<<24);   		                    //CLK16M_DIV
	REG_SCU_CTRLPROTECT = 0xa5a55a5a;
	REG_SCU_CTRL0 |= (1<<24);    		                    //RTC 16.384M时钟分频；
	REG_SCU_CTRLPROTECT = 0xffffffff;

	REG_SCU_IOCTRLPROTECT = 0xa5a55a5a;
	REG_SCU_PGSEL |= (REG_SCU_PGSEL&(~(0xF<<4)))|(0xF<<4);  //端口PG1功能选择RTC_FOUT
	REG_SCU_IOCTRLPROTECT = 0xffffffff;
	
	REG_RTC_FSEL = 0xF;  		 				            //频率输出选择信号
}

/************************************************************************
 * Function     : rtc_ltbc_init
 * Description  : rtc ltbc init
 * Input        : none
 * Output		: none
 * Return       : none
 ************************************************************************/
void rtc_ltbc_init(void)  //RTC_LTBC数字校准
{
	REG_RTC_ADJUST = 0x08D;		                    //最大值0x7ff              				
	REG_RTC_ADSIGN = 0x00;		                    //正向调整              					
	REG_RTC_PRISEN = 0x00;		                    //虚拟调校
}


/************************************************************************
 * Function     : rtc_stamp_init
 * Description  : rtc stamp init
 * Input        : none
 * Output		: none
 * Return       : none
 * 	PA4,PB7,PD0-STAMP0
 *	PB3,PB6,PD3-STAMP1
 * 下面的代码示例：使用PD0,PD3管脚作为触发源
 ************************************************************************/
void rtc_stamp_init(void)  //RTC时间戳
{
	REG_SCU_PERIRESET  |= ((uint32_t)0x01<<19);     // 释放GPIOD复位 
	REG_SCU_PERICLKEN |= ((uint32_t)0x01<<19);      // 使能GPIOD时钟 

	REG_SCU_IOCTRLPROTECT = 0xa5a55a5a;

	REG_SCU_PDSEL |= (5<<12);                       //PD3选择RTC_STAMP1
	REG_SCU_PDSEL |= (5<<0);                        //PD0选择RTC_STAMP0

	REG_SCU_PADIE0 |= (1<<27);                      //PD3输入使能
	REG_SCU_PADIE0 |= (1<<24);                      //PD0输入使能

	REG_GPIO_DIR(GPIOD)	&= ~(1<<3);                 //PD3设为输入
	REG_GPIO_DIR(GPIOD)	&= ~(1<<0);                 //PD0设为输入
	REG_SCU_IOCTRLPROTECT = 0xffffffff;


	REG_RTC_STAMPEN |= (1<<0);                      //STAMP0触发的时间戳功能使能位
	REG_RTC_STAMPEN |= (1<<1);                      //STAMP1触发的时间戳功能使能位
}

/******************************file end ********************************/
