/**********************************************************************************************************************
 *  COPYRIGHT
 *  -------------------------------------------------------------------------------------------------------------------
 *  \verbatim
 *
 *                 TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION
 *
 *                 Property of Texas Instruments, Unauthorized reproduction and/or distribution
 *                 is strictly prohibited.  This product  is  protected  under  copyright  law
 *                 and  trade  secret law as an  unpublished work.
 *                 (C) Copyright Texas Instruments - 2014.  All rights reserved.
 *
 *  \endverbatim
 *  -------------------------------------------------------------------------------------------------------------------
 * 
 *  -------------------------------------------------------------------------------------------------------------------
 *  FILE DESCRIPTION
 *  -------------------------------------------------------------------------------------------------------------------
 *         File:  Adc.c
 *    Component:  Tms570_AutosarAdcDriver
 *       Module:  AdcDriver
 *    Generator:  None
 *
 *  Description:  The ADC driver is responsible for controlling the analog-digital converter and for accessing the 
 *                results of a conversion. In detail it initializes the converter, provides services for starting
 *                and ending a conversion, and for selecting the trigger source and trigger condition.
 * 
 *---------------------------------------------------------------------------------------------------------------------
 * Author:  Vishwanath Reddy
 *---------------------------------------------------------------------------------------------------------------------
 * Revision History
 *---------------------------------------------------------------------------------------------------------------------
 * Version        Date         Author               Change ID        Description
 *---------------------------------------------------------------------------------------------------------------------
 * 02.21.00       30Sep2014    Vishwanath Reddy     SDOCM00113127    Initial Version
 * 02.21.01       23Aug2016    Vishwanath Reddy     SDOCM00121248    Version history updated. 
 * 02.30.00       01Dec2016    Sudhakar Singh           None         Update version info
 * 05.30.00       15Mar2017    Sudhakar Singh       SDOCM00122834    Version supports TMS570LSxx Family of Devices.
  ********************************************************************************************************************/

/**********************************************************************************************************************
 *  INCLUDES
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_036 */
/* DesignId : ADC_DesignId_002 */
/* Requirements : AR_ADC_SR1, AR_ADC_SR2, AR_ADC_SR3 */
#include "Std_Types.h"
#include "Adc.h"
#include "Adc_Irq.h"

/* SourceId : ADC_SourceId_001 */
/* DesignId : ADC_DesignId_001 */
/* Requirements : AR_ADC_SR_52 */
#if (ADC_DEV_ERROR_DETECT == STD_ON)
#include "Det.h"
#endif

/**********************************************************************************************************************
 *  VERSION CHECK
 *********************************************************************************************************************/
#define ADC_SW_C_MAJOR_VERSION               (5U)
#define ADC_SW_C_MINOR_VERSION               (30U)
#define ADC_SW_C_PATCH_VERSION               (0U)

 
 /* SourceId : ADC_SourceId_002 */
/* DesignId : ADC_DesignId_001 */
/* Requirements : AR_ADC_SR47  */
 /* Check version information of all header files included */
#if (  (ADC_SW_MAJOR_VERSION != ADC_SW_C_MAJOR_VERSION) || \
       (ADC_SW_MINOR_VERSION != ADC_SW_C_MINOR_VERSION) )
  #error "Vendor specific version numbers of Adc.c and Adc.h are inconsistent"
#endif

#if (  (ADC_CFG_MAJOR_VERSION != ADC_SW_C_MAJOR_VERSION) || \
       (ADC_CFG_MINOR_VERSION != ADC_SW_C_MINOR_VERSION) )
  #error "Version numbers of Adc.c and Adc_Cfg.h are inconsistent!" 
#endif

#if (  (ADC_IRQ_MAJOR_VERSION != ADC_SW_C_MAJOR_VERSION) || \
       (ADC_IRQ_MINOR_VERSION != ADC_SW_C_MINOR_VERSION) )
  #error "Version numbers of Adc.c and Adc_Irq.h are inconsistent!" 
#endif
/* AUTOSAR version information check has to match definition in header file */
#if (  (ADC_AR_RELEASE_MAJOR_VERSION    != (0x04U)) \
    || (ADC_AR_RELEASE_MINOR_VERSION    != (0x00U)) \
    || (ADC_AR_RELEASE_REVISION_VERSION != (0x03U)) )
  #error "ADC: AUTOSAR Version Numbers of ADC are different"
#endif
/**********************************************************************************************************************
 *  LOCAL CONSTANT MACROS
 *********************************************************************************************************************/
#define ADC_INVALID_GRP_ID              (0xFFU)
#define ADC_NUMBER_OF_HW_UNITS          ( 2U)
#define ADC_GROUPS_PER_HW_UNIT          ( 3U)

/* Definition of non-group-specific registers. The offset is given in units of 32 bit and not in bytes, like in the
 * hw manual. These defines are for use with a pointer on uint32.*/
#define Adc_OpModeCtrlReg               ((uint32)( 1U)) /* Operation mode control register */   
#define Adc_PrescaleCtrlReg             ((uint32)( 2U)) /* Clock prescale control register */
#define Adc_FifoBoundCtrlReg            ((uint32)(22U)) /* Fifo Boundary control register */
#define Adc_FifoEndCtrlReg              ((uint32)(23U)) /* Control register for Fifo size */

#define Adc_calibCtrlReg               ((uint32)( 3U))  /* Calibration control register */
#define Adc_calibReg                   ((uint32)( 33U)) /* ADC Calibration and Error Offset Correction Register*/
#define Adc_evtSelReg                  ((uint32)( 30U)) /* Event group channel sel reg */
#define Adc_grp1SelReg                 ((uint32)( 31U)) /* group1 channel sel reg */
#define Adc_grp2SelReg                 ((uint32)( 32U)) /* group2 channel sel reg */
#define Adc_parityCtrlReg              ((uint32)( 96U)) /* ADC Parity Control Register */


/* Offset of bits in registers (for shift operations) */
#define ADC_FIFO_BND_A_OFFSET           (16U)
#define ADC_CONV_MODE_OFFSET            ( 1U)
#define ADC_HW_TRIG_OFFSET              ( 3U) 
#define ADC_EDGE_SELECT_OFFSET          ( 3U)

/* Offset of the DATA_FMT bits (PSFC66) or the 8BIT bit (PSFD62) in the MODECR register which specify the resolution
 * of the conversion */

#define ADC_DATA_FORMAT_OFFSET      (8U)

/* Maximum conversion result. Use this for masking the buffer result, because buffer contains other information, too. */
#if (STD_ON == ADC_CFG12_BIT_MODE_SUPPORTED)
   #define ADC_MAX_CONVERSION_VALUE    (0x0FFFU)
#else
   #define ADC_MAX_CONVERSION_VALUE    (0x03FFU)
#endif

#define ADC_GROUP_END_INT_ENA_OFFSET    ( 3U) 
#define ADC_GROUP_END_INT_FLAG_OFFSET   ( 3U)

/* Mask to get the sign bit (bit 8) of the interrupt threshold register */
#define ADC_INT_THR_REG_SIGN_MASK       (0x00000100U)

/* Mask to get the absolute value (bits 7:0 without sign bit 8) of the interrupt threshold register */
#define ADC_INT_THR_REG_ABS_VALUE_MASK  (0x000000FFU)

#define ADC_PIN_SHORTED_TO_ADVREF_HIGH  0x01U
#define ADC_PIN_SHORTED_TO_ADVREF_LOW   0x02U
#define ADC_PIN_OPEN                    0x03U
#define ADC_PIN_GOOD                    0x00U

#define Adc_EnterCritical() 	SchM_Enter_Adc_ADC_EXCLUSIVE_AREA_0()
#define Adc_LeaveCritical()		SchM_Exit_Adc_ADC_EXCLUSIVE_AREA_0()

/**********************************************************************************************************************
 *  LOCAL FUNCTION PROTOTYPES
 *********************************************************************************************************************/
#if (STD_ON ==  ADC_SRAM_PARITY_ENABLE)
FUNC(void, ADC_CODE) Adc_SramParityEnable(Adc_HwUnitType HwUnitId);
FUNC(void, ADC_CODE) Adc_SramParityDisable(Adc_HwUnitType HwUnitId);
#endif

#if (STD_ON == ADC_DEV_ERROR_DETECT)
static boolean Adc_SetupResultBufferDet(Adc_GroupType Group, Adc_ValueGroupRefType DataBufferPtr);
#endif

/**********************************************************************************************************************
 *  LOCAL DATA PROTOTYPES
 *********************************************************************************************************************/
#if(STD_ON == ADC_SAFETI_API)
/*SAFETYMCUSW 25 D MR:8.7 <APPROVED> "Reason - This is used in other files."*/
Adc_AdcConfigReg Adc_AdcConfig;
#endif

#define ADC_START_SEC_VAR_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"

/* Adc_ConfigPtr_pt keeps the reference to the post-build configuration set, which is passed to function Adc_Init() */
static VAR(Adc_ConfigRefType, ADC_VAR) Adc_ConfigPtr_pt = NULL_PTR;

#define ADC_STOP_SEC_VAR_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"

#define ADC_START_SEC_VAR_NOINIT_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"

/* The array Adc_HwUnitGroupAssignment_at stores the numeric Id of the channel group, which was started last on the 
 * according Hw conversion group. The first index represents the hw unit. The second one represents the hw unit's 
 * conversion group.
 * 
 * This table has to be consulted, EACH TIME THE DRIVER READS OR WRITES A HW REGISTER (for example the fifo buffer), to
 * see if the software group, for which an API function is called, is allowed to modify the hardware.
 */
static VAR(Adc_GroupType, ADC_VAR) Adc_HwUnitGroupAssignment_at[ADC_NUMBER_OF_HW_UNITS][ADC_GROUPS_PER_HW_UNIT];


#define ADC_STOP_SEC_VAR_NOINIT_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"

/*SAFETYMCUSW 580 S MR:1.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#define ADC_START_SEC_CONST_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"
const Adc_PublishedInformationType Adc_PublishedInformation =
{
    ADC_CHANNEL_VALUESIGNED,
    ADC_GROUP_FIRST_CHANNEL_FIXED,
    ADC_MAX_CHANNEL_RESOLUTION
};
/*SAFETYMCUSW 580 S MR:1.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#define ADC_STOP_SEC_CONST_UNSPECIFIED
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"

/**********************************************************************************************************************
 *  LOCAL FUNCTIONS
 *********************************************************************************************************************/
#define ADC_START_SEC_CODE
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h"

/**********************************************************************************************************************
 * Adc_ProcessBufferSingle
 *********************************************************************************************************************/
/*! \brief      Process Buffer Single
 * 
 *              This method copies results from hardware fifo buffer to application result buffer. It is called for
 *              groups with single buffer access.
 * 
 *  \param[in]  GroupConfigPtr           Pointer to the relevant group configuration and group data variables
 * 
 *  \context    This function can be called on task and interrupt level.
 *********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_ProcessBufferSingle  (Adc_GroupConfigRefType GroupConfigPtr)
{
  Adc_ThresholdType SampleCounter = 0U;
  uint8 ChCounter_u8 = 0U;
  Adc_ValueGroupType ConversionResult = 0U;
  
  /* Loop samples */
  for (SampleCounter = 0U; SampleCounter < GroupConfigPtr->GroupData_pt->Threshold_t; SampleCounter++)
  {
    /* Loop channels of a sample */
    for (ChCounter_u8 = 0U; ChCounter_u8 < GroupConfigPtr->NumberOfGroupChannels_u8; ChCounter_u8++)
    {
      /* Get one result out of fifo. Only read the lower bits (as specified in ADC_MAX_CONVERSION_VALUE), because
       * the buffer also contains status information. */
      /*SAFETYMCUSW 439 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	  ConversionResult = (Adc_ValueGroupType)( (*(GroupConfigPtr->HwFifoBuffer_p)) & ADC_MAX_CONVERSION_VALUE);
      /* Store it in the result buffer at the current position. */
      GroupConfigPtr->GroupData_pt->ResultBuffer_pt[ChCounter_u8] = ConversionResult;
    }
  }
  
  /* Add number of new samples to SampleCount. This value is cropped in the related Adc_ProcessConversion function. */
  GroupConfigPtr->GroupData_pt->ValidSampleCount_t = GroupConfigPtr->GroupData_pt->Threshold_t;  
}

/**********************************************************************************************************************
 * Adc_ProcessBufferLinear
 *********************************************************************************************************************/
/*! \brief      Process Buffer Linear
 * 
 *              This method copies results from hardware fifo buffer to application result buffer. It is called for
 *              groups with linear streaming buffer access.
 * 
 *  \param[in]  GroupConfigPtr           Pointer to the relevant group configuration and group data variables
 * 
 *  \context    This function can be called on task and interrupt level.
 *********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_ProcessBufferLinear  (Adc_GroupConfigRefType GroupConfigPtr)
{
  Adc_ThresholdType SampleCounter = 0U;
  Adc_ThresholdType NumberOfSamples = 0U; /* The number of samples that have to be copied. */
  uint8 ChCounter_u8 = 0U;
  Adc_ValueGroupType ConversionResult = 0U;
  
  /* Set NumberOfSamples to the minimum of Threshold and SampleCountdown */
  if (GroupConfigPtr->GroupData_pt->Threshold_t < (Adc_ThresholdType)GroupConfigPtr->GroupData_pt->SampleCountdown_t)
  {
    /* Get all samples out of the fifo, because all of them fit into result buffer. */
    NumberOfSamples = GroupConfigPtr->GroupData_pt->Threshold_t;
  }
  else
  {
    /* The buffer is almost filled completely. Get only several examples out of the buffer. */
    /* This cast is not critical, because this else-branch is only executed when SampleCountdown is less than 255 */
    NumberOfSamples = (Adc_ThresholdType) GroupConfigPtr->GroupData_pt->SampleCountdown_t;
  }
  
  /* Loop samples */
  for (SampleCounter = 0U; SampleCounter < NumberOfSamples; SampleCounter++)
  {
    /* Loop channels of a sample */
    for (ChCounter_u8 = 0U; ChCounter_u8 < GroupConfigPtr->NumberOfGroupChannels_u8; ChCounter_u8++)
    {
      /* Get one result out of fifo. Only read the lower bits (as specified in ADC_MAX_CONVERSION_VALUE), because
       * the buffer also contains status information. */
      /*SAFETYMCUSW 439 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	  ConversionResult = (Adc_ValueGroupType)( (*(GroupConfigPtr->HwFifoBuffer_p)) & ADC_MAX_CONVERSION_VALUE);

      GroupConfigPtr->GroupData_pt->ResultBuffer_pt
          /* StrNumSamples - SampleCountdown: Write next value at this postion */
          /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
		  [((uint32)((GroupConfigPtr->StreamingNumSamples_t) - (GroupConfigPtr->GroupData_pt->SampleCountdown_t))) + 
          /* This is the offset of the channel relative to channel 0 */
          ((GroupConfigPtr->StreamingNumSamples_t) * (ChCounter_u8))] = ConversionResult;
    }
    
    /* decrement SampleCountdown when a complete sample (all channels) is added to buffer. */
    GroupConfigPtr->GroupData_pt->SampleCountdown_t--;
    /* increment ValidSampleCount when a complete sample (all channels) is added to buffer. */
    GroupConfigPtr->GroupData_pt->ValidSampleCount_t++;
  }  
}

/**********************************************************************************************************************
 * Adc_ProcessBufferCircular
 *********************************************************************************************************************/
/*! \brief      Process Buffer Circular
 * 
 *              This method copies results from hardware fifo buffer to application result buffer. It is called for
 *              groups with circular streaming buffer access.
 * 
 *  \param[in]  GroupConfigPtr           Pointer to the relevant group configuration and group data variables
 * 
 *  \context    This function can be called on task and interrupt level.
 *********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_ProcessBufferCircular(Adc_GroupConfigRefType GroupConfigPtr)
{
  Adc_ThresholdType SampleCounter = 0U;
  Adc_ThresholdType NumberOfSamples = 0U; /* The number of samples that have to be copied. */
  uint8 ChCounter_u8 = 0U;
  Adc_ValueGroupType ConversionResult = 0U;
  
  NumberOfSamples = GroupConfigPtr->GroupData_pt->Threshold_t;
  
  /* Loop samples */
  for (SampleCounter = 0U; SampleCounter < NumberOfSamples; SampleCounter++)
  {
    /* Loop channels of a sample */
    for (ChCounter_u8 = 0U; ChCounter_u8 < GroupConfigPtr->NumberOfGroupChannels_u8; ChCounter_u8++)
    {
      /* Get one result out of fifo. Only read the lower bits (as specified in ADC_MAX_CONVERSION_VALUE), because
       * the buffer also contains status information. */
	  /*SAFETYMCUSW 439 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	  ConversionResult = (Adc_ValueGroupType)( (*(GroupConfigPtr->HwFifoBuffer_p)) & ADC_MAX_CONVERSION_VALUE);

      GroupConfigPtr->GroupData_pt->ResultBuffer_pt
          /* StrNumSamples - SampleCountdown: Write next value at this postion */
          /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
		  [((uint32)((GroupConfigPtr->StreamingNumSamples_t) - (GroupConfigPtr->GroupData_pt->SampleCountdown_t))) + 
          /* This is the offset of the channel relative to channel 0 */
          ((GroupConfigPtr->StreamingNumSamples_t) * (ChCounter_u8))] = ConversionResult;
    }
    
    /* decrement SampleCountdown when a complete sample (all channels) is added to buffer */
    GroupConfigPtr->GroupData_pt->SampleCountdown_t--;
    /* Check if end of buffer is reached. */
    if (GroupConfigPtr->GroupData_pt->SampleCountdown_t == 0U)
    {
      /* Perform a wrap around of buffer. Start at begin of buffer. */
      GroupConfigPtr->GroupData_pt->SampleCountdown_t = GroupConfigPtr->StreamingNumSamples_t;
    }    
     /*else no wrap around */
    
    /* increment ValidSampleCount when a complete sample (all channels) is added to buffer. This value is cropped
     * in the related Adc_ProcessConversion function. */
    GroupConfigPtr->GroupData_pt->ValidSampleCount_t++;
  }  
}

/**********************************************************************************************************************
 * Adc_ProcessConversionSingle
 *********************************************************************************************************************/
/*! \brief     Process Conversion Single
* 
*              This method is called each time results have been copied from hardware fifo buffer to application result
*              buffer. It is responsible for setting ValidSampleCount and group status. This variant is used for 
*              single buffer access.
* 
*  \param[in]  GroupConfigPtr           Pointer to the relevant group configuration and group data variables
* 
*  \context    This function can be called on task and interrupt level.
**********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_ProcessConversionSingle(Adc_GroupConfigRefType GroupConfigPtr)
{
  if (GroupConfigPtr->GroupData_pt->ValidSampleCount_t > 0U)
  {
    /* Results are in buffer. Set ValidSampleCount to max., which is 1, because of SingleAccess. */
    GroupConfigPtr->GroupData_pt->ValidSampleCount_t = 1U;
    GroupConfigPtr->GroupData_pt->Status_t = ADC_STREAM_COMPLETED;
  }  
  /* else No valid samples in buffer. Keep state. */
  
}

/**********************************************************************************************************************
 * Adc_ProcessConversionLinear
 *********************************************************************************************************************/
/*! \brief     Process Conversion Linear
* 
*              This method is called each time results have been copied from hardware fifo buffer to application result
*              buffer. It is responsible for setting ValidSampleCount and group status. This variant is used for 
*              linear streaming buffer access.
* 
*  \param[in]  GroupConfigPtr           Pointer to the relevant group configuration and group data variables
* 
*  \context    This function can be called on task and interrupt level.
**********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_ProcessConversionLinear(Adc_GroupConfigRefType GroupConfigPtr)
{
  if (GroupConfigPtr->GroupData_pt->SampleCountdown_t > 0U)
  {
    /* Results are remaining, conversion is ongoing. */
    GroupConfigPtr->GroupData_pt->Status_t = ADC_COMPLETED;
  }
  else
  {
    /* Conversion has been finished, no results are remaining. */
    GroupConfigPtr->GroupData_pt->Status_t = ADC_STREAM_COMPLETED;
    
    /* Stop hardware for linear streaming groups. */
    GroupConfigPtr->HwGroupBase_pt->ChSelectReg = (uint32)(0x0000U);
    /* Disable interrupts */
    GroupConfigPtr->HwGroupBase_pt->IntEnaReg = (uint32)(0x0000U);
    /* Reset HwUnitGroupAssignment to default state, because Hw is not in use anymore */
    /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
	Adc_HwUnitGroupAssignment_at[GroupConfigPtr->GroupHwUnitId_t]
                                [GroupConfigPtr->GroupHwGroupId_u8] = ADC_INVALID_GRP_ID;
  }  
}

/**********************************************************************************************************************
 * Adc_ProcessConversionCircular
 *********************************************************************************************************************/
/*! \brief     Process Conversion Circular
* 
*              This method is called each time results have been copied from hardware fifo buffer to application result
*              buffer. It is responsible for setting ValidSampleCount and group status. This variant is used for 
*              circular streaming buffer access.
* 
*  \param[in]  GroupConfigPtr           Pointer to the relevant group configuration and group data variables
* 
*  \context    This function can be called on task and interrupt level.
**********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_ProcessConversionCircular(Adc_GroupConfigRefType GroupConfigPtr)
{
  if (GroupConfigPtr->GroupData_pt->ValidSampleCount_t > 0U)
  {
    /* There are results in buffer. Check if buffer is filled completely. */
    if (GroupConfigPtr->GroupData_pt->ValidSampleCount_t >= GroupConfigPtr->StreamingNumSamples_t)
    {
      /* Buffer is filled completely. Set ValidSampleCount to max. */
      GroupConfigPtr->GroupData_pt->ValidSampleCount_t = GroupConfigPtr->StreamingNumSamples_t;
      GroupConfigPtr->GroupData_pt->Status_t = ADC_STREAM_COMPLETED;
    }
    else
    {
      /* Buffer is not filled completely. */
      GroupConfigPtr->GroupData_pt->Status_t = ADC_COMPLETED;
    }
  }  
  /* else No valid samples in buffer. Keep state. */
  
}

/**********************************************************************************************************************
 * Adc_AvoidNotification
 *********************************************************************************************************************/
/*! \brief     Avoid Notification
* 
*              This empty method is called for a group, that has no notification function configured, or in case 
*              notification is switched off.
* \param[in]   void
*  \context    This function can be called interrupt level.
**********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_AvoidNotification(void)
{
  /* This dummy function is called in case notification is disabled or no notification is configured. */  
  return;
}

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

/**********************************************************************************************************************
 * Adc_Init
 *********************************************************************************************************************/
/*! \brief      Module Initialisation Service
 * 
 *              This method is the Adc initialization service. It is responsible for setting up hardware and driver 
 *              module.
 * 
 *  \param[in]  ConfigPtr               Configuration structure for initialising the module
 * 
 *  \pre        Input parameter must not be NULL.
 * 
 *  \context    System Startup
 * 
 *  \note       Specification of module initialisation
 
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_003 */
/* DesignId : ADC_DesignId_003 */
/* Requirements : AR_ADC_SR53, AR_ADC_SR57, AR_ADC_SR67, AR_ADC_SR68, AR_ADC_SR69, AR_ADC_SR70, AR_ADC_SR76, AR_ADC_SR77
                  AR_ADC_SR78, AR_ADC_SR80 */
FUNC(void, ADC_CODE) Adc_Init(P2CONST(Adc_ConfigType, AUTOMATIC, ADC_PBCFG) ConfigPtr)
{
	uint8 GroupCounter_u8 = 0U;
	uint8 HwUnitCounter_u8 = 0U;
	uint8 HwGroupCounter_u8 = 0U;	
	/* Pointer on uint32 (Register) */
	volatile Adc_RegisterRefType HwUnitBasePtr;
	/* Pointer on struct. */
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr;
    
	#if(STD_ON == ADC_DEV_ERROR_DETECT)
    /* Perform a check on Adc_ConfigPtr_pt whether Adc is already initialized or not */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if(NULL_PTR != Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_INIT, ADC_E_ALREADY_INITIALIZED);      
    }
    /* Perform NULL_PTR check on ConfigPtr */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	else if (NULL_PTR == ConfigPtr)
	{
	  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_INIT, ADC_E_PARAM_CONFIG);	  
	}
    else
	#endif  
	{
	  /* Store parameter 'ConfigPtr' in Adc_ConfigPtr_pt for use in other API functions */
	  Adc_ConfigPtr_pt = ConfigPtr;
	  /* Reset Adc_HwUnitGroupAssignment_at to ADC_INVALID_GRP_ID. */
	  Adc_HwUnitGroupAssignment_at[0][ADC_HW_GROUP_EVT] = ADC_INVALID_GRP_ID;
	  Adc_HwUnitGroupAssignment_at[0][ADC_HW_GROUP_G1]  = ADC_INVALID_GRP_ID;
	  Adc_HwUnitGroupAssignment_at[0][ADC_HW_GROUP_G2]  = ADC_INVALID_GRP_ID;
	  Adc_HwUnitGroupAssignment_at[1][ADC_HW_GROUP_EVT] = ADC_INVALID_GRP_ID;
	  Adc_HwUnitGroupAssignment_at[1][ADC_HW_GROUP_G1]  = ADC_INVALID_GRP_ID;
	  Adc_HwUnitGroupAssignment_at[1][ADC_HW_GROUP_G2]  = ADC_INVALID_GRP_ID;  	

	  /* Initialize all hw units */
	  for (HwUnitCounter_u8 = 0U; HwUnitCounter_u8 < Adc_ConfigPtr_pt->NumberOfHwUnits_t; HwUnitCounter_u8++)
	  {
		/* Get base address of the current hw unit's register set */
		HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[HwUnitCounter_u8].HwUnitBase_pu32;  
	  
		#if (STD_ON == ADC_CFG12_BIT_MODE_SUPPORTED)
		  /* Set enable bit for hw unit (ADC EN) and 12bit-conversion-bit */
		  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer. "*/
		  HwUnitBasePtr[Adc_OpModeCtrlReg]    |= (uint32)(0x80000001U);
		#else
		  /* Set enable bit for hw unit (ADC EN) */
		  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer. "*/
		  HwUnitBasePtr[Adc_OpModeCtrlReg]    |= (uint32)(1U);
		#endif
			
		/* Set end boundary of fifo */
		/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer. "*/
		HwUnitBasePtr[Adc_FifoEndCtrlReg]   = ADC_FIFO_BND_END;
		/* Set boundaries of fifo: copy boundary a to 24:16 and boundary b to 8:0 */
		/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer. "*/
		HwUnitBasePtr[Adc_FifoBoundCtrlReg] 
		  = (Adc_ConfigPtr_pt->HwUnit_at[HwUnitCounter_u8].FifoBndA_u32 << ADC_FIFO_BND_A_OFFSET)
		  | (Adc_ConfigPtr_pt->HwUnit_at[HwUnitCounter_u8].FifoBndB_u32);
		/* Set the clock prescale factor. Set register to 0 to get factor 1, to 1 to get factor 2,...Therefore subtract
		 * 1 to get the register value. */
		/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer. "*/
		HwUnitBasePtr[Adc_PrescaleCtrlReg]  = Adc_ConfigPtr_pt->HwUnit_at[HwUnitCounter_u8].Prescale_t - 1U;
		
		/* Reset interrupt enable bits and interrupt flags for event, sw1 and sw2 group. */
		/* loop conversion groups on this hw */
		/* Reset all group specific registers */
		for (HwGroupCounter_u8 = 0U; HwGroupCounter_u8 < ADC_GROUPS_PER_HW_UNIT; HwGroupCounter_u8++)
		{
		  /* Get the base address of the current hw group on the current hw unit. This is the base pointer of the hw 
		     unit at 0, 1 or 2. Make a type cast before pointer assignment. */
		  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
		  /*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwGroupBasePtr is pointer. "*/
		  /*SAFETYMCUSW 132 S MR:12.3 <APPROVED> "Reason - volatile usage is required here. "*/
		  /*SAFETYMCUSW 47 S MR:21.1 <APPROVED> "Reason -  HwGroupCounter_u8 is limited to groups."*/
		  /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason -  volatile is required here."*/
		  HwGroupBasePtr = (volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE)) (&HwUnitBasePtr[HwGroupCounter_u8]);
		  
		  HwGroupBasePtr->ModeCtrlReg = (uint32)0x00U;
		  HwGroupBasePtr->SourceReg   = (uint32)0x00U;
		  HwGroupBasePtr->IntEnaReg   = (uint32)0x00U;
		  HwGroupBasePtr->IntFlgReg   = (uint32)0x04U;     /* MEM EMPTY bit defaults to 1 */
		  HwGroupBasePtr->IntThrReg   = (uint32)0x00U;
		  HwGroupBasePtr->DmaCtrlReg  = (uint32)0x00U;
		  HwGroupBasePtr->SampTimeReg = (uint32)0x00U;
		  HwGroupBasePtr->StatusReg   = (uint32)0x08U;     /* MEM EMPTY bit defaults to 1 */
		  HwGroupBasePtr->ChSelectReg = (uint32)0x00U;
		}

		#if (STD_ON == ADC_SRAM_PARITY_ENABLE)
		 Adc_SramParityEnable(HwUnitCounter_u8);
		#endif		
	  }	  
	  /* Initialize all groups in use */
	  for(GroupCounter_u8 = 0U; GroupCounter_u8 < Adc_ConfigPtr_pt->NumberOfGroups_t; GroupCounter_u8++)
	  {
		Adc_ConfigPtr_pt->Group_at[GroupCounter_u8].GroupData_pt->Notification_u8    = ADC_NOTIFICATION_OFF;
		Adc_ConfigPtr_pt->Group_at[GroupCounter_u8].GroupData_pt->Status_t           = ADC_IDLE;
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		Adc_ConfigPtr_pt->Group_at[GroupCounter_u8].GroupData_pt->ResultBuffer_pt    = NULL_PTR;
		Adc_ConfigPtr_pt->Group_at[GroupCounter_u8].GroupData_pt->SampleCountdown_t  = 0U;
		Adc_ConfigPtr_pt->Group_at[GroupCounter_u8].GroupData_pt->Threshold_t        = 0U;
		Adc_ConfigPtr_pt->Group_at[GroupCounter_u8].GroupData_pt->ValidSampleCount_t = 0U;
		/* Hardware trigger cannot be disabled at this time. */
	  }
	}	
} /* End of Adc_Init() */

/*********************************************************************************************************************
 * Adc_SetupResultBuffer
 *********************************************************************************************************************/
/*! \brief      Result Buffer Setup Service
 * 
 *              This method is the Adc group result buffer setup service. It is responsible for setting up the result 
 *              buffer pointer of the group 'Group'.
 * 
 *  \param[in]  Group             Numeric Id of requested Adc channel group.
 *  \param[in]  DataBufferPtr     Adc result buffer pointer is initialized with the value of the
 *                                data buffer pointer.
 * 
 *  \return     E_OK              Result buffer pointer initialized correctly.
 *  \return     E_NOT_OK          Operation failed or development error occured.
 * 
 *  \pre        The module has to be initialized.
 * 
 *  \context    This function can be called on task level.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_004 */
/* DesignId : ADC_DesignId_005 */
/* Requirements : AR_ADC_SR81, AR_ADC_SR82, AR_ADC_SR83, AR_ADC_SR85, AR_ADC_SR86, AR_ADC_SR87, AR_ADC_SR88 */
 FUNC(Std_ReturnType, ADC_CODE) Adc_SetupResultBuffer(Adc_GroupType Group, Adc_ValueGroupRefType DataBufferPtr)
{
	/* Pointer that references the static configuration of the group passed as parameter 'Group' */
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;	
	Std_ReturnType ReturnStatus1 = E_OK;   
  
	#if (STD_ON == ADC_DEV_ERROR_DETECT)	
	if(FALSE == Adc_SetupResultBufferDet(Group,DataBufferPtr))
	{
	  ReturnStatus1 = E_NOT_OK;
	}      
    else
	#endif      	
	{
		/* After validation of parameter 'Group' set a reference to the configuration of that group. */
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]); 			
		
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		/* Check group status */	
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		if (ADC_IDLE != CurrentGroupConfigPtr->GroupData_pt->Status_t)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_SETUP_RESULT_BUFFER, ADC_E_BUSY);		  
		  ReturnStatus1 = E_NOT_OK;
		}
		else		
		#endif
		{
			CurrentGroupConfigPtr->GroupData_pt->ResultBuffer_pt = DataBufferPtr;
		}	
	}	
	return (ReturnStatus1);
}

#if (ADC_DEV_ERROR_DETECT == STD_ON)
static boolean Adc_SetupResultBufferDet(Adc_GroupType Group, Adc_ValueGroupRefType DataBufferPtr)
{	
	boolean returnstatus = TRUE;
	
	/* Check for uninitialized module */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_SETUP_RESULT_BUFFER, ADC_E_UNINIT); 	  
	  returnstatus = FALSE;	  
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
	{
	  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_SETUP_RESULT_BUFFER, ADC_E_PARAM_GROUP);	  
	  returnstatus = FALSE;
	}
	/* Validate parameter 'DataBufferPtr' */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	else 
	{
	  if(NULL_PTR == DataBufferPtr)
	  {
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_SETUP_RESULT_BUFFER, ADC_E_PARAM_POINTER);	  
		  returnstatus = FALSE;
	  }	  
	}		
	return returnstatus;
}
#endif
#if (STD_ON == ADC_DEINIT_API)
/**********************************************************************************************************************
 * Adc_DeInit
 *********************************************************************************************************************/
/*! \brief      Module Deinitialisation Service
 * 
 *              This method is the Adc deinitialization service. It is responsible for resetting the hardware to a 
 *              state, comparable to it's reset state.
 * 
 *  \pre        The module has to be initialized.
 * 
 *  \context    
 * 
 *  \note       Specification of module deinitialisation
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_005 */
/* DesignId : ADC_DesignId_004 */
/* Requirements : AR_ADC_SR89, AR_ADC_SR90, AR_ADC_SR91, AR_ADC_SR92, AR_ADC_SR93, AR_ADC_SR94, AR_ADC_SR95 */
 FUNC(void, ADC_CODE) Adc_DeInit(void)
{
	uint8 SwGroupCounter_u8;
	uint8 HwUnitCounter_u8;
	uint8 HwGroupCounter_u8;
	boolean bError = FALSE;
	volatile Adc_RegisterRefType HwUnitBasePtr;
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr;
  
	/* Perform a check on Adc_ConfigPtr_pt whether Adc has been initialized or not */
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DEINIT, ADC_E_UNINIT);
      bError = TRUE;
    }   
	#endif
  	
	if(bError == FALSE)
	{
		/* Check if any of the groups is still converting. If so, raise error to DET and return. */
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		for(SwGroupCounter_u8 = 0U; SwGroupCounter_u8 < Adc_ConfigPtr_pt->NumberOfGroups_t; SwGroupCounter_u8++)
		{
		  if ((ADC_BUSY     == Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->Status_t)
		  || (ADC_COMPLETED == Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->Status_t))
		  {
			/* These states indicate, that the group is still converting */
			(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DEINIT, ADC_E_BUSY);
			bError = TRUE;
		  }
		  else if(ADC_STREAM_COMPLETED == Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->Status_t)
		  {
			/* Check if this group is a group that has to be stopped explicitly. */
			if (ADC_GROUP_STOP_EXPLICIT == Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupStopMode_u8)
			{
			  /* Group has to be stopped explicitly. State ADC_STREAM_COMPLETED means, that group is still converting. */
			  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DEINIT, ADC_E_BUSY);
			  bError = TRUE;
			}
			/* else Group stops implicitly. State ADC_STREAM_COMPLETED indicates, that group conversion has finished. 
			   Continue. */			   			
		  }	
		  else
		  {
			/* else This group is not converting: continue */		 
		  }		  
		} /* end for-loop*/
		#endif 
	}
    
	if(bError == FALSE)
	{
		/* Deinitialize all registers of all hw units */
		/* loop hw units */
		for (HwUnitCounter_u8 = 0U; HwUnitCounter_u8 < Adc_ConfigPtr_pt->NumberOfHwUnits_t; HwUnitCounter_u8++)
		{
			/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[HwUnitCounter_u8].HwUnitBase_pu32;

			/* Reset enable bit for hw unit (ADC EN) */
			/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			HwUnitBasePtr[Adc_OpModeCtrlReg]    = (uint32)(0U);
			/* Reset boundaries of fifo */
			/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			HwUnitBasePtr[Adc_FifoBoundCtrlReg] = (uint32)(0U);
			/* Set the clock prescale factor. */
			/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			HwUnitBasePtr[Adc_PrescaleCtrlReg]  = (uint32)(0U);
			/* Reset fifo end register */
			/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			HwUnitBasePtr[Adc_FifoEndCtrlReg]   = (uint32)(0U);    
		
			/* loop conversion groups on this hw */
			/* Reset all group specific registers */
			for (HwGroupCounter_u8 = 0U; HwGroupCounter_u8 < ADC_GROUPS_PER_HW_UNIT; HwGroupCounter_u8++)
			{
				/* Get the base address of the current hw group on the current hw unit. This is the base pointer of the
                   hw unit at 0, 1 or 2. Make a type cast before pointer assignment.	*/
				/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
				/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
				/*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/				
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwGroupBasePtr is pointer. "*/
				/*SAFETYMCUSW 132 S MR:12.3 <APPROVED> "Reason - volatile usage is required here. "*/
				/*SAFETYMCUSW 47 S MR:21.1 <APPROVED> "Reason -  HwGroupCounter_u8 is limited to groups."*/
				/*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason -  volatile is required here."*/
				HwGroupBasePtr = (volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE)) (&HwUnitBasePtr[HwGroupCounter_u8]);
			  
				HwGroupBasePtr->ModeCtrlReg = (uint32)0x00U;
				HwGroupBasePtr->SourceReg   = (uint32)0x00U;
				HwGroupBasePtr->IntEnaReg   = (uint32)0x00U;
				HwGroupBasePtr->IntFlgReg   = (uint32)0x04U;     /* MEM EMPTY bit defaults to 1 */
				HwGroupBasePtr->IntThrReg   = (uint32)0x00U;
				HwGroupBasePtr->DmaCtrlReg  = (uint32)0x00U;
				HwGroupBasePtr->SampTimeReg = (uint32)0x00U;
				HwGroupBasePtr->StatusReg   = (uint32)0x08U;     /* MEM EMPTY bit defaults to 1 */
				HwGroupBasePtr->ChSelectReg = (uint32)0x00U;
			}
		  }
		  
		  /* Deinitialize all software groups in use */
		  for (SwGroupCounter_u8 = 0U; SwGroupCounter_u8 < Adc_ConfigPtr_pt->NumberOfGroups_t; SwGroupCounter_u8++)
		  {
			/* Reset all runtime variables. */
			Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->Status_t           = ADC_IDLE;                        
			/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
			Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->ResultBuffer_pt    = NULL_PTR;
			Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->SampleCountdown_t  = 0U;
			Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->ValidSampleCount_t = 0U;
			Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->Threshold_t        = 0U;
			Adc_ConfigPtr_pt->Group_at[SwGroupCounter_u8].GroupData_pt->Notification_u8    = ADC_NOTIFICATION_OFF;
		  }
	  
		  /* Reset the global Adc_ConfigPtr_pt, which is used for ADC_E_UNINIT check. */
		  /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		  Adc_ConfigPtr_pt = NULL_PTR;
	}
} /* End of Adc_DeInit() */
#endif /* (ADC_DEINIT_API == STD_ON) */

#if (STD_ON == ADC_ENABLE_START_STOP_GROUP_API)
/**********************************************************************************************************************
 * Adc_StartGroupConversion
 *********************************************************************************************************************/
/*! \brief      Start group conversion
 * 
 *              This method starts a software triggered conversion of all channels of the requested Adc channel group. 
 * 
 *  \param[in]  Group             Numeric Id of requested Adc channel group.
 *
 *  \pre        The module has to be initialized.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_006 */
/* DesignId : ADC_DesignId_006 */
/* Requirements : AR_ADC_SR11, AR_ADC_SR12, AR_ADC_SR17, AR_ADC_SR96, AR_ADC_SR97, AR_ADC_SR98, AR_ADC_SR99, 
                  AR_ADC_SR100, AR_ADC_SR101, AR_ADC_SR102, AR_ADC_SR103, AR_ADC_SR110, AR_ADC_SR111   */
 FUNC(void, ADC_CODE) Adc_StartGroupConversion(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	uint32 ModeCtrlRegWorkingCopy = 0U;
	uint32 SampTimeRegWorkingCopy = 0U;
	uint32 IntEnaRegWorkingCopy = 0U;
	uint32 IntThrRegWorkingCopy = 0U;
	boolean bError = FALSE;
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
	Adc_GroupType LastGroup = 0U;
	Adc_GroupType GroupOne = 0U;
	#endif


	/* Check for uninitialized module */
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_PARAM_GROUP);      
    }
	else	
	#endif    
    {
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;  
    
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		if (NULL_PTR == CurrentGroupConfigPtr->GroupData_pt->ResultBuffer_pt)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_BUFFER_UNINIT);		  
		}
		/* Validate trigger source */
		else if (ADC_TRIGG_SRC_HW == CurrentGroupConfigPtr->GroupTriggSrc_t)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_WRONG_TRIGG_SRC);
		}
		else		
		#endif
		{
			Adc_EnterCritical();    
			#if (STD_ON == ADC_DEV_ERROR_DETECT)			
			/* Check which software group was started last on the requested hardware group. */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
												 [CurrentGroupConfigPtr->GroupHwGroupId_u8];
			
			if (ADC_INVALID_GRP_ID == LastGroup)
			{
			  /* Currently there is no group converting on the requested HW unit. */
			}
			else
			{
			  /* Another software group has been started on this hardware group before.  
			   * Check if the other group has finished conversion before starting this group.*/
			  if ((ADC_BUSY     == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupData_pt->Status_t)
			  || (ADC_COMPLETED == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupData_pt->Status_t))
			  {
				/* The group that was started before has not finished until now. */
				Adc_LeaveCritical();
				(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_BUSY);			
				bError = TRUE;
			  }
			  else 
			  {
				if (ADC_STREAM_COMPLETED == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupData_pt->Status_t)
				{
					/* Check if the group, that was started before, was a group that has to be stopped explicitly. */
					if (ADC_GROUP_STOP_EXPLICIT == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupStopMode_u8)
					{
					  /* Group has to be stopped explicitly. State ADC_STREAM_COMPLETED means, that group is still 
						 converting, but only buffer is filled completely. Error.*/
					  Adc_LeaveCritical();
					  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_BUSY);			  
					  bError = TRUE;
					}			
				}	
			  }			  
			} /* end of: ADC_INVALID_GRP_ID == LastGroup */
			
			/* Check which software group was started last on ADC_HW_GROUP_G1. No group at all can be started on this 
			   hw unit, when ADC_HW_GROUP_G1 is in continuous conversion mode with circular streaming buffer access 
			   and still actively converting.*/		
			if(bError == FALSE)
			{
				/* Get the group, that was started last on the requested hw units' ADC_HW_GROUP_G1 */
				GroupOne = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t][ADC_HW_GROUP_G1];
				
				if (ADC_INVALID_GRP_ID == GroupOne)
				{
				  /* Currently there is no group converting on this HW unit. */
				}
				else
				{
				  /* Check if GroupOne is still active */
				  if (ADC_IDLE != Adc_ConfigPtr_pt->Group_at[GroupOne].GroupData_pt->Status_t)
				  {
					/* The group that was started before has not finished until now. 
					 * Check now for continuous conversion mode with circular streaming buffer access. */
					if ((ADC_CONV_MODE_CONTINUOUS  == Adc_ConfigPtr_pt->Group_at[GroupOne].GroupConversionMode_t)
						&& (ADC_ACCESS_MODE_STREAMING  == Adc_ConfigPtr_pt->Group_at[GroupOne].GroupAccessMode_t)
						&& (ADC_STREAM_BUFFER_CIRCULAR == Adc_ConfigPtr_pt->Group_at[GroupOne].StreamingBufferMode_t))
					{
					  /* No group can be started, when group G1 is in this mode. */
					  Adc_LeaveCritical();
					  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_BUSY);			  
					  bError = TRUE;
					}			
				  }		  
				}
			}		
			#endif /* (STD_ON == ADC_CFG_CHK_BUSY) */
			
			if(bError == FALSE)
			{
			  /* Register settings: */
			  
			  /* Modify freeze bit of mode control register: MODECR_FRZ */
			  if (ADC_HW_GROUP_G2 == CurrentGroupConfigPtr->GroupHwGroupId_u8)
			  {
				/* Reset all bits of MODECR to their default state. Set freeze enable bit (bit 0) to 1 */
				ModeCtrlRegWorkingCopy = (uint32)1U;    
			  }
			  else
			  {
				/* Reset all bits of MODECR to their default state. Amongst others freeze enable bit (bit 0) 
				   is set to 0 */
				ModeCtrlRegWorkingCopy = (uint32)0U;
			  }
			  
			  /* Modify mode bit of mode control register: MODECR_MODE */  
			  if (ADC_CONV_MODE_CONTINUOUS == CurrentGroupConfigPtr->GroupConversionMode_t)
			  {
				/* Set mode bit (bit 1) to 1: enable continuous conversion */
				ModeCtrlRegWorkingCopy |= ((uint32)1U << ADC_CONV_MODE_OFFSET);
			  }			  
			  /* else Mode bit remains 0: single conversion mode */
			  

			  /* Modify hw trigger bit of mode control register: MODECR_HW_TRIG */ 
			  /* Trigger bit remains 0: group is software triggered */
				
			  /* Resolution: Modify data format bits (PSFC66) or 8BIT bit (PSFD62) of mode control register: 
			     MODECR_DATA_FMT */
			  #if(STD_ON == ADC_CFG12_BIT_MODE_SUPPORTED)
			  if(((uint32)CurrentGroupConfigPtr->GroupResolution_t & 12U) == 12U)
			  {
				  /* 12 bit resolution is default */	
			  }
			  else if(((uint32)CurrentGroupConfigPtr->GroupResolution_t & 10U) == 10U)
			  {
				  ModeCtrlRegWorkingCopy |= (ADC_CFG_RES_10BIT << ADC_DATA_FORMAT_OFFSET);				  
			  }
			  else 
			  {
				  if(((uint32)CurrentGroupConfigPtr->GroupResolution_t & 8U) == 8U)
				  {
					ModeCtrlRegWorkingCopy |= (ADC_CFG_RES_8BIT << ADC_DATA_FORMAT_OFFSET);				  
				  }	
			  }			  
			  #endif
			  
			  /* Set group acquisition prescale bits (ACQ) of sample time register (SAMP). 
			   * Set register value = configured value - 2
			   * Reason: Total sample time = register value + 2 */
			  SampTimeRegWorkingCopy = (uint32)(CurrentGroupConfigPtr->GroupSampTime_t - 2U);
			  
			  /* Set interrupt enable bits (INT_EN) of register INT_ENA */
			  if (ADC_NOTIFICATION_OFF == CurrentGroupConfigPtr->GroupData_pt->Notification_u8)
			  {
				/* Enable threshold interrupt */
				IntEnaRegWorkingCopy = (uint32)1U;
				/* Set threshold variable */
				CurrentGroupConfigPtr->GroupData_pt->Threshold_t = CurrentGroupConfigPtr->GroupThreshold_t;
			  }
			  else
			  {
				/* Enable group end interrupt so that notification is sent each time a group conversion is completed */
				IntEnaRegWorkingCopy = ((uint32)1U << ADC_GROUP_END_INT_ENA_OFFSET);
				/* Set threshold variable */
				CurrentGroupConfigPtr->GroupData_pt->Threshold_t = 1U;
			  }
			  
			  /* Set bits 7:0 of threshold register to the number of RESULTS (channels, not full samples) after which 
			     an interrupt shall be generated. Therefore multiply GroupThreshold(which contains the number of 
				 SAMPLES after which an interrupt shall be generated) by NumberOfGroupChannels. */
			  IntThrRegWorkingCopy = 
				(uint32)((CurrentGroupConfigPtr->GroupThreshold_t * CurrentGroupConfigPtr->NumberOfGroupChannels_u8) 
					& ADC_INT_THR_REG_ABS_VALUE_MASK);
			  
			  /* Reset countdown variable to the number of stream samples, that fit in application result buffer */
			  CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t  = CurrentGroupConfigPtr->StreamingNumSamples_t;
			  /* Reset sample counter. No valid samples shall be in the buffer when group starts. */
			  CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U;
			  /* Toggle group state to ADC_BUSY */
			  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;
			  
			  /* Fill in group assignment table, to see which group was started last on the hw conversion group. */
			  /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			  Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
										  [CurrentGroupConfigPtr->GroupHwGroupId_u8] = Group; 

			  /* Set registers */
			  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
			  HwGroupBasePtr->ModeCtrlReg = ModeCtrlRegWorkingCopy;
			  HwGroupBasePtr->SampTimeReg = SampTimeRegWorkingCopy;
			  HwGroupBasePtr->IntEnaReg   = IntEnaRegWorkingCopy;
			  HwGroupBasePtr->IntThrReg   = IntThrRegWorkingCopy;
			  /* Set channel select register (CHNSEL) to start the group conversion */
			  HwGroupBasePtr->ChSelectReg = CurrentGroupConfigPtr->GroupDefinition_t;			  
			  Adc_LeaveCritical();
		  }
		} 
	}   
} /* End of Adc_StartGroupConversion() */

/**********************************************************************************************************************
 * Adc_StopGroupConversion
 *********************************************************************************************************************/
/*! \brief      Stop group conversion
 * 
 *              This method stops a software triggered group conversion. 
 * 
 *  \param[in]  Group           Numeric Id of requested Adc channel group.
 *
 *  \pre        The module has to be initialized. A group conversion shall be ongoing.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_007 */
/* DesignId : ADC_DesignId_007 */
/* Requirements : AR_ADC_SR112, AR_ADC_SR113, AR_ADC_SR115, AR_ADC_SR117, AR_ADC_SR118, AR_ADC_SR119, AR_ADC_SR120,
                  AR_ADC_SR121, AR_ADC_SR122, AR_ADC_SR123, AR_ADC_SR124 */
 FUNC(void, ADC_CODE) Adc_StopGroupConversion(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	Adc_GroupType LastGroup = 0U;
    
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /* Check for uninitialized module */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_STOP_GROUP_CONVERSION, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_STOP_GROUP_CONVERSION, ADC_E_PARAM_GROUP);      
    }
	else	
	#endif  
	{
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
		
		/* Validate trigger source */
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		if (ADC_TRIGG_SRC_HW == CurrentGroupConfigPtr->GroupTriggSrc_t)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_STOP_GROUP_CONVERSION, ADC_E_WRONG_TRIGG_SRC);		  
		}
		/* Check, if the group is active. Only an active, non-idling group can be stopped. */
		else if (ADC_IDLE == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		{
		  /* Current Group is in state ADC_IDLE: cannot be stopped. */
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_STOP_GROUP_CONVERSION, ADC_E_IDLE);		  
		}
		else	
		#endif   
		{
		  /* Get the index of the software group that was started last on this hardware group. */
		  /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
		  LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
												  [CurrentGroupConfigPtr->GroupHwGroupId_u8];
		  /* Affect hw only when the current group 'Group' was started last on this hw group and was not stopped in the 
		     meantime. */
		  if (Group == LastGroup)
		  {
			/* Stop hardware group. */
			/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
			HwGroupBasePtr->ChSelectReg = (uint32)(0x00U);
			/* Disable interrupts */
			HwGroupBasePtr->IntEnaReg = (uint32)(0x00U);
			/* Reset HwUnitGroupAssignment to default state, because HW is not in use anymore */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
										[CurrentGroupConfigPtr->GroupHwGroupId_u8] = ADC_INVALID_GRP_ID;
		  }		  
		  /* else Don't modify any hw registers, because group 'Group' is not on the HW anymore. */
		  
		  
		  /* Disable group notification */
		  CurrentGroupConfigPtr->GroupData_pt->Notification_u8 = ADC_NOTIFICATION_OFF;
		  
		  /* Set group state to ADC_IDLE */
		  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_IDLE;
		  
		  /* Reset ValidSampleCount and SampleCountdown */
		  CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t = CurrentGroupConfigPtr->StreamingNumSamples_t;
		  CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U;
		}  
	}  
}
#endif /* (STD_ON == ADC_ENABLE_START_STOP_GROUP_API) */

#if (ADC_READ_GROUP_API == STD_ON)
/**********************************************************************************************************************
 * Adc_ReadGroup
 *********************************************************************************************************************/
/*! \brief      Read group
 * 
 *              Reads the group conversion result of the last completed conversion round of the requested group and
 *              stores the channel values starting at the DataBufferPtr address. The group channel values are stored in 
 *              ascending channel number order (in contrast to the storage layout of the result buffer if streaming
 *              access is configured).
 * 
 *  \param[in]  Group               Numeric ID of requested ADC channel group.
 *  \param[in]  DataBufferPtr       ADC results of all channels of the selected group are stored in the data buffer 
 *                                  addressed with the pointer.
 * 
 *  \param[out] versioninfo         Data structure where the version info shall be written to
 * 
 *  \return     E_OK                Results are available and written to the data buffer.
 *  \return     E_NOT_OK            No results are available or development error occured          
 * 
 *  \pre        The module has to be initialized.
 * 
 *  \context    This function can be called on task level.
 **********************************************************************************************************************/
/* SourceId : ADC_SourceId_008 */
/* DesignId : ADC_DesignId_008 */
/* Requirements : AR_ADC_SR15, AR_ADC_SR16, AR_ADC_SR125, AR_ADC_SR126, AR_ADC_SR128, AR_ADC_SR129, AR_ADC_SR130,
                  AR_ADC_SR131, AR_ADC_SR132, AR_ADC_SR133, AR_ADC_SR134, AR_ADC_SR135 */
 FUNC(Std_ReturnType, ADC_CODE) Adc_ReadGroup(Adc_GroupType Group, Adc_ValueGroupRefType DataBufferPtr)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	Adc_ThresholdType OriginalThreshold = 0U;
	uint32 ChCounter_u32 = 0U;
	uint32 ResultPosition_u32 = 0U;
	Adc_GroupType LastGroup = 0U;  
	Std_ReturnType ReturnValue = E_OK;
  
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
	/* Check for uninitialized module */
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_READ_GROUP, ADC_E_UNINIT);
      ReturnValue = E_NOT_OK;
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_READ_GROUP, ADC_E_PARAM_GROUP);
      ReturnValue = E_NOT_OK; 
    }
	else	
	#endif 
	{
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
	  
		/* Check parameter 'DataBufferPtr' for referencing NULL_PTR. */
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		if (NULL_PTR == DataBufferPtr)
		{
		  /* DataBufferPtr references NULL_PTR. */
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_READ_GROUP, ADC_E_PARAM_READ_BUFFER);
		  ReturnValue = E_NOT_OK; 
		}
		/* Check, if the group is active. Only an active, non-idling group can be read. */
		else if (ADC_IDLE == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		{
		  /* Current Group is in state ADC_IDLE: cannot be read. */
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_READ_GROUP, ADC_E_IDLE);
		  ReturnValue = E_NOT_OK; 
		}
		else
		#endif    
		{
		  /* Get the index of the software group that was started last on this hardware group. */
		  /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
		  LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
												  [CurrentGroupConfigPtr->GroupHwGroupId_u8];
		  /* Affect HW only when the current group 'Group' was started last on this hw group and is still using it. */
			
		  Adc_EnterCritical();
		  
		  if ((Group == LastGroup) && (ADC_NOTIFICATION_OFF == CurrentGroupConfigPtr->GroupData_pt->Notification_u8))
		  {
			/* Force reading out fifo to get the latest values into application result buffer */			
			/* Store original threshold for later backup of the threshold value */
			OriginalThreshold = CurrentGroupConfigPtr->GroupData_pt->Threshold_t;
			
			/* The value 'Threshold' is needed by Adc_ProcessBuffer and Adc_ProcessConversion. Set this value to the
               number of completed conversion rounds (samples), that are currently in fifo and need to be copied to 
			   application result buffer.*/
			/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
			if (ADC_INT_THR_REG_SIGN_MASK == (uint32)(HwGroupBasePtr->IntThrReg & ADC_INT_THR_REG_SIGN_MASK))
			{
			  /* The value in IntThrReg has a negative sign. To get the number of samples, that are curr. in fifo 
			     divide the register absolute value by NumberOfGroupChannels and add this new value to 
				 GroupThreshold, which has been configured initially.*/
			  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
															   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
															   + (uint32)((HwGroupBasePtr->IntThrReg) & ADC_INT_THR_REG_ABS_VALUE_MASK))
															   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
			}
			else
			{
			  /* The value in IntThrReg has a positive sign. To get the number of samples, that are curr. in fifo 
			     divide the register abs. value by NumberOfGroupChannels and subtract this new value from 
				 GroupThreshold, which has been configured initially. */
			  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
															   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
															   - (HwGroupBasePtr->IntThrReg))
															   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
			}
			
			if (0U < CurrentGroupConfigPtr->GroupData_pt->Threshold_t)
			{
			  CurrentGroupConfigPtr->ProcessBuffer_p(CurrentGroupConfigPtr);
			  CurrentGroupConfigPtr->ProcessConversion_p(CurrentGroupConfigPtr);
			}			
			/*else no buffer processing neccessary, because no results are in fifo.*/
			
			/* Restore threshold value. */
			CurrentGroupConfigPtr->GroupData_pt->Threshold_t = OriginalThreshold;
		  }		  
		 /* else Notification is on, so after every completed conversion results are copied from fifo to result buffer
		    automatically. Buffer is always up to date: continue */
		  
		  
		  if (ADC_BUSY == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		  {
			/* No results are available. Group cannot be read. */			
			ReturnValue = E_NOT_OK;
		  }		  
		   /*else  State equals ADC_COMPLETED or ADC_STREAM_COMPLETED, so results are available: start reading group*/
		  
		  
		  /* No need for masking out other information, there is only the pure conversion result in result buffer 
		     without status bits or other information that needs to be masked out. */
		  
		  /* Calculate position of the NEXT entry in buffer */
		  ResultPosition_u32 = CurrentGroupConfigPtr->StreamingNumSamples_t 
							 - CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t;
		  
		  if (0U == ResultPosition_u32)
		  {
			/* The NEXT sample will be written at position [0], so the LATEST sample is at the last position 
			   in the buffer, which is [StreamingNumSamples - 1] */
			ResultPosition_u32 = CurrentGroupConfigPtr->StreamingNumSamples_t - 1U;
		  }
		  else
		  {
			/* The next result will be written at position [n], so the latest result in buffer is at [n-1] */
			ResultPosition_u32--;
		  }
			
		  for (ChCounter_u32 = 0U; ChCounter_u32 < CurrentGroupConfigPtr->NumberOfGroupChannels_u8; ChCounter_u32++)
		  {
			/* Explanation of the formula below:
			 * 
			 * Write the channel i (i = 0..n-1) of the latest sample in the application result buffer to 
			 * position[i] of the application read buffer.
			 * 
			 * ChCounter_u32 * CurrentGroupConfigPtr->StreamingNumSamples :   provides the offset of the n-th channel 
			 *                                                                base address to the result buffer base address.
			 * 
			 * ResultPosition_u32 :                                           provides the position of the latest converted 
			 *                                                                sample in buffer
			 */
			
			/* Write to application read buffer */
			/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - DataBufferPtr is pointer. "*/
			DataBufferPtr[ChCounter_u32] =
			 CurrentGroupConfigPtr->GroupData_pt->ResultBuffer_pt[(ChCounter_u32 * CurrentGroupConfigPtr->StreamingNumSamples_t)
			 + ResultPosition_u32];
		  }
		  
		  /* Reset ValidSampleCount after read process */
		  CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U;
		  
		  /* State transition after reading to buffer */
		  if (ADC_COMPLETED == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		  {
			/* Conversion has not been finished, when the group was read. State transition to ADC_BUSY */
			CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;
		  }
		  else
		  {
			/* Conversion has been finished before the group was read. 
			 * State transition to ADC_IDLE if the group stops implicitly or
			 *                  to ADC_BUSY if the group has to be stopped explicitly. */
			if (ADC_GROUP_STOP_EXPLICIT == CurrentGroupConfigPtr->GroupStopMode_u8)
			{
			  /* Group has to be stopped explicitly, so conversion is going on after this read. */
			  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;
			}
			else 
			{
			  /* Group stops implicitly when ADC_STREAM_COMPLETED is reached and the group is read. */
			  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_IDLE;		
			}
		  }
		  Adc_LeaveCritical();
		}  
	}  
	return (ReturnValue);
}
#endif /* (ADC_READ_GROUP_API == STD_ON) */

#if (STD_ON == ADC_HW_TRIGGER_API)
/**********************************************************************************************************************
 * Adc_EnableHardwareTrigger
 *********************************************************************************************************************/
/*! \brief      Enable Hardware Trigger
 * 
 *              Enables the hardware trigger for the requested Adc channel group. 
 * 
 *  \param[in]  Group             Numeric Id of requested Adc channel group.
 *
 *  \pre        The module has to be initialized.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_009 */
/* DesignId : ADC_DesignId_009 */
/* Requirements : AR_ADC_SR136, AR_ADC_SR137, AR_ADC_SR138, AR_ADC_SR139, AR_ADC_SR140, AR_ADC_SR141, AR_ADC_SR142,
                  AR_ADC_SR143, AR_ADC_SR144, AR_ADC_SR145, AR_ADC_SR146, AR_ADC_SR147, AR_ADC_SR148, AR_ADC_SR149, 
				  AR_ADC_SR150 */
FUNC(void, ADC_CODE) Adc_EnableHardwareTrigger(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	uint32 ModeCtrlRegWorkingCopy = 0U;
	uint32 SourceRegWorkingCopy = 0U;
	uint32 SampTimeRegWorkingCopy = 0U;
	uint32 IntEnaRegWorkingCopy = 0U;
	uint32 IntThrRegWorkingCopy = 0U;
	boolean bError = FALSE;
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
	Adc_GroupType LastGroup = 0U;
	#endif

  
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /* Check for uninitialized module */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_PARAM_GROUP);     
    }
    else
	#endif 
	{
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
		
		/* Validate trigger source */
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		if (ADC_TRIGG_SRC_SW == CurrentGroupConfigPtr->GroupTriggSrc_t)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_WRONG_TRIGG_SRC);
		}
		else if(ADC_CONV_MODE_CONTINUOUS  == CurrentGroupConfigPtr->GroupConversionMode_t)
		{
			(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_WRONG_CONV_MODE);
		}
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		else if (NULL_PTR == CurrentGroupConfigPtr->GroupData_pt->ResultBuffer_pt)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_BUFFER_UNINIT);		  
		}
		else	
		#endif		
		{
			Adc_EnterCritical();

			/* Check if requested Hw unit is ready for use. */  
			#if (STD_ON == ADC_DEV_ERROR_DETECT)			
			/* Check which software group was started last on the requested hardware group. */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
													[CurrentGroupConfigPtr->GroupHwGroupId_u8];
			
			if (ADC_INVALID_GRP_ID == LastGroup)
			{
			  /* Currently there no group using this HW unit. */
			}
			else
			{
			  /* Another software group has been started on this hardware group before.  
			   * Check if the other group has finished conversion before starting this group.  */
			  if ((ADC_BUSY     == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupData_pt->Status_t)
			  || (ADC_COMPLETED == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupData_pt->Status_t))
			  {
				/* The group that was started before has not finished until now. */
				Adc_LeaveCritical();
				(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_BUSY);
				bError = TRUE;
			  }
			  else 
			  {
				if (ADC_STREAM_COMPLETED == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupData_pt->Status_t)
				{
					/* Check if the group, that was started before, was a group that has to be stopped explicitly. */
					if (ADC_GROUP_STOP_EXPLICIT == Adc_ConfigPtr_pt->Group_at[LastGroup].GroupStopMode_u8)
					{
					  /* Group has to be stopped explicitly. State ADC_STREAM_COMPLETED means, that group is still converting, but
					   * only buffer is filled completely. Error. */
					  Adc_LeaveCritical();
					  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_HARDWARE_TRIGGER, ADC_E_BUSY);
					  bError = TRUE;
					}				
				}	
			  }			  			  
			} /* end of: ADC_INVALID_GRP_ID == LastGroup */
		  #endif
		
		  if(bError == FALSE)		
		  {
			  /* Register settings: */		  
			  
			  /* Modify freeze bit of mode control register: MODECR_FRZ */
			  if (ADC_HW_GROUP_G2 == CurrentGroupConfigPtr->GroupHwGroupId_u8)
			  {
				/* Reset all bits of MODECR to their default state. Set freeze enable bit (bit 0) to 1 */
				ModeCtrlRegWorkingCopy = (uint32)1U;    
			  }
			  else
			  {
				/* Reset all bits of MODECR to their default state. Amongst others, freeze enable bit (bit 0) is set to 0 */
				ModeCtrlRegWorkingCopy = (uint32)0U;
			  }
			  
			  /* Mode bit remains 0: always single conversion mode */
			  
			  /* Modify hw trigger bit of mode control register: MODECR_HW_TRIG */ 
			  /* Set trigger bit (bit 3) to 1: conversion is hardware triggered */
			  /* Set this bit for all the groups, even though event group does not provide (need) this bit, because it is always
			   * hardware triggered. Writing this bit to event group has no effect. */
			  ModeCtrlRegWorkingCopy |= ((uint32)1U << ADC_HW_TRIG_OFFSET);
			  /* Set hardware trigger source(SRC): 0 for event pin, 1 - 7 for internal timers  */
			  /* Reset all other bits of register SRC */
			  SourceRegWorkingCopy = (uint32)CurrentGroupConfigPtr->GroupHwTriggerTimer_t;
			  /* Set edge (EDG_SEL) (raising or falling) on which the group shall be triggered */
			  if (ADC_HW_TRIG_RISING_EDGE == CurrentGroupConfigPtr->HwTrigSignal_t)
			  {
				/* Set EDG_SEL bit (bit 3) of SRC register to 1 (rising edge) */
				SourceRegWorkingCopy |= ((uint32)1U << ADC_EDGE_SELECT_OFFSET);
			  }
			  else if (ADC_HW_TRIG_BOTH_EDGES == CurrentGroupConfigPtr->HwTrigSignal_t)
			  {
				/* Set EDG_SEL bits (bit 3 and 4) of SRC register to 10(binary) (both edges) */
				SourceRegWorkingCopy |= ((uint32)2U << ADC_EDGE_SELECT_OFFSET);
			  }
			  else
			  {
				 /*EDG_SEL bit (bit) of SRC register remains 0 (falling edge) */
			  }
			  
			  /* Resolution: Modify data format bits (PSFC66) or 8BIT bit (PSFD62) of mode control register: MODECR_DATA_FMT */
			   #if(STD_ON == ADC_CFG12_BIT_MODE_SUPPORTED)
			  if(((uint32)CurrentGroupConfigPtr->GroupResolution_t & 10U) == 10U)
			  {
				  ModeCtrlRegWorkingCopy |= (ADC_CFG_RES_10BIT << ADC_DATA_FORMAT_OFFSET);				  
			  }
			  else if(((uint32)CurrentGroupConfigPtr->GroupResolution_t & 8U) == 8U)
			  {
				  ModeCtrlRegWorkingCopy |= (ADC_CFG_RES_8BIT << ADC_DATA_FORMAT_OFFSET);				  
			  }
			  else
			  {
				  /* 12 bit resolution is default */	
			  }
			  #endif			  
			  
			  /* Set group acquisition prescale bits (ACQ) of sample time register (SAMP). 
			   * Set register value = configured value - 2
			   * Reason: Total sample time = register value + 2 */
			  SampTimeRegWorkingCopy = (uint32)(CurrentGroupConfigPtr->GroupSampTime_t - 2U);
			  
			  /* Set interrupt enable bits (INT_EN) of register INT_ENA */
			  if (ADC_NOTIFICATION_OFF == CurrentGroupConfigPtr->GroupData_pt->Notification_u8)
			  {
				/* Enable threshold interrupt */
				IntEnaRegWorkingCopy = (uint32)1U;
				/* Set threshold variable */
				CurrentGroupConfigPtr->GroupData_pt->Threshold_t = CurrentGroupConfigPtr->GroupThreshold_t;
			  }
			  else
			  {
				/* Enable group end interrupt so that notification is sent each time a group conversion is completed */
				IntEnaRegWorkingCopy = ((uint32)1U << ADC_GROUP_END_INT_ENA_OFFSET);
				/* Set threshold variable */
				CurrentGroupConfigPtr->GroupData_pt->Threshold_t = 1U;
			  }
			  
			  /* Set bits 7:0 of threshold register to the number of RESULTS (channels, not full samples) after which 
			     an interrupt shall be generated. Therefore multiply GroupThreshold(which contains the number of 
				 SAMPLES after which an interrupt shall be generated) by NumberOfGroupChannels.*/
			  IntThrRegWorkingCopy = 
				(uint32)((CurrentGroupConfigPtr->GroupThreshold_t * CurrentGroupConfigPtr->NumberOfGroupChannels_u8) 
					& ADC_INT_THR_REG_ABS_VALUE_MASK);
			  
			  /* Reset countdown variable to the number of stream samples, that fit in buffer */
			  CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t = CurrentGroupConfigPtr->StreamingNumSamples_t;
			  /* Reset sample counter. No valid samples shall be in the buffer when group starts. */
			  CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U;
			  /* Toggle group state to ADC_BUSY */
			  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;
			  
			  /* Fill in group assignment table, to see which group was started last on the hw conversion group. */
			  /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			  Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
										  [CurrentGroupConfigPtr->GroupHwGroupId_u8] = Group; 

			  /* Set registers */
			  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
			  HwGroupBasePtr->SourceReg = SourceRegWorkingCopy;
			  HwGroupBasePtr->ModeCtrlReg = ModeCtrlRegWorkingCopy;
			  HwGroupBasePtr->SampTimeReg = SampTimeRegWorkingCopy;
			  HwGroupBasePtr->IntEnaReg = IntEnaRegWorkingCopy;
			  HwGroupBasePtr->IntThrReg = IntThrRegWorkingCopy;
			  /* Set channel select register (CHNSEL) to finally start the group conversion */
			  HwGroupBasePtr->ChSelectReg = CurrentGroupConfigPtr->GroupDefinition_t;
			  
			  Adc_LeaveCritical();
		  }	
		}  
	}  
}

/*********************************************************************************************************************
 * Adc_DisableHardwareTrigger
 *********************************************************************************************************************/
/*! \brief      Disable Hardware Trigger
 * 
 *              Disables the hardware trigger for the requested Adc channel group. 
 * 
 *  \param[in]  Group             Numeric Id of requested Adc channel group.
 *
 *  \pre        The module has to be initialized.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_010 */
/* DesignId : ADC_DesignId_010 */
/* Requirements : AR_ADC_SR151, AR_ADC_SR152, AR_ADC_SR154, AR_ADC_SR155, AR_ADC_SR156, AR_ADC_SR157, AR_ADC_SR158,
                  AR_ADC_SR159, AR_ADC_SR160, AR_ADC_SR161, AR_ADC_SR162, AR_ADC_SR163 */
 FUNC(void, ADC_CODE) Adc_DisableHardwareTrigger(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	Adc_GroupType LastGroup = 0U;
 	
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /* Check for uninitialized module */
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_HARDWARE_TRIGGER, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_HARDWARE_TRIGGER, ADC_E_PARAM_GROUP);     
    } 
	else	
	#endif 
	{
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;		
	  
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		/* Validate trigger source */
		if (ADC_TRIGG_SRC_SW == CurrentGroupConfigPtr->GroupTriggSrc_t)
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_HARDWARE_TRIGGER, ADC_E_WRONG_TRIGG_SRC);		  
		}
		else if(ADC_CONV_MODE_CONTINUOUS  == CurrentGroupConfigPtr->GroupConversionMode_t)
		{
			(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_HARDWARE_TRIGGER, ADC_E_WRONG_CONV_MODE);
		}
		/* Check, if the group is active. Only an active, non-idling group can be stopped. */
		else if (ADC_IDLE == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		{
		  /* Current Group is in state ADC_IDLE: cannot be stopped. */
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_HARDWARE_TRIGGER, ADC_E_IDLE);		  
		} 
		else	
		#endif
		{
			/* Get the index of the software group that was started last on this hardware group. */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
												  [CurrentGroupConfigPtr->GroupHwGroupId_u8];
			/* Affect hw only when the current group 'Group' was started last on this hw group and is still active. */
			if (Group == LastGroup)  
			{
				/* Stop hardware conversion group. */
				/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
				HwGroupBasePtr->ChSelectReg = (uint32)(0x00U);
				/* Disable interrupts */
				HwGroupBasePtr->IntEnaReg = (uint32)(0x00U);
				/* Reset HwUnitGroupAssignment to default state, because HW is not in use anymore */
				/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
				Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
										[CurrentGroupConfigPtr->GroupHwGroupId_u8] = ADC_INVALID_GRP_ID;
			}	
		  
			/* Disable group notification */
			CurrentGroupConfigPtr->GroupData_pt->Notification_u8 = ADC_NOTIFICATION_OFF;
		  
			/* Set group state to ADC_IDLE */
			CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_IDLE;
		  
			/* Reset ValidSampleCount and SampleCountdown */
			CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t = CurrentGroupConfigPtr->StreamingNumSamples_t;
			CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U; 
		}	
	}	
}
#endif /* (STD_ON == ADC_HW_TRIGGER_API) */ 

#if (STD_ON == ADC_GRP_NOTIF_CAPABILITY)
/**********************************************************************************************************************
 * Adc_EnableGroupNotification
 *********************************************************************************************************************/
/*! \brief      Enable Group Notification
 * 
 *              Enables the notification mechanism for the requested Adc channel group. 
 * 
 *  \param[in]  Group             Numeric Id of requested Adc channel group.
 *
 *  \pre        The module has to be initialized.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_011 */
/* DesignId : ADC_DesignId_011 */
/* Requirements : AR_ADC_SR164, AR_ADC_SR165, AR_ADC_SR166, AR_ADC_SR167, AR_ADC_SR168, AR_ADC_SR169 */
 FUNC(void, ADC_CODE) Adc_EnableGroupNotification(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr;
	Adc_GroupConfigRefType CurrentGroupConfigPtr;
	Adc_GroupType LastGroup;
	
	/* Check for uninitialized module */
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_GROUP_NOTIFICATION, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_GROUP_NOTIFICATION, ADC_E_PARAM_GROUP);      
    }
	else	
	#endif 
	{  
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
	  
		/* Validate notification function pointers */
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		if ( NULL_PTR == CurrentGroupConfigPtr->Notification_p[1] )
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_ENABLE_GROUP_NOTIFICATION, ADC_E_NOTIF_CAPABILITY);     
		}
		else	
		#endif
		{
			/* Get the index of the software group that was started last on this hardware group. */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
													[CurrentGroupConfigPtr->GroupHwGroupId_u8];
		  
			Adc_EnterCritical();
		  
			/* Read buffer only when the current software group 'Group' was started last on this hw unit and is 
			   still active  */
			if (Group == LastGroup)
			{
				/* Force reading out fifo to get the latest values into application result buffer */
			
				/* The value 'Threshold' is needed by Adc_ProcessBuffer and Adc_ProcessConversion. Set this value
                   to the number of completed conversion rounds (samples), that are currently in fifo and need 
				   to be copied to application result buffer.*/
				/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
				if (ADC_INT_THR_REG_SIGN_MASK == (uint32)(HwGroupBasePtr->IntThrReg & ADC_INT_THR_REG_SIGN_MASK))
				{
					/* The value in IntThrReg has a negative sign. To get the number of samples, that are curr. 
					   in fifo divide the register absolute value by NumberOfGroupChannels and add this new 
					   value to GroupThreshold, which has been configured initially.*/
					CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
																	 * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
																	 + (uint32)((HwGroupBasePtr->IntThrReg) & ADC_INT_THR_REG_ABS_VALUE_MASK))
																	 / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
				}
				else
				{
				  /* The value in IntThrReg has a positive sign. To get the number of samples, that are curr. 
				     in fifo divide the register abs. value by NumberOfGroupChannels and subtract this new 
					 value from GroupThreshold, which has been configured initially.  */
				  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
																   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
																   - (HwGroupBasePtr->IntThrReg))
																   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
				}
			
				if (0U < CurrentGroupConfigPtr->GroupData_pt->Threshold_t)
				{
				  CurrentGroupConfigPtr->ProcessBuffer_p(CurrentGroupConfigPtr);
				  CurrentGroupConfigPtr->ProcessConversion_p(CurrentGroupConfigPtr);
				}		
			}	  

			/* Modify interrupt enable bits only when the current software group 'Group' was started last on this hw, 
			  or if HW is currently not in use (ADC_INVALID_GRP_ID).*/
			if ((Group == LastGroup) || (ADC_INVALID_GRP_ID == LastGroup))
			{
				/* Toggle interrupt enable bits. Notification is on, so group end interrupt has to be enabled and group
				   threshold interrupt has to be disabled. If group end interrupt is enabled, ISR is executed each time
                   a conversion round has been finished. */
				HwGroupBasePtr->IntEnaReg = ((uint32)1U << ADC_GROUP_END_INT_ENA_OFFSET);
			
			}

			/* Set threshold value to 1u, because notification is enabled, and ISR is called after each conversion. */
			CurrentGroupConfigPtr->GroupData_pt->Threshold_t = 1U;
		   
			/* Set group notification status to on */
			CurrentGroupConfigPtr->GroupData_pt->Notification_u8 = ADC_NOTIFICATION_ON;
		  
			Adc_LeaveCritical();
		}  
	}    
}

/**********************************************************************************************************************
 * Adc_DisableGroupNotification
 *********************************************************************************************************************/
/*! \brief      Disable Group Notification
 * 
 *              Disables the notification mechanism for the requested Adc channel group. 
 * 
 *  \param[in]  Group             Numeric Id of requested Adc channel group.
 *
 *  \pre        The module has to be initialized.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_012 */
/* DesignId : ADC_DesignId_012 */
/* Requirements : AR_ADC_SR170, AR_ADC_SR171, AR_ADC_SR172, AR_ADC_SR173, AR_ADC_SR174, AR_ADC_SR175 */
 FUNC(void, ADC_CODE) Adc_DisableGroupNotification(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	Adc_GroupType LastGroup = 0U;

	/* Check for uninitialized module */
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_GROUP_NOTIFICATION, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_GROUP_NOTIFICATION, ADC_E_PARAM_GROUP);     
    }
	else	
	#endif
	{
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
	  
	  /* Validate notification function pointers */
		#if (STD_ON == ADC_DEV_ERROR_DETECT)
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		if ( NULL_PTR == CurrentGroupConfigPtr->Notification_p[1U] )
		{
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_DISABLE_GROUP_NOTIFICATION, ADC_E_NOTIF_CAPABILITY);		  
		}
		else	
		#endif
		{
			/* Get the index of the software group that was started last on this hardware group. */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]			  									    
													[CurrentGroupConfigPtr->GroupHwGroupId_u8];
			  
			Adc_EnterCritical();
			  
			/* Affect hw only when the current group 'Group' was started last on this hw group, or when HW is 
			   currently not in use. */
			if ((Group == LastGroup) || (ADC_INVALID_GRP_ID == LastGroup))
			{
				/* Change interrupt enable flags. Disable group end interrupt and enable group threshold 
				   interrupt. */
				/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a 
				  value in INI."*/
				HwGroupBasePtr->IntEnaReg = (uint32)1U;
			}	  
			  
			/* Change threshold to the number of samples that are configured statically. */
			CurrentGroupConfigPtr->GroupData_pt->Threshold_t = CurrentGroupConfigPtr->GroupThreshold_t;
			  
			/* Change notification status */
			CurrentGroupConfigPtr->GroupData_pt->Notification_u8 = ADC_NOTIFICATION_OFF;	  
			Adc_LeaveCritical();
		}  
	}  
}
#endif /* (STD_ON == ADC_GRP_NOTIF_CAPABILITY) */

/**********************************************************************************************************************
 * Adc_GetGroupStatus
 *********************************************************************************************************************/
/*! \brief      Get Group Status
 * 
 *              Returns the conversion status of the requested ADC channel group
 *
 *  \param[in]  Group                     Numeric Id of requested Adc channel group.
 * 
 *  \return     Adc_StatusType            Conversion status for the requested group.
 * 
 *  \pre        The module has to be initialized.
 * 
 *  \context    This function can be called on task level.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_013 */
/* DesignId : ADC_DesignId_013 */
/* Requirements : AR_ADC_SR176, AR_ADC_SR177, AR_ADC_SR178, AR_ADC_SR179, AR_ADC_SR180, AR_ADC_SR181, AR_ADC_SR183,
                  AR_ADC_SR184, AR_ADC_SR185 */
 FUNC(Adc_StatusType, ADC_CODE) Adc_GetGroupStatus(Adc_GroupType Group)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	Adc_GroupType LastGroup = 0U;
	Adc_ThresholdType OriginalThreshold = 0U;
	Adc_StatusType Status = ADC_IDLE;

	/* Check for uninitialized module */
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_GROUP_STATUS, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_GROUP_STATUS, ADC_E_PARAM_GROUP);      
    }
	else	
	#endif 
	{
		/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already assigned a value in INI."*/
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
		HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt; 
	  
		if (ADC_IDLE == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		{
			/* Group has not been started yet. */			
		}
		else
		{	  
			/* Get the index of the software group that was started last on this hardware group. */
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]												  
												    [CurrentGroupConfigPtr->GroupHwGroupId_u8];
			/* Affect hw only when the current group 'Group' was started last on this hw group and is still active. */			
			Adc_EnterCritical();		  
			if ((Group == LastGroup) && (ADC_NOTIFICATION_OFF == CurrentGroupConfigPtr->GroupData_pt->Notification_u8))
			{
				/* Force reading out fifo to get the latest values into application result buffer */
				
				/* Store original threshold for later backup of the threshold value */
				OriginalThreshold = CurrentGroupConfigPtr->GroupData_pt->Threshold_t;
				
				/* The value 'Threshold' is needed by Adc_ProcessBuffer and Adc_ProcessConversion. Set this value to 
				   the number of completed conversion rounds (samples), that are currently in fifo and need to be 
				   copied to application result buffer. */
				/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
				if (ADC_INT_THR_REG_SIGN_MASK == (uint32)(HwGroupBasePtr->IntThrReg & ADC_INT_THR_REG_SIGN_MASK))
				{
				  /* The value in IntThrReg has a negative sign. To get the number of samples, that are curr. in fifo 
				     divide the register absolute value by NumberOfGroupChannels and add this new value to 
					 GroupThreshold, which has been configured initially. */
				  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
																   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
																   + (uint32)((HwGroupBasePtr->IntThrReg) & ADC_INT_THR_REG_ABS_VALUE_MASK))
																   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
				}
				else
				{
				  /* The value in IntThrReg has a positive sign. To get the number of samples, that are curr. in fifo
                     divide the register abs. value by NumberOfGroupChannels and subtract this new value from 
					 GroupThreshold, which has been configured initially. */
				  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
																   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
																   - (HwGroupBasePtr->IntThrReg))
																   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
				}
			
				if (0U < CurrentGroupConfigPtr->GroupData_pt->Threshold_t)
				{
				  CurrentGroupConfigPtr->ProcessBuffer_p(CurrentGroupConfigPtr);
				  CurrentGroupConfigPtr->ProcessConversion_p(CurrentGroupConfigPtr);
				}		
				/* Restore threshold value. */
				CurrentGroupConfigPtr->GroupData_pt->Threshold_t = OriginalThreshold;
			}	 
			Adc_LeaveCritical();
			Status = CurrentGroupConfigPtr->GroupData_pt->Status_t;
		}	
	}    
	return (Status);
}


/**********************************************************************************************************************
 * Adc_GetStreamLastPointer
 *********************************************************************************************************************/
/*! \brief      Get Stream Last Pointer
 * 
 *              Returns the number of valid samples per channel, stored in the result buffer.
 *              Reads a pointer, pointing to a position in the group result buffer. With the pointer position, the 
 *              results of all group channels of the last completed conversion round can be accessed.
 *              With the pointer and the return value, all valid group conversion results can be accessed 
 *              (the user has to take the layout of the result buffer into account).
 *
 *  \param[in]  Group                     Numeric Id of requested Adc channel group.
 *  \param[out] PtrToSamplePtr            Pointer to result buffer pointer.
 * 
 *  \return     Adc_StreamNumSampleType   Number of valid samples per channel.
 * 
 *  \pre        The module has to be initialized.
 * 
 *  \context    This function can be called on task level.
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_014 */
/* DesignId : ADC_DesignId_014 */
/* Requirements : AR_ADC_SR14, AR_ADC_SR187, AR_ADC_SR188, AR_ADC_SR190, AR_ADC_SR191, AR_ADC_SR192, AR_ADC_SR193,
                  AR_ADC_SR194, AR_ADC_SR195, AR_ADC_SR196, AR_ADC_SR197, AR_ADC_SR198 */
 FUNC(Adc_StreamNumSampleType, ADC_CODE) Adc_GetStreamLastPointer(Adc_GroupType Group,
                                                                 Adc_ValueGroupRefRefType PtrToSamplePtr)
{
	volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr = 0U;
	Adc_GroupConfigRefType CurrentGroupConfigPtr = 0U;
	Adc_GroupType LastGroup = 0U;
	Adc_ThresholdType OriginalThreshold = 0U;
	uint32 ResultPosition_u32 = 0U;
	Adc_StreamNumSampleType SampleReturnValue = 0U;
	boolean bError = FALSE;

	/* Check for uninitialized module */
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == Adc_ConfigPtr_pt)
    {
      /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	  *PtrToSamplePtr = NULL_PTR;
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_STREAM_LAST_POINTER, ADC_E_UNINIT);      
    }
    /* Validate parameter 'Group' */
	else if (Group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
    {
      /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	  *PtrToSamplePtr = NULL_PTR;
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_STREAM_LAST_POINTER, ADC_E_PARAM_GROUP);      
    }    
	else
	#endif
	{
	  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Since Adc_ConfigPtr_pt is already checked for NULL in INI,
														CurrentGroupConfigPtr cannot be NULL."*/
	  CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
	  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
	  HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt; 
	  
	  #if (STD_ON == ADC_DEV_ERROR_DETECT)
	  /* Validate parameter PtrToSamplePtr */
	  /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	  if (NULL_PTR == PtrToSamplePtr)
	  {
		  (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_STREAM_LAST_POINTER, ADC_E_PARAM_STREAM_PTR);		  
	  }
	  else if(ADC_IDLE == CurrentGroupConfigPtr->GroupData_pt->Status_t)
	  {
		/* Current Group is in state ADC_IDLE: cannot be read. */
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
		*PtrToSamplePtr = NULL_PTR;
		(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_STREAM_LAST_POINTER, ADC_E_IDLE);		
	  }
	  else
	  #endif
	  {		  
		  /* Get the index of the software group that was started last on this hardware group. */
		  /*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
		  LastGroup = Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]												  
												  [CurrentGroupConfigPtr->GroupHwGroupId_u8];
		  /* Affect hw only when the current group 'Group' was started last on this hw group and is still active. */
			
		  Adc_EnterCritical();
		  
		  if ((Group == LastGroup) && (ADC_NOTIFICATION_OFF == CurrentGroupConfigPtr->GroupData_pt->Notification_u8))
		  {
			/* Force reading out fifo to get the latest values into application result buffer */
			
			/* Store original threshold for later backup of the threshold value */
			OriginalThreshold = CurrentGroupConfigPtr->GroupData_pt->Threshold_t;
			
			/* The value 'Threshold' is needed by Adc_ProcessBuffer and Adc_ProcessConversion. Set this value to 
			   the number of completed conversion rounds (samples), that are currently in fifo and need to be 
			   copied to application result buffer.*/
			/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
			if (ADC_INT_THR_REG_SIGN_MASK == (uint32)(HwGroupBasePtr->IntThrReg & ADC_INT_THR_REG_SIGN_MASK))
			{
			  /* The value in IntThrReg has a negative sign. To get the number of samples, that are curr. in fifo 
			     divide the register absolute value by NumberOfGroupChannels and add this new value to GroupThreshold,
				 which has been configured initially. */
			  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
															   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
															   + (uint32)((HwGroupBasePtr->IntThrReg) & (uint32)ADC_INT_THR_REG_ABS_VALUE_MASK))
															   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
			}
			else
			{
			  /* The value in IntThrReg has a positive sign. To get the number of samples, that are curr. in fifo 
			     divide the register abs. value by NumberOfGroupChannels and subtract this new value from 
				 GroupThreshold, which has been configured initially. */
			  CurrentGroupConfigPtr->GroupData_pt->Threshold_t = (Adc_ThresholdType)((uint32)(((CurrentGroupConfigPtr->GroupThreshold_t)
															   * (uint32)(CurrentGroupConfigPtr->NumberOfGroupChannels_u8))
															   - (HwGroupBasePtr->IntThrReg))
															   / (CurrentGroupConfigPtr->NumberOfGroupChannels_u8));  
			}
			
			if (0U < CurrentGroupConfigPtr->GroupData_pt->Threshold_t)
			{
			  CurrentGroupConfigPtr->ProcessBuffer_p(CurrentGroupConfigPtr);
			  CurrentGroupConfigPtr->ProcessConversion_p(CurrentGroupConfigPtr);
			}		
			/* else no buffer processing neccessary, because no results are in fifo. */
			
			/* Restore threshold value. */
			CurrentGroupConfigPtr->GroupData_pt->Threshold_t = OriginalThreshold;
		  }		  
		  /*else Notification is on, so after every completed conversion results are copied from fifo to result buffer
		    automatically. Buffer is always up to date: continue*/
		  
		  
		  if(ADC_BUSY == CurrentGroupConfigPtr->GroupData_pt->Status_t)		     
		  {
			/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
			*PtrToSamplePtr = NULL_PTR;
			Adc_LeaveCritical();
			bError = TRUE;
		  }
		  if(ADC_IDLE == CurrentGroupConfigPtr->GroupData_pt->Status_t)
		  {
			Adc_LeaveCritical();
			bError = TRUE;
		  }
		  	
		  /* No need for masking out other information, there is only the pure conversion result in result buffer 
		     without status bits or other information that needs to be masked out.  */
		  if(bError == FALSE)
		  {
			  /* Calculate position of the NEXT entry in buffer */
			  ResultPosition_u32 = CurrentGroupConfigPtr->StreamingNumSamples_t 
								 - CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t;
			  
			  if (0U == ResultPosition_u32)
			  {
				/* The NEXT result will be written at position [0], so the LATEST result is at the last position 
				   in the buffer, which is [StreamingNumSamples - 1] */
				ResultPosition_u32 = CurrentGroupConfigPtr->StreamingNumSamples_t - 1U;
			  }
			  else
			  {
				/* The next result will be written at position [n], so the latest result in buffer is at [n-1] */
				ResultPosition_u32--;
			  } 
			  
			  /* Let PtrToSamplePtr refer to the latest element in application result buffer. */
			  (*PtrToSamplePtr) = &(CurrentGroupConfigPtr->GroupData_pt->ResultBuffer_pt[ResultPosition_u32]);
			  
			  SampleReturnValue = CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t;
			  
			  /* Reset ValidSampleCount after read process */
			  CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U;
			  
			  /* State transition after getting StreamLastPointer */
			  if (ADC_COMPLETED == CurrentGroupConfigPtr->GroupData_pt->Status_t)
			  {
				/* Conversion has not been finished, when the group was read. State transition to ADC_BUSY */
				CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;
			  }
			  else
			  {
				/* Conversion has been finished before the group was read. 
				 * State transition to ADC_IDLE if the group stops implicitly or
				 *                  to ADC_BUSY if the group has to be stopped explicitly. */
				if (ADC_GROUP_STOP_EXPLICIT == CurrentGroupConfigPtr->GroupStopMode_u8)
				{
				  /* Group has to be stopped explicitly, so conversion is going on after this read. */
				  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;
				}
				else 
				{
				  /* Group stops implicitly when ADC_STREAM_COMPLETED is reached and the group is read. */
				  CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_IDLE;		
				}
			  }			  
		  }  
		  Adc_LeaveCritical();
		}  
	}  
  return (SampleReturnValue);
}

#if (ADC_VERSION_INFO_API == STD_ON)
/**********************************************************************************************************************
 * Adc_GetVersionInfo
 *********************************************************************************************************************/
/*! \brief      Version Information Service
 * 
 *              This service writes the version information of this module into the data structure referenced by the 
 *              parameter. If this parameter references NULL_PTR, a development error is reported to Det. This service
 *              is only available if the pre-compile configuration parameter ADC_VERSION_INFO_API is enabled.
 * 
 *  \param[out] versioninfo         data structure where the version info shall be written to
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_015 */
/* DesignId : ADC_DesignId_015 */
/* Requirements : AR_ADC_SR199, AR_ADC_SR200, AR_ADC_SR201, AR_ADC_SR202 */
 FUNC(void, ADC_CODE) Adc_GetVersionInfo(P2VAR(Std_VersionInfoType, AUTOMATIC, ADC_APPL_DATA) versioninfo)
{
	#if (STD_ON == ADC_DEV_ERROR_DETECT)
    /*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - Casting is required here."*/
	if (NULL_PTR == versioninfo)
    {        
      (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_GET_VERSION_INFO, ADC_E_PARAM_POINTER);     
    }    
	else
	#endif
	{
	  versioninfo->vendorID         = (uint16) ADC_VENDOR_ID;
	  versioninfo->moduleID         = (uint16) ADC_MODULE_ID;
	  versioninfo->sw_major_version = (uint8)  ADC_SW_MAJOR_VERSION;
	  versioninfo->sw_minor_version = (uint8)  ADC_SW_MINOR_VERSION;
	  versioninfo->sw_patch_version = (uint8)  ADC_SW_PATCH_VERSION; 
    }  
} /* End of Adc_GetVersionInfo() */
#endif /* End of: (ADC_VERSION_INFO_API == STD_ON) */

/**********************************************************************************************************************
 *  Adc_IrqFunction
 *********************************************************************************************************************/
/*! \brief      Interrupt Handler
 * 
 *              This handler is called by the ISR. It is responsible for looking up the group Id, of the software group
 *              which triggered the interrupt, for reading results from fifo to application result buffer and calling
 *              the notification function, if enabled. 
 * 
 *  \param[in]  Adc_HwUnitId              The device ID of the Adc converter hardware, could be 0 or 1.
 *  \param[in]  Adc_HwGroupId             The Id of the hardware group, that is responsible for the interrupt. 
 * 
 *  \return     void
 * 
 *  \context    Function is called on interrupt level.
 **********************************************************************************************************************/
/* SourceId : ADC_SourceId_016 */
/* DesignId : ADC_DesignId_016 */
/* Requirements : AR_ADC_SR36, AR_ADC_SR206 */
/*SAFETYMCUSW 69 S MR:3.4 <APPROVED> "Reason - Pragma usage is required here to force ISR to ARM mode."*/
#pragma CODE_STATE(Adc_IrqFunction, 32)    
FUNC(void, ADC_CODE) Adc_IrqFunction (uint8 Adc_HwUnitId, uint8 Adc_HwGroupId)
{
  volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr;
  Adc_GroupConfigRefType CurrentGroupConfigPtr;
  
  /* Get the group Id of the software group for which the interrupt was generated. */
  Adc_GroupType Group = Adc_HwUnitGroupAssignment_at[Adc_HwUnitId][Adc_HwGroupId];
  
  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Adc_ConfigPtr_pt is already checked for NULL in INI."*/
  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Since Adc_ConfigPtr_pt is already checked for NULL in INI,
													CurrentGroupConfigPtr cannot be NULL."*/
  CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[Group]);
  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
  HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
  
  /* Acknowledge interrupt. Clear both flags (threshold and group end) because this function is used for both interrupt
   * sources.*/
   /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  HwGroupBase_pt is already assigned a value in INI."*/
  HwGroupBasePtr->IntFlgReg |= (uint32) ((1U << ADC_GROUP_END_INT_FLAG_OFFSET) | 1U);
  
  /* Get the latest conversion results out of the buffer. Copy them to application result buffer. */
  CurrentGroupConfigPtr->ProcessBuffer_p(CurrentGroupConfigPtr);
  CurrentGroupConfigPtr->ProcessConversion_p(CurrentGroupConfigPtr);
  
  /* Call notification function. This is either a pointer to an empty function, in case notification is disabled, or to 
   * a non-empty function in case notification shall be sent. */
  CurrentGroupConfigPtr->Notification_p[CurrentGroupConfigPtr->GroupData_pt->Notification_u8]();  
}

#if (STD_ON ==  ADC_SRAM_PARITY_ENABLE)
/**********************************************************************************************************************
 *  Adc_SramParityEnable
 *********************************************************************************************************************/
/*! \brief      SRAM Parity enable routine
 *
 *              This routine will Enable the Parity of the SRAM in ADC module.
 *
 *  \param      Adc_HwUnitId : Unit in which Parity needs to be enabled
 *
 *  \return     void
 *
 *  \context    Function called from task level
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_017 */
/* Requirements : AR_ADC_SR217*/
 FUNC(void, ADC_CODE) Adc_SramParityEnable(Adc_HwUnitType HwUintId)
{

  volatile Adc_RegisterRefType HwUnitBasePtr;
  Adc_EnterCritical();
  /*get the address for the Hardware base*/
  HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[HwUintId].HwUnitBase_pu32;

  HwUnitBasePtr[Adc_parityCtrlReg] = 0x01U;
  Adc_LeaveCritical();

}
/**********************************************************************************************************************
 *  Adc_SramParityDisable
 *********************************************************************************************************************/
/*! \brief      SRAM Parity Disable routine
 *
 *              This routine will Disable the Parity of the SRAM in ADC module.
 *
 *  \param      Adc_HwUnitId : Unit in which Parity needs to be enabled
 *
 *  \return     void
 *
 *  \context    Function called from task level
 *********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_SramParityDisable(Adc_HwUnitType HwUintId)
{
  volatile Adc_RegisterRefType HwUnitBasePtr;
  Adc_EnterCritical();
  /*get the address for the Hardware base*/
  HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[HwUintId].HwUnitBase_pu32;

  HwUnitBasePtr[Adc_parityCtrlReg] = 0x05U;
  Adc_LeaveCritical();

}
#endif



#if (STD_ON ==  ADC_CALIBRATE_FUNCTION_ENABLE)
/**********************************************************************************************************************
 *  Adc_CalibrateFunction
 *********************************************************************************************************************/
/*! \brief      Calibration routine
 *
 *              This routine will Perform the Calibration.
 *
 *  \param      Adc_HwUnitId : Unit on which the calibration needs to be performed
 *
 *  \return     void
 *
 *  \context    Function called from task level
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_018 */
/* DesignId : ADC_DesignId_017 */
/* Requirements : AR_ADC_SR215*/
 FUNC(Std_ReturnType, ADC_CODE) Adc_CalibrateFunction(uint32 Adc_HwUnitId)
{  
  uint32 conv_val[5]={0,0,0,0,0};
  uint8 loop_index=0U;
  uint32 offset_error=0U;
  uint32 backup_mode;
  volatile Adc_RegisterRefType HwUnitBasePtr;
  Std_ReturnType ReturnStatus2 = E_OK;  
  
  /*loop through the hardware table to see if the hw is free...*/  
  if((Adc_HwUnitGroupAssignment_at[Adc_HwUnitId][0] != ADC_INVALID_GRP_ID) || 
     (Adc_HwUnitGroupAssignment_at[Adc_HwUnitId][1] != ADC_INVALID_GRP_ID) || 
	 (Adc_HwUnitGroupAssignment_at[Adc_HwUnitId][2] != ADC_INVALID_GRP_ID))
  {
    ReturnStatus2 = E_NOT_OK;
  }
  else 
  {
	  if((Adc_ConfigPtr_pt != NULL_PTR) && (Adc_HwUnitId < Adc_ConfigPtr_pt->NumberOfHwUnits_t))
	  {
		  Adc_EnterCritical();
		  /*get the address for the Hardware base*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[Adc_HwUnitId].HwUnitBase_pu32;
		  if(NULL_PTR != HwUnitBasePtr)
		  {	  
			  /* Backup Mode before Calibration  */
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  backup_mode = HwUnitBasePtr[Adc_OpModeCtrlReg];

			  /* Enable 12-BIT ADC  */
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_OpModeCtrlReg] |= 0x80000000U;

			  /* Disable all channels for conversion */
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_evtSelReg] =0U;
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_grp1SelReg] =0U;
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_grp2SelReg] =0U;

			  for(loop_index=0U;loop_index<4U;loop_index++)
			  {
				/* Disable Self Test and Calibration mode */
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
				HwUnitBasePtr[Adc_calibCtrlReg] =0U;

				switch(loop_index)
				{
				    case 0U : 	/* Test 1 : Bride En = 0 , HiLo =0 */
						   /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
						   HwUnitBasePtr[Adc_calibCtrlReg] =0x0U;
						   break;

					case 1U :	/* Test 2 : Bride En = 0 , HiLo =1 */
							/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
							HwUnitBasePtr[Adc_calibCtrlReg] =0x0100U;
							break;

					case 2U : 	/* Test 3 : Bride En = 1 , HiLo =0 */
							/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
							HwUnitBasePtr[Adc_calibCtrlReg] =0x0200U;
							break;

					case 3U : 	/* Test 4 : Bride En = 1 , HiLo =1 */
							/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
							HwUnitBasePtr[Adc_calibCtrlReg] =0x0300U;
							break;
					default :
							break; 				
				}

				/* Enable Calibration mode */
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
				HwUnitBasePtr[Adc_calibCtrlReg] |=0x01U;

				/* Start calibration conversion */
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
				HwUnitBasePtr[Adc_calibCtrlReg] |=0x00010000U;

				/* Wait for calibration conversion to complete */
				/*SAFETYMCUSW 132 S MR:12.3 <APPROVED> "Reason - volatile usage is required here. "*/
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
				/*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason -  volatile is required here."*/
				while((/*adc->CALCR*/HwUnitBasePtr[Adc_calibCtrlReg] & 0x00010000U)==0x00010000U)
				{			
				}
				/* Read converted value */
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
				conv_val[loop_index]= HwUnitBasePtr[Adc_calibReg] ;
			  }

			  /* Disable Self Test and Calibration mode */
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_calibCtrlReg] =0U;

			  /* Compute the Offset error correction value */
			  conv_val[4]=conv_val[0]+ conv_val[1] + conv_val[2] + conv_val[3];

			  conv_val[4]=(conv_val[4]/4U);

			  offset_error=conv_val[4]-0x7FFU;

			  /*Write the offset error to the Calibration register */
			  /* Load 2;s complement of the computed value to ADCALR register */
			  offset_error=~offset_error;
			  offset_error=offset_error & 0xFFFU;
			  offset_error=offset_error+1U;

			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_calibReg] = offset_error;

			  /* Restore Mode after Calibration  */
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
			  HwUnitBasePtr[Adc_OpModeCtrlReg] = backup_mode;
		  }
		  Adc_LeaveCritical();
	  }	  
  }  

  return ReturnStatus2;
}
#endif


#if ((STD_ON == ADC_SELF_TEST_ENABLE) && (STD_ON == ADC_READ_GROUP_API))
/**********************************************************************************************************************
 *  Adc_SelfTestPerform
 *********************************************************************************************************************/
/*! \brief      Self test routine
 *              Prerequisite to this function: Result buffer for this group
 *              needs to be set and HW needs to be in Idle mode.
 *
 *              This routine will Perform the selfTest of the specified group.
 *              This routine will only do the self test in one shot sw mode with single access buffer.
 *              This will over ride all the settings for that group.
 *
 *  \param[in]  group on which the self test needs to be performed
 *  \param[out] uint8 resutl - status of the pin -> shorted to refhi, shorted to reflo, good, open.
 *
 *  \return     status of the function
 *
 *
 *********************************************************************************************************************/
/* SourceId : ADC_SourceId_019 */
/* DesignId : ADC_DesignId_018 */
/* Requirements : AR_ADC_SR214*/
 FUNC(Std_ReturnType, ADC_CODE) Adc_SelfTestPerform(Adc_GroupType group,uint8 *result)
{
  uint16 bufferVd[32];
  uint16 bufferVu[32];
  uint16 bufferVn[32];

  uint16 adRefHi=0U;
  uint16 adRefLo=0U;
  uint8 loopIndex=0U;

  Adc_GroupConfigRefType CurrentGroupConfigPtr;  
  volatile Adc_RegisterRefType HwUnitBasePtr;
  uint32 backup_mode;
  Std_ReturnType ReturnStatus3 = E_OK; 

#if (STD_ON == ADC_DEV_ERROR_DETECT)
  /* Check for uninitialized module */  
  if (NULL_PTR == Adc_ConfigPtr_pt)
  {
    (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_UNINIT);
    ReturnStatus3 = E_NOT_OK;
  }
  else if(group >= Adc_ConfigPtr_pt->NumberOfGroups_t)
  {
	/* Validate parameter 'Group' */
	(void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_PARAM_GROUP);
	ReturnStatus3 = E_NOT_OK;
  }
  else if(NULL_PTR == result)
  {
	/*check if the result buffer is setup*/
    (void)Det_ReportError((ADC_MODULE_ID), ADC_INSTANCE_ID, ADC_SID_START_GROUP_CONVERSION, ADC_E_BUFFER_UNINIT);
	ReturnStatus3 = E_NOT_OK;
  }
  else
#endif
  {
	  Adc_EnterCritical();
	  
	  CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[group]);
	  /* check if the group is free*/
	  /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  CurrentGroupConfigPtr is already assigned a value."*/
	  if((Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t][ADC_HW_GROUP_G1] != ADC_INVALID_GRP_ID) ||
		 (Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t][ADC_HW_GROUP_G2] != ADC_INVALID_GRP_ID) ||
		 (Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t][ADC_HW_GROUP_EVT] != ADC_INVALID_GRP_ID))
	  {
		 ReturnStatus3 = E_NOT_OK;
	  }
	  else
	  {
		  /*get the address for the Hardware base */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[CurrentGroupConfigPtr->GroupHwUnitId_t].HwUnitBase_pu32;
		  /*disable any self tst and Calib mode first */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] =0U;

		  /*first find out AdRefHi and AdRefLo by using Calibration method*/
		  /* Backup Mode before Calibration  */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  backup_mode = HwUnitBasePtr[Adc_OpModeCtrlReg];

		  /* Enable 12-BIT ADC  */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_OpModeCtrlReg] |= 0x80000000U;
		  /* Disable all channels for conversion */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_evtSelReg] =0U;
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_grp1SelReg] =0U;
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_grp2SelReg] =0U;

		  /* Test 1 : Bride En = 1 , HiLo =0 Calib Enabled, Start Calibration */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] = (0x0200U |0x00010000U| 0x01U) ;

		  /* Wait for calibration conversion to complete */
		  /*SAFETYMCUSW 132 S MR:12.3 <APPROVED> "Reason - volatile usage is required here. "*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason -  volatile is required here."*/
		  /*SAFETYMCUSW 139 S MR:13.7 <APPROVED> "Reason - Need to check for bit position. "*/
		  while((/*adc->CALCR*/HwUnitBasePtr[Adc_calibCtrlReg] & 0x00010000U)==0x00010000U)
		  {
		  }
		  /* Read converted value */
		  /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason -  volatile is required here."*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  adRefLo = (uint16)HwUnitBasePtr[Adc_calibReg] ;

		  /*  Bride En = 1 , HiLo =1 Calib Enabled, Start Calibration */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] = (0x0300U |0x00010000U| 0x01U) ;

		  /* Wait for calibration conversion to complete */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason - volatile usage is required here. "*/
		  /*SAFETYMCUSW 139 S MR:13.7 <APPROVED> "Reason - Need to check for bit position. "*/
		  while((/*adc->CALCR*/HwUnitBasePtr[Adc_calibCtrlReg] & 0x00010000U)==0x00010000U)
		  {
		  }
		  /* Read converted value */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Reason -  volatile is required here."*/
		  adRefHi= (uint16)HwUnitBasePtr[Adc_calibReg] ;

		  /* Restore Mode after Calibration  */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_OpModeCtrlReg] = backup_mode;
		  /* disable any self tst and Calib mode first*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] =0U;

		  /* for this self test put the adc group in single shot non streaming mode & later restore the
			 setting to original */

		  /* set the ADC hw in the self test mode and start the test.*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] |= (1U<< 24U);
		  /* set HiLo to 0 to connect AdVref = low */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] &= ~(1U<< 8U);

		  /*enable ADC channels as programmed in the group */
		  Adc_StartConversionSelfTest(group);

		  /* check for the status of the group to see if it is finished*/
		  while ( !(Adc_GetGroupStatus(group) == ADC_STREAM_COMPLETED))
		  {
		  }
		  /* copy the results into the buffer*/
		  /*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 69 D MR:9.1 <APPROVED> "Reason -  bufferVd will be updated by Adc_ReadGroup."*/
		  (void)Adc_ReadGroup(group,(Adc_ValueGroupRefType)&bufferVd[0]);

		   /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] |= (1U<< 8U);

		  /*enable ADC channels as programmed in the group*/
		  Adc_StartConversionSelfTest(group);

		  /* check for the status of the group to see if it is finished*/
		  while ( !(Adc_GetGroupStatus(group) == ADC_STREAM_COMPLETED))
		  {
		  }
		  /*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 69 D MR:9.1 <APPROVED> "Reason -  bufferVd will be updated by Adc_ReadGroup."*/
		  (void)Adc_ReadGroup(group,(Adc_ValueGroupRefType)&bufferVu[0]);

		  /*disable any self tst and Calib mode first*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] =0U;

		  /*enable ADC channels as programmed in the group*/
		  Adc_StartConversionSelfTest(group);

		  /* check for the status of the group to see if it is finished*/
		  while ( !(Adc_GetGroupStatus(group) == ADC_STREAM_COMPLETED))
		  {
		  }
		  /*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
		  /*SAFETYMCUSW 69 D MR:9.1 <APPROVED> "Reason -  bufferVd will be updated by Adc_ReadGroup."*/
		  (void)Adc_ReadGroup(group,(Adc_ValueGroupRefType)&bufferVn[0]);

		  for(loopIndex = 0U; loopIndex < CurrentGroupConfigPtr->NumberOfGroupChannels_u8;loopIndex++)
		  {
			/* find the differences and set the voltages levels to ref_low or rel_hig for proper comparision */
			if((adRefHi - bufferVn[loopIndex]) < (uint16)3U )
			{
				bufferVn[loopIndex] = adRefHi; /* consider voltage as hig and mark as hi */
			}
			else
			{
				if (( bufferVn[loopIndex]-adRefLo ) < (uint16)3U )
				{
					bufferVn[loopIndex] = adRefLo; /*consider voltage as Lo and mark as lo*/
				}	
			}

			if((adRefHi - bufferVu[loopIndex]) < (uint16)3U )
			{
				bufferVu[loopIndex] = adRefHi; /* consider voltage as hig and mark as hi */
			}
			else
			{
				if (( bufferVu[loopIndex]-adRefLo ) < (uint16)3U )
				{
					bufferVu[loopIndex] = adRefLo;/*consider voltage as Lo and mark as lo*/
				}	
			}

			if((adRefHi - bufferVd[loopIndex]) < (uint16)3U )
			{
				bufferVd[loopIndex] = adRefHi; /* consider voltage as hig and mark as hi */
			}
			else
			{
				if (( bufferVd[loopIndex]-adRefLo ) < (uint16)3U )
				{
					bufferVd[loopIndex] = adRefLo;/*consider voltage as Lo and mark as lo*/
				}	
			}

			if((bufferVn[loopIndex]==adRefHi) && (bufferVu[loopIndex]==adRefHi) && (bufferVd[loopIndex]==adRefHi))
			{
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - result is pointer. "*/
			  result[loopIndex]= ADC_PIN_SHORTED_TO_ADVREF_HIGH ;
			}
			else if((bufferVn[loopIndex]==adRefLo) && (bufferVu[loopIndex]==adRefLo) && (bufferVd[loopIndex]==adRefLo))
			{
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - result is pointer. "*/
			  result[loopIndex]= ADC_PIN_SHORTED_TO_ADVREF_LOW ;
			}
			else if(((bufferVu[loopIndex]< adRefHi)&& (bufferVu[loopIndex] > bufferVn[loopIndex]))&&((bufferVd[loopIndex]> adRefLo)&& (bufferVd[loopIndex] < bufferVn[loopIndex])))
			{
			  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - result is pointer. "*/
			  result[loopIndex]= ADC_PIN_GOOD ;
			}
			else
			{
			  if((bufferVu[loopIndex]==adRefHi) && (bufferVd[loopIndex]==adRefLo)  )
			  {
				/*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - result is pointer. "*/
				result[loopIndex]= ADC_PIN_OPEN ;
			  }
			}
		  }

		  /*disable any self tst and Calib mode first*/
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_calibCtrlReg] =0U;
		  /* Disable all channels for conversion */
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_evtSelReg] =0U;
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_grp1SelReg] =0U;
		  /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		  HwUnitBasePtr[Adc_grp2SelReg] =0U;
	  }
		  Adc_LeaveCritical();
  }
  return ReturnStatus3;
}
  
/**********************************************************************************************************************
 * Adc_StartConversionSelfTest
 *********************************************************************************************************************/
/*! \brief     Start the conversion for self test
*
*              This function is called to start the conversion of the group selected in the self test.
*
*  \param[in]  Group
*
*  \return     result - status of the self test --> pin is open, or short
**********************************************************************************************************************/
FUNC(void, ADC_CODE) Adc_StartConversionSelfTest(Adc_GroupType group)
{
  volatile P2VAR(Adc_RegType, AUTOMATIC, MSR_REGSPACE) HwGroupBasePtr;
  Adc_GroupConfigRefType CurrentGroupConfigPtr;
  uint32 ModeCtrlRegWorkingCopy;
  uint32 SampTimeRegWorkingCopy;
  uint32 IntEnaRegWorkingCopy;
  uint32 IntThrRegWorkingCopy;


  if(NULL_PTR !=Adc_ConfigPtr_pt)
  {
		CurrentGroupConfigPtr = &(Adc_ConfigPtr_pt->Group_at[group]);  
		if(NULL_PTR != CurrentGroupConfigPtr)
		{
			HwGroupBasePtr = CurrentGroupConfigPtr->HwGroupBase_pt;
		}	
	    if(NULL_PTR != HwGroupBasePtr)
		{	   
		   /* Register settings: */
		   /* Modify freeze bit of mode control register: MODECR_FRZ */
		   /* Reset all bits of MODECR to their default state. Amongst others freeze enable bit (bit 0) is set to 0 */
		   /* Set mode bit (bit 1) to 1: enable continuous conversion */
		   ModeCtrlRegWorkingCopy = (uint32)0U;
		   /* Resolution: Modify data format bits (PSFC66) or 8BIT bit (PSFD62) of mode control register: MODECR_DATA_FMT */
		   ModeCtrlRegWorkingCopy |= ((uint32)(CurrentGroupConfigPtr->GroupResolution_t << ADC_DATA_FORMAT_OFFSET));

		   /* Set group acquisition prescale bits (ACQ) of sample time register (SAMP).
			* Set register value = configured value - 2
			* Reason: Total sample time = register value + 2
			*/
		   SampTimeRegWorkingCopy = (uint32)(CurrentGroupConfigPtr->GroupSampTime_t - 2U);

		   /* Set interrupt enable bits (INT_EN) of register INT_ENA */
		   if (ADC_NOTIFICATION_OFF == CurrentGroupConfigPtr->GroupData_pt->Notification_u8)
		   {
			 /* Enable threshold interrupt */
			 IntEnaRegWorkingCopy = (uint32)1U;
			 /* Set threshold variable */
			 CurrentGroupConfigPtr->GroupData_pt->Threshold_t = CurrentGroupConfigPtr->GroupThreshold_t;
		   }
		   else
		   {
			 /* Enable group end interrupt so that notification is sent each time a group conversion is completed */
			 IntEnaRegWorkingCopy = ((uint32)1U << ADC_GROUP_END_INT_ENA_OFFSET);
			 /* Set threshold variable */
			 CurrentGroupConfigPtr->GroupData_pt->Threshold_t = 1U;
		   }

		   /* Set bits 7:0 of threshold register to the number of RESULTS (channels, not full samples) after which an interrupt
			* shall be generated. Therefore multiply GroupThreshold(which contains the number of SAMPLES after which an
			* interrupt shall be generated) by NumberOfGroupChannels.
			*/
		   IntThrRegWorkingCopy =
			 (uint32)((CurrentGroupConfigPtr->GroupThreshold_t * CurrentGroupConfigPtr->NumberOfGroupChannels_u8)
				 & ADC_INT_THR_REG_ABS_VALUE_MASK);

		   /* Reset countdown variable to the number of stream samples, that fit in application result buffer */
		   CurrentGroupConfigPtr->GroupData_pt->SampleCountdown_t  = CurrentGroupConfigPtr->StreamingNumSamples_t;
		   /* Reset sample counter. No valid samples shall be in the buffer when group starts. */
		   CurrentGroupConfigPtr->GroupData_pt->ValidSampleCount_t = 0U;
		   /* Toggle group state to ADC_BUSY */
		   CurrentGroupConfigPtr->GroupData_pt->Status_t = ADC_BUSY;

		   /* Fill in group assignment table, to see which group was started last on the hw conversion group. */
		   Adc_HwUnitGroupAssignment_at[CurrentGroupConfigPtr->GroupHwUnitId_t]
									   [CurrentGroupConfigPtr->GroupHwGroupId_u8] = group;

		   /* Set registers */
		   HwGroupBasePtr->ModeCtrlReg = ModeCtrlRegWorkingCopy;
		   HwGroupBasePtr->SampTimeReg = SampTimeRegWorkingCopy;
		   HwGroupBasePtr->IntEnaReg   = IntEnaRegWorkingCopy;
		   HwGroupBasePtr->IntThrReg   = IntThrRegWorkingCopy;
		   /* Set channel select register (CHNSEL) to start the group conversion */
		   HwGroupBasePtr->ChSelectReg = CurrentGroupConfigPtr->GroupDefinition_t;  
		}	
   }	
}
#endif

#if(STD_ON == ADC_SAFETI_API)
/**********************************************************************************************************************
 * Adc_ConfigRegReadBack
 *********************************************************************************************************************/
/*! \brief     Configuration Register Read Back
*
*              This function is called to read back configuration registers.
*
*  \param[in]  Adc_HwUnitId              The device ID of the Adc converter hardware, could be 0 or 1.
*
*  \return     Std_ReturnType
**********************************************************************************************************************/
/* SourceId : ADC_SourceId_020 */
/* DesignId : ADC_DesignId_019 */
/* Requirements : AR_ADC_SR220*/
FUNC(Std_ReturnType, ADC_CODE) Adc_ConfigRegReadBack(VAR(uint32, AUTOMATIC) Adc_HwUnitId)
{		
	volatile Adc_RegisterRefType HwUnitBasePtr = 0U;
	VAR(Std_ReturnType, AUTOMATIC)  ReturnStatus4;
    ReturnStatus4 = (Std_ReturnType)E_NOT_OK;	
	
	/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason - NULL pointer is defined as void pointer to zero."*/
	if((Adc_ConfigPtr_pt != NULL_PTR) && (Adc_HwUnitId < Adc_ConfigPtr_pt->NumberOfHwUnits_t))
    {
	   /*get the address for the Hardware base*/
	   HwUnitBasePtr = Adc_ConfigPtr_pt->HwUnit_at[Adc_HwUnitId].HwUnitBase_pu32;
	   
	   /* Read configuration registers value */	    
	   if(NULL_PTR != HwUnitBasePtr)
	   {
		   /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		   Adc_AdcConfig.Adc_ReaBack_OpModeCtrlReg 		= HwUnitBasePtr[Adc_OpModeCtrlReg];
		   /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		   Adc_AdcConfig.Adc_ReaBack_FifoEndCtrlReg 	= HwUnitBasePtr[Adc_FifoEndCtrlReg];
		   /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		   Adc_AdcConfig.Adc_ReaBack_FifoBoundCtrlReg	= HwUnitBasePtr[Adc_FifoBoundCtrlReg];
		   /*SAFETYMCUSW 436 S MR:17.1,17.4 <APPROVED> "Reason - HwUnitBasePtr is pointer to register array. "*/
		   Adc_AdcConfig.Adc_ReaBack_PrescaleCtrlReg    = HwUnitBasePtr[Adc_PrescaleCtrlReg];		
		   ReturnStatus4 = E_OK;	   
	   }   
    }
	return(ReturnStatus4);
}
#endif

#define ADC_STOP_SEC_CODE
/*SAFETYMCUSW 338 S MR:19.1 <APPROVED> "Reason - This is the format to use for specifying memorysections."*/
#include "MemMap.h" 
/**********************************************************************************************************************
 *  END OF FILE: ADC.C
 *********************************************************************************************************************/
