You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

515 lines
17 KiB

/************************************************************************
 * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
 * @file     rtc.c
 * @author   UartTFT Application Team
 * @version  V1.0.0
 * @date     2023-02-24
 * @brief
 *************************************************************************/
#include "rtc.h"
#include "rtc_drv.h"
#include "cpm_reg.h"
#include "sys.h"
_calendar_obj calendar;		// Clock structure
struct DS1302DATA gRtcTime = {18, 11, 25, 9, 42, 5, 7};
const uint8_t Clock_Time[7] = {19, 8, 8, 2, 5, 50, 4};
uint8_t RTC_One_Sec_Update = 0;
static uint8_t LT_AsciiToBcd(uint8_t asciiData)
{
	uint8_t bcdData = 0;
	bcdData = (((asciiData / 10) << 4) | ((asciiData % 10)));
	return bcdData;
}
uint8_t LT_BcdToAscii(uint8_t bcdData)
{
	uint8_t asciiData = 0;
	asciiData = (((bcdData & 0xf0) >> 4) * 10 + (bcdData & 0x0f));
	return asciiData;
}
uint8_t LT_RtcInit(void)
{
	UINT32 rtc_wclk_div = 0;
	rtc_wclk_div = g_sys_clk / 10000000;
	if (rtc_wclk_div >= 1)
		rtc_wclk_div--;
	/*For debug
	 Update RTC Counter(function case Dir=0)
	 NVIC_Init(2, 1, PMU_RTC_IRQn, 2);
	*/
	RTC->RTC_PRKEYR = 0x5aa55aa5;			// input key
	RTC->RTC_PRC1R &= (~WCLK_DIV_MASK);
	RTC->RTC_PRC1R |= (rtc_wclk_div << 3);	// 8 frequency division
	RTC->RTC_PRC1R &= ~Dir; 				// set dir = 0;
	RTC->RTC_PRC1R |= Sec_IEN;
	RTC_Get();
	if (calendar.w_year == 0 && calendar.w_month == 0 && calendar.w_date == 0)
	{
		RTC_Set(2023, 4, 7, 17, 3, 0);
	}
	else
	{
		RTC_Set(calendar.w_year, calendar.w_month, calendar.w_date, calendar.hour, calendar.min, calendar.sec);
	}
	DelayMS(50);
	NVIC_Init(2, 1, PMU_RTC_IRQn, 2); 		// Open RTC interrupt
	RTC_Get();
}
// RTC clock interrupt
void PMU_RTC_IRQHandler(void)
{
	UINT32 prc1r;
	uint8_t i = 0, j = 0;
	uint8_t rebuf[40];
	prc1r = RTC->RTC_PRC1R;
	if (((prc1r & Sec_intf) == Sec_intf) && ((prc1r & Sec_IEN) == Sec_IEN)) // second interrupt
	{
		RTC->RTC_PRC1R |= Sec_intf;
		RTC_Get();
		RTC_flag = 1;
		Clock_flag = 1;
		Count_flag = 1;
		for (i = 0; i < Count_sum; i++)
		{
			if (((var[gCount_Info[i].c_add * 2] << 8) + var[gCount_Info[i].c_add * 2 + 1]) == 1)
			{
				if (gCount_Info[i].dir == 0) // Count backwards
				{
					if (var[gCount_Info[i].t_add * 2 + 1] > 0)
							var[gCount_Info[i].t_add * 2 + 1] = var[gCount_Info[i].t_add * 2 + 1] - 1;
						
					else if (var[gCount_Info[i].t_add * 2 + 1] == 0 && var[gCount_Info[i].t_add * 2] > 0)
					{
						var[gCount_Info[i].t_add * 2] = var[gCount_Info[i].t_add * 2] - 1;
						var[gCount_Info[i].t_add * 2 + 1] = 0xFF;
					}
					else if (((var[gCount_Info[i].t_add * 2] << 8) + var[gCount_Info[i].t_add * 2 + 1]) == 0)
					{
						var[gCount_Info[i].c_add * 2] = 0;
						var[gCount_Info[i].c_add * 2 + 1] = 0;
						
						for (j = 0; j < 8; j++)
						{
							if (gCount_Info[i].var_addr[j] != 0xFFFF && gCount_Info[i].var_addr[j] < 0x7200)
							{
								var[gCount_Info[i].var_addr[j] * 2] = (gCount_Info[i].var[j] >> 8) & 0xFF;
								var[gCount_Info[i].var_addr[j] * 2 + 1] = gCount_Info[i].var[j] & 0xFF;
								if (gCount_Info[i].var_addr[j] >= 0x7000)
								{
									//reg_operation(gCount_Info[i].var_addr[j]);
									Count_reg[Count_reg_num] = gCount_Info[i].var_addr[j];
									Count_reg_num++;
								}
							}
						}
						if (gCount_Info[i].end_feedback == 1) // Feedback
						{
							rebuf[3] = 0x41;
							for (j = 0; j < 8; j++)
							{
								rebuf[4 * j + 4] = gCount_Info[i].var_addr[j] >> 8;
								rebuf[4 * j + 5] = gCount_Info[i].var_addr[j] & 0xFF;
								rebuf[4 * j + 6] = gCount_Info[i].var[j] >> 8;
								rebuf[4 * j + 7] = gCount_Info[i].var[j] & 0xFF;
							}
							LT_SendData_CRC_Frame(rebuf, 33);
						}
					}
				}
				else if (gCount_Info[i].dir == 1) // Positive number
				{
					if (((var[gCount_Info[i].t_add * 2] << 8) + var[gCount_Info[i].t_add * 2 + 1]) >=
						((var[gCount_Info[i].v_add * 2] << 8) + var[gCount_Info[i].v_add * 2 + 1]))
					{
						var[gCount_Info[i].c_add * 2] = 0;
						var[gCount_Info[i].c_add * 2 + 1] = 0;
						for (j = 0; j < 8; j++)
						{
							if (gCount_Info[i].var_addr[j] != 0xFFFF && gCount_Info[i].var_addr[j] < 0x7200)
							{
								var[gCount_Info[i].var_addr[j] * 2] = (gCount_Info[i].var[j] >> 8) & 0xFF;
								var[gCount_Info[i].var_addr[j] * 2 + 1] = gCount_Info[i].var[j] & 0xFF;
								if (gCount_Info[i].var_addr[j] >= 0x7000)
								{
									//reg_operation(gCount_Info[i].var_addr[j]);
									Count_reg[Count_reg_num] = gCount_Info[i].var_addr[j];
									Count_reg_num++;
									
								}
							}
						}
	
						if (gCount_Info[i].end_feedback == 1) // Feedback
						{
							rebuf[3] = 0x41;
							for (j = 0; j < 8; j++)
							{  
								rebuf[4 * j + 4] = gCount_Info[i].var_addr[j] >> 8;
								rebuf[4 * j + 5] = gCount_Info[i].var_addr[j] & 0xFF;
								rebuf[4 * j + 6] = gCount_Info[i].var[j] >> 8;
								rebuf[4 * j + 7] = gCount_Info[i].var[j] & 0xFF;
							}
							LT_SendData_CRC_Frame(rebuf, 33);
						}
					}
					if (((var[gCount_Info[i].c_add * 2] << 8) + var[gCount_Info[i].c_add * 2 + 1]) != 0x00)
					{
						if (var[gCount_Info[i].t_add * 2 + 1] < 0xFF)
							var[gCount_Info[i].t_add * 2 + 1] = var[gCount_Info[i].t_add * 2 + 1] + 1;
						else if (var[gCount_Info[i].t_add * 2 + 1] == 0xFF)
						{
							var[gCount_Info[i].t_add * 2] = var[gCount_Info[i].t_add * 2] + 1;
							var[gCount_Info[i].t_add * 2 + 1] = 0;
						}
					}
				}
			}
		}
		for (i = 0; i < Record_count; i++)
		{
			if (((var[gRecord_count_Info[i].c_add * 2] << 8) + var[gRecord_count_Info[i].c_add * 2 + 1]) == 1)
			{
				if (gRecord_count_Info[i].dir == 0) // Count backwards
				{
					if (var[gRecord_count_Info[i].t_add * 2 + 1] > 0)
						var[gRecord_count_Info[i].t_add * 2 + 1] = var[gRecord_count_Info[i].t_add * 2 + 1] - 1;
					else if (var[gRecord_count_Info[i].t_add * 2 + 1] == 0 && var[gRecord_count_Info[i].t_add * 2] > 0)
					{
						var[gRecord_count_Info[i].t_add * 2] = var[gRecord_count_Info[i].t_add * 2] - 1;
						var[gRecord_count_Info[i].t_add * 2 + 1] = 0xFF;
					}
					if (((var[gRecord_count_Info[i].t_add * 2] << 8) + var[gRecord_count_Info[i].t_add * 2 + 1]) == 0)
					{
						for (j = 0; j < 8; j++)
						{
							if (gRecord_count_Info[i].var_addr[j] != 0xfFFF && gRecord_count_Info[i].var_addr[j] < 0x7200)
							{
								var[gRecord_count_Info[i].var_addr[j] * 2] = (gRecord_count_Info[i].var[j] >> 8) & 0xFF;
								var[gRecord_count_Info[i].var_addr[j] * 2 + 1] = gRecord_count_Info[i].var[j] & 0xFF;
								if (gRecord_count_Info[i].var_addr[j] >= 0x7000)
								{
									//reg_operation(gRecord_count_Info[i].var_addr[j]);
									Count_reg[Count_reg_num] = gCount_Info[i].var_addr[j];
									Count_reg_num++;
								}
							}
						}
						if (gRecord_count_Info[i].end_feedback == 1) // Feedback
						{
							rebuf[3] = 0x41;
							for (j = 0; j < 8; j++)
							{
								rebuf[4 * j + 4] = gRecord_count_Info[i].var_addr[j] >> 8;
								rebuf[4 * j + 5] = gRecord_count_Info[i].var_addr[j] & 0xFF;
								rebuf[4 * j + 6] = gRecord_count_Info[i].var[j] >> 8;
								rebuf[4 * j + 7] = gRecord_count_Info[i].var[j] & 0xFF;
							}
							LT_SendData_CRC_Frame(rebuf, 33);
						}
						gRecord_count_Info[i].v_add = gRecord_count_Info[Record_count - 1].v_add;
						gRecord_count_Info[i].t_add = gRecord_count_Info[Record_count - 1].t_add;
						gRecord_count_Info[i].c_add = gRecord_count_Info[Record_count - 1].c_add;
						gRecord_count_Info[i].dir = gRecord_count_Info[Record_count - 1].dir;
						gRecord_count_Info[i].end_feedback = gRecord_count_Info[Record_count - 1].end_feedback;
						gRecord_count_Info[i].var[0] = gRecord_count_Info[Record_count - 1].var[0];
						gRecord_count_Info[i].var_addr[0] = gRecord_count_Info[Record_count - 1].var_addr[0];
						gRecord_count_Info[i].var[1] = gRecord_count_Info[Record_count - 1].var[1];
						gRecord_count_Info[i].var_addr[1] = gRecord_count_Info[Record_count - 1].var_addr[1];
						gRecord_count_Info[i].var[2] = gRecord_count_Info[Record_count - 1].var[2];
						gRecord_count_Info[i].var_addr[2] = gRecord_count_Info[Record_count - 1].var_addr[2];
						gRecord_count_Info[i].var[3] = gRecord_count_Info[Record_count - 1].var[3];
						gRecord_count_Info[i].var_addr[3] = gRecord_count_Info[Record_count - 1].var_addr[3];
						gRecord_count_Info[i].var[4] = gRecord_count_Info[Record_count - 1].var[4];
						gRecord_count_Info[i].var_addr[4] = gRecord_count_Info[Record_count - 1].var_addr[4];
						gRecord_count_Info[i].var[5] = gRecord_count_Info[Record_count - 1].var[5];
						gRecord_count_Info[i].var_addr[5] = gRecord_count_Info[Record_count - 1].var_addr[5];
						gRecord_count_Info[i].var[6] = gRecord_count_Info[Record_count - 1].var[6];
						gRecord_count_Info[i].var_addr[6] = gRecord_count_Info[Record_count - 1].var_addr[6];
						gRecord_count_Info[i].var[7] = gRecord_count_Info[Record_count - 1].var[7];
						gRecord_count_Info[i].var_addr[7] = gRecord_count_Info[Record_count - 1].var_addr[7];
						i--;
						Record_count--;
					}
				}
				else if (gRecord_count_Info[i].dir == 1) // Positive number
				{
					if (var[gRecord_count_Info[i].t_add * 2 + 1] < 0xFF)
						var[gRecord_count_Info[i].t_add * 2 + 1] = var[gRecord_count_Info[i].t_add * 2 + 1] + 1;
					else if (var[gRecord_count_Info[i].t_add * 2 + 1] == 0xFF)
					{
						var[gRecord_count_Info[i].t_add * 2] = var[gRecord_count_Info[i].t_add * 2] + 1;
						var[gRecord_count_Info[i].t_add * 2 + 1] = 0;
					}
					if (((var[gRecord_count_Info[i].t_add * 2] << 8) + var[gRecord_count_Info[i].t_add * 2 + 1]) >=
						((var[gRecord_count_Info[i].v_add * 2] << 8) + var[gRecord_count_Info[i].v_add * 2 + 1]))
					{
						for (j = 0; j < 8; j++)
						{
							if (gRecord_count_Info[i].var_addr[j] != 0xFFFF && gRecord_count_Info[i].var_addr[j] < 0x7200)
							{
								var[gRecord_count_Info[i].var_addr[j] * 2] = (gRecord_count_Info[i].var[j] >> 8) & 0xFF;
								var[gRecord_count_Info[i].var_addr[j] * 2 + 1] = gRecord_count_Info[i].var[j] & 0xFF;
								if (gRecord_count_Info[i].var_addr[j] >= 0x7000)
								{
									//reg_operation(gRecord_count_Info[i].var_addr[j]);
									Count_reg[Count_reg_num] = gCount_Info[i].var_addr[j];
									Count_reg_num++;
								}
							}
						}
						if (gRecord_count_Info[i].end_feedback == 1) // Feedback
						{
							rebuf[3] = 0x41;
							for (j = 0; j < 8; j++)
							{
								rebuf[4 * j + 4] = gRecord_count_Info[i].var_addr[j] >> 8;
								rebuf[4 * j + 5] = gRecord_count_Info[i].var_addr[j] & 0xFF;
								rebuf[4 * j + 6] = gRecord_count_Info[i].var[j] >> 8;
								rebuf[4 * j + 7] = gRecord_count_Info[i].var[j] & 0xFF;
							}
							LT_SendData_CRC_Frame(rebuf, 33);
						}
						gRecord_count_Info[i].v_add = gRecord_count_Info[Record_count - 1].v_add;
						gRecord_count_Info[i].t_add = gRecord_count_Info[Record_count - 1].t_add;
						gRecord_count_Info[i].c_add = gRecord_count_Info[Record_count - 1].c_add;
						gRecord_count_Info[i].dir = gRecord_count_Info[Record_count - 1].dir;
						gRecord_count_Info[i].end_feedback = gRecord_count_Info[Record_count - 1].end_feedback;
						gRecord_count_Info[i].var[0] = gRecord_count_Info[Record_count - 1].var[0];
						gRecord_count_Info[i].var_addr[0] = gRecord_count_Info[Record_count - 1].var_addr[0];
						gRecord_count_Info[i].var[1] = gRecord_count_Info[Record_count - 1].var[1];
						gRecord_count_Info[i].var_addr[1] = gRecord_count_Info[Record_count - 1].var_addr[1];
						gRecord_count_Info[i].var[2] = gRecord_count_Info[Record_count - 1].var[2];
						gRecord_count_Info[i].var_addr[2] = gRecord_count_Info[Record_count - 1].var_addr[2];
						gRecord_count_Info[i].var[3] = gRecord_count_Info[Record_count - 1].var[3];
						gRecord_count_Info[i].var_addr[3] = gRecord_count_Info[Record_count - 1].var_addr[3];
						gRecord_count_Info[i].var[4] = gRecord_count_Info[Record_count - 1].var[4];
						gRecord_count_Info[i].var_addr[4] = gRecord_count_Info[Record_count - 1].var_addr[4];
						gRecord_count_Info[i].var[5] = gRecord_count_Info[Record_count - 1].var[5];
						gRecord_count_Info[i].var_addr[5] = gRecord_count_Info[Record_count - 1].var_addr[5];
						gRecord_count_Info[i].var[6] = gRecord_count_Info[Record_count - 1].var[6];
						gRecord_count_Info[i].var_addr[6] = gRecord_count_Info[Record_count - 1].var_addr[6];
						gRecord_count_Info[i].var[7] = gRecord_count_Info[Record_count - 1].var[7];
						gRecord_count_Info[i].var_addr[7] = gRecord_count_Info[Record_count - 1].var_addr[7];
						i--;
						Record_count--;
					}
				}
			}
		}
	}
}
// month           1  2  3  4  5  6  7  8  9  10 11 12
// leap year       31 29 31 30 31 30 31 31 30 31 30 31
// non-leap years  31 28 31 30 31 30 31 31 30 31 30 31
/********************************************************************************
 * Function Name	: Is_Leap_Year
 * Description  	: Judge whether it is a leap year.
 * Input        	: - year:
 * Output       	: None
 * Return       	: Is this year a leap year. 1:yes, 0:no
 *********************************************************************************/
uint8_t Is_Leap_Year(uint16_t year)
{
	if (year % 4 == 0) // Must be divisible by 4
	{
		if (year % 100 == 0)
		{
			if (year % 400 == 0)
				return 1; // If it ends with 00, it should be divisible by 400
			else
				return 0;
		}
		else
			return 1;
	}
	else
		return 0;
}
// Monthly data table
uint8_t const table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; // Monthly correction data sheet
// Date table of the month in the ordinary year
const uint8_t mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/********************************************************************************
* Function Name	: RTC_Set
* Description  	: set clock.
* Input        	: - syear: Only gregorian 1970-2099 allowed
				  - smon:
				  - sday:
				  - hour:
				  - min:
				  - sec:
* Output       	: None
* Return       	: week
*********************************************************************************/
uint8_t RTC_Set(uint16_t syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec)
{
	uint16_t t;
	tm timer;
	UINT16 days = 0;
	if (syear < 2010 || syear > 2099)
		return 1;
	for (t = 2010; t < syear; t++)	// Add the seconds of all years
	{
		if (Is_Leap_Year(t))
			days += 366;			// Days in leap year
		else
			days += 365;			// Days in non-leap years
	}
	smon -= 1;
	for (t = 0; t < smon; t++)		// Add the number of seconds in the previous month
	{
		days += (uint32_t)mon_table[t]; // Add months and seconds
		if (Is_Leap_Year(syear) && t == 1)
			days++; 				// Increase the number of seconds of one day in February of leap year
	}
	days += (sday - 1);				// Add the seconds of the previous date
	timer.day = days;
	if (hour >= 24)
		hour = 23;
	timer.hour = hour;
	if (min >= 60)
		min = 59;
	timer.minute = min;
	if (sec >= 60)
		sec = 59;
	timer.second = sec;
	RTC_SetTime(timer);
	return 0;
}
/********************************************************************************
* Function Name	: RTC_Get
* Description  	: Get calendar date and time.
* Input        	: - year: Only gregorian 1901-2099 allowed
				  - month: Gregorian month
				  - day: Gregorian day
* Output       	: None
* Return       	: week
*********************************************************************************/
uint8_t RTC_Get(void)
{
	static uint16_t daycnt = 0;
	uint32_t temp = 0;
	uint16_t temp1 = 0;
	UINT16 days = 0;
	tm timer;
	RTC_GetTime(&timer);
	days = timer.day;
	temp = days;					// Get Days
	if (daycnt != temp)				// More than a day
	{
		daycnt = temp;
		temp1 = 2010; 				// From 2010
		while (temp >= 365)
		{
			if (Is_Leap_Year(temp1))// leap year
			{
				if (temp >= 366)
					temp -= 366;	// leap year seconds
				else
				{
					temp1++;
					break;
				}
			}
			else
				temp -= 365;		// non-leap year
			temp1++;
		}
		calendar.w_year = temp1;	// Get year
		temp1 = 0;
		while (temp >= 28)			// More than a month
		{
			if (Is_Leap_Year(calendar.w_year) && temp1 == 1)	// Is that leap year in February
			{
				if (temp >= 29)
					temp -= 29;		// leap year seconds
				else
					break;
			}
			else
			{
				if (temp >= mon_table[temp1])
					temp -= mon_table[temp1];	// non-leap year
				else
					break;
			}
			temp1++;
		}
		calendar.w_month = temp1 + 1;			// Get month
		calendar.w_date = temp + 1;				// Get date
	}
	calendar.hour = timer.hour;
	calendar.min = timer.minute;
	calendar.sec = timer.second;
	calendar.week = RTC_Get_Week(calendar.w_year, calendar.w_month, calendar.w_date);	// Get week
	return 0;
}
/********************************************************************************
* Function Name	: RTC_Get_Week
* Description  	: Get the week according to the gregorian calendar date.
* Input        	: - year: Only gregorian 1901-2099 allowed
				  - month: Gregorian month
				  - day: Gregorian day
* Output       	: None
* Return       	: week
*********************************************************************************/
uint8_t RTC_Get_Week(uint16_t year, uint8_t month, uint8_t day)
{
	uint16_t temp2;
	uint8_t yearH, yearL;
	yearH = year / 100;
	yearL = year % 100;
	// If it is the 21st century, add 100 years
	if (yearH > 19)
		yearL += 100;
	// The number of leap years passed is only counted after 1900
	temp2 = yearL + yearL / 4;
	temp2 = temp2 % 7;
	temp2 = temp2 + day + table_week[month - 1];
	if (yearL % 4 == 0 && month < 3)
		temp2--;
	return (temp2 % 7);
}