
/******************************************************************************
*@file  : fxx_rtc.c
*@brief : RTC SPL module driver.
******************************************************************************/
#include  "fxx_rtc.h" 



/******************************************************************************
* @brief:  Deinitializes the RTC registers to their default reset values.       
* @param:  None
* @return: None  
******************************************************************************/
void RTC_DeInit(void)
{
    /* Enable RTC PCLK */
    SCU->IPCKENR1 |= (1 << 13);     
    System_Delay(5); 
    
    /* Enable RTC RTC domain access */
    SCU->STOPCFG |= (1 << 0); 

    /* 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;
     
    /* Disable the write protection for RTC registers */
    RTC->WP = RTC_WRITE_ENABLE;
    
    /* 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 = RTC_WRITE_DISABLE;  

}

/******************************************************************************
* @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 RTC PCLK */
    SCU->IPCKENR1 |= (1 << 13);     
    System_Delay(5); 
    
    /* Enable RTC RTC domain access */
    SCU->STOPCFG |= (1 << 0); 

    if(ClockSource == RTC_CLOCK_RC32K)
    {
        /* RC32K Enable */
        PMU_RC32KCmd(PMU_STATE_ENABLE);	
		
        /* RTC CLK selects RC32K */
        PMU_RTCClkSelect(PMU_RTC_CLK_RC32K);

    }
    else 
    {
        /* Set XTLDRV */
        PMU_XTLDriveConfig(PMU_XTL_NORMAL, PMU_XTL_DRIVE_HIGH);
        
        /* XTL Enable */
        PMU_XTLCmd(PMU_STATE_ENABLE);

        /* RTC CLK selects XTL */
        PMU_RTCClkSelect(PMU_RTC_CLK_XTL);
    }
    /* Enable RTC CLK */
    PMU_RTCClkCmd(PMU_STATE_ENABLE);
}

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

    if (NewState != RTC_STATE_DISABLE)
    {
        /* Enable the write protection for RTC registers */
        RTC->WP = RTC_WRITE_DISABLE;   
    }
    else
    {
        /* Disable the write protection for RTC registers */
        RTC->WP = RTC_WRITE_ENABLE;   
    }
}


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

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

    tmpreg1 = TimeStruct->Hour;
    tmpreg2 = TimeStruct->Minute;
    tmpreg3 = TimeStruct->Second;
        
    if (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_MINUTE(tmpreg2));
    assert_param(IS_RTC_SECOND(tmpreg3));

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

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

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

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

    /* Fill the structure fields with the read parameters */
    TimeStruct->Hour = (uint8_t)RTC->HOUR;
    TimeStruct->Minute = (uint8_t)RTC->MIN;
    TimeStruct->Second = (uint8_t)RTC->SEC;

    if (Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to Binary format */
        TimeStruct->Hour = (uint8_t)RTC_BcdToDecimal(TimeStruct->Hour);
        TimeStruct->Minute = (uint8_t)RTC_BcdToDecimal(TimeStruct->Minute);
        TimeStruct->Second = (uint8_t)RTC_BcdToDecimal(TimeStruct->Second);   
    }
}

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

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

    tmpreg1 = DateStruct->Year;
    tmpreg2 = DateStruct->Month;
    tmpreg3 = DateStruct->Day;
    tmpreg4 = DateStruct->Week;
        
    if (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_WEEK(tmpreg4));

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

    /* 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 = RTC_WRITE_DISABLE; 
}

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

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

    if (Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to Binary format */
        DateStruct->Year = (uint8_t)RTC_BcdToDecimal(DateStruct->Year);
        DateStruct->Month = (uint8_t)RTC_BcdToDecimal(DateStruct->Month);
        DateStruct->Day = (uint8_t)RTC_BcdToDecimal(DateStruct->Day);
        DateStruct->Week = (uint8_t)RTC_BcdToDecimal(DateStruct->Week);
    }
}


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

    /* Check the parameters */
    assert_param(IS_RTC_FORMAT(Format));
    assert_param(IS_ALARM_MASK(AlarmStruct->RTC_AlarmMask));
    assert_param(IS_RTC_ALARM_MODE(AlarmStruct->RTC_AlarmMode));

    tmpreg1 = AlarmStruct->RTC_AlarmTime.Hour;
    tmpreg2 = AlarmStruct->RTC_AlarmTime.Minute;
    tmpreg3 = AlarmStruct->RTC_AlarmTime.Second;
    tmpreg4 = AlarmStruct->RTC_AlarmDayOrWeek;
        
    if (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_MINUTE(tmpreg2));
    assert_param(IS_RTC_SECOND(tmpreg3));
    
    if(AlarmStruct->RTC_AlarmMode == RTC_ALARM_DAY)
    {
        assert_param(IS_RTC_DAY(tmpreg4));      
    }
    else
    {
        assert_param(IS_RTC_WEEK(tmpreg4));
        if(tmpreg4 == 0x07)
        {
            tmpreg = 0;
        }
        else
        {
            tmpreg = tmpreg4;
        }
        tmpreg4 = (1 << tmpreg);
    }
    
    /* Set the new Alarm */
    RTC->ALM = (AlarmStruct->RTC_AlarmMode | \
               (tmpreg1 <<  RTC_ALM_ALMHOUR_Pos) | \
               (tmpreg2 <<  RTC_ALM_ALMMIN_Pos) | \
               (tmpreg3 <<  RTC_ALM_ALMSEC_Pos) | \
               (tmpreg4 <<  RTC_ALM_ALMWEEK_DAY_Pos));
          
    /* Clear ALM_MSKD¡¢ALM_MSKH¡¢ALM_MSKM bit */
    RTC->CR &= (~RTC_ALARM_MASK_ALL);
    
    /* Set the new Alarm Mask */
    RTC->CR |= AlarmStruct->RTC_AlarmMask;            
}

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

    /* Alarm Date Settings : Date = 1st day of the month */
    AlarmStruct->RTC_AlarmMode = RTC_ALARM_DAY;
    AlarmStruct->RTC_AlarmDayOrWeek = 1;

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

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

    /* Fill the structure with the read parameters */
    AlarmStruct->RTC_AlarmTime.Hour = (uint8_t)((RTC->ALM & RTC_ALM_ALMHOUR_Msk) >> RTC_ALM_ALMHOUR_Pos);
    AlarmStruct->RTC_AlarmTime.Minute = (uint8_t)((RTC->ALM & RTC_ALM_ALMMIN_Msk)  >> RTC_ALM_ALMMIN_Pos);
    AlarmStruct->RTC_AlarmTime.Second = (uint8_t)(RTC->ALM & RTC_ALM_ALMSEC_Msk);
    AlarmStruct->RTC_AlarmDayOrWeek = (uint8_t)((RTC->ALM & RTC_ALM_ALMWEEK_DAY_Msk) >> RTC_ALM_ALMWEEK_DAY_Pos);
    AlarmStruct->RTC_AlarmMode = (uint32_t)(RTC->ALM & RTC_ALM_ALMWDS_Msk);
    AlarmStruct->RTC_AlarmMask = (uint32_t)(RTC->CR & RTC_ALARM_MASK_ALL);

    if (Format == RTC_FORMAT_DECIMAL)
    {
        /* Convert the structure parameters to Binary format */
        AlarmStruct->RTC_AlarmTime.Hour = RTC_BcdToDecimal(AlarmStruct->RTC_AlarmTime.Hour);
        AlarmStruct->RTC_AlarmTime.Minute = RTC_BcdToDecimal(AlarmStruct->RTC_AlarmTime.Minute);
        AlarmStruct->RTC_AlarmTime.Second = RTC_BcdToDecimal(AlarmStruct->RTC_AlarmTime.Second);
        AlarmStruct->RTC_AlarmDayOrWeek = RTC_BcdToDecimal(AlarmStruct->RTC_AlarmDayOrWeek);
    }  
}

/******************************************************************************
* @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(uint32_t NewState)
{
    /* Check the parameters */
    assert_param(IS_RTC_STATE(NewState));

    /* Configure the Alarm state */
    if (NewState != RTC_STATE_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 output source.
* @param  Output: Specified frequency output selection signal. 
* @return: None
******************************************************************************/
void RTC_FselOutputConfig(uint32_t Output)
{
    /* Check the parameters */
    assert_param(IS_RTC_FSEL(Output));

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

    /* Configure the output selection */
    RTC->CR |= Output;
    
    /* Configure PC13 as digital IO */
    PMU->IOCR  &= ~(1 << 6);
    /* Configure PC13 as RTC Fout function */
    PMU->IOSEL = (PMU->IOSEL & (~(0x03))) | 0x01;
    /* Configure PC13 Push pull output */
    PMU->IOSEL = (PMU->IOSEL & (~(1 << 8))) | (1 << 8);
}

/******************************************************************************
* @brief:  Configures the adjust parameters.
* @param:  AdjustSign: specifies the sign of the coarse calibration value.
* @param:  AdjustValue: value of adjust expressed in ppm.        
* @return: None
******************************************************************************/
void RTC_AdjustConfig(uint32_t AdjustSign, uint32_t AdjustValue)
{
    /* Check the parameters */
    assert_param(IS_RTC_ADJUST_SIGN(AdjustSign));
    assert_param(IS_RTC_ADJUST_VALUE(AdjustValue)); 

    /* Set Initialization mode */
    RTC->ADJUST = (AdjustValue | AdjustSign);

}


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

    if (Tamper == RTC_TAMPER_1)
    {  
        if(TamperEdge == RTC_TAMPER_FALLING) 
        {
            // Configure PC13 pull up
            PMU->IOCR |= (1 << 0);   
            PMU->IOCR &= ~(1 << 1);
        }
        else
        {
            // Configure PC13 pull down
            PMU->IOCR &= ~(1 << 0);
            PMU->IOCR |=(1 << 1);	
        }
        //RTC->CR = (RTC->CR & (~RTC_CR_TS1EDGE_Msk)) | (TamperEdge << RTC_CR_TS1EDGE_Pos);        
    }
    else
    { 
        if(TamperEdge == RTC_TAMPER_FALLING) 
        {
            // Configure PA0 pull up
            SCU->PABPUR |= (1 << 0);   
            SCU->PABPDR &= ~(1 << 0);
        }
        else
        {
            // Configure PA0 pull down
            SCU->PABPUR &= ~(1 << 0);   
            SCU->PABPDR |= (1 << 0);
        }
        //RTC->CR = (RTC->CR & (~RTC_CR_TS2EDGE_Msk)) | (TamperEdge << RTC_CR_TS2EDGE_Pos);        
    }  
}

/******************************************************************************
* @brief:  Enables or Disables the Tamper detection.
* @param:  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 Tamper, uint32_t NewState)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER(Tamper));  
    assert_param(IS_RTC_STATE(NewState));

    if(NewState != RTC_STATE_DISABLE)
    {
        /* Enable the selected Tamper pin */
        RTC->CR |= Tamper;     
        
        /* PC13 pin function selects RTC input as Tamper */ 
        if(Tamper == RTC_TAMPER_1)
        {
            /* Configure PC13 as digital IO */
            PMU->IOCR  &= ~(1 << 6);
            /* Configure PC13 as tamper function */
            PMU->IOSEL = (PMU->IOSEL & (~(0x03))) | 0x02;
        }
        else
        {
            /* Configure PA0 as digital IO */
            SCU->PABADS &= ~(1 << 0);            
        }
    }
    else
    {
        /* Disable the selected Tamper pin */
        RTC->CR &= (~Tamper);    
    }
}

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

    if (Tamper == RTC_TAMPER_1)
    {  
        RTC->CR = (RTC->CR & (~RTC_CR_TAMP1FLTEN_Msk)) | (FilterState << RTC_CR_TAMP1FLTEN_Pos);   
    }
    else
    {
        RTC->CR = (RTC->CR & (~RTC_CR_TAMP2FLTEN_Msk)) | (FilterState << RTC_CR_TAMP2FLTEN_Pos);
    }    
}

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

    if (Tamper == RTC_TAMPER_1)
    {  
        RTC->CR  = (RTC->CR & (~RTC_CR_TAMP1FLT_Msk)) | (FilterPeriod << RTC_CR_TAMP1FLT_Pos);
    }
    else
    {
        RTC->CR  = (RTC->CR & (~RTC_CR_TAMP2FLT_Msk)) | (FilterPeriod << 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 FilterClock)
{
    /* Check the parameters */
    assert_param(IS_RTC_TAMPER_FILTER_CLOCK(FilterClock));
    
    RTC->CR = (RTC->CR & (~RTC_CR_TAMPFLTCLK_Msk)) | (uint32_t)FilterClock;
}

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

    if (Tamper == RTC_TAMPER_1)
    {  
        RTC->CR = (RTC->CR & (~RTC_CR_TAMP1FCLR_Msk)) | (TamperClear << RTC_CR_TAMP1FCLR_Pos);
        
    }
    else
    {
        RTC->CR = (RTC->CR & (~RTC_CR_TAMP2FCLR_Msk)) | (TamperClear << RTC_CR_TAMP2FCLR_Pos);
    }
}

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

    if (Tamper == RTC_TAMPER_1)
    {  
        RTC->CR = (RTC->CR & (~RTC_CR_TAMP1RCLR_Msk)) | (TamperClear << RTC_CR_TAMP1RCLR_Pos); 
    }
    else
    {
        RTC->CR = (RTC->CR & (~RTC_CR_TAMP2RCLR_Msk)) | (TamperClear << RTC_CR_TAMP2RCLR_Pos);
    }
}

/******************************************************************************
* @brief:  Writes a data in a specified RTC Backup data register.
* @param:  Number: RTC Backup data Register number.
*          This parameter can be: RTC_BACKUP_x where x can be from 0 to 4 to 
*          specify the register.
* @param:  Data: Data to be written in the specified RTC Backup data register.                     
* @return: None
******************************************************************************/
void RTC_WriteBackupRegister(uint32_t Number, uint32_t Data)
{
    /* Check the parameters */
    assert_param(IS_RTC_BACKUP(Number));

    /* Write the specified register */
    RTC->BACKUP[Number] = Data;
}

/******************************************************************************
* @brief:  Reads data from the specified RTC Backup data Register.
* @param:  Number: RTC Backup data Register number.
*          This parameter can be: RTC_BACKUP_x where x can be from 0 to 4 to 
*          specify the register.                   
* @return: Read value
******************************************************************************/
uint32_t RTC_ReadBackupRegister(uint32_t Number)
{
    /* Check the parameters */
    assert_param(IS_RTC_BACKUP(Number));

    /* Read the specified register */
    return (RTC->BACKUP[Number]);
}

/******************************************************************************
* @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, uint32_t NewState)
{
    /* Check the parameters */
    assert_param(IS_RTC_IT_FLAG(RTC_IT));
    assert_param(IS_RTC_STATE(NewState));

    if (NewState != RTC_STATE_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
******************************************************************************/
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
******************************************************************************/
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));
}













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




