/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: 	Sino
Version: 	V0.0
Date: 		2020/04/26
History:
	V2.0	2020/04/26		 Preliminary
********************************************************************************/
#include "Main.h"


BOOL bRTCErr;
BOOL bRTCTwiRWErr;
U8  xdata ucRTCTwiRWErrDelayCnt;
RTC_VAR xdata RTC;						//For External RTC

/*************************************************************************************************
* 函数名: RTCTwiCheck
* 参  数: 无
* 返回值: 无
* 描  述: 连续5S检测到RTC的I2C通讯错误，则置位bRTCErr=1
*************************************************************************************************/
void RTCTwiCheck(void)
{
	if(bEnEEPRomBK)
	{
		if(bRTCTwiRWErr)
		{
			if(++ucRTCTwiRWErrDelayCnt >= TIME_1S_5S)
			{
				bRTCErr = 1;
				ucRTCTwiRWErrDelayCnt = TIME_1S_5S;
			}
		}
		else
		{
			ucRTCTwiRWErrDelayCnt = 0;
		}
	}
}


/*************************************************************************************************
* 函数名: RTCWrite
* 参  数: WrAddr: 寄存器地址；Length：数据长度；WrBuf：数据缓存Buf
* 返回值: 无
* 描  述: RTC写寄存器操作，如果出错连续写两次
*************************************************************************************************/
BOOL RTCWrite(U8 WrAddr, U8 Length, U8 xdata *WrBuf)
{
	BOOL Result = 0;
	U8 i;
	
	if(!bRTCErr)
	{
		for(i=0; i<5; i++)
		{
			#ifdef TWI_Hardware_Module
			if(TwiWrite(RTC_ID, WrAddr, TWI_ADDR_1B, Length, TWI_CRC_NO, WrBuf))
			{
				Result = 1;
				break;
			}                
			#else 
			if(Result = TwiWrite(RTC_ID, WrAddr, Length, WrBuf))
			{
				Result = 1;
				break;
			}	
			#endif
			Delay1ms(1);
		}
	}
	bRTCTwiRWErr = !Result;
	
	return Result;
}


/*************************************************************************************************
* 函数名: RTCRead
* 参  数: RdAddr: 寄存器地址；Length：数据长度；WrBuf：数据缓存Buf
* 返回值: 无
* 描  述: RTC读寄存器操作，如果出错连续读两次
*************************************************************************************************/
BOOL RTCRead(U8 RdAddr, U8 Length, U8 xdata *RdBuf)
{
	BOOL Result = 0;
	U8 i;
	
	if(!bRTCErr)
	{
		for(i=0; i<5; i++)
		{
			#ifdef TWI_Hardware_Module
			if(TwiRead(RTC_ID, RdAddr, TWI_ADDR_1B, Length, TWI_CRC_NO, RdBuf))
			{
				Result = 1;
				break;
			}                
			#else
			if(TwiRead(RTC_ID, RdAddr, Length, RdBuf))
			{
				Result = 1;
				break;
			}	
			#endif
			Delay1ms(1);
		}
	}
	bRTCTwiRWErr = !Result;
	
	return Result;
}

/*************************************************************************************************
* 函数名: RTCReadTime
* 参  数: RdAddr: 寄存器地址；Length：数据长度；WrBuf：数据缓存Buf
* 返回值: 无
* 描  述: RTC读寄存器操作，如果出错连续读两次
*************************************************************************************************/
BOOL RTCReadTime(RTC_VAR xdata *RtcRdVal)
{
	U8 xdata rtcbuf[9];
	BOOL Result = 0;
	
	if(RTCRead(0x00, 9, &rtcbuf))                               //从RTC读取时间
	{
		if((rtcbuf[7]&0x01) == 0x00)                            //judge RTCF bit，看是否曾经掉过电
		{
            if( ((rtcbuf[2]&0x80) == 0)                         //不是24小时制
            || ((rtcbuf[0]&0x70) > 0x50) || ((rtcbuf[0]&0x0F) > 0x09) || ((rtcbuf[0]&0x7F) > 0x59)
            || ((rtcbuf[1]&0x70) > 0x50) || ((rtcbuf[1]&0x0F) > 0x09) || ((rtcbuf[1]&0x7F) > 0x59)
            || ((rtcbuf[2]&0x30) > 0x20) || ((rtcbuf[2]&0x0F) > 0x09) || ((rtcbuf[2]&0x2F) > 0x24)
            || ((rtcbuf[3]&0x30) > 0x30) || ((rtcbuf[3]&0x0F) > 0x09) || ((rtcbuf[3]&0x3F) > 0x31) || (!(rtcbuf[3]&0x3F))
            || ((rtcbuf[4]&0x10) > 0x10) || ((rtcbuf[4]&0x0F) > 0x09) || ((rtcbuf[4]&0x1F) > 0x12) || (!(rtcbuf[4]&0x1F))
            || ((rtcbuf[5]&0xF0) > 0x90) || ((rtcbuf[5]&0x0F) > 0x09) || ((rtcbuf[5]&0xFF) > 0x99)
            || ((rtcbuf[6]&0x07) > 0x06) )                      //对小时制及数据合法性进行检查
            {
                rtcbuf[0] = RtcRdVal->Second;                   //数据不合法，可能是因为RTC未初始化导致
                rtcbuf[1] = RtcRdVal->Minute;
                rtcbuf[2] = RtcRdVal->Hour;
                rtcbuf[3] = RtcRdVal->Date;
                rtcbuf[4] = RtcRdVal->Month;
                rtcbuf[5] = RtcRdVal->Year;
                rtcbuf[6] = RtcRdVal->Week;
                
                Result = RTCModifyTime((RTC_VAR xdata *)(&rtcbuf));
            }
            else
            {
                RtcRdVal->Second = rtcbuf[0];                   //数据合法，则保存从RTC读回的时间
                RtcRdVal->Minute = rtcbuf[1];
                RtcRdVal->Hour = rtcbuf[2]&0x1F;
                RtcRdVal->Date = rtcbuf[3];
                RtcRdVal->Month = rtcbuf[4];
                RtcRdVal->Year = rtcbuf[5];
                RtcRdVal->Week = rtcbuf[6];
                
                Result = 1;
            }
		}
		else                                                    //曾经掉电过，认为RTC不准。
		{
            Result = RTCModifyTime((RTC_VAR xdata *)RtcRdVal);  //将当前的时间，或从E2中读取的时间，或固定时间重新写入RTC
		}
	}

	return Result;
}


/*************************************************************************************************
* 函数名: RTCModifyTime
* 参  数: RTC：将RTC参数传递进来，进行RTC更新
* 返回值: 无
* 描  述: RTC读寄存器操作，如果出错连续读两次
*************************************************************************************************/
BOOL RTCModifyTime(RTC_VAR xdata *RtcMdyVal)
{
	BOOL Result = 0;
	U8 xdata rtcdata;
	U8 xdata rtctemp[7];
	
	rtcdata = 0x90;
	Result = RTCWrite(RTC_REG_STATUS, 1, &rtcdata);
	
	rtctemp[0] = RtcMdyVal->Second;
	rtctemp[1] = RtcMdyVal->Minute;
	rtctemp[2] = RtcMdyVal->Hour|0x80;                          //设置为24小时制
	rtctemp[3] = RtcMdyVal->Date;
	rtctemp[4] = RtcMdyVal->Month;
	rtctemp[5] = RtcMdyVal->Year;
	rtctemp[6] = RtcMdyVal->Week;

	Result = RTCWrite(RTC_REG_SECOND, 7, (U8 xdata *)&rtctemp);

	return  Result;
}


/*************************************************************************************************
* 函数名: RTCInitTime
* 参  数: RTC：将RTC参数传递进来，进行RTC初始化
* 返回值: 无
* 描  述: 初始化，从EEP读取保存的RTC时间参数进行第一次初始化，如果EEP没有保存，则默认初始化时间：20年5月1日12点
*************************************************************************************************/
BOOL RTCInitTime(RTC_VAR xdata *RtcInitVal)
{
	BOOL Result = 0;
	U8 xdata rtcbuf[9];
	U8 xdata i;
	U8 xdata checksum = 0;
    
	MemorySet(rtcbuf, 0, sizeof(rtcbuf));
	
	E2PRomRead(E2PROM_RTC_ADDR, 9, rtcbuf);                     //从E2备份区读出RTC数据
	for(i=0; i<7; i++)
	{
		checksum += rtcbuf[i];
	}
	
	if((rtcbuf[7]!=checksum) || (rtcbuf[8]!=0x5a))              //若校验失败，说明E2读出的时间不可靠，直接把出厂时间拿来用
	{
		rtcbuf[0] = 0x00;                                       //second
		rtcbuf[1] = 0x00;                                       //minute
		rtcbuf[2] = 0x12;                                       //hour
		rtcbuf[3] = 0x01;                                       //date
		rtcbuf[4] = 0x05;                                       //month
		rtcbuf[5] = 0x20;                                       //year
		rtcbuf[6] = 0x05;                                       //week
	}

	MemoryCopy(rtcbuf, (U8 xdata *)RtcInitVal, 7);              //从E2读出的时间或出厂时间先放到RTC时间寄存器中存起来
    Result = RTCReadTime((RTC_VAR xdata *)RtcInitVal);
            
	return Result;
}






