/*!
* @file     Gpt.c
*
* @version  1.0.0
*
* @brief    AUTOSAR Gpt Driver implementations
*
* @attention
*
* Project Name      : AUTOSAR MCAL 
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_01-Otc-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  /* ifdef __cplusplus */

#include "Gpt_Hw.h"
#include "Gpt.h"
#include "EcuM_Cbk.h"

#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
#include "Det.h"
#endif

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup GPT_Driver
  * @brief GPT driver modules
  @{
*/

/** @defgroup GPT_Macros
  @{
*/
/*******************************************************************************
                        VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define GPT_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define GPT_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define GPT_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define GPT_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define GPT_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define GPT_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define GPT_SW_PATCH_VERSION                       0x00U

/**@} end of group GPT_Macros */
/*******************************************************************************
                              GLOBAL VARIABLE
*******************************************************************************/
/** @defgroup GPT_Variable
  @{
*/

#define GPT_START_SEC_VAR_INIT_UNSPECIFIED
#include "Gpt_MemMap.h"

/** point to GPT driver coniguration data. */
P2CONST(Gpt_ConfigType, GPT_VAR, GPT_APPL_CONST) gs_gptConfigPtr = NULL_PTR;

static VAR(Gpt_TimerHwIdType, GPT_VAR) gs_NowHwId = GPT_TMR_RETAIN;

static VAR(Gpt_TimerHwChannelIdType, GPT_VAR) gs_NowHwChannelId = TMR_CHANNEL_RETAIN;

#define GPT_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "GPT_MemMap.h"

#define GPT_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Gpt_MemMap.h"

/** the array stored the time count value when it's stop of all logic channel. */
static volatile VAR(Gpt_ValueType, GPT_VAR) gs_gptStopTime[GPT_CHANNEL_IDX_NUM];

static VAR(Gpt_ChannelCCValueType,GPT_VAR) gs_GptHwCCValue[9];

/** the array stored runtime infomation of all logic channel. */
VAR(Gpt_ChannelInfoType, GPT_VAR) gs_gptChannelInfo[GPT_CHANNEL_IDX_NUM];

VAR(Gpt_RuntimeStateType,GPT_VAR) gs_GptRuntimeState;

/**@} end of group GPT_Variable */

#define GPT_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Gpt_MemMap.h"
/*******************************************************************************
                              LOCAL FUNCTIONS
*******************************************************************************/
#define GPT_START_SEC_CODE
#include "Gpt_MemMap.h"

/** @defgroup GPT_Fuctions
  @{
*/

/*!
* @brief       Configure the maximum auto-reload value
*
* @param       hwUnitId     Target timer hardware ID
*
* @retval      none
*/
static FUNC(void, GPT_CODE) Gpt_ConfigMaxAutorldValue(Gpt_TimerHwIdType hwUnitId)
{
    uint32 temp = 0;
    uint32 maxVal = 0;
    
    maxVal = gs_GptHwCCValue[hwUnitId].channelCCValue[1];
    
    if (hwUnitId <= GPT_TMR4)
    {
        for (temp = 2; temp < (uint32)6; temp++)
        {
            if (gs_GptHwCCValue[(uint8)hwUnitId].channelCCValue[temp] > maxVal)
            {
                maxVal = gs_GptHwCCValue[hwUnitId].channelCCValue[temp];
            }
            else
            {
                /* nothing */
            }
        }
    }
    else
    {
        /* nothing */
    }
    Gpt_Hw_ConfigAutoReloadValue(hwUnitId,maxVal - 1u);
}


/*!
* @brief       Get the current hardware and hardware channel number
*
* @param       Channel            gpt channel id
* @param       nowHwId            Current hardware ID number
* @param       nowHwChannelId     Current hardware channel number
*
* @retval      Std_ReturnType     E_NOT_OK or E_OK
*/
static FUNC(Std_ReturnType, GPT_CODE) Gpt_GetNowHwAndChannelId(VAR(Gpt_ChannelType, AUTOMATIC) Channel, 
                                                               Gpt_TimerHwIdType * nowHwId, 
                                                               Gpt_TimerHwChannelIdType * nowHwChannelId)
{
    Std_ReturnType tempVal = E_OK;

    uint8 tempHwId = (uint8)g_gptConfg.ChannelConfig[Channel].HwChannel >> 4;
    uint8 tempHwChannelId = (uint8)g_gptConfg.ChannelConfig[Channel].HwChannel & (uint8)0xf;

    if ((tempHwId > (uint8)8) || (tempHwChannelId > (uint8)4))
    {
        tempVal = E_NOT_OK;
    }
    else
    {
        switch (tempHwId)
        {
            case 1: *nowHwId = GPT_TMR1; break;
            case 2: *nowHwId = GPT_TMR2; break;
            case 3: *nowHwId = GPT_TMR3; break;
            case 4: *nowHwId = GPT_TMR4; break;
            case 6: *nowHwId = GPT_TMR6; break;
            case 7: *nowHwId = GPT_TMR7; break;
            case 8: *nowHwId = GPT_TMR8; break;
            default: /* nothing */ break;
        }
        switch (tempHwChannelId)
        {
            case 1: *nowHwChannelId = TMR_CHANNEL_1; break;
            case 2: *nowHwChannelId = TMR_CHANNEL_2; break;
            case 3: *nowHwChannelId = TMR_CHANNEL_3; break;
            case 4: *nowHwChannelId = TMR_CHANNEL_4; break;
            default: /* nothing */ break;
        }

    }
    return tempVal;
}

/*******************************************************************************
                              GLOBAL FUNCTION
*******************************************************************************/

/*!
* @brief        Initializes the GPT driver.
*
* @param[in]    ConfigPtr      Pointer to a selected configuration structure.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_Init(P2CONST(Gpt_ConfigType, AUTOMATIC, GPT_APPL_CONST) ConfigPtr)
{
    Gpt_ChannelType ch = 0;
    Gpt_ChannelType chNum = 0;
    uint8 tempHwId = 0;
    uint8 tempHwChannelId = 0;

#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR != gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_INIT_SRVID, GPT_E_ALREADY_INITIALIZED);
    }
    else if (NULL_PTR == ConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_INIT_SRVID, GPT_E_INIT_FAILED);
    }
    else
    {
#endif
        gs_gptConfigPtr = ConfigPtr;
        
        gs_GptRuntimeState.ModuleState = GPT_MODE_NORMAL;
        
        for (ch = 0; ch < GPT_HW_TIMER_NUM; ch++)
        {
            Gpt_Hw_ConfigFreqDivw(gs_gptConfigPtr->gptTmrConfigPtr[ch].HardwareUnitId,
                                 gs_gptConfigPtr->gptTmrConfigPtr[ch].ChannelPrescaler);
            Gpt_Hw_UpdataEventGenerate(gs_gptConfigPtr->gptTmrConfigPtr[ch].HardwareUnitId,ENABLE);
            
            if (gs_gptConfigPtr->gptTmrConfigPtr[ch].ChannelMode == GPT_COUNT_MODE_ONESHOT)
            {
                Gpt_Hw_OperationSinglePulseMode(gs_gptConfigPtr->gptTmrConfigPtr[ch].HardwareUnitId,ENABLE);
            }
            else
            {
                Gpt_Hw_OperationAutoreloadPre(gs_gptConfigPtr->gptTmrConfigPtr[ch].HardwareUnitId,DISABLE);
                Gpt_Hw_ConfigAutoReloadValue(gs_gptConfigPtr->gptTmrConfigPtr[ch].HardwareUnitId,0);
            }
        }
        
        for (chNum = 0; chNum < gs_gptConfigPtr->Gpt_ChannelCount; chNum++)
        {
            gs_GptRuntimeState.ChannelState[gs_gptConfigPtr->ChannelConfig[chNum].ChannelId] = GPT_CHANNELSTATUS_INITIALIZED;
            gs_GptRuntimeState.MaxValueState[gs_gptConfigPtr->ChannelConfig[chNum].ChannelId] = gs_gptConfigPtr->ChannelConfig[chNum].ChannelValueMax;
            gs_GptRuntimeState.WakeupState[gs_gptConfigPtr->ChannelConfig[chNum].ChannelId] = gs_gptConfigPtr->ChannelConfig[chNum].EnableWakeup;
#if(STD_ON == GPT_ENABLE_DISABLE_NOTIFICATION_API_ENABLE)
            if (gs_gptConfigPtr->ChannelConfig[chNum].Notification != NULL_PTR)
            {
                gs_GptRuntimeState.IsrState[gs_gptConfigPtr->ChannelConfig[chNum].ChannelId] = TRUE;
            }
            else
            {
                gs_GptRuntimeState.IsrState[gs_gptConfigPtr->ChannelConfig[chNum].ChannelId] = FALSE;
            }
#endif
            tempHwId = (uint8)gs_gptConfigPtr->ChannelConfig[chNum].HwChannel >> 4;
            tempHwChannelId = (uint8)gs_gptConfigPtr->ChannelConfig[chNum].HwChannel & (uint8)0xf;

            Gpt_Hw_OperationCompareChannel(tempHwId,tempHwChannelId);
        }
        
        for (ch = 0; ch < GPT_HW_TIMER_NUM; ch++)
        {
            if (gs_gptConfigPtr->gptTmrConfigPtr[ch].ChannelMode == GPT_COUNT_MODE_ONESHOT)
            {
                Gpt_Hw_OperationSinglePulseMode(gs_gptConfigPtr->gptTmrConfigPtr[ch].HardwareUnitId,ENABLE);
            } 
            else
            {
                /* nothing */
            }
        }
        
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    }
#endif
}


/*!
* @brief        Starts a timer channel.
*
* @param[in]    Channel Numeric identifier of the GPT channel
* @param[in]    Value   Target time in number of ticks.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_StartTimer(VAR(Gpt_ChannelType, AUTOMATIC) Channel, VAR(Gpt_ValueType, AUTOMATIC) Value)
{
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_STARTTIMER_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_STARTTIMER_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            if (GPT_CHANNELSTATUS_RUNNING == gs_GptRuntimeState.ChannelState[Channel])
            {
                /* Report error: null pointer */
                (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                                GPT_STARTTIMER_SRVID, GPT_E_BUSY);
            }
            else if (((Gpt_ValueType)0 == Value) || (Value > gs_GptRuntimeState.MaxValueState[Channel]))
            {
                /* Report error: null pointer */
                (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                                GPT_STARTTIMER_SRVID, GPT_E_PARAM_VALUE);
            }
            else
            {
#endif
                Gpt_Hw_ConfigCounterValue(gs_NowHwId,0); 
                
                gs_GptHwCCValue[gs_NowHwId].channelCCValue[gs_NowHwChannelId] = Value;
                Gpt_ConfigMaxAutorldValue(gs_NowHwId);

                if (GPT_CHANNELSTATUS_INITIALIZED == gs_GptRuntimeState.ChannelState[Channel])
                {
                    gs_GptRuntimeState.ChannelState[Channel] = GPT_CHANNELSTATUS_RUNNING;
                }
                else
                {
                    /* nothing */
                }
                gs_gptStopTime[Channel] = Value;
                
                Gpt_Hw_ConfigCompareValue(gs_NowHwId,(uint8)gs_NowHwChannelId,Value);
                Gpt_Hw_OperationCounter(gs_NowHwId,ENABLE);
                
                if (GPT_MODE_NORMAL == gs_GptRuntimeState.ModuleState)
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,(uint8)gs_NowHwChannelId,ENABLE);
                }
                else
                {
                    /* nothing */
                }

#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            }
        }
        else
        {
            /* nothing */
        }
#endif
    }
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
}


/*!
* @brief        Stops a timer channel.
*
* @param[in]    Channel       Numeric identifier of the GPT channel.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_StopTimer(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_STOPTIMER_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_STOPTIMER_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
            gs_GptHwCCValue[gs_NowHwId].channelCCValue[gs_NowHwChannelId] = 0;
            
            Gpt_ConfigMaxAutorldValue(gs_NowHwId);
            
            if (GPT_CHANNELSTATUS_RUNNING == gs_GptRuntimeState.ChannelState[Channel])
            {
                gs_GptRuntimeState.ChannelState[Channel] = GPT_CHANNELSTATUS_STOPPED;
            }
            else
            {
                /* nothing */
            }
            
            if (GPT_MODE_NORMAL == gs_GptRuntimeState.ModuleState)
            {
                Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,(uint8)gs_NowHwChannelId,DISABLE);
            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            /* nothing */
        }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    }
#endif
    
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
}



#if (GPT_TIME_ELAPSED_API_ENABLE == STD_ON)
/*!
* @brief        Returns the time already elapsed.
*
* @param[in]    Channel         Numeric identifier of the GPT channel
*
* @retval       Gpt_ValueType   Elapsed timer value (in number of ticks)
**/
FUNC(Gpt_ValueType, GPT_CODE) Gpt_GetTimeElapsed(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
    Gpt_ValueType tempRetVal = 0;
    
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_TIMEELAPSED_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_TIMEELAPSED_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else 
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
            if ((GPT_CHANNELSTATUS_RUNNING != gs_GptRuntimeState.ChannelState[Channel]) &&
                (GPT_CHANNELSTATUS_STOPPED != gs_GptRuntimeState.ChannelState[Channel]))
            {
                tempRetVal = 0;
            }
            else if ((GPT_CHANNELSTATUS_STOPPED == gs_GptRuntimeState.ChannelState[Channel]) ||
                     (GPT_CHANNELSTATUS_RUNNING == gs_GptRuntimeState.ChannelState[Channel]))
            {
                tempRetVal = Gpt_Hw_NowCounterValue(gs_NowHwId);
            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            /* nothing */
        }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    }
#endif
    
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
    
    return tempRetVal;
}
#endif



#if (GPT_TIME_REMAINING_API_ENABLE == STD_ON)
/*!
* @brief        Returns the time remaining until the target time is reached.
*
* @param[in]    Channel         Numeric identifier of the GPT channel
*
* @retval       Gpt_ValueType   Remaining timer value (in number of ticks)
**/
FUNC(Gpt_ValueType, GPT_CODE) Gpt_GetTimeRemaining(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
    Gpt_ValueType tempRetVal = 0;
    Gpt_ValueType tempMaxVal = 0;
    Gpt_ValueType tempNowVal = 0;
    
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_TIMEREMAINING_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_TIMEREMAINING_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
            if ((GPT_CHANNELSTATUS_RUNNING != gs_GptRuntimeState.ChannelState[Channel]) &&
                (GPT_CHANNELSTATUS_STOPPED != gs_GptRuntimeState.ChannelState[Channel]))
            {
                tempRetVal = 0;
            }
            else if ((GPT_CHANNELSTATUS_STOPPED == gs_GptRuntimeState.ChannelState[Channel]) ||
                     (GPT_CHANNELSTATUS_RUNNING == gs_GptRuntimeState.ChannelState[Channel]))
            {
                tempMaxVal = gs_gptStopTime[Channel];
                tempNowVal = Gpt_Hw_NowCounterValue(gs_NowHwId);
                
                if (tempMaxVal > tempNowVal)
                {
                    tempRetVal = tempMaxVal - tempNowVal;
                }
                else
                {
                    /* nothing */
                }

            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            /* nothing */
        }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    }
#endif
    
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
    
    return tempRetVal;
}
#endif


#if(STD_ON == GPT_ENABLE_DISABLE_NOTIFICATION_API_ENABLE)
/*!
* @brief        Enables the interrupt notification for a channel (relevant in normal mode).
*
* @param[in]    Channel       Numeric identifier of the GPT channel.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_EnableNotification(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_ENABLENOTIFICATION_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_ENABLENOTIFICATION_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            if ((boolean)FALSE == gs_GptRuntimeState.IsrState[Channel])
            {
                /* Report error: null pointer */
                (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                                GPT_ENABLENOTIFICATION_SRVID, GPT_E_PARAM_CHANNEL);
            }
            else
            {
#endif
                gs_gptChannelInfo[Channel].notificationEnabled = TRUE;

#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            }
        }
        else
        {
            /* nothing */
        }
#endif
    }
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
}


/*!
* @brief        Disables the interrupt notification for a channel (relevant in normal mode).
*
* @param[in]    Channel       Numeric identifier of the GPT channel.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_DisableNotification(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_DISABLENOTIFICATION_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_DISABLENOTIFICATION_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            if ((boolean)FALSE == gs_GptRuntimeState.IsrState[Channel])
            {
                /* Report error: null pointer */
                (void)Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                                GPT_DISABLENOTIFICATION_SRVID, GPT_E_PARAM_CHANNEL);
            }
            else
            {
#endif
                gs_gptChannelInfo[Channel].notificationEnabled = FALSE;

#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            }
        }
        else
        {
            /* nothing */
        }
#endif
    }
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
}
#endif


#if (STD_ON  == GPT_ENABLE_DISABLE_WAKEUP_FUNCTIONALITY_API_ENABLE)
/*!
* @brief        Enables the wakeup interrupt of a channel.
*
* @param[in]    Channel      Numeric identifier of the GPT channel.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_EnableWakeup(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
#if (GPT_REPORT_WAKEUP_SOURCE_ENABLE == STD_ON)
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_ENABLEWAKEUP_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_ENABLEWAKEUP_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            if (FALSE == gs_GptRuntimeState.WakeupState[Channel])
            {
            /* Report error: null pointer */
            Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                            GPT_ENABLEWAKEUP_SRVID, GPT_E_PARAM_CHANNEL);
            }
            else
            {
#endif
                gs_gptChannelInfo[Channel].wakeupEnabled = TRUE;
                
                if (GPT_MODE_SLEEP == gs_GptRuntimeState.ModuleState)
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,gs_NowHwChannelId,ENABLE);
                }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            }
        }
#endif
    }
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
#endif
}


/*!
* @brief        Disables the wakeup interrupt of a channel.
*
* @param[in]    Channel      Numeric identifier of the GPT channel.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_DisableWakeup(VAR(Gpt_ChannelType, AUTOMATIC) Channel)
{
#if (GPT_REPORT_WAKEUP_SOURCE_ENABLE == STD_ON)
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_ENABLEWAKEUP_SRVID, GPT_E_UNINIT);
    }
    else if (Channel > gs_gptConfigPtr->Gpt_ChannelCount)
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_ENABLEWAKEUP_SRVID, GPT_E_PARAM_CHANNEL);
    }
    else
    {
#endif
        if (E_OK == Gpt_GetNowHwAndChannelId(Channel,&gs_NowHwId,&gs_NowHwChannelId))
        {
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            if (FALSE == gs_GptRuntimeState.WakeupState[Channel])
            {
            /* Report error: null pointer */
            Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                            GPT_ENABLEWAKEUP_SRVID, GPT_E_PARAM_CHANNEL);
            }
            else
            {
#endif
                gs_gptChannelInfo[Channel].wakeupEnabled = FALSE;
                
                if (GPT_MODE_SLEEP == gs_GptRuntimeState.ModuleState)
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,gs_NowHwChannelId,DISABLE);
                }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
            }
        }
#endif
    }
    gs_NowHwId = GPT_TMR_RETAIN;
    gs_NowHwChannelId = TMR_CHANNEL_RETAIN;
#endif
}


/*!
* @brief        Checks if a wakeup capable GPT channel is the source for a wakeup event and
*               calls the ECU state manager service EcuM_SetWakeupEvent in case of a valid
*               GPT channel wakeup event.
*
* @param[in]    WakeupSource        Information on wakeup source to be checked. The associated
*                                   GPT channel can be determined from configuration data.
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_CheckWakeup(VAR(EcuM_WakeupSourceType, AUTOMATIC) WakeupSource)
{
#if (GPT_REPORT_WAKEUP_SOURCE_ENABLE == STD_ON)
    VAR(Gpt_ChannelType, AUTOMATIC) channel = 0;
    
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_CHECKWAKEUP_SRVID, GPT_E_UNINIT);
    }
    else
    {
#endif
        for (Gpt_ChannelType chNum = 0; chNum < GPT_CHANNEL_IDX_NUM; chNum++)
        {
            if (WakeupSource == gs_gptConfigPtr->ChannelConfig[chNum].Gpt_WakeupSource)
            {
                gs_gptChannelInfo[channel].wakeupGenerated = (boolean)FALSE;
                EcuM_SetWakeupEvent(WakeupSource);
            }
        }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    }
#endif
#endif
}


/*!
* @brief        Sets the operation mode of the GPT.
*
* @param[in]    Mode       GPT_MODE_NORMAL: Normal operation mode of the GPT driver.
*                          GPT_MODE_SLEEP : Sleep mode of the GPT driver (wakeup capable).
*
* @retval       None
**/
FUNC(void, GPT_CODE) Gpt_SetMode(VAR(Gpt_ModeType, AUTOMATIC) Mode)
{
    VAR(Gpt_ValueType, AUTOMATIC) elapsedTime = 0U;
    uint8 channel = 0;

#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    if (NULL_PTR == gs_gptConfigPtr)
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_SETMODE_SRVID, GPT_E_UNINIT);
    }
    else if ((Mode != GPT_MODE_NORMAL)||(Mode != GPT_MODE_SLEEP))
    {
        /* Report error: null pointer */
        Det_ReportError((uint16)GPT_H_MODULE_ID, GPT_INSTANCE_MODULE_ID,
                        GPT_SETMODE_SRVID, GPT_E_PARAM_MODE);
    }
    else
    {
#endif
        if (GPT_MODE_SLEEP == Mode)
        {
            for (Gpt_ChannelType chNum = 0; chNum < GPT_CHANNEL_IDX_NUM; chNum++)
            {
                channel = gs_gptConfigPtr->ChannelConfig[chNum].ChannelId;
                
                if (TRUE == gs_gptChannelInfo[channel].wakeupEnabled)
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,
                                                  gs_gptConfigPtr->ChannelConfig[chNum].HwChannel,
                                                  ENABLE);
                }
                else
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,
                                                  gs_gptConfigPtr->ChannelConfig[chNum].HwChannel,
                                                  DISABLE);
                }
                
                if (FALSE == gs_gptChannelInfo[channel].wakeupEnabled)
                {
                    elapsedTime = Gpt_Hw_NowCounterValue(gs_NowHwId);
                }
                
                if (GPT_CHANNELSTATUS_RUNNING == gs_GptRuntimeState.ChannelState[channel] &&
                    FALSE == gs_gptChannelInfo[channel].wakeupEnabled)
                {
                    if (gs_gptConfigPtr->gptTmrConfigPtr[chNum].ChannelMode == GPT_COUNT_MODE_ONESHOT)
                    {
                        gs_GptRuntimeState.ChannelState[channel] = GPT_CHANNELSTATUS_EXPIRED;
                    }
                    else
                    {
                        gs_gptStopTime[channel] = elapsedTime;
                        gs_GptRuntimeState.ChannelState[channel] = GPT_CHANNELSTATUS_STOPPED;
                    }
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,
                                                  gs_gptConfigPtr->ChannelConfig[chNum].HwChannel,
                                                  DISABLE);
                }
            }
            gs_GptRuntimeState.ModuleState = GPT_MODE_SLEEP;
        }
        else if (GPT_MODE_NORMAL == Mode)
        {
            for (Gpt_ChannelType chNum = 0; chNum < GPT_CHANNEL_IDX_NUM; chNum++)
            {
                channel = gs_gptConfigPtr->ChannelConfig[chNum].ChannelId;
#if(STD_ON  == GPT_ENABLE_DISABLE_NOTIFICATION_API_ENABLE)
                if (TRUE == gs_gptChannelInfo[channel].notificationEnabled)
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,
                                                  gs_gptConfigPtr->ChannelConfig[chNum].HwChannel,
                                                  ENABLE);
                }
                else
                {
                    if ((GPT_CHANNELSTATUS_RUNNING != gs_GptRuntimeState.ChannelState[channel]) ||
                        GPT_COUNT_MODE_CONTINUOUS == gs_gptConfigPtr->gptTmrConfigPtr[chNum].ChannelMode)
                    {
                        Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,
                                                      gs_gptConfigPtr->ChannelConfig[chNum].HwChannel,
                                                      DISABLE);
                    }
                }
#else
                if ((GPT_CHANNELSTATUS_RUNNING != gs_GptRuntimeState.ChannelState[channel]) ||
                    GPT_COUNT_MODE_CONTINUOUS == gs_gptConfigPtr->gptTmrConfigPtr[chNum].ChannelMode)
                {
                    Gpt_Hw_ConfigCompareInterrupt(gs_NowHwId,
                                                  gs_gptConfigPtr->ChannelConfig[chNum].HwChannel,
                                                  DISABLE);
                }
#endif
            }
            gs_GptRuntimeState.ModuleState = GPT_MODE_NORMAL;
        }
#if (GPT_DEV_ERROR_DETECT_ENABLE == STD_ON)
    }
#endif
}
#endif

/**@} end of group GPT_Fuctions */

#define GPT_STOP_SEC_CODE
#include "Gpt_MemMap.h"

#ifdef __cplusplus
}
#endif  /* ifdef __cplusplus */

/**@} end of group GPT_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
