/*!
* @file     Rtc_Hw.c
*
* @version  1.0.0
*
* @brief    This file provides hardware functions of the Real-Time Clock (RTC) peripheral.
*
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_15-Nov-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/

#ifdef __cplusplus
extern "C"{
#endif
    
#include "Rtc_Hw.h"
#include "Rtc_Reg.h"
#include "Mcu_RcmTypes.h"
/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup RTC_Driver
  * @brief RTC driver modules
  @{
*/

/** @defgroup RTC_Macros
  @{
*/
/**********************************************************************************************************************
                                    VENDOR ID & AUTOSAR VERSION INFO
***********************************************************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define RTC_HW_VENDOR_ID                      0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */ 
#define RTC_HW_AR_RELEASE_MAJOR_VERSION       0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define RTC_HW_AR_RELEASE_MINOR_VERSION       0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define RTC_HW_AR_RELEASE_REVISION_VERSION    0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define RTC_HW_SW_MAJOR_VERSION               0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define RTC_HW_SW_MINOR_VERSION               0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define RTC_HW_SW_PATCH_VERSION               0x00U

/**@} end of group RTC_Macros */
/**********************************************************************************************************************
                                            LOCAL FUNCTIONS
***********************************************************************************************************************/
/** @defgroup RTC_Fuctions
  @{
*/
/*!
* @brief     Converts a 2 digit decimal to BCD format
*
* @param     val: Byte to be converted
*
* @retval    Converted byte
*/
LOCAL_INLINE FUNC(uint8, RTC_CODE) Rtc_Hw_ByteConBcd2(VAR(uint8, AUTOMATIC) val)
{
    VAR(uint8, AUTOMATIC) bcdhigh = 0;
    uint32_t tmp = val;
    while (tmp >= 10u)
    {
        bcdhigh++;
        tmp = tmp - 10u;
    }

    return (uint8_t)(((uint32)bcdhigh << 4u) | tmp);
}

/*!
* @brief     Convert from 2 digit BCD to Binary
*
* @param     val: BCD value to be converted
*
* @retval    Converted word
*/
LOCAL_INLINE FUNC(uint8, RTC_CODE) Rtc_Hw_Bcd2ConByte(VAR(uint8, AUTOMATIC) val)
{
    VAR(uint8, AUTOMATIC) tmp = 0;
    tmp = (uint8_t)(((((uint32)val & (uint32)0xF0) >> (uint32)0x4)) * 10u);
    return (tmp + (val & (uint8_t)0x0F));
}

/**********************************************************************************************************************
                                            GLOBAL FUNCTIONS
***********************************************************************************************************************/

/*!
* @brief       Deinitializes the RTC registers to their default reset values
*
* @param       None
*
* @retval      TRUE or FALSE
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_Reset(void)
{
    VAR(uint8, AUTOMATIC) status = TRUE;
    Rtc_Hw_DisableWriteProtection();

    if (Rtc_Hw_EnableInit() == FALSE)
    {
        Rtc_Hw_EnableWriteProtection();
        status = FALSE;
    }
    else
    {
        REG_WRITE32(RTC_TIME_REG_ADDR, (uint32_t)0x00000000);
        REG_WRITE32(RTC_DATE_REG_ADDR, (uint32_t)0x00002101);
        REG_WRITE32(RTC_CTRL_REG_ADDR, (uint32_t)0x00000000);
        REG_WRITE32(RTC_PSC_REG_ADDR, (uint32_t)0x007F00FF);
        REG_WRITE32(RTC_ALRMA_REG_ADDR, (uint32_t)0x00000000);
        REG_WRITE32(RTC_SHIFT_REG_ADDR, (uint32_t)0x00000000);
        REG_WRITE32(RTC_CAL_REG_ADDR, (uint32_t)0x00000000);
        REG_WRITE32(RTC_ALRMASS_REG_ADDR, (uint32_t)0x00000000);
        REG_WRITE32(RTC_STS_REG_ADDR, (uint32_t)0x00000007);

        if (Rtc_Hw_WaitForSynchro() == FALSE)
        {
            Rtc_Hw_EnableWriteProtection();
            status = FALSE;
        }
        else
        {
            Rtc_Hw_EnableWriteProtection();
            status = TRUE;
        }
    }
    /* Soft reset the controller */
    Mcu_Rcm_OperationPeriphReset(ENABLE, RCM_RTC_PERIPH, RCM_RTCCTRL_RTC);
    Mcu_Rcm_OperationPeriphReset(DISABLE, RCM_RTC_PERIPH, RCM_RTCCTRL_RTC);
    
    return status;
}

/*!
* @brief       Deinitializes the RTC registers to their default reset values
*
* @param       Struct : pointer to a Rtc_TimeInitType structure which will be initialized
*
* @retval      TRUE or FALSE
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_Config(P2CONST(Rtc_TimeInitType, AUTOMATIC, RTC_APPL_CONST) Struct)
{
    VAR(uint8, AUTOMATIC) status = TRUE;
    VAR(uint32, AUTOMATIC) prediv = 0;
    Rtc_Hw_DisableWriteProtection();

    if (Rtc_Hw_EnableInit() == FALSE)
    {
        Rtc_Hw_EnableWriteProtection();
        status = FALSE;
    }
    else
    {
        prediv = (uint32)(Struct->SynchPrediv | (Struct->AsynchPrediv << 16));
        REG_RMW32(RTC_CTRL_REG_ADDR, RTC_CTRL_TIMEFCFG_MASK, Struct->format);
        REG_WRITE32(RTC_PSC_REG_ADDR,prediv);
        Rtc_Hw_DisableInit();
        Rtc_Hw_EnableWriteProtection();
        status = TRUE;
    }
    return status;
}

/*!
* @brief       Enable the write protection for RTC registers
*
* @param       None
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_EnableWriteProtection(void)
{
    REG_WRITE32(RTC_WRPROT_REG_ADDR, 0xFF);
}

/*!
* @brief       Disable the write protection for RTC registers
*
* @param       None
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_DisableWriteProtection(void)
{
    REG_WRITE32(RTC_WRPROT_REG_ADDR, 0xCA);
    REG_WRITE32(RTC_WRPROT_REG_ADDR, 0x53);
}

/*!
* @brief       Enable the RTC Initialization mode.
*
* @param       None
*
* @retval      TRUE or FALSE
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_EnableInit(void)
{
    VAR(uint8, AUTOMATIC) status = FALSE;
    volatile VAR(uint32, AUTOMATIC) cnt = 0x00;
    VAR(uint32, AUTOMATIC) initstatus = 0x00;

    if(RTC_STS_RINITFLG_MASK != REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RINITFLG_MASK))
    {
        REG_WRITE32(RTC_STS_REG_ADDR, (uint32_t)0xFFFFFFFFu);
        
        do
        {
            initstatus = REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RINITFLG_MASK);
            cnt = cnt + 1u;
        }
        while ((cnt != RTC_INITMODE_TIMEOUT) && (initstatus != RTC_STS_RINITFLG_MASK));

        if (RTC_STS_RINITFLG_MASK == REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RINITFLG_MASK))
        {
            status = TRUE;
        }
        else
        {
            status = FALSE;
        }
    }
    else
    {
        status = TRUE;
    }
    return status;
}

/*!
* @brief       Disable the RTC Initialization mode.
*
* @param       None
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_DisableInit(void)
{
    REG_RMW32(RTC_STS_REG_ADDR, RTC_STS_INITEN_MASK, (uint32)(FALSE << RTC_STS_INITEN_SHIFT));
}

/*!
* @brief       Waits until the RTC Time and Date registers (RTC_TIME and RTC_DATA) are
*              synchronized with RTC APB clock
* @param       None
*
* @retval      TRUE or FALSE
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_WaitForSynchro(void)
{
    volatile VAR(uint32, AUTOMATIC) cnt = 0x00;
    VAR(uint32, AUTOMATIC) synchrostatus = 0x00;
    VAR(uint8, AUTOMATIC) status = FALSE;
    if (RTC_CTRL_RCMCFG_MASK != REG_BIT_GET32(RTC_CTRL_REG_ADDR,RTC_CTRL_RCMCFG_MASK))
    {
        status = TRUE;
    }
    else
    {
        Rtc_Hw_DisableWriteProtection();
        REG_BIT_CLEAR32(RTC_STS_REG_ADDR,RTC_STS_RSFLG_MASK | RTC_STS_INITEN_MASK);
        do
        {
            synchrostatus = REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RSFLG_MASK);
            cnt = cnt + 1u;
        }
        while ((cnt != RTC_SYNCHRO_TIMEOUT) && (synchrostatus == 0x00u));

        if (RTC_STS_RSFLG_MASK == REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RSFLG_MASK))
        {
            Rtc_Hw_EnableWriteProtection();
            status = TRUE;
        }
        else
        {
            Rtc_Hw_EnableWriteProtection();
            status = FALSE;
        }
    }
    return status;
}

/*!
* @brief       Read Calendar Value Mode Configure: BypassShadow
*
* @param       None
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_EnableBypassShadow(void)
{
    Rtc_Hw_DisableWriteProtection();
    REG_BIT_CLEAR32(RTC_CTRL_REG_ADDR,RTC_CTRL_RCMCFG_MASK);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief       Read Calendar Value Mode Configure: directly
*
* @param       None
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_DisableBypassShadow(void)
{
    Rtc_Hw_DisableWriteProtection();
    REG_BIT_SET32(RTC_CTRL_REG_ADDR,RTC_CTRL_RCMCFG_MASK);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief       Config the RTC current time
*
* @param       format: specifies the format to write
*                      This parameter can be one of the following values:
*                      RTC_FORMAT_BIN: format in Bin
*                      RTC_FORMAT_BCD: format in BCD
*
* @param       timeStruct:  Pointer to a Rtc_TimeType structure that
*                          contains the configuration information for the RTC peripheral
*
* @retval      None
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_ConfigTime(VAR(Rtc_FormatType, AUTOMATIC) Format, P2VAR(Rtc_TimeType, AUTOMATIC, RTC_APPL_DATA) TimeStruct)
{
    VAR(uint8, AUTOMATIC) state = FALSE;
    VAR(uint32, AUTOMATIC) temp = 0;
    
    if (RTC_CTRL_TIMEFCFG_MASK != REG_BIT_GET32(RTC_CTRL_REG_ADDR,RTC_CTRL_TIMEFCFG_MASK))
    {
        TimeStruct->H12 = (uint8_t)RTC_H12_AM;
    }
    else
    {
        /* nothing */
    }

    if (Format != RTC_FORMAT_BIN)
    {
        temp = (((uint32_t)(TimeStruct->hours) << 16u) | \
                ((uint32_t)(TimeStruct->minutes) << 8u) | \
                ((uint32_t)(TimeStruct->seconds)) | \
                ((uint32_t)(TimeStruct->H12) << 22u));
    }
    else
    {
        temp = (((uint32_t)Rtc_Hw_ByteConBcd2(TimeStruct->hours) << 16u) | \
                ((uint32_t)Rtc_Hw_ByteConBcd2(TimeStruct->minutes) << 8u) | \
                ((uint32_t)Rtc_Hw_ByteConBcd2(TimeStruct->seconds)) | \
                ((uint32_t)(TimeStruct->H12) << 22u));
    }

    Rtc_Hw_DisableWriteProtection();

    if (Rtc_Hw_EnableInit() == FALSE)
    {
        state = FALSE;
    }
    else
    {
        REG_WRITE32(RTC_TIME_REG_ADDR, (uint32_t)(temp & 0x007F7F7Fu));
        Rtc_Hw_DisableInit();

        if (RTC_CTRL_RCMCFG_MASK != REG_BIT_GET32(RTC_CTRL_REG_ADDR,RTC_CTRL_RCMCFG_MASK))
        {
            if (Rtc_Hw_WaitForSynchro() == FALSE)
            {
                state = FALSE;
            }
            else
            {
                state = TRUE;
            }
        }
        else
        {
            state = TRUE;
        }
    }

    Rtc_Hw_EnableWriteProtection();
    return state;
}

/*!
* @brief       Read the RTC current Time
*
* @param       format: specifies the format to write
*                      This parameter can be one of the following values:
*                      RTC_FORMAT_BIN: format in Bin
*                      RTC_FORMAT_BCD: format in BCD
*
* @param       timeStruct:  Pointer to a Rtc_TimeType structure that
*                           contains the configuration information for the RTC peripheral
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ReadTime(VAR(Rtc_FormatType, AUTOMATIC) Format, P2VAR(Rtc_TimeType, AUTOMATIC, RTC_APPL_DATA) TimeStruct)
{
    VAR(uint32, AUTOMATIC) temp = 0;
    temp = (uint32_t)((REG_READ32(RTC_TIME_REG_ADDR)) & 0x007F7F7Fu);

    TimeStruct->hours   = (uint8_t)((temp & 0x003F0000u) >> 16u);
    TimeStruct->minutes = (uint8_t)((temp & 0x00007F00u) >> 8u);
    TimeStruct->seconds = (uint8_t)(temp &  0x0000007Fu);
    TimeStruct->H12 = (uint8_t)((temp & 0x00400000u) >> 22u);

    if (Format == RTC_FORMAT_BIN)
    {
        TimeStruct->hours   = (uint8_t)Rtc_Hw_Bcd2ConByte(TimeStruct->hours);
        TimeStruct->minutes = (uint8_t)Rtc_Hw_Bcd2ConByte(TimeStruct->minutes);
        TimeStruct->seconds = (uint8_t)Rtc_Hw_Bcd2ConByte(TimeStruct->seconds);
    }
    else
    {
        /* nothing */
    }
}

/*!
* @brief       Read the RTC current Calendar Subseconds value
*
* @param       None
*
* @retval      RTC current Calendar Subseconds value
*/
FUNC(uint32, RTC_CODE) Rtc_Hw_ReadSubSecond(void)
{
    VAR(uint32, AUTOMATIC) temp = 0;
    temp = (uint32_t)(REG_READ32(RTC_SUBSEC_REG_ADDR));
    (void)(REG_READ32(RTC_DATE_REG_ADDR));
    return (temp);
}

/*!
* @brief       Config the RTC current time
*
* @param       format: specifies the format to write
*                      This parameter can be one of the following values:
*                      RTC_FORMAT_BIN: format in Bin
*                      RTC_FORMAT_BCD: format in BCD
*
* @param       dateStruct:  Pointer to a Rtc_DateType structure that
*                           contains the configuration DATE information for the RTC peripheral
*
* @retval      None
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_ConfigDate(VAR(Rtc_FormatType, AUTOMATIC) Format, P2CONST(Rtc_DateType, AUTOMATIC, RTC_APPL_CONST) DateStruct)
{
    VAR(uint8, AUTOMATIC) state = FALSE;
    VAR(uint32, AUTOMATIC) temp = 0;

    if (Format != RTC_FORMAT_BIN)
    {
        temp = (((uint32_t)(DateStruct->year) << 16) | \
                ((uint32_t)(DateStruct->month) << 8) | \
                ((uint32_t)(DateStruct->date)) | \
                ((uint32_t)(DateStruct->weekday) << 13));
    }
    else
    {
        temp = (((uint32_t)Rtc_Hw_ByteConBcd2(DateStruct->year) << 16) | \
                ((uint32_t)Rtc_Hw_ByteConBcd2(DateStruct->month) << 8) | \
                ((uint32_t)Rtc_Hw_ByteConBcd2(DateStruct->date)) | \
                ((uint32_t)(DateStruct->weekday) << 13));

    }

    Rtc_Hw_DisableWriteProtection();

    if (Rtc_Hw_EnableInit() == FALSE)
    {
        state = FALSE;
    }
    else
    {
        REG_WRITE32(RTC_DATE_REG_ADDR,(uint32_t)(temp & 0x00FFFF3Fu));
        Rtc_Hw_DisableInit();

        if (RTC_CTRL_RCMCFG_MASK != REG_BIT_GET32(RTC_CTRL_REG_ADDR,RTC_CTRL_RCMCFG_MASK))
        {
            if (Rtc_Hw_WaitForSynchro() == FALSE)
            {
                state = FALSE;
            }
            else
            {
                state = TRUE;
            }
        }
        else
        {
            state = TRUE;
        }
    }

    Rtc_Hw_EnableWriteProtection();
    return state;
}

/*!
* @brief       Fills each dateStruct member with its default value
*
* @param       dateStruct:  Pointer to a Rtc_DateType structure that
*                           contains the configuration DATE information for the RTC peripheral
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ConfigDateStructInit(P2VAR(Rtc_DateType, AUTOMATIC, RTC_APPL_DATA) DateStruct)
{
    DateStruct->weekday = RTC_WEEKDAY_MONDAY;
    DateStruct->month = RTC_MONTH_JANUARY;
    DateStruct->date = 1;
    DateStruct->year = 0;
}

/*!
* @brief       the RTC current date
*
* @param       format: specifies the format to write
*                      This parameter can be one of the following values:
*                      RTC_FORMAT_BIN: format in Bin
*                      RTC_FORMAT_BCD: format in BCD
*
* @param       dateStruct:  Pointer to a Rtc_DateType structure that
*                           contains the configuration DATE information for the RTC peripheral
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ReadDate(VAR(Rtc_FormatType, AUTOMATIC) Format, P2VAR(Rtc_DateType, AUTOMATIC, RTC_APPL_DATA) DateStruct)
{
    VAR(uint32, AUTOMATIC) temp = 0;
    temp = (uint32_t)((REG_READ32(RTC_DATE_REG_ADDR)) & 0x00FFFF3Fu);

    DateStruct->year  = (uint8_t)((temp & 0x00FF0000u) >> 16u);
    DateStruct->month = (uint8_t)((temp & 0x00001F00u) >> 8u);
    DateStruct->date  = (uint8_t)(temp &  0x0000003Fu);
    DateStruct->weekday = (uint8_t)((temp & 0x0000E000u) >> 13u);

    if (Format == RTC_FORMAT_BIN)
    {
        DateStruct->year  = (uint8_t)Rtc_Hw_Bcd2ConByte(DateStruct->year);
        DateStruct->month = (uint8_t)Rtc_Hw_Bcd2ConByte(DateStruct->month);
        DateStruct->date  = (uint8_t)Rtc_Hw_Bcd2ConByte(DateStruct->date);
        DateStruct->weekday = (uint8_t)(DateStruct->weekday);
    }
    else
    {
        /* nothing */
    }
}

/*!
* @brief       Config the specified RTC ALRMA
*
* @param       format: specifies the format to write
*                      This parameter can be one of the following values:
*                      RTC_FORMAT_BIN: format in Bin
*                      RTC_FORMAT_BCD: format in BCD
*
* @param       AlarmStruct: Pointer to a Rtc_AlarmType structure that
*                           contains the configuration ALRMA information for the RTC peripheral
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ConfigAlarm(VAR(Rtc_FormatType, AUTOMATIC) Format, P2VAR(Rtc_AlarmType, AUTOMATIC, RTC_APPL_DATA) AlarmStruct)
{
    VAR(uint32, AUTOMATIC) regValue = 0U;
    VAR(uint8, AUTOMATIC) hour = 0U;
    VAR(uint8, AUTOMATIC) minute = 0U;
    VAR(uint8, AUTOMATIC) second = 0U;
    VAR(uint8, AUTOMATIC) date;
    
    
    if (RTC_CTRL_TIMEFCFG_MASK != REG_BIT_GET32(RTC_CTRL_REG_ADDR,RTC_CTRL_TIMEFCFG_MASK))
    {
        AlarmStruct->time.H12 = 0x00U;
    }
    else
    {
        /* nothing */
    }
    
    if (Format == RTC_FORMAT_BIN)
    {
        hour = Rtc_Hw_ByteConBcd2(AlarmStruct->time.hours);
        minute = Rtc_Hw_ByteConBcd2(AlarmStruct->time.minutes);
        second = Rtc_Hw_ByteConBcd2(AlarmStruct->time.seconds);
        date = Rtc_Hw_ByteConBcd2(AlarmStruct->AlarmDateWeekDay);
    }
    else
    {
        hour = AlarmStruct->time.hours;
        minute = AlarmStruct->time.minutes;
        second = AlarmStruct->time.seconds;
        date = AlarmStruct->AlarmDateWeekDay;
    }
    
    regValue = ((uint32)date                         << 24U) |
               ((uint32)AlarmStruct->AlarmDateWeekDaySel << 30U) |
               ((uint32)AlarmStruct->time.H12        << 22U) |
               ((uint32)hour                         << 16U) |
               ((uint32)minute                       << 8U)  |
               ((uint32)second)                             |
               ((uint32)AlarmStruct->AlarmMask);

    Rtc_Hw_DisableWriteProtection();
    REG_WRITE32(RTC_ALRMA_REG_ADDR,regValue);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief       Get the RTC ALRMA value and masks
*
* @param       format: specifies the format to write
*                      This parameter can be one of the following values:
*                      RTC_FORMAT_BIN: format in Bin
*                      RTC_FORMAT_BCD: format in BCD
*
* @param       AlarmStruct: Pointer to a Rtc_AlarmType structure that
*                           contains the configuration ALRMA information for the RTC peripheral
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ReadAlarm(VAR(Rtc_FormatType, AUTOMATIC) Format, P2VAR(Rtc_AlarmType, AUTOMATIC, RTC_APPL_DATA) AlarmStruct)
{
    VAR(uint8, AUTOMATIC) dayTens = 0u; 
    VAR(uint8, AUTOMATIC) dayUnits = 0u; 
    VAR(uint8, AUTOMATIC) hoursTens = 0u; 
    VAR(uint8, AUTOMATIC) hoursUnits = 0u; 
    VAR(uint8, AUTOMATIC) minutesTens = 0u; 
    VAR(uint8, AUTOMATIC) minutesUnits = 0u; 
    VAR(uint8, AUTOMATIC) secondsTens = 0u; 
    VAR(uint8, AUTOMATIC) secondsUnits = 0u;
    VAR(uint32, AUTOMATIC) dayMask = 0u;
    VAR(uint32, AUTOMATIC) hoursMask = 0u; 
    VAR(uint32, AUTOMATIC) minutesMask = 0u; 
    VAR(uint32, AUTOMATIC) secondsMask = 0u;
    VAR(uint32, AUTOMATIC) weekSel = 0u;

    dayTens = (uint8)((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_DAYT_MASK) >> RTC_ALRMA_DAYT_SHIFT) << 0x04u);
    dayUnits = (uint8)((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_DAYU_MASK) >> RTC_ALRMA_DAYU_SHIFT));
    
    hoursTens = (uint8)((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_HRT_MASK) >> RTC_ALRMA_HRT_SHIFT) << 0x04u);
    hoursUnits = (uint8)((uint32)REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_HRU_MASK) >> RTC_ALRMA_HRU_SHIFT);
    
    minutesTens = (uint8)((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_MINT_MASK) >> RTC_ALRMA_MINT_SHIFT) << 0x04u);
    minutesUnits = (uint8)((uint32)REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_MINU_MASK) >> RTC_ALRMA_MINU_SHIFT);
    
    secondsTens = (uint8)((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_SECT_MASK) >> RTC_ALRMA_SECT_SHIFT) << 0x04u);
    secondsUnits = (uint8)((uint32)REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_SECU_MASK) >> RTC_ALRMA_SECU_SHIFT);

    dayMask = ((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_DAYEMEN_MASK) >> RTC_ALRMA_DAYEMEN_SHIFT) << 8u);
    hoursMask = ((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_HRMEN_MASK) >> RTC_ALRMA_HRMEN_SHIFT) << 8u);
    minutesMask = ((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_MINMEN_MASK) >> RTC_ALRMA_MINMEN_SHIFT) << 8u);
    secondsMask = ((uint32)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_SECMEN_MASK) >> RTC_ALRMA_SECMEN_SHIFT) << 7u);

    AlarmStruct->time.hours   = (uint8_t)(hoursTens | hoursUnits);
    AlarmStruct->time.minutes = (uint8_t)(minutesTens | minutesUnits);
    AlarmStruct->time.seconds = (uint8_t)(secondsTens | secondsUnits);
    AlarmStruct->time.H12     = (uint8_t)(REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_TIMEFCFG_MASK) >> RTC_ALRMA_TIMEFCFG_SHIFT);
    AlarmStruct->AlarmDateWeekDay = (uint8_t)(dayTens | dayUnits);
    
    weekSel = REG_BIT_GET32(RTC_ALRMA_REG_ADDR,RTC_ALRMA_WEEKSEL_MASK) >> (uint32)RTC_ALRMA_WEEKSEL_SHIFT;
    switch(weekSel)
    {
        case 0u:
            AlarmStruct->AlarmDateWeekDaySel = RTC_WEEKDAY_SEL_DATE;
            break;
        case 1u:
            AlarmStruct->AlarmDateWeekDaySel = RTC_WEEKDAY_SEL_WEEKDAY;
            break;
        default:
            /* nothing */
            break;
    }
    AlarmStruct->AlarmMask = (uint32_t)(dayMask | hoursMask | minutesMask | secondsMask);

    if (Format == RTC_FORMAT_BIN)
    {
        AlarmStruct->time.hours = (uint8_t)Rtc_Hw_Bcd2ConByte(AlarmStruct->time.hours);
        AlarmStruct->time.minutes = (uint8_t)Rtc_Hw_Bcd2ConByte(AlarmStruct->time.minutes);
        AlarmStruct->time.seconds = (uint8_t)Rtc_Hw_Bcd2ConByte(AlarmStruct->time.seconds);
        AlarmStruct->AlarmDateWeekDay = (uint8_t)Rtc_Hw_Bcd2ConByte(AlarmStruct->AlarmDateWeekDay);
    }
    else
    {
        /* nothing */
    }
}

/*!
* @brief       Enable the RTC ALRMA.
*
* @param       None
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_EnableAlarm(void)
{
    Rtc_Hw_DisableWriteProtection();
    REG_BIT_SET32(RTC_CTRL_REG_ADDR, RTC_CTRL_ALREN_MASK);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief       Disable the the RTC ALRMA.
*
* @param       None
*
* @retval      None
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_DisableAlarm(void)
{
    volatile VAR(uint32, AUTOMATIC) count = 0x00;
    VAR(uint8, AUTOMATIC) status = FALSE;
    Rtc_Hw_DisableWriteProtection();
    REG_BIT_CLEAR32(RTC_CTRL_REG_ADDR,RTC_CTRL_ALREN_MASK);
    
    while ((count != RTC_INITMODE_TIMEOUT) && ((RTC_STS_ALRWFLG_MASK != REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_ALRWFLG_MASK))))
    {
        count = count + 1u;
    }

    if ((RTC_STS_ALRWFLG_MASK != REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_ALRWFLG_MASK)))
    {
        Rtc_Hw_EnableWriteProtection();
        status = FALSE;
    }
    else
    {
        Rtc_Hw_EnableWriteProtection();
        status = TRUE;
    }
    return status;
}

/*!
* @brief       Read the RTC ALRMA Subseconds value
*
* @param       val: specifies the value for ALRMA Sub Second
*                   this value must less than 0x00007FFF
*
* @param       mask: specifies the mask for ALRMA Sub Second
*                   this value must less than 0x0f
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ConfigAlarmSubSecond(VAR(uint32, AUTOMATIC) Val, VAR(uint8, AUTOMATIC) Mask)
{
    Rtc_Hw_DisableWriteProtection();
    REG_RMW32(RTC_ALRMASS_REG_ADDR, RTC_ALRMASS_SUBSEC_MASK, Val);
    REG_RMW32(RTC_ALRMASS_REG_ADDR, RTC_ALRMASS_MASKSEL_MASK, ((uint32)Mask) << RTC_ALRMASS_MASKSEL_SHIFT);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief       Read the RTC ALRMA Subseconds value
*
* @param       None
*
* @retval      RTC ALRMA Subseconds value
*/
FUNC(uint32, RTC_CODE) Rtc_Hw_ReadAlarmSubSecond(void)
{
    return (uint32_t)(REG_BIT_GET32(RTC_ALRMASS_REG_ADDR,RTC_ALRMASS_SUBSEC_MASK));
}

/*!
* @brief       Adds or substract one hour from the current time
*
* @param       sav:   specifies the DayLightSaving
*                     This parameter can be one of the following values:
*                     RTC_DLS_SUB1H
*                     RTC_DLS_ADD1H
*
* @param       bit:   specifies the DayLightSaving
*                     This parameter can be one of the following values:
*                     RTC_SO_RESET
*                     RTC_SO_SET
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_ConfigDayLightSaving(VAR(Rtc_DayLightSavingType, AUTOMATIC) Sav, VAR(Rtc_StoreOperationType, AUTOMATIC) Bit)
{
    Rtc_Hw_DisableWriteProtection();

    if (Sav == RTC_DLS_ADD1H)
    {
        REG_BIT_SET32(RTC_CTRL_REG_ADDR,RTC_CTRL_STCCFG_MASK);
        REG_BIT_CLEAR32(RTC_CTRL_REG_ADDR,RTC_CTRL_WTCCFG_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(RTC_CTRL_REG_ADDR,RTC_CTRL_STCCFG_MASK);
        REG_BIT_SET32(RTC_CTRL_REG_ADDR,RTC_CTRL_WTCCFG_MASK);
    }

    REG_RMW32(RTC_CTRL_REG_ADDR, RTC_CTRL_BAKE_MASK, Bit);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief       Returns the RTC Day Light Saving stored operation
*
* @param       None
*
* @retval      RTC Day Light Saving stored operation
*/
FUNC(uint32, RTC_CODE) Rtc_Hw_ReadStoreOperation(void)
{
    return REG_BIT_GET32(RTC_CTRL_REG_ADDR,RTC_CTRL_BAKE_MASK) << RTC_CTRL_BAKE_SHIFT;
}


/*!
* @brief       Configures the Synchronization Shift Control Settings.
*
* @param       period: Select the Smooth Calibration period.
*                      This parameter can be can be one of the following values:
*                      RTC_SCP_16SEC: The smooth calibration periode is 16.
*                      RTC_SCP_8SEC:  The smooth calibartion periode is 8s.
*
* @param       bit:    Select to Set or reset the CALP bit.
*                      This parameter can be one of the following values:
*                      RTC_SCPP_RESET: Add one RTCCLK puls every 2**11 pulses.
*                      RTC_SCPP_SET:   No RTCCLK pulses are added.
*
* @param       value:  Select the value of CALM[8:0] bits.
*                      This parameter can be one any value from 0 to 0x000001FF.
*
* @retval         TRUE or FALSE
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_ConfigSmoothCalib(VAR(Rtc_ScpType, AUTOMATIC) Period, VAR(Rtc_ScppType, AUTOMATIC) Bit, VAR(uint32, AUTOMATIC) Value)
{
    VAR(uint8, AUTOMATIC) state = FALSE;
    VAR(uint32, AUTOMATIC) count = 0;

    Rtc_Hw_DisableWriteProtection();

    if ((RTC_STS_RCALPFLG_MASK != REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RCALPFLG_MASK)))
    {
        while (((RTC_STS_RCALPFLG_MASK == REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RCALPFLG_MASK))) && (count != RTC_RECALPF_TIMEOUT))
        {
            count++;
        }
    }
    else
    {
        /* nothing */
    }
    if ((RTC_STS_RCALPFLG_MASK != REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_RCALPFLG_MASK)))
    {
        if (Period == RTC_SCP_16SEC)
        {
            REG_WRITE32(RTC_CAL_REG_ADDR,((((uint32_t)Bit << 15u) | ((uint32_t)TRUE << 13u)) | ((uint32_t)Value)));
        }
        else
        {
            REG_WRITE32(RTC_CAL_REG_ADDR,((((uint32_t)Bit << 15u) | ((uint32_t)TRUE << 14u)) | ((uint32_t)Value)));
        }

        state = TRUE;
    }
    else
    {
        state = FALSE;
    }

    Rtc_Hw_EnableWriteProtection();
    return (state);
}

/*!
* @brief       Configures the Synchronization Shift Control Settings.
*
* @param       add1S:  Select to add or not 1 second to the time Calendar.
*                      This parameter can be one of the following values :
*                      RTC_SHIFTADD1S_SET: Add one second to the clock calendar.
*                      RTC_SHIFTADD1S_RESET:   No effect.
*
* @param       subFS:  Select the number of Second Fractions to Substitute.
*                      This parameter can be one any value from 0 to 0x7FFF.
*
* @retval      TRUE or FALSE
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_ConfigSynchroShift(VAR(Rtc_ShiftAdd1sType, AUTOMATIC) Add1S, VAR(uint32, AUTOMATIC) SubFS)
{
    VAR(uint8, AUTOMATIC) state = FALSE;
    VAR(uint32, AUTOMATIC) shpfcount = 0;
    Rtc_Hw_DisableWriteProtection();

    if ((RTC_STS_SOPFLG_MASK == REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_SOPFLG_MASK)))
    {
        while (((RTC_STS_SOPFLG_MASK == REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_SOPFLG_MASK))) && (shpfcount != RTC_SHPF_TIMEOUT))
        {
            shpfcount++;
        }
    }
    else
    {
        /* nothing */
    }
    if ((RTC_STS_SOPFLG_MASK != REG_BIT_GET32(RTC_STS_REG_ADDR,RTC_STS_SOPFLG_MASK)))
    {
        REG_RMW32(RTC_SHIFT_REG_ADDR, RTC_SHIFT_ADD1SECEN_MASK, Add1S);
        REG_RMW32(RTC_SHIFT_REG_ADDR, RTC_SHIFT_SFSEC_MASK, SubFS);
        if (Rtc_Hw_WaitForSynchro() == FALSE)
        {
            state = FALSE;
        }
        else
        {
            state = TRUE;
        }
    }
    else
    {
        state = FALSE;
    }

    Rtc_Hw_EnableWriteProtection();
    return (state);
}

/*!
* @brief       Enable RTC interrupts.
*
* @param       interrupt: specifies the RTC interrupt sources to be enabled
*                       This parameter can be any combination of the following values:
*                       RTC_INT_ALR:  ALRMA A interrupt mask
*                       RTC_INT_WT:  WakeUp Timer interrupt mas
*
* @retval      None
*/
FUNC(void, RTC_CODE) Rtc_Hw_EnableInterrupt(VAR(uint32, AUTOMATIC) Interrupt)
{
    Rtc_Hw_DisableWriteProtection();
    REG_BIT_SET32(RTC_CTRL_REG_ADDR,Interrupt);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief     Disable RTC interrupts.
*
* @param     interrupt: specifies the RTC interrupt sources to be disable
*                       This parameter can be any combination of the following values:
*                       RTC_INT_ALR:  ALRMA A interrupt mask
*                       RTC_INT_WT:   WakeUp Timer interrupt mask
*
* @retval    None
*/
FUNC(void, RTC_CODE) Rtc_Hw_DisableInterrupt(VAR(uint32, AUTOMATIC) Interrupt)
{
    Rtc_Hw_DisableWriteProtection();
    REG_BIT_CLEAR32(RTC_CTRL_REG_ADDR,Interrupt);
    Rtc_Hw_EnableWriteProtection();
}

/*!
* @brief     Read interrupt flag bit is set
*
* @param     flag: specifies the flag to read.
*                  This parameter can be one of the following values:
*                  RTC_INT_FLAG_ALR: ALRMA interrupt
*                  RTC_INT_FLAG_WT: WakeUp Timer interrupt
* @retval    The new state of flag (TRUE or FALSE).
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_ReadIntFlag(VAR(Rtc_IntFlagType, AUTOMATIC) Flag)
{
    VAR(uint32, AUTOMATIC) intEnable;
    VAR(uint32, AUTOMATIC) intStatus;
    VAR(uint8, AUTOMATIC) status = FALSE;
    
    intEnable = REG_READ32(RTC_CTRL_REG_ADDR);
    intStatus = (uint32_t)(REG_READ32(RTC_STS_REG_ADDR) & ((uint32)Flag >> 4u));

    if ((intEnable != 0u) && (intStatus != 0u))
    {
        status = TRUE;
    }
    else
    {
        /* nothing */
    }
    return status;
}

/*!
* @brief     Checks whether the specified RTC flag is set or not.
*
* @param     flag: specifies the flag to check.
*                  This parameter can be one of the following values:
*                  RTC_FLAG_AWF:  Alarm Write Flag 
*                  RTC_FLAG_SOPF:  Shift Operation Pending Flag 
*                  RTC_FLAG_ISF:  Initialization State Flag 
*                  RTC_FLAG_RSF:  Registers Synchronization Flag 
*                  RTC_FLAG_INTF:  Register Initialization Flag 
*                  RTC_FLAG_ALRF:   Alarm Match Flag 
*                  RTC_FLAG_RPF:  Recalibration Pending Flag 
* @retval    The new state of RTC_FLAG (TRUE or FALSE).
*/
FUNC(uint8, RTC_CODE) Rtc_Hw_ReadStatusFlag(VAR(Rtc_FlagType, AUTOMATIC) Flag)
{
    VAR(uint8, AUTOMATIC) status = FALSE;
    if(FALSE != (REG_READ32(RTC_STS_REG_ADDR) & (uint32)Flag))
    {
        status = TRUE;
    }
    else
    {
        /* nothing */
    }
    return status;
}

/*!
* @brief     Clears the RTC's status flags.
* @param     flag: specifies the RTC flag to clear.
*                  This parameter can be any combination of the following values:
*                  RTC_FLAG_AWF:  Alarm Write Flag 
*                  RTC_FLAG_SOPF:  Shift Operation Pending Flag 
*                  RTC_FLAG_ISF:  Initialization State Flag 
*                  RTC_FLAG_RSF:  Registers Synchronization Flag 
*                  RTC_FLAG_INTF:  Register Initialization Flag 
*                  RTC_FLAG_ALRF:   Alarm Match Flag 
*                  RTC_FLAG_RPF:  Recalibration Pending Flag 
*/
FUNC(void, RTC_CODE) Rtc_Hw_ClearStatusFlag(VAR(uint32, AUTOMATIC) flag)
{
    REG_BIT_CLEAR32(RTC_STS_REG_ADDR,flag);
}

/**@} end of group RTC_Fuctions */
#ifdef __cplusplus
}
#endif
/**@} end of group RTC_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
