
#include "r_typedefs.h"
#include "dr7f701441.dvf.h"
#include "RTC.h"
#include <string.h>

RTC_Information_st_t g_stRTCInformation;
#define RTC_TIME_OUT_COUNT 500U

static uint8_t Cal_RTC_Week(uint16_t Year, uint8_t Month, uint8_t Day);

/* BCD Convert   decimalism*/
/*The valid range of parameters is not judged*/
static uint8_t RTC_BCD_To_Dec(uint8_t u8RTCBCD)
{
    uint8_t u8RTCData = ((u8RTCBCD >> 4U) * 10U) + (u8RTCBCD & 0X0FU);
    return u8RTCData;
}
/* decimalism Convert  BCD */
static uint8_t RTC_Dec_To_BCD(uint8_t u8RTCDec)
{
    uint8_t u8RTCData = (((u8RTCDec / 10U) % 10U) << 4U) + (u8RTCDec % 10U);
    return u8RTCData;
}
static void RTC_Stop(void)
{
    uint16_t u16RTCCount = 0U;
    /*Stop sub-counter */
    RTCA0CE = 0U;
    /*Wait  sub-counter  stop*/
    while ((RTCA0CEST != 0) && (u16RTCCount < RTC_TIME_OUT_COUNT))
    {
        u16RTCCount++;
    }
}

void RTC_Pre_Init(void)
{
    uint16_t u16RTCCount = 0U;
    RTC_Stop(); /* Stop RTCA*/

#if (RTC_MODE_SELECT == RTC_MODE_MAIN)
    RTCA0SLSB = 1U;			   /*Frequency selection mode*/
    RTCA0SCMP = 4000000U - 1U; /*4M*/
#else
    RTCA0SLSB = 0U; /*32.768 kHz mode*/
    RTCA0SUBU = 0U; /*Reserved Later modified,Error Correction*/
#endif

    RTCA0AMPM = 1U; /*fix 24Hour Format*/

    /*Write start values*/
    RTCA0YEAR = RTC_Dec_To_BCD(RTC_DEFAULT_YEAR);
    RTCA0MONTH = RTC_Dec_To_BCD(RTC_DEFAULT_MONTH);
    RTCA0DAY = RTC_Dec_To_BCD(RTC_DEFAULT_DATE);
    RTCA0HOUR = RTC_Dec_To_BCD(RTC_DEFAULT_HOUR);
    RTCA0MIN = RTC_Dec_To_BCD(RTC_DEFAULT_MINUTE);
    RTCA0SEC = RTC_Dec_To_BCD(RTC_DEFAULT_SECOND);

    /*Starts sub-counter*/
    RTCA0CE = 1U;
    u16RTCCount = 0U;
    /*Wait  sub-counter  enable*/
    while ((RTCA0CEST != 1U) && (u16RTCCount < RTC_TIME_OUT_COUNT))
    {
        u16RTCCount++;
    }
}

void RTC_Set_Time(uint8_t year, uint8_t month, uint16_t day, uint8_t hour, uint8_t minute, uint8_t second)
{
    uint16_t u16RTCCount = 0U;
    while ((RTCA0WST != 0U) && (u16RTCCount < RTC_TIME_OUT_COUNT)) /*Check that all clock counters are running.*/
    {
        u16RTCCount++;
    }
    RTCA0WAIT = 1U; /*Stop all clock counters*/
    u16RTCCount = 0U;
    while ((RTCA0WST != 1U) && (u16RTCCount < RTC_TIME_OUT_COUNT)) /*Wait  all clock counters  stop*/
    {
        u16RTCCount++;
    }
    /*Write start values*/
    RTCA0YEAR = RTC_Dec_To_BCD(year);
    RTCA0MONTH = RTC_Dec_To_BCD(month);
    RTCA0DAY = RTC_Dec_To_BCD(day);
    RTCA0HOUR = RTC_Dec_To_BCD(hour);
    RTCA0MIN = RTC_Dec_To_BCD(minute);
    RTCA0SEC = RTC_Dec_To_BCD(second);

    /*Start all clock counters*/
    RTCA0WAIT = 0U;
    u16RTCCount = 0U;
    while ((RTCA0WST != 0U) && (u16RTCCount < RTC_TIME_OUT_COUNT)) /*Check that all clock counters are running.*/
    {
        u16RTCCount++;
    }
}

void RTC_Get_Time(void)
{
    uint16_t u16RTCCount = 0U;
    uint8_t Week = 0 ;

    while ((RTCA0WST != 0U) && (u16RTCCount < RTC_TIME_OUT_COUNT)) /*Check that all clock counters are running.*/
    {
        u16RTCCount++;
    }
    RTCA0WAIT = 1U; /*Stop all clock counters*/
    u16RTCCount = 0U;
    while ((RTCA0WST != 1U) && (u16RTCCount < RTC_TIME_OUT_COUNT)) /*Wait  all clock counters  stop*/
    {
        u16RTCCount++;
    }
    /*Read  data*/
    g_stRTCInformation.u8RTCYear = RTC_BCD_To_Dec(RTCA0YEAR);
    g_stRTCInformation.u8RTCMonth = RTC_BCD_To_Dec(RTCA0MONTH);
    g_stRTCInformation.u8RTCDayOfMonth = RTC_BCD_To_Dec(RTCA0DAY);
    g_stRTCInformation.u8RTCHour = RTC_BCD_To_Dec(RTCA0HOUR);
    g_stRTCInformation.u8RTCMinute = RTC_BCD_To_Dec(RTCA0MIN);
    g_stRTCInformation.u8RTCSecond = RTC_BCD_To_Dec(RTCA0SEC);

    Week = Cal_RTC_Week(g_stRTCInformation.u8RTCYear, g_stRTCInformation.u8RTCMonth, g_stRTCInformation.u8RTCDayOfMonth);

    g_stRTCInformation.u8RTCWeek = Week ;
    /*Start all clock counters*/
    RTCA0WAIT = 0U;
    u16RTCCount = 0U;
    while ((RTCA0WST != 0U) && (u16RTCCount < RTC_TIME_OUT_COUNT)) /*Check that all clock counters are running.*/
    {
        u16RTCCount++;
    }
}

#pragma ghs section bss=".NonInitArea"
RTC_Information_st_t RtcBackup;
#pragma ghs section bss=default
void RTC_Backup_Time(void)
{
    RTC_Get_Time();
    memcpy((uint8_t*)&RtcBackup, (uint8_t*)&g_stRTCInformation, sizeof (RtcBackup));
}

void Rtc_Restore_Time(void)
{
    uint16_t u16RTCCount = 0U;
    RTC_Stop(); /* Stop RTCA*/

#if (RTC_MODE_SELECT == RTC_MODE_MAIN)
    RTCA0SLSB = 1U;			   /*Frequency selection mode*/
    RTCA0SCMP = 4000000U - 1U; /*4M*/
#else
    RTCA0SLSB = 0U; /*32.768 kHz mode*/
    RTCA0SUBU = 0U; /*Reserved Later modified,Error Correction*/
#endif

    RTCA0AMPM = 1U; /*fix 24Hour Format*/

    /*Write start values*/
    RTCA0YEAR = RTC_Dec_To_BCD(RtcBackup.u8RTCYear);
    RTCA0MONTH = RTC_Dec_To_BCD(RtcBackup.u8RTCMonth);
    RTCA0DAY = RTC_Dec_To_BCD(RtcBackup.u8RTCDayOfMonth);
    RTCA0HOUR = RTC_Dec_To_BCD(RtcBackup.u8RTCHour);
    RTCA0MIN = RTC_Dec_To_BCD(RtcBackup.u8RTCMinute);
    RTCA0SEC = RTC_Dec_To_BCD(RtcBackup.u8RTCSecond);

    /*Starts sub-counter*/
    RTCA0CE = 1U;
    u16RTCCount = 0U;
    /*Wait  sub-counter  enable*/
    while ((RTCA0CEST != 1U) && (u16RTCCount < RTC_TIME_OUT_COUNT))
    {
        u16RTCCount++;
    }
}
/*¼ÆËã ÐÇÆÚ¼¸*/
static uint8_t Cal_RTC_Week(uint16_t Year, uint8_t Month, uint8_t Day)
{
    if (Month < 3)
    {
        Month += 12;
        Year--;
    }

    uint8_t tmp_0 = (uint8_t)(Year % 100);
    uint8_t tmp_1 = (uint8_t)(Year / 100);
    uint8_t week  = (uint8_t)((tmp_0 + (tmp_0 >> 2) + (tmp_1 >> 2) + 13 * (Month + 1) / 5 + Day - 1 - (tmp_1 << 1)) % 7);

    return week;
}
