
/******************************************************************************
* @file      : spl_rtc.c
* @version   : 1.0
* @date      : 2023.02.01
* @brief     : RTC SPL module driver
*   
* @history   :	
*   2023.02.01    lwq    create
*   
******************************************************************************/
#include "acm32g103_spl_conf.h" 


//#ifdef SPL_RTC_MODULE_ENABLED

static uint8_t RTC_DecimalToBcd(uint8_t Value);
static uint8_t RTC_BcdToDecimal(uint8_t Value);

/******************************************************************************
* @brief:  Deinitializes the RTC registers to their default reset values.       
* @param:  None
* @return: None  
******************************************************************************/
void RTC_DeInit(void)
{
    __IO uint32_t wutcounter = 0x00;
    uint32_t wutwfstatus = 0x00;

    /* RTC domain write enable */
    PMU->CTRL0 |= PMU_CTL0_RTC_WE;
    
    /* Reset the IE register to the default value */
    RTC->IE = 0x00000000;
    
    /* Clear RTC SR register */
    RTC->SR = 0xFFFFFFFF;
    
    /* Reset the ALM register to the default value */
    RTC->ALM = 0x7F000000;
    
    /* Reset the CR register to the default value */
    RTC->CR = 0x00400000;
    
    /* Reset ADJUST registers */
    RTC->ADJUST = 0x00000000;
    
    /* Reset the WUTR register to the default value */
    RTC->WUTR = 0x0000FFFF;
    
    /* Disable the write protection for RTC registers */
    RTC->WP = 0xCA53CA53;
    
    /* Reset all Date and Time registers */
    RTC->HOUR = 0x00000000;
    RTC->MIN  = 0x00000000;
    RTC->SEC  = 0x00000000;
    RTC->YEAR = 0x00000000;
    RTC->MONTH = 0x00000000;
    RTC->DAY = 0x00000000;
    RTC->WEEK = 0x00000000;

    /* Enable the write protection for RTC registers */
    RTC->WP = 0;  


}

/******************************************************************************
* @brief:  Initialize the RTC peripheral.
* @param:  ClockSource: The RTC Clock Source to be configured.
* @return: None  
******************************************************************************/
void RTC_Init(uint32_t ClockSource)
{
    /* Check the parameters */
    assert_param(IS_RTC_CLOCKSRC(ClockSource));

    /* Enable PMU CLK */
    __RCC_PMU_CLK_ENABLE();	

    /* Enable RTC CLK */
    __RCC_RTC_CLK_ENABLE();

    /* Enable RTC CLK */ 
    RCC->STDBYCTRL |= RCC_STDBYCTRL_RTCEN;

    /* RTC domain write enable */
    PMU->CTRL0 |= PMU_CTL0_RTC_WE;

    if(ClockSource == RTC_CLOCK_RC32K)
    {
        /* RC32K Enable */
        RCC->STDBYCTRL |= RCC_STDBYCTRL_RC32EN;
        
        /* Wait for the RC32K clock to be ready */
        while(!(RCC->STDBYCTRL & RCC_STDBYCTRL_RC32KRDY));	
		
        /* RTC CLK selects RC32K */
        RCC->STDBYCTRL &= (~RCC_STDBYCTRL_RTCSEL_Msk);

    }
    else 
    {
        /* Clear XTLDRV bits */
        RCC->STDBYCTRL &= (~RCC_STDBYCTRL_XTLDRV_Msk);
        
        /* Set XTLDRV */
        RCC->STDBYCTRL |= (RCC_STDBYCTRL_XTLDRV_1 | RCC_STDBYCTRL_XTLDRV_0);
        
        /* XTL Enable */
        RCC->STDBYCTRL |= RCC_STDBYCTRL_XTLEN;
        
        /* Wait for the XTL clock to be ready */
        while(!(RCC->STDBYCTRL & RCC_STDBYCTRL_XTLRDY));

        /* RTC CLK selects XTL */
        RCC->STDBYCTRL |= RCC_STDBYCTRL_RTCSEL_0;
    }
}

/******************************************************************************
* @brief:  Enables or disables the RTC registers write protection.
* @param:  NewState: new state of the write protection.
*          This parameter can be: ENABLE or DISABLE.
* @return: None
******************************************************************************/
void RTC_WriteProtectionCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the write protection for RTC registers */
        RTC->WP = 0x0;   
    }
    else
    {
        /* Disable the write protection for RTC registers */
        RTC->WP = 0xCA53CA53;   
    }
}


/******************************************************************************
* @brief:  Set the RTC current time.
* @param:  RTC_Format: specifies the format of the entered parameters.
* @param:  RTC_TimeStruct: pointer to a RTC_TimeTypeDef structure that contains 
*                          the time configuration information for the RTC.     
* @return: None
******************************************************************************/
void RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct)
{
    uint8_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0;

    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(RTC_Format));

    tmpreg1 = RTC_TimeStruct->Hours;
    tmpreg2 = RTC_TimeStruct->Minutes;
    tmpreg3 = RTC_TimeStruct->Seconds;
        
    if (RTC_Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to BCD format */
        tmpreg1 = RTC_DecimalToBcd(tmpreg1);
        tmpreg2 = RTC_DecimalToBcd(tmpreg2);
        tmpreg3 = RTC_DecimalToBcd(tmpreg3);
    }
    
    /* Check the parameters */
    assert_param(IS_RTC_HOUR(tmpreg1));
    assert_param(IS_RTC_MINUTES(tmpreg2));
    assert_param(IS_RTC_SECONDS(tmpreg3));

    /* Disable the write protection for RTC registers */
    RTC->WP = 0xCA53CA53;

    /* Set the new Time */
    RTC->HOUR = tmpreg1;
    RTC->MIN  = tmpreg2;
    RTC->SEC  = tmpreg3;
    
    /* Enable the write protection for RTC registers */
    RTC->WP = 0; 
}

/******************************************************************************
* @brief:  Fills each RTC_TimeStruct member with its default value
*         (Time = 00h:00min:00sec).
* @param:  RTC_TimeStruct: pointer to a RTC_TimeTypeDef structure which will be 
*          initialized.
* @return: None
******************************************************************************/
void RTC_TimeStructInit(RTC_TimeTypeDef* RTC_TimeStruct)
{
    /* Time = 00h:00min:00sec */
    RTC_TimeStruct->Hours = 0;
    RTC_TimeStruct->Minutes = 0;
    RTC_TimeStruct->Seconds = 0; 
}

/******************************************************************************
* @brief:  Get the RTC current Time.
* @param:  RTC_Format: specifies the format of the returned parameters.
* @param:  RTC_TimeStruct: pointer to a RTC_TimeTypeDef structure that will 
*                          contain the returned current time configuration.     
* @return: None
******************************************************************************/
void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct)
{
    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(RTC_Format));

    /* Fill the structure fields with the read parameters */
    RTC_TimeStruct->Hours = (uint8_t)RTC->HOUR;
    RTC_TimeStruct->Minutes = (uint8_t)RTC->MIN;
    RTC_TimeStruct->Seconds = (uint8_t)RTC->SEC;

    if (RTC_Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to Binary format */
        RTC_TimeStruct->Hours = (uint8_t)RTC_BcdToDecimal(RTC_TimeStruct->Hours);
        RTC_TimeStruct->Minutes = (uint8_t)RTC_BcdToDecimal(RTC_TimeStruct->Minutes);
        RTC_TimeStruct->Seconds = (uint8_t)RTC_BcdToDecimal(RTC_TimeStruct->Seconds);   
    }
}

/******************************************************************************
* @brief:  Set the RTC current date.
* @param:  RTC_Format: specifies the format of the entered parameters.
* @param:  RTC_DateStruct: pointer to a RTC_DateTypeDef structure that contains 
*                         the date configuration information for the RTC.
* @return: None
******************************************************************************/
void RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct)
{
    uint8_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0, tmpreg4 = 0;

    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(RTC_Format));

    tmpreg1 = RTC_DateStruct->Year;
    tmpreg2 = RTC_DateStruct->Month;
    tmpreg3 = RTC_DateStruct->Date;
    tmpreg4 = RTC_DateStruct->WeekDay;
        
    if (RTC_Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to BCD format */
        tmpreg1 = RTC_DecimalToBcd(tmpreg1);
        tmpreg2 = RTC_DecimalToBcd(tmpreg2);
        tmpreg3 = RTC_DecimalToBcd(tmpreg3);
        tmpreg4 = RTC_DecimalToBcd(tmpreg4);
    }
    
    /* Check the parameters */
    assert_param(IS_RTC_YEAR(tmpreg1));
    assert_param(IS_RTC_MONTH(tmpreg2));
    assert_param(IS_RTC_DAY(tmpreg3));
    assert_param(IS_RTC_WEEKDAY(tmpreg4));

    /* Disable the write protection for RTC registers */
    RTC->WP = 0xCA53CA53;

    /* Set the new Date */
    RTC->YEAR = tmpreg1;
    RTC->MONTH = tmpreg2;
    RTC->DAY = tmpreg3;
    RTC->WEEK = tmpreg4;
    
    /* Enable the write protection for RTC registers */
    RTC->WP = 0; 
}

/******************************************************************************
* @brief:  Fills each RTC_DateStruct member with its default value
*         (Monday, January 01 xx00).
* @param  RTC_DateStruct: pointer to a RTC_DateTypeDef structure which will be 
*         initialized.
* @return: None
******************************************************************************/
void RTC_DateStructInit(RTC_DateTypeDef* RTC_DateStruct)
{
    /* Monday, January 01 xx00 */
    RTC_DateStruct->WeekDay = 1;
    RTC_DateStruct->Date = 1;
    RTC_DateStruct->Month = 1;
    RTC_DateStruct->Year = 0;
}

/******************************************************************************
* @brief:  Get the RTC current date. 
* @param:  RTC_Format: specifies the format of the returned parameters.
* @param: RTC_DateStruct: pointer to a RTC_DateTypeDef structure that will 
*                         contain the returned current date configuration.     
* @return: None
******************************************************************************/
void RTC_GetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct)
{
    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(RTC_Format));
    
    /* Fill the structure fields with the read parameters */
    RTC_DateStruct->Year = (uint8_t)RTC->YEAR;
    RTC_DateStruct->Month = (uint8_t)RTC->MONTH;
    RTC_DateStruct->Date = (uint8_t)RTC->DAY;
    RTC_DateStruct->WeekDay = (uint8_t)RTC->WEEK;

    if (RTC_Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to Binary format */
        RTC_DateStruct->Year = (uint8_t)RTC_BcdToDecimal(RTC_DateStruct->Year);
        RTC_DateStruct->Month = (uint8_t)RTC_BcdToDecimal(RTC_DateStruct->Month);
        RTC_DateStruct->Date = (uint8_t)RTC_BcdToDecimal(RTC_DateStruct->Date);
        RTC_DateStruct->WeekDay = (uint8_t)RTC_BcdToDecimal(RTC_DateStruct->WeekDay);
    }
}


/******************************************************************************
* @brief:  Set the specified RTC Alarm.  
* @param:  RTC_Format: specifies the format of the returned parameters.
* @param:  RTC_AlarmStruct: pointer to a RTC_AlarmTypeDef structure that 
*                           contains the alarm configuration parameters.     
* @return: None
******************************************************************************/
void RTC_SetAlarm(uint32_t RTC_Format, RTC_AlarmTypeDef* RTC_AlarmStruct)
{
    uint8_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0, tmpreg4 = 0, tmpreg = 0;

    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(RTC_Format));
    assert_param(IS_ALARM_MASK(RTC_AlarmStruct->RTC_AlarmMask));
    assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(RTC_AlarmStruct->RTC_AlarmDateWeekDaySel));

    tmpreg1 = RTC_AlarmStruct->RTC_AlarmTime.Hours;
    tmpreg2 = RTC_AlarmStruct->RTC_AlarmTime.Minutes;
    tmpreg3 = RTC_AlarmStruct->RTC_AlarmTime.Seconds;
    tmpreg4 = RTC_AlarmStruct->RTC_AlarmDateWeekDay;
        
    if (RTC_Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to BCD format */
        tmpreg1 = RTC_DecimalToBcd(tmpreg1);
        tmpreg2 = RTC_DecimalToBcd(tmpreg2);
        tmpreg3 = RTC_DecimalToBcd(tmpreg3);
        tmpreg4 = RTC_DecimalToBcd(tmpreg4);
    }
    
    /* Check the parameters */
    assert_param(IS_RTC_HOUR(tmpreg1));
    assert_param(IS_RTC_MINUTES(tmpreg2));
    assert_param(IS_RTC_SECONDS(tmpreg3));
    
    if(RTC_AlarmStruct->RTC_AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
    {
        assert_param(IS_RTC_DAY(tmpreg4));      
    }
    else
    {
        assert_param(IS_RTC_WEEKDAY(tmpreg4));
        if(tmpreg4 == 0x07)
        {
            tmpreg = 0;
        }
        else
        {
            tmpreg = tmpreg4;
        }
        tmpreg4 = (1 << tmpreg);
    }
    
    /* Set the new Alarm */
    RTC->ALM = (RTC_AlarmStruct->RTC_AlarmDateWeekDaySel | \
               (tmpreg1 <<  RTC_ALM_ALMHOUR_Pos) | \
               (tmpreg2 <<  RTC_ALM_ALMMIN_Pos) | \
               (tmpreg3 <<  RTC_ALM_ALMSEC_Pos) | \
               (tmpreg <<  RTC_ALM_ALMWEEK_Pos));
          
    /* Clear ALM_MSKD¡¢ALM_MSKH¡¢ALM_MSKM bit */
    RTC->CR &= (~RTC_ALARMMASK_ALL);
    
    /* Set the new Alarm Mask */
    RTC->CR |= RTC_AlarmStruct->RTC_AlarmMask;            
}

/******************************************************************************
* @brief:  Fills each RTC_AlarmStruct member with its default value
*          (Time = 00h:00mn:00sec / Date = 1st day of the month/Mask =
*          all fields are masked).
* @param:  RTC_AlarmStruct: pointer to a @ref RTC_AlarmTypeDef structure which
*          will be initialized.
* @return: None
******************************************************************************/
void RTC_AlarmStructInit(RTC_AlarmTypeDef* RTC_AlarmStruct)
{
    /* Alarm Time Settings : Time = 00h:00mn:00sec */
    RTC_AlarmStruct->RTC_AlarmTime.Hours = 0;
    RTC_AlarmStruct->RTC_AlarmTime.Minutes = 0;
    RTC_AlarmStruct->RTC_AlarmTime.Seconds = 0;

    /* Alarm Date Settings : Date = 1st day of the month */
    RTC_AlarmStruct->RTC_AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
    RTC_AlarmStruct->RTC_AlarmDateWeekDay = 1;

    /* Alarm Masks Settings : Mask =  all fields are not masked */
    RTC_AlarmStruct->RTC_AlarmMask = RTC_ALARMMASK_NONE;
}

/******************************************************************************
* @brief:  Get the RTC Alarm value and masks.
* @param:  RTC_Format: specifies the format of the output parameters.
* @param:  RTC_AlarmStruct: pointer to a RTC_AlarmTypeDef structure that will 
*                           contains the output alarm configuration values.     
* @return: None
******************************************************************************/
void RTC_GetAlarm(uint32_t RTC_Format, RTC_AlarmTypeDef* RTC_AlarmStruct)
{
    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(RTC_Format));

    /* Fill the structure with the read parameters */
    RTC_AlarmStruct->RTC_AlarmTime.Hours = (uint8_t)(RTC->ALM >> RTC_ALM_ALMHOUR_Pos);
    RTC_AlarmStruct->RTC_AlarmTime.Minutes = (uint8_t)(RTC->ALM >> RTC_ALM_ALMMIN_Pos);
    RTC_AlarmStruct->RTC_AlarmTime.Seconds = (uint8_t)(RTC->ALM);
    RTC_AlarmStruct->RTC_AlarmDateWeekDay = (uint8_t)(RTC->ALM >> RTC_ALM_ALM_WDS_Pos);
    RTC_AlarmStruct->RTC_AlarmDateWeekDaySel = (uint32_t)(RTC->ALM & RTC_ALM_ALM_WDS_Msk);
    RTC_AlarmStruct->RTC_AlarmMask = (uint32_t)(RTC->CR & RTC_ALARMMASK_ALL);

    if (RTC_Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to Binary format */
        RTC_AlarmStruct->RTC_AlarmTime.Hours = RTC_BcdToDecimal(RTC_AlarmStruct->RTC_AlarmTime.Hours);
        RTC_AlarmStruct->RTC_AlarmTime.Minutes = RTC_BcdToDecimal(RTC_AlarmStruct->RTC_AlarmTime.Minutes);
        RTC_AlarmStruct->RTC_AlarmTime.Seconds = RTC_BcdToDecimal(RTC_AlarmStruct->RTC_AlarmTime.Seconds);
        RTC_AlarmStruct->RTC_AlarmDateWeekDay = RTC_BcdToDecimal(RTC_AlarmStruct->RTC_AlarmDateWeekDay);
    }  
}

/******************************************************************************
* @brief:  Enables or disables the specified RTC Alarm.
* @param:  NewState: new state of the specified alarm.
*          This parameter can be: ENABLE or DISABLE.
* @return: None
******************************************************************************/
void RTC_AlarmCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    /* Configure the Alarm state */
    if (NewState != DISABLE)
    {
        RTC->CR |= RTC_CR_ALM_EN;   
    }
    else
    { 
        /* Disable the Alarm in RTC_CR register */
        RTC->CR &= (~RTC_CR_ALM_EN);
    } 
}

/******************************************************************************
* @brief:  Configures the RTC Wakeup clock source.    
* @param:  RTC_WakeUpClock: Wakeup Clock source.
* @return: None
******************************************************************************/
void RTC_WakeUpClockConfig(uint32_t RTC_WakeUpClock)
{
    /* Check the parameters */
    assert_param(IS_RTC_WAKEUP_CLOCK(RTC_WakeUpClock));

    /* Clear the Wakeup Timer clock source bits in CR register */
    RTC->CR &= (~RTC_CR_WUCKSEL_Msk);

    /* Configure the clock source */
    RTC->CR |= RTC_WakeUpClock;

}

/******************************************************************************
* @brief:  Configures the RTC Wakeup counter.       
* @param:  RTC_WakeUpCounter: specifies the WakeUp counter.
* @return: None
******************************************************************************/
void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter)
{
    /* Check the parameters */
    assert_param(IS_RTC_WAKEUP_COUNTER(RTC_WakeUpCounter));

    /* Configure the Wakeup Timer counter */
    RTC->WUTR = RTC_WakeUpCounter;
}

/******************************************************************************
* @brief:  Returns the RTC WakeUp timer counter value.
* @param:  None
* @return: None
******************************************************************************/
uint32_t RTC_GetWakeUpCounter(void)
{
    /* Get the counter value */
    return ((uint32_t)(RTC->WUTR & 0xFFFF));
}

/******************************************************************************
* @brief:  Enables or Disables the RTC WakeUp timer.
* @param:  NewState: new state of the WakeUp timer.
*          This parameter can be: ENABLE or DISABLE.
* @return: None
******************************************************************************/
void RTC_WakeUpCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the Wakeup Timer */
        RTC->CR |= RTC_CR_WUTE;   
    }
    else
    {
        /* Disable the Wakeup Timer */
        RTC->CR &= (~RTC_CR_WUTE);   
    }
}

/******************************************************************************
* @brief  Configures the RTC output source.
* @param  RTC_Output: Specified frequency output selection signal. 
* @return: None
******************************************************************************/
void RTC_OutputConfig(uint32_t RTC_Output)
{
    /* Check the parameters */
    assert_param(IS_RTC_OUTPUT(RTC_Output));

    /* Clear the bits to be configured */
    RTC->CR &= (~RTC_CR_FSEL_Msk);

    /* Configure the output selection */
    RTC->CR |= RTC_Output;
}

/******************************************************************************
* @brief:  Configures the Coarse calibration parameters.
* @param:  RTC_CalibSign: specifies the sign of the coarse calibration value.
* @param:  Value: value of coarse calibration expressed in ppm.        
* @return: None
******************************************************************************/
void RTC_CoarseCalibConfig(uint32_t RTC_CalibSign, uint32_t Value)
{
    /* Check the parameters */
    assert_param(IS_RTC_CALIB_SIGN(RTC_CalibSign));
    assert_param(IS_RTC_CALIB_VALUE(Value)); 

    /* Set Initialization mode */
    RTC->ADJUST = (Value | RTC_CalibSign);

}


/******************************************************************************
* @brief:  Configures the select Tamper trigger edge.
* @param:  RTC_Tamper: Selected tamper.
*          This parameter can be RTC_Tamper_1 or RTC_Tamper 2
* @param:  RTC_TamperTrigger: Specifies the trigger on the tamper pin that 
*          stimulates tamper event. 
* @return: None
******************************************************************************/
void RTC_TamperTriggerConfig(uint32_t RTC_Tamper, uint32_t RTC_TamperTrigger)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(RTC_Tamper)); 
    assert_param(IS_RTC_TAMPER_TRIGGER(RTC_TamperTrigger));

    if (RTC_Tamper == RTC_TAMPER_1)
    {  
        /* Clear TS1EDGE bit in CR register */
        RTC->CR &= (~RTC_CR_TS1EDGE_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperTrigger << RTC_CR_TS1EDGE_Pos);
        
    }
    else
    { 
        /* Clear TS2EDGE bit in CR register */
        RTC->CR &= (~RTC_CR_TS2EDGE_Msk);
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperTrigger << RTC_CR_TS2EDGE_Pos);
    }  
}

/******************************************************************************
* @brief:  Enables or Disables the Tamper detection.
* @param:  RTC_Tamper: Selected tamper.
*          This parameter can be RTC_Tamper_1 or RTC_Tamper_2
* @param:  NewState: new state of the tamper.
*          This parameter can be: ENABLE or DISABLE.                   
* @return: None
******************************************************************************/
void RTC_TamperCmd(uint32_t RTC_Tamper, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(RTC_Tamper));  
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected Tamper pin */
        RTC->CR |= RTC_Tamper;
    }
    else
    {
        /* Disable the selected Tamper pin */
        RTC->CR &= (~RTC_Tamper);    
    }

    /* PC13 pin function selects RTC input as Tamper */ 
    if(RTC_Tamper == RTC_TAMPER_1)
    {
        PMU_STANDBYDomainPinConfig(PMU_PIN_PC13, PMU_PIN_FUNCTION_2);
    }
}

/******************************************************************************
* @brief:  Enables or Disables the Tampers Filter.
* @param:  RTC_Tamper: Selected tamper.
* @param:  RTC_TamperFilterStatus: new state of the tamper Filter.
* @return: None
******************************************************************************/
void RTC_TamperFilterCmd(uint32_t RTC_Tamper, uint32_t RTC_TamperFilterStatus)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(RTC_Tamper)); 
    assert_param(IS_RTC_TAMPER_FILTER_STATUS(RTC_TamperFilterStatus));

    if (RTC_Tamper == RTC_TAMPER_1)
    {  
        /* Clear TAMP1FLT bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP1FLTEN_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperFilterStatus << RTC_CR_TAMP1FLTEN_Pos);
        
    }
    else
    {
        /* Clear TAMP2FLT bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP2FLTEN_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperFilterStatus << RTC_CR_TAMP2FLTEN_Pos);
    }    
}

/******************************************************************************
* @brief:  Configures the Tampers Filter Period.
* @param:  RTC_Tamper: Selected tamper.
* @param:  RTC_TamperFilter: Specifies the tampers filter.
* @return: None
******************************************************************************/
void RTC_TamperFilterPeriodConfig(uint32_t RTC_Tamper, uint32_t RTC_TamperFilter)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(RTC_Tamper)); 
    assert_param(IS_RTC_TAMPER_FILTER(RTC_TamperFilter));

    if (RTC_Tamper == RTC_TAMPER_1)
    {  
        /* Clear TAMP1FLT bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP1FLT_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperFilter << RTC_CR_TAMP1FLT_Pos);
        
    }
    else
    {
        /* Clear TAMP2FLT bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP2FLT_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperFilter << RTC_CR_TAMP2FLT_Pos);
    }    
}

/******************************************************************************
* @brief:  Configures the Tampers Filter Clock.
* @param:  RTC_TamperSamplingFreq: Specifies the tampers Sampling Frequency.
* @return: None
******************************************************************************/
void RTC_TamperFilterClockConfig(uint32_t RTC_TamperSamplingClock)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER_FILTER_CLOCK(RTC_TamperSamplingClock));

    /* Clear TAMPFLTCLK bits in the RTC_CR register */
    RTC->CR &= (~RTC_CR_TAMPFLTCLK_Msk);

    /* Configure the RTC_TAFCR register */
    RTC->CR |= (uint32_t)RTC_TamperSamplingClock;
}

/******************************************************************************
* @brief:  Enables or Disables the tamper falling edge clear backup register.
* @param:  RTC_Tamper: Selected tamper. 
* @param:  RTC_TamperFallingClear: Whether the falling edge clears the backup register.
* @return: None
******************************************************************************/
void RTC_TamperFallingClearBackpConfig(uint32_t RTC_Tamper, uint32_t RTC_TamperFallingClear)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(RTC_Tamper));
    assert_param(IS_RTC_TAMPER_FALLING_CLEAR(RTC_TamperFallingClear));

    if (RTC_Tamper == RTC_TAMPER_1)
    {  
        /* Clear TAMP1FCLR bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP1FCLR_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperFallingClear << RTC_CR_TAMP1FCLR_Pos);
        
    }
    else
    {
        /* Clear TAMP1FCLR bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP2FCLR_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperFallingClear << RTC_CR_TAMP2FCLR_Pos);
    }
}

/******************************************************************************
* @brief:  Enables or Disables the tamper rasing edge clear backup register.
* @param:  RTC_Tamper: Selected tamper. 
* @param:  RTC_TamperRasingClear: Whether the rasing edge clears the backup register.
* @return: None
******************************************************************************/
void RTC_TamperRasingClearBackpConfig(uint32_t RTC_Tamper, uint32_t RTC_TamperRasingClear)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(RTC_Tamper));
    assert_param(IS_RTC_TAMPER_RASING_CLEAR(RTC_TamperRasingClear));

    if (RTC_Tamper == RTC_TAMPER_1)
    {  
        /* Clear TAMP1FCLR bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP1RCLR_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperRasingClear << RTC_CR_TAMP1RCLR_Pos);
        
    }
    else
    {
        /* Clear TAMP1FCLR bit in CR register */
        RTC->CR &= (~RTC_CR_TAMP2RCLR_Msk);	
        
        /* Set a new configuration */
        RTC->CR |= (RTC_TamperRasingClear << RTC_CR_TAMP2RCLR_Pos);
    }
}

/******************************************************************************
* @brief:  Writes a data in a specified RTC Backup data register.
* @param:  RTC_BKP_DR: RTC Backup data Register number.
*          This parameter can be: RTC_BKP_DRx where x can be from 0 to 15 to 
*          specify the register.
* @param:  Data: Data to be written in the specified RTC Backup data register.                     
* @return: None
******************************************************************************/
void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data)
{
    __IO uint32_t tmp = 0;

    /* Check the parameters */
    assert_param(IS_RTC_BKP(RTC_BKP_DR));

    tmp = RTC_BASE_ADDR + 0x70;
    tmp += (RTC_BKP_DR * 4);

    /* Write the specified register */
    *(__IO uint32_t *)tmp = (uint32_t)Data;
}

/******************************************************************************
* @brief:  Reads data from the specified RTC Backup data Register.
* @param:  RTC_BKP_DR: RTC Backup data Register number.
*          This parameter can be: RTC_BKP_DRx where x can be from 0 to 15 to 
*          specify the register.                   
* @return: Read value
******************************************************************************/
uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR)
{
    __IO uint32_t tmp = 0;

    /* Check the parameters */
    assert_param(IS_RTC_BKP(RTC_BKP_DR));

    tmp = RTC_BASE_ADDR + 0x70;
    tmp += (RTC_BKP_DR * 4);

    /* Read the specified register */
    return (*(__IO uint32_t *)tmp);
}

/******************************************************************************
* @brief:  Enables or disables the specified RTC interrupts.
* @param:  RTC_IT: specifies the RTC interrupt sources to be enabled or disabled. 
* @param:  NewState: new state of the specified RTC interrupts.
*          This parameter can be: ENABLE or DISABLE.
* @return: None
******************************************************************************/
void RTC_ITConfig(uint32_t RTC_IT, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RTC_IT_FLAG(RTC_IT));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the RTC_IT Interrupt in the RTC_IE */
        RTC->IE |= RTC_IT ;
    }
    else
    {
        /* Disable the RTC_IT Interrupt in the RTC_IE */
        RTC->IE &= (~RTC_IT);
    }
}

/******************************************************************************
* @brief:  Checks whether the specified RTC flag is set or not.
* @param:  RTC_FLAG: specifies the flag to check.
* @return: The new state of RTC_FLAG (SET or RESET).
******************************************************************************/
FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG)
{
    FlagStatus bitstatus = RESET;

    /* Check the parameters */
    assert_param(IS_RTC_IT_FLAG(RTC_FLAG));

    /* Return the status of the flag */
    if ((RTC->SR & RTC_FLAG) != (uint32_t)RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/******************************************************************************
* @brief:  Clears the RTC's pending flags.
* @param:  RTC_FLAG: specifies the RTC flag to clear.
* @return: None
******************************************************************************/
void RTC_ClearFlag(uint32_t RTC_FLAG)
{
    /* Check the parameters */
    assert_param(IS_RTC_IT_FLAG(RTC_FLAG));

    /* Clear the Flags in the RTC_ISR register */
    RTC->SR = RTC_FLAG;  
}

/******************************************************************************
* @brief:  Checks whether the specified RTC interrupt has occurred or not.
* @param:  RTC_IT: specifies the RTC interrupt source to check.
* @return: The new state of RTC_IT (SET or RESET).
******************************************************************************/
ITStatus RTC_GetITStatus(uint32_t RTC_IT)
{
    ITStatus bitstatus = RESET;

    /* Check the parameters */
    assert_param(IS_RTC_IT_FLAG(RTC_IT));

    /* Get the status of the Interrupt */
    if (((RTC->IE & RTC_IT) != (uint32_t)RESET) && ((RTC->SR & RTC_IT) != (uint32_t)RESET))
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/******************************************************************************
* @brief:  Clears the RTC's interrupt pending bits.
* @param:  RTC_IT: specifies the RTC interrupt pending bit to clear.
* @return: none
******************************************************************************/
void RTC_ClearITPendingBit(uint32_t RTC_IT)
{
    /* Check the parameters */
    assert_param(IS_RTC_IT_FLAG(RTC_IT));
    
    if((RTC->IE & RTC_IT)!= RESET)
    {
        /* Clear the interrupt pending bits in the RTC_SR register */
        RTC->SR = RTC_IT;
    } 
}

/******************************************************************************
* @brief:  Converts a 2 digit decimal to BCD format.
* @param:  Value: Byte to be converted.
* @return: Converted byte
******************************************************************************/
static uint8_t RTC_DecimalToBcd(uint8_t Value)
{
    uint8_t bcdhigh = 0;

    while (Value >= 10)
    {
        bcdhigh++;
        Value -= 10;
    }

    return  ((uint8_t)(bcdhigh << 4) | Value);
}

/******************************************************************************
* @brief:  Convert from 2 digit BCD to decimal.
* @param:  Value: BCD value to be converted.
* @return: Converted word
******************************************************************************/
static uint8_t RTC_BcdToDecimal(uint8_t Value)
{
    uint8_t tmp = 0;
    tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;
    return (tmp + (Value & (uint8_t)0x0F));
}










//#endif    /* SPL_RTC_MODULE_ENABLED */


/************************ (C) COPYRIGHT AISINOCHIP *****END OF FILE****/




