/**
*   @file    IoDal_Dio.c
*   @version 1.0.0
*
*   @brief   Integration Framework - IO Driver Abstraction Layer component for digital
*                                      input/output channels
*   @details This file implements the IODAL interface to application layer to lower layers                  
*            DIO, ICU, OCU             
*            
*   (c) Copyright 2006-2016 Freescale Semiconductor, Inc. 
*       Copyright 2017-2018 NXP
*   All Rights Reserved.
*   This file contains sample code only. It is not part of the production code deliverables.
*
*   @addtogroup IODAL
*   @{
*/
/*=========================================================================================================================
*   Platform             : PA
*
*   Autosar Version      : 4.3.1
*   Autosar Revision     : ASR_REL_4_3_REV_0001
*   
*   SW Version           : 1.0.0
*   Build Version        : MPC5777CXG_MCAL_1_0_0_RTM_ASR_REL_4_3_REV_0001_20190318
*
============================================================================================================================*/
/*============================================================================================================================
==============================================================================================================================*/



#ifdef __cplusplus
extern "C"{
#endif

/*===================================================================================================================
                                         INCLUDE FILES
 1) system and project includes
 2) needed interfaces from external units
 3) internal and external interfaces from this unit
====================================================================================================================*/
#include "Std_Types.h"
#include "Mcal.h"
#include "IoDal_Drv_Cfg.h"
#include "IoDal_Types.h"
#include "IoDal_Cfg.h"
#include "IoDal_Dio.h"
#include "Dio.h"
#if IODAL_MAX_ICU_DESCRIPTORS > 0U
#include "Icu.h"
#endif
/*===================================================================================================================
*                              SOURCE FILE VERSION INFORMATION
====================================================================================================================*/
#define IODAL_DIO_VENDOR_ID_C                       43

#define IODAL_DIO_AR_RELEASE_MAJOR_VERSION_C        4
#define IODAL_DIO_AR_RELEASE_MINOR_VERSION_C        3
#define IODAL_DIO_AR_RELEASE_REVISION_VERSION_C     1

#define IODAL_DIO_SW_MAJOR_VERSION_C                1
#define IODAL_DIO_SW_MINOR_VERSION_C                0
#define IODAL_DIO_SW_PATCH_VERSION_C                0

/*===================================================================================================================
*                                     FILE VERSION CHECKS
====================================================================================================================*/
/* Check if source file and IODAL header file are of the same vendor */
#if (IODAL_DIO_VENDOR_ID_C != IODAL_CFG_VENDOR_ID)
    #error "IoDal_Dio.c and IoDal_Cfg.h have different vendor ids"
#endif

/* Check if source file and IODAL header file are of the same Autosar version */
#if ((IODAL_DIO_AR_RELEASE_MAJOR_VERSION_C != IODAL_CFG_AR_RELEASE_MAJOR_VERSION) || \
     (IODAL_DIO_AR_RELEASE_MINOR_VERSION_C != IODAL_CFG_AR_RELEASE_MINOR_VERSION) || \
     (IODAL_DIO_AR_RELEASE_REVISION_VERSION_C != IODAL_CFG_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of IoDal_Dio.c and IoDal_Cfg.h are different"
#endif

/* Check if source file and IODAL header file are of the same Software version */
#if ((IODAL_DIO_SW_MAJOR_VERSION_C != IODAL_CFG_SW_MAJOR_VERSION) || \
     (IODAL_DIO_SW_MINOR_VERSION_C != IODAL_CFG_SW_MINOR_VERSION) || \
     (IODAL_DIO_SW_PATCH_VERSION_C != IODAL_CFG_SW_PATCH_VERSION) \
    )
    #error "Software Version Numbers of IoDal_Dio.c and IoDal_Cfg.h are different"
#endif

/* Check if source file and IODAL IPW header file are from the same vendor */
#if (IODAL_DIO_VENDOR_ID_C != IODAL_DIO_VENDOR_ID)
    #error "IoDal_Dio.c and IoDal_Dio.h have different vendor ids"
#endif

/* Check if source file and IODAL types header file are of the same Autosar version */
#if ((IODAL_DIO_AR_RELEASE_MAJOR_VERSION_C != IODAL_DIO_AR_RELEASE_MAJOR_VERSION) || \
     (IODAL_DIO_AR_RELEASE_MINOR_VERSION_C != IODAL_DIO_AR_RELEASE_MINOR_VERSION) || \
     (IODAL_DIO_AR_RELEASE_REVISION_VERSION_C != IODAL_DIO_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of IoDal_Dio.c and IoDal_Dio.h are different"
#endif

/* Check if source file and IODAL types header file are of the same Software version */
#if ((IODAL_DIO_SW_MAJOR_VERSION_C != IODAL_DIO_SW_MAJOR_VERSION) || \
     (IODAL_DIO_SW_MINOR_VERSION_C != IODAL_DIO_SW_MINOR_VERSION) || \
     (IODAL_DIO_SW_PATCH_VERSION_C != IODAL_DIO_SW_PATCH_VERSION) \
    )
  #error "Software Version Numbers of IoDal_Dio.c and IoDal_Dio.h are different"
#endif


#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
 /* Check if source file and Std_Types header file are of the same AutoSar version */
 #if ((IODAL_DIO_AR_RELEASE_MAJOR_VERSION_C != STD_AR_RELEASE_MAJOR_VERSION) || \
      (IODAL_DIO_AR_RELEASE_MINOR_VERSION_C != STD_AR_RELEASE_MINOR_VERSION) \
     )
 #error "AutoSar Version Numbers of IoDal_Dio.c and Std_Types.h are different"
 #endif
 /* Check if source file and Mcal header file are of the same AutoSar version */
 #if ((IODAL_DIO_AR_RELEASE_MAJOR_VERSION_C != MCAL_AR_RELEASE_MAJOR_VERSION) || \
      (IODAL_DIO_AR_RELEASE_MINOR_VERSION_C != MCAL_AR_RELEASE_MINOR_VERSION) \
     )
 #error "AutoSar Version Numbers of IoDal_Dio.c and Mcal.h are different"
 #endif 
#endif
#if IODAL_MAX_DIO_DESCRIPTORS > 0U

/*===================================================================================================================
                                      FILE VERSION CHECKS
====================================================================================================================*/


/*===================================================================================================================
                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
====================================================================================================================*/
/* Shift needed in order to encode clockwise command */
#define IODAL_EXT_SENS_DEV_CLOCKWISE_SHIFT 4

#if IODAL_MAX_ICU_DESCRIPTORS > 0U

/* ICU measurements for averaging */
#define ICU_MAX_READ_VALUES     4

/* ICU shift for fast averaging */
#define ICU_AVERAGE_SHIFT       2

/* Icu extra measurements needed in order to establish speed is zero */
#define ICU_TIMEOUT_VALUE       1

#endif /* IODAL_MAX_ICU_DESCRIPTORS > 0U */
/*===================================================================================================================
                                       LOCAL CONSTANTS
====================================================================================================================*/
/**
* @brief          Global Configuration Pointer for Digital inputs components.
* @details        Data structure containing the set of configuration parameters required for
*                 initializing the IODAL - DIO components.
*
*/
static P2CONST(IoDal_BswIoConfigType, IODAL_VAR,  IODAL_APPL_CONST) IoDal_pDioGlobalCfgPtr=NULL_PTR;

/*===================================================================================================================
                                       LOCAL VARIABLES
====================================================================================================================*/

#if (IODAL_DIO_EXT_SYNC_DEVICE == STD_ON) 
/**
* @brief          Data array storing the digital level from input value read from asynchronous sources
* @details        Data array hold the level value from asynchronous inputs (inputs which are read from
*                 external devices or from ICU)
*
*/
static VAR(Dio_LevelType, AUTOMATIC) IoDal_DigitalInputLevel[IODAL_MAX_DIO_DESCRIPTORS];

/**
* @brief          Data array storing the request for changing the output level to the value in the 
*                 IoDal_DigitalOutputLevel for the given channel  
*
*/
static VAR(boolean,       AUTOMATIC) IoDal_DioResyncRequest[IODAL_MAX_DIO_DESCRIPTORS];

/**
* @brief          Data array storing the digital output level which was requested by application.
* @details        Data array stores the level value foR asynchronous outputs (outputs which mapped on 
*                 external devices or OCU)
*
*/
static VAR(uint32,        AUTOMATIC) IoDal_DigitalOutputLevel[IODAL_MAX_DIO_DESCRIPTORS];
#endif


#if IODAL_MAX_ICU_DESCRIPTORS > 0U

/**
* @brief          Data array storing average ticks since measurement has started for each channel.
*/
static VAR(uint32,                    AUTOMATIC) IoDal_IcuPeriodAvg[IODAL_MAX_ICU_DESCRIPTORS];

/**
* @brief          Data array storing state of each measured channel.               
*
*/
static VAR(IoDal_IcuStateType,        AUTOMATIC) Iodal_IcuState[IODAL_MAX_ICU_DESCRIPTORS];

/**
* @brief          This data array stores period time and active time for the digital signal measured.               
*/
static VAR(Icu_DutyCycleType,         AUTOMATIC) Iodal_IcuPeriodTime[IODAL_MAX_ICU_DESCRIPTORS]; 

/**
* @brief          This data array stores period time and active time for the digital signal measured.               
*/
static VAR(uint32,         AUTOMATIC) Iodal_IcuLastValidPeriodTime[IODAL_MAX_ICU_DESCRIPTORS]; 


/**
* @brief          Data array storing the state of each measurement channel, defining what is the 
*                 current measurement status
*/
static VAR(IoDal_IcuMeasStatusType,   AUTOMATIC) IoDal_IcuMeasStatus[IODAL_MAX_ICU_DESCRIPTORS];
 
/**
* @brief          Data array containing sampling frequency for each ICU channel.
*
*/
static VAR(uint32,                    AUTOMATIC) IoDal_IcuSamplingFrequency[IODAL_MAX_ICU_DESCRIPTORS];

/**
* @brief          Data array storing timeout counter for each ICU channel, in order to detect whenever 
*                 signal is stopped.
*/ 
static VAR(uint8,                     AUTOMATIC) IoDal_IcuTimeoutCounter[IODAL_MAX_ICU_DESCRIPTORS];

/**
* @brief          Data matrix storing all the read values for each ICU channel.                
*
*/ 
static VAR(uint32,                    AUTOMATIC) Icu_PeriodTimeSum[IODAL_MAX_ICU_DESCRIPTORS][ICU_MAX_READ_VALUES];

 /**
* @brief          Variable signalizing ICU source clock overflow, avoiding false results.
*/
static VAR(uint8,                      AUTOMATIC) Iodal_IcuOverflow = 0;

/**
* @brief          Data array storing current measurement's index.
*
*/ 
static VAR(uint8,                      AUTOMATIC) Iodal_Icu_PeriodMeasurementIndex[IODAL_MAX_ICU_DESCRIPTORS]; 

#endif /*IODAL_MAX_ICU_DESCRIPTORS > 0*/
/*===================================================================================================================
                                       GLOBAL CONSTANTS
====================================================================================================================*/


/*===================================================================================================================
                                       GLOBAL VARIABLES
====================================================================================================================*/


/*===================================================================================================================
                                   LOCAL FUNCTION PROTOTYPES
====================================================================================================================*/


/*===================================================================================================================
                                       LOCAL FUNCTIONS
====================================================================================================================*/


/*===================================================================================================================
                                       GLOBAL FUNCTIONS
====================================================================================================================*/
/*==================================================================================================================*/
/**
@brief      IoDal_Dio_Init - Initialize the IODAL DIO components

@param[in]  ConfigPtr    Pointer to configuration data (this data is shared between all IODAL components)

@return     Returns the value of success
@retval     E_OK or E_NOT_OK

@pre None
@post None
*/
/*===================================================================================================================*/
FUNC(void, IODAL_APP_CODE) IoDal_Dio_Init(P2CONST(IoDal_BswIoConfigType, AUTOMATIC, IODAL_APP_CONST) ConfigPtr)
{
#if (IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)   
    VAR(uint8, AUTOMATIC)                DioDescriptorIndex;    
#endif
    VAR(uint8, AUTOMATIC)                BswIoChannel;
    VAR(IoDal_BswChannelType, AUTOMATIC) ChannelType;
    VAR(uint8, AUTOMATIC)                MaxIoChannels;
#if IODAL_MAX_ICU_DESCRIPTORS > 0U             
    VAR(uint8, AUTOMATIC)                IcuDescriptorIndex;   
#endif /* IODAL_MAX_ICU_DESCRIPTORS > 0U */   
    IoDal_pDioGlobalCfgPtr = ConfigPtr;
    

    MaxIoChannels =  IoDal_pDioGlobalCfgPtr->AdcDescriptorsCount + IoDal_pDioGlobalCfgPtr->PwmChannelCount + \
                           IoDal_pDioGlobalCfgPtr->DioChannelCount  + IoDal_pDioGlobalCfgPtr->OcuChannelCount + \
                           IoDal_pDioGlobalCfgPtr->IcuChannelCount + IoDal_pDioGlobalCfgPtr->BridgeChannelCount;
#if (IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)         
    /*initialized digital data array*/
    for(DioDescriptorIndex = 0U; DioDescriptorIndex < IODAL_MAX_DIO_DESCRIPTORS; DioDescriptorIndex++)
    {    
        IoDal_DigitalOutputLevel[DioDescriptorIndex] = STD_LOW;
        IoDal_DigitalInputLevel[DioDescriptorIndex]  = STD_LOW;
        IoDal_DioResyncRequest[DioDescriptorIndex]   = FALSE; 
    }
#endif    
#if IODAL_MAX_ICU_DESCRIPTORS > 0U    
    for(IcuDescriptorIndex = 0U; IcuDescriptorIndex < IODAL_MAX_ICU_DESCRIPTORS; IcuDescriptorIndex++)
    {
        IoDal_IcuPeriodAvg[IcuDescriptorIndex]   = 0U;
        Iodal_IcuState[IcuDescriptorIndex]       = IODAL_ICU_INITIAL_STATE;
    }
#endif /* IODAL_MAX_ICU_DESCRIPTORS > 0U */          
        
    for (BswIoChannel = 0U;  BswIoChannel < MaxIoChannels; BswIoChannel++ )
    {    
        ChannelType = IoDal_pDioGlobalCfgPtr->pBswChannelMap[BswIoChannel].BswChannelType;
    
        switch (ChannelType)
        {    
            
#if(IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)
            case IODAL_EXT_DEV_OUTPUT:
            {                    
                DioDescriptorIndex = IoDal_pDioGlobalCfgPtr->pBswChannelMap[BswIoChannel].BswDescriptorIndex;
                
                /*setup all configured channels to their default values*/
                IoDal_DigitalOutputLevel[DioDescriptorIndex] = (Dio_LevelType)(IoDal_pDioGlobalCfgPtr->pDioChanDescriptor[DioDescriptorIndex].ChannelLevel);
            }
            break;
#endif /*(IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)*/
#if IODAL_MAX_ICU_DESCRIPTORS > 0U            
            case IODAL_TIMER_CAPTURE:
            {
                IcuDescriptorIndex = IoDal_pDioGlobalCfgPtr->pBswChannelMap[BswIoChannel].BswDescriptorIndex;
                IoDal_IcuSamplingFrequency[IcuDescriptorIndex] = IoDal_pDioGlobalCfgPtr->pIcuChanDescriptor[IcuDescriptorIndex].InputCaptureSamplingFrequency;
                /*setup all configured channels to their default values*/
                IoDal_IcuPeriodAvg[IcuDescriptorIndex] = 0U;
            }
            break;            
#endif /* IODAL_MAX_ICU_DESCRIPTORS > 0U */             
            case IODAL_TIMER_OUTPUT:
            break;
            
            case IODAL_EXT_DEV_INPUT:
            break;
            
            
            default:
            break;    
        }
    }    
}

/*===================================================================================================================*/
/**
@brief      IoDal_Dio_DeInit - DeInitialize the IODAL_DIO and IODAL_ICU

@return     void
@retval     

@pre None
@post None
*/
/*===================================================================================================================*/
FUNC(void, IODAL_APP_CODE) IoDal_Dio_DeInit(void)
{
 #if(IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)
    VAR(uint8, AUTOMATIC)                DioDescriptorIndex;
#endif
#if IODAL_MAX_ICU_DESCRIPTORS > 0U  
    VAR(uint8, AUTOMATIC)                IcuDescriptorIndex;
#endif /* IODAL_MAX_ICU_DESCRIPTORS > 0U */
#if(IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)       
    for(DioDescriptorIndex = 0U; DioDescriptorIndex < IODAL_MAX_DIO_DESCRIPTORS; DioDescriptorIndex++)
    {    
        IoDal_DigitalOutputLevel[DioDescriptorIndex] = STD_LOW;
        IoDal_DigitalInputLevel[DioDescriptorIndex]  = STD_LOW;
        IoDal_DioResyncRequest[DioDescriptorIndex]   = FALSE; 
    }
#endif  /*(IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)   */  
#if IODAL_MAX_ICU_DESCRIPTORS > 0U      
    for(IcuDescriptorIndex = 0U; IcuDescriptorIndex < IODAL_MAX_ICU_DESCRIPTORS; IcuDescriptorIndex++)
    {
        IoDal_IcuPeriodAvg[IcuDescriptorIndex]   = 0U;
        Iodal_IcuState[IcuDescriptorIndex]       = IODAL_ICU_UNINIT_STATE;
    }
#endif  /* IODAL_MAX_ICU_DESCRIPTORS > 0U */  
    IoDal_pDioGlobalCfgPtr = NULL_PTR;
}


/*===================================================================================================================*/
/**
@brief      IoDal_Dio_ReadDigitalInputs - Read the Processed Digital Inputs
@details    For channels connected to DIO  this function shall call the driver directly.
            For external devices this function shall read the internal buffer associated to the BSW channel.
            This buffer shall be cyclically updated by the IODAL main function which handles external devices.

@param[in]  BswIoChannel    Logical BSW input channel id.
@param[out] InputValue      Value read from the assigned digital input channel.

@return     void
@retval     

@pre None
@post None
*/
/*===================================================================================================================*/
FUNC(Std_ReturnType, IODAL_APP_CODE) IoDal_Dio_ReadInputs(IoDal_BswChannelIdType BswIoChannel, IoDal_BswValueType  * InputValue)
{    
    VAR(uint8, AUTOMATIC)               DioDescriptorIndex;
    VAR(Dio_ChannelType, AUTOMATIC)     ChannelId;
    VAR(Dio_LevelType, AUTOMATIC)       ChannelValue;
    VAR(IoDal_BswChannelType, AUTOMATIC) ChannelType;
    VAR(IoDal_Dio_UpdateCalloutType, AUTOMATIC)   pfCallout; 
    VAR(Std_ReturnType, AUTOMATIC)       retVal = E_NOT_OK;

    if(NULL_PTR != IoDal_pDioGlobalCfgPtr)
    {        
        DioDescriptorIndex    =  ((IoDal_pDioGlobalCfgPtr->pBswChannelMap))[BswIoChannel].BswDescriptorIndex;        
        
        ChannelId    = (((IoDal_pDioGlobalCfgPtr->pDioChanDescriptor))[DioDescriptorIndex]).DioChannel;

        ChannelType = ((IoDal_pDioGlobalCfgPtr->pBswChannelMap))[BswIoChannel].BswChannelType;
                
        switch(ChannelType)
        {    
            case IODAL_DIO_INPUT:
            {
                ChannelValue = Dio_ReadChannel((Dio_ChannelType)ChannelId);
                *InputValue = (IoDal_BswValueType)ChannelValue;
                retVal = E_OK;
            }
            break;
                    
  
            case IODAL_EXT_DEV_INPUT: 
            {             
                /*get external device handler function*/    
                pfCallout  =  ((IoDal_pDioGlobalCfgPtr->pDioChanDescriptor)[DioDescriptorIndex]).pfExtDioChannelCfg;                

                if(NULL_PTR != pfCallout)
                {
                    pfCallout(InputValue);    
                    retVal = E_OK;
                }    
            }    
            break;
            
            default:
            break;
        }
    }
    else
    {
        /*do nothing*/
    }    
    
    return retVal;
}



#if IODAL_MAX_ICU_DESCRIPTORS > 0U 

/*===================================================================================================================*/
/**
@brief      Iodal_Icu_OverflowNotification - Signal ICU channel that the source clock has overflowed.
@details    This function is being called whenever ICU's source clock has overflowed, and needs to discard current
            measurement.

@return     void
@retval     

@pre None
@post None
*/
/*===================================================================================================================*/
void Iodal_Icu_OverflowNotification(void)
{
    Iodal_IcuOverflow = 1;
}
/*===================================================================================================================*/
/**
@brief      Iodal_Icu_MainFunction - Read the Processed ICU Inputs
@details    For channels connected to ICU  this function shall call the driver directly, receiving information and 
            exporting it to other IODAL functions.

@param[in]  BswIoChannel    Logical BSW input channel id.
@param[out] InputValue      Value read from the assigned digital input channel.

@return     void
@retval     

@pre None
@post None
*/
/*===================================================================================================================*/
FUNC(void, IODAL_APP_CODE) Iodal_Icu_MainFunction(IoDal_BswChannelIdType BswIoChannel)
{
    VAR(uint8,  AUTOMATIC) index; 
    VAR(uint8,  AUTOMATIC) IcuDescriptorIndex; 
    VAR(uint8,  AUTOMATIC) IcuChannelId; 
    VAR(uint32, AUTOMATIC) Icu_PeriodTimeAvg = 0U;
    
    IcuDescriptorIndex = IoDal_pDioGlobalCfgPtr->pBswChannelMap[BswIoChannel].BswDescriptorIndex;
    IcuChannelId = (((IoDal_pDioGlobalCfgPtr->pIcuChanDescriptor))[IcuDescriptorIndex]).InputCaptureChannel;
    /* ICU state machine */
    switch(Iodal_IcuState[IcuDescriptorIndex])
    {
        case IODAL_ICU_INITIAL_STATE:
        {
            Icu_StartSignalMeasurement(IcuChannelId);
                    
            for(index = 0; index < ICU_MAX_READ_VALUES; index++)
            {
                Icu_PeriodTimeSum[IcuDescriptorIndex][index] = 0;            
            }    
            Iodal_Icu_PeriodMeasurementIndex[IcuDescriptorIndex] = 0;

            /*previous measurement performed without error*/    
            if(IODAL_ICU_MEAS_NO_ERROR == IoDal_IcuMeasStatus[IcuDescriptorIndex])
             {
                /*save last valid perdiod time*/
                Iodal_IcuLastValidPeriodTime[IcuDescriptorIndex] = IoDal_IcuPeriodAvg[IcuDescriptorIndex];
            }
        
            /* Mark old measurement as obsolete */
            IoDal_IcuMeasStatus[IcuDescriptorIndex] = IODAL_ICU_MEAS_OBSOLETE;
            /* Go to next state  */
            Iodal_IcuState[IcuDescriptorIndex] =  IODAL_ICU_RUNNING_STATE;  
        }
        break;
        
        /* Measure channel's parameters */
        case IODAL_ICU_RUNNING_STATE:
        {
            if(ICU_ACTIVE == Icu_GetInputState(IcuChannelId))
            {
                if(0 == Iodal_IcuOverflow)
                {
                    Icu_GetDutyCycleValues(IcuChannelId, &Iodal_IcuPeriodTime[IcuDescriptorIndex]);
                    /* Index received duty cycle values */
                    Icu_PeriodTimeSum[IcuDescriptorIndex][Iodal_Icu_PeriodMeasurementIndex[IcuDescriptorIndex]] = Iodal_IcuPeriodTime[IcuDescriptorIndex].PeriodTime;
                    Iodal_Icu_PeriodMeasurementIndex[IcuDescriptorIndex]++;
                    /* Go to next state if all the measurements have been done */
                    if(ICU_MAX_READ_VALUES == Iodal_Icu_PeriodMeasurementIndex[IcuDescriptorIndex])
                    {
                        Iodal_Icu_PeriodMeasurementIndex[IcuDescriptorIndex] = 0;
                        Iodal_IcuState[IcuDescriptorIndex] = IODAL_ICU_COMPLETE_STATE;
                    }
                }
                else
                {
                    Iodal_IcuOverflow = 0;
                }         

            }
            else 
            {    
                /* motor might be stopped.*/
                IoDal_IcuTimeoutCounter[IcuDescriptorIndex] ++;
                if(IoDal_IcuTimeoutCounter[IcuDescriptorIndex]  >= ICU_TIMEOUT_VALUE)
                {
                    IoDal_IcuPeriodAvg[IcuDescriptorIndex] = 0;
                    /* Set measurement status as successful */
                    IoDal_IcuMeasStatus[IcuDescriptorIndex] = IODAL_ICU_MEAS_INVALID;
                    IoDal_IcuTimeoutCounter[IcuDescriptorIndex] = 0;
                }
                
                /* Go to next state */
                Iodal_IcuState[IcuDescriptorIndex] =  IODAL_ICU_INITIAL_STATE;
            }            
        } break;
        
        case IODAL_ICU_COMPLETE_STATE:
        {   
            /* Reset timeout counter */
            IoDal_IcuTimeoutCounter[IcuDescriptorIndex] = 0; 
            Icu_StopSignalMeasurement(IcuChannelId);
            
            /* Calculate average value for current channel */
            for(index = 0; index <= ICU_MAX_READ_VALUES; index ++)
            {
                Icu_PeriodTimeAvg += Icu_PeriodTimeSum[IcuDescriptorIndex][index] >> ICU_AVERAGE_SHIFT;
            }
            /* Calculate ticks per minute for current channel */
            IoDal_IcuPeriodAvg[IcuDescriptorIndex] = (IoDal_IcuSamplingFrequency[IcuDescriptorIndex] / Icu_PeriodTimeAvg) * 60;

            Iodal_IcuState[IcuDescriptorIndex] =  IODAL_ICU_INITIAL_STATE;
            
            /* Mark measurement as successful */
            IoDal_IcuMeasStatus[IcuDescriptorIndex] = IODAL_ICU_MEAS_NO_ERROR;
        } break;

        default:
        {
            /* Reset state machine */
            Iodal_IcuState[IcuDescriptorIndex] = IODAL_ICU_INITIAL_STATE;
            IoDal_IcuMeasStatus[IcuDescriptorIndex] = IODAL_ICU_MEAS_OBSOLETE;

        } break;

    }
}
/*===================================================================================================================*/
/**
@brief      IoDal_Icu_ReadInputs - Read the Processed Digital Inputs
@details    For channels connected to ICU  this function shall call the driver directly.
            For external devices this function shall read the internal buffer associated to the BSW channel.
            This buffer shall be cyclically updated by the IODAL main function which handles external devices.

@param[in]  BswIoChannel    Logical BSW input channel id.
@param[out] InputValue      Value read from the assigned digital input channel.

@return     void
@retval     

*/
/*===================================================================================================================*/
FUNC(Std_ReturnType, IODAL_APP_CODE) IoDal_Icu_ReadInputs(IoDal_BswChannelIdType BswIoChannel, IoDal_BswValueType  * InputValue)
{   
    VAR(uint8,          AUTOMATIC)        IcuDescriptorIndex; 
    VAR(Std_ReturnType, AUTOMATIC)        Iodal_IcuStatus = E_OK;
    
    IcuDescriptorIndex = IoDal_pDioGlobalCfgPtr->pBswChannelMap[BswIoChannel].BswDescriptorIndex;

    if(IODAL_ICU_MEAS_NO_ERROR == IoDal_IcuMeasStatus[IcuDescriptorIndex])
    {
        *InputValue = (uint32)IoDal_IcuPeriodAvg[IcuDescriptorIndex];
    }
    else if(IODAL_ICU_MEAS_OBSOLETE  == IoDal_IcuMeasStatus[IcuDescriptorIndex] ) 
    {
        *InputValue = Iodal_IcuLastValidPeriodTime[IcuDescriptorIndex];
    }
    else
    {
        *InputValue = (uint32)0;
        Iodal_IcuStatus = E_NOT_OK;
    }    
        
    return Iodal_IcuStatus;
}
#endif /*IODAL_MAX_ICU_DESCRIPTORS > 0U */

/*===================================================================================================================*/
/**
@brief      IoDal_WriteDigitalOutputs - Write the output requests.
@details    For channels connected to DIO  this function shall call the driver directly.
            For external devices this function shall buffer the requested output value and 
            the handling of the device shall be done on the next call of the Main function.

@param[in]  BswIoChannel    Logical BSW output channel id.
@param[out] OutputValue     Value to be written to a digital output channel.

@return     void
@retval     

@pre None
@post None
*/
/*===================================================================================================================*/
FUNC(void, IODAL_APP_CODE) IoDal_Dio_WriteOutputs(IoDal_BswChannelIdType BswIoChannel, IoDal_BswValueType OutputValue)
{
    VAR(uint8, AUTOMATIC)               DioDescriptorIndex;
    VAR(Dio_ChannelType, AUTOMATIC)     ChannelId;
    VAR(IoDal_BswChannelType, AUTOMATIC) ChannelType;

        
    if(NULL_PTR != IoDal_pDioGlobalCfgPtr)
    {
        DioDescriptorIndex    =  ((IoDal_pDioGlobalCfgPtr->pBswChannelMap))[BswIoChannel].BswDescriptorIndex;        
        
        ChannelId    = (((IoDal_pDioGlobalCfgPtr->pDioChanDescriptor))[DioDescriptorIndex]).DioChannel;

        ChannelType = ((IoDal_pDioGlobalCfgPtr->pBswChannelMap))[BswIoChannel].BswChannelType;
                
        switch(ChannelType)
        {
            
            case IODAL_DIO_OUTPUT:
                Dio_WriteChannel((Dio_ChannelType)ChannelId, (Dio_LevelType)OutputValue);
            break;
                    
            case IODAL_TIMER_OUTPUT:
            break;

#if (IODAL_DIO_EXT_SYNC_DEVICE == STD_ON)             
            case IODAL_EXT_DEV_OUTPUT:    
                IoDal_DigitalOutputLevel[DioDescriptorIndex] = OutputValue;
                IoDal_DioResyncRequest[DioDescriptorIndex]   = TRUE;
            break;    
#endif            
            default:
            break;
        }
    }
}

#endif
/*===================================================================================================================*/

#ifdef __cplusplus
}
#endif /* IODAL_MAX_DIO_DESCRIPTORS > 0U */
/** @} */
