/*!
* @file     Adc_Irq.c
*
* @version  1.0.0
*
* @brief    The underlying driver code of the adc irq module.
*
* @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 "Adc_Hw.h"
#include "Adc_Cfg.h"
#include "Adc_Reg.h"

#if (ADC_HARDWARE_TRIG_API == STD_ON)
#include "Pdl_TmrReg.h"
#endif

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup ADC_Driver
  * @brief ADC driver modules
  @{
*/

/** @defgroup ADC_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define ADC_IRQ_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define ADC_IRQ_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define ADC_IRQ_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define ADC_IRQ_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define ADC_IRQ_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define ADC_IRQ_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define ADC_IRQ_SW_PATCH_VERSION                       0x00U
  
/**@} end of group ADC_Macros */
/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
#define ADC_START_SEC_CODE
#include "Adc_MemMap.h"

/** @defgroup ADC_Fuctions
  @{
*/

/*!
* @brief        ADC software-triggered interrupt handler
*
* @param[in]    None
*
*/
static FUNC(void, GPT_CODE) Adc_Irq_SoftwareTriggerInterrupt(void)
{
    uint8 tempAdc = g_adcConfigPtr->adcSelect;
    uint16 rawValue = 0;
    uint16 tempGroup = g_adcActiveGroup;
    
    if ((uint32)0 != ADC_STATUS_REG->EOCFLG)
    {
        rawValue = (uint16)REG_READ32(ADC_DATA_REG_ADDR(tempAdc));
        
        if (ADC_ACCESS_MODE_SINGLE == g_adcGroupPtr[tempGroup].accessModeCfg.accessMode)
        {
            g_adcGroupPtr[tempGroup].adcGroupResultBuffer[tempGroup][g_adcCurrentChannel] = rawValue;
            g_adcCurrentChannel++;
            if (g_adcCurrentChannel >= g_adcConfigPtr->addGroupCfg[tempGroup].channelCount)
            {
                if ((g_adcGroupStatus[tempGroup].notificationStatus == ADC_GROUP_NOTIFICATION_ENABLED) &&
                    (g_adcGroupPtr[tempGroup].adcGroupNotification != NULL_PTR))
                {
                    g_adcGroupPtr[tempGroup].adcGroupNotification();
                    g_adcGroupStatus[tempGroup].groupStatus = ADC_STREAM_COMPLETED;
                }
                else
                {
                    /* nothing */
                }

                g_adcCurrentChannel = 0;
                Adc_RemoveQueueMem(tempGroup);
                Adc_Hw_StopGroupConversion(tempGroup);
                
                if ((uint8)0 == g_adcHwPrioQueStatus.queueCount)
                {
                    /* nothing */
                }
                else
                {
                    g_adcGroupStatus[g_adcHwPrioQueStatus.groupPriority.groupQueue[0]].groupStatus = ADC_IDLE;
                    Adc_Hw_StartGroupConversion(g_adcHwPrioQueStatus.groupPriority.groupQueue[0]);
                }
            }
            else
            {
                /* nothing */
            }
        }
        else if ((ADC_ACCESS_MODE_STREAMING == g_adcGroupPtr[tempGroup].accessModeCfg.accessMode) &&
                 (ADC_STREAM_BUFFER_LINEAR == g_adcGroupPtr[tempGroup].accessModeCfg.streamMode))
        {
            if ((uint8)0 != Adc_Hw_GetChannelNum(tempAdc))
            {
                g_adcGroupPtr[tempGroup].adcGroupResultBuffer[tempGroup][g_adcCurrentChannel + g_adcIrqQueueNumLinear] = rawValue;
                g_adcCurrentChannel = g_adcCurrentChannel + g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples;
                g_adcGroupStatus[tempGroup].groupStatus = ADC_COMPLETED;
            }
            else
            {
                /* nothing */
            }

            if ((g_adcIrqQueueNumLinear == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples - (uint16)1)) && 
                (g_adcCurrentChannel == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples *
                                         g_adcGroupPtr[tempGroup].channelCount)))
            {
                g_adcIrqQueueNumLinear = 0;
                
                if ((g_adcGroupStatus[tempGroup].notificationStatus == ADC_GROUP_NOTIFICATION_ENABLED) &&
                    (g_adcGroupPtr[tempGroup].adcGroupNotification != NULL_PTR))
                {
                    g_adcGroupPtr[tempGroup].adcGroupNotification();
                    g_adcGroupStatus[tempGroup].groupStatus = ADC_STREAM_COMPLETED;
                }
                else
                {
                    /* nothing */
                }
                
                Adc_RemoveQueueMem((Adc_GroupType)tempGroup);
                Adc_Hw_StopGroupConversion(tempGroup);
                
                if ((uint8)0 == g_adcHwPrioQueStatus.queueCount)
                {
                    /* nothing */
                }
                else
                {
                    g_adcGroupStatus[g_adcHwPrioQueStatus.groupPriority.groupQueue[0]].groupStatus = ADC_IDLE;
                    Adc_Hw_StartGroupConversion(g_adcHwPrioQueStatus.groupPriority.groupQueue[0]);
                }
            }
            else
            {
                /* nothing */
            }

            if (g_adcCurrentChannel == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples *
                                        g_adcGroupPtr[tempGroup].channelCount))
            {
                g_adcIrqQueueNumLinear++;
                g_adcCurrentChannel = 0;
                
                if ((g_adcGroupStatus[tempGroup].groupStatus == ADC_COMPLETED) &&
                    (g_adcIrqQueueNumLinear == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples - (uint16)1)))
                {
                    Adc_Hw_EnableConversion(tempAdc,ENABLE);
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                /* nothing */
            }
            
        }
        else if ((ADC_ACCESS_MODE_STREAMING == g_adcGroupPtr[tempGroup].accessModeCfg.accessMode) &&
                 (ADC_STREAM_BUFFER_CIRCULAR == g_adcGroupPtr[tempGroup].accessModeCfg.streamMode))
        {
            g_adcGroupPtr[tempGroup].adcGroupResultBuffer[tempGroup][g_adcCurrentChannel + g_adcIrqQueueNum] = rawValue;
            g_adcCurrentChannel = g_adcCurrentChannel + g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples;
            
            if (g_adcCurrentChannel == (g_adcGroupPtr[g_adcActiveGroup].accessModeCfg.streamNumSamples * 
                                        g_adcGroupPtr[g_adcActiveGroup].channelCount))
            {
                g_adcIrqQueueNum++;
                g_adcCurrentChannel = 0;
                
                if (g_adcIrqQueueNum == g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples)
                {
                    g_adcIrqQueueNum = 0;
                    
                    
                    if ((g_adcGroupStatus[tempGroup].notificationStatus == ADC_GROUP_NOTIFICATION_ENABLED) &&
                        (g_adcGroupPtr[tempGroup].adcGroupNotification != NULL_PTR))
                    {
                        g_adcGroupPtr[tempGroup].adcGroupNotification();
                        g_adcGroupStatus[tempGroup].groupStatus = ADC_COMPLETED;
                    }
                    else
                    {
                        /* nothing */
                    }
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* nothing */
    }
}

/*!
* @brief        ADC Hardware-triggered interrupt handler
*
* @param[in]    None
*
*/
static FUNC(void, GPT_CODE) Adc_Irq_HardwareTriggerInterrupt(void)
{
    uint8 tempAdc = g_adcConfigPtr->adcSelect;
    uint16 rawValue = 0;
    uint16 tempGroup = g_adcActiveGroup;
    
    if ((uint32)0 != ADC_STATUS_REG->EOCFLG)
    {
        rawValue = (uint16)REG_READ32(ADC_DATA_REG_ADDR(tempAdc));
        
        if (ADC_ACCESS_MODE_SINGLE == g_adcGroupPtr[tempGroup].accessModeCfg.accessMode)
        {
            g_adcGroupPtr[tempGroup].adcGroupResultBuffer[tempGroup][g_adcCurrentChannel] = rawValue;
            g_adcCurrentChannel++;
            if (g_adcCurrentChannel >= g_adcConfigPtr->addGroupCfg[tempGroup].channelCount)
            {
                if ((g_adcGroupStatus[tempGroup].notificationStatus == ADC_GROUP_NOTIFICATION_ENABLED) &&
                    (g_adcGroupPtr[tempGroup].adcGroupNotification != NULL_PTR))
                {
                    g_adcGroupPtr[tempGroup].adcGroupNotification();
                    g_adcGroupStatus[tempGroup].groupStatus = ADC_STREAM_COMPLETED;
                }
                else
                {
                    /* nothing */
                }
                g_adcCurrentChannel = 0;
            }
            else
            {
                /* nothing */
            }
        }
        else if ((ADC_ACCESS_MODE_STREAMING == g_adcGroupPtr[tempGroup].accessModeCfg.accessMode) &&
                 (ADC_STREAM_BUFFER_LINEAR == g_adcGroupPtr[tempGroup].accessModeCfg.streamMode))
        {
            if ((uint8)0 != Adc_Hw_GetChannelNum(tempAdc))
            {
                g_adcGroupPtr[tempGroup].adcGroupResultBuffer[tempGroup][g_adcCurrentChannel + g_adcIrqQueueNumLinear] = rawValue;
                g_adcCurrentChannel = g_adcCurrentChannel + g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples;
                g_adcGroupStatus[tempGroup].groupStatus = ADC_COMPLETED;
            }
            else
            {
                /* nothing */
            }
            
            if ((g_adcIrqQueueNumLinear == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples - (uint16)1)) && 
                (g_adcCurrentChannel == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples *
                                         g_adcGroupPtr[tempGroup].channelCount)))
            {
                g_adcIrqQueueNumLinear = 0;
                
                if ((g_adcGroupStatus[tempGroup].notificationStatus == ADC_GROUP_NOTIFICATION_ENABLED) &&
                    (g_adcGroupPtr[tempGroup].adcGroupNotification != NULL_PTR))
                {
                    g_adcGroupPtr[tempGroup].adcGroupNotification();
                    g_adcGroupStatus[tempGroup].groupStatus = ADC_STREAM_COMPLETED;
                    
                    Adc_Hw_StopGroupConversion(tempGroup);
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                /* nothing */
            }

            if (g_adcCurrentChannel == (g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples *
                                       g_adcGroupPtr[tempGroup].channelCount))
            {
                g_adcIrqQueueNumLinear++;
                g_adcCurrentChannel = 0;
            }
            else
            {
                /* nothing */
            }
        }
        else if ((ADC_ACCESS_MODE_STREAMING == g_adcGroupPtr[tempGroup].accessModeCfg.accessMode) &&
                 (ADC_STREAM_BUFFER_CIRCULAR == g_adcGroupPtr[tempGroup].accessModeCfg.streamMode))
        {
            g_adcGroupPtr[tempGroup].adcGroupResultBuffer[tempGroup][g_adcCurrentChannel + g_adcIrqQueueNum] = rawValue;
            g_adcCurrentChannel = g_adcCurrentChannel + g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples;
            
            if (g_adcCurrentChannel == (g_adcGroupPtr[g_adcActiveGroup].accessModeCfg.streamNumSamples * 
                                       g_adcGroupPtr[g_adcActiveGroup].channelCount))
            {
                g_adcIrqQueueNum++;
                g_adcCurrentChannel = 0;
                
                if (g_adcIrqQueueNum == g_adcGroupPtr[tempGroup].accessModeCfg.streamNumSamples)
                {
                    g_adcIrqQueueNum = 0;
                    
                    if ((g_adcGroupStatus[tempGroup].notificationStatus == ADC_GROUP_NOTIFICATION_ENABLED) &&
                        (g_adcGroupPtr[tempGroup].adcGroupNotification != NULL_PTR))
                    {
                        g_adcGroupPtr[tempGroup].adcGroupNotification();
                        g_adcGroupStatus[tempGroup].groupStatus = ADC_COMPLETED;
                    }
                    else
                    {
                        /* nothing */
                    }
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* nothing */
    }
}


FUNC(void, USART_CODE) ADC_IRQHandler(void)
{
    uint16 tempGroup = g_adcActiveGroup;
#if (STD_ON == ADC_LIMIT_VALUE_DETECTION_ENABLE)
    uint8 tempAdc = g_adcConfigPtr->adcSelect;

    if (SET == Adc_Hw_GetInterruptFlag(tempAdc,ADC_INT_FLAG_AWD))
    {
        Adc_Hw_WriteInterruptFlag(tempAdc,ADC_INT_FLAG_AWD);
        
        if ((ADC_TRIGG_SRC_SW == g_adcGroupPtr[tempGroup].selTrigger) &&
            (ADC_CONV_MODE_ONESHOT == g_adcGroupPtr[tempGroup].converMode))
        {
            g_adcGroupStatus[tempGroup].groupStatus = ADC_BUSY;
            Adc_Hw_OperationInterrupt(tempAdc,ADC_INT_AWD,DISABLE);
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
#endif
        if (ADC_TRIGG_SRC_SW == g_adcGroupPtr[tempGroup].selTrigger)
        {
            Adc_Irq_SoftwareTriggerInterrupt();
        }
        else
        {
            Adc_Irq_HardwareTriggerInterrupt();
        }
#if (STD_ON == ADC_LIMIT_VALUE_DETECTION_ENABLE)
    }
#endif
}
/**@} end of group ADC_Fuctions */

#define ADC_STOP_SEC_CODE
#include "Adc_MemMap.h"

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

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