/**********************************************************************************************************************
 *  COPYRIGHT
 *  -------------------------------------------------------------------------------------------------------------------
 *  \verbatim
 *  Copyright (c) 2007-2014 by Vector Informatik GmbH.                                             All rights reserved.
 *
 *                This software is copyright protected and proprietary to Vector Informatik GmbH.
 *                Vector Informatik GmbH grants to you only those rights as set out in the license conditions.
 *                All other rights remain with Vector Informatik GmbH.
 *  \endverbatim
 *  -------------------------------------------------------------------------------------------------------------------
 *  FILE DESCRIPTION
 *  -------------------------------------------------------------------------------------------------------------------
 *         File:  CanNm.c
 *    Component:  AUTOSAR CAN Network Management
 *       Module:  AUTOSAR Network Management
 *    Generator:  -
 *
 *  Description:  Source of AUTOSAR CAN Network Management
 *                AUTOSAR Release 3.0
 *  
 *********************************************************************************************************************/
#include "Can_BusOff.h"
#include "CanIf.h"
#include "Can.h"
#include "Com_Cfg.h"
#include "CanNm.h"
#include "Com.h"
STATIC VAR(uint8_t, CAN_BUSOFF_PRIVATE_DATA) BusOffFlagAry[CAN_USED_CONTROLLER_NUM];
STATIC VAR(uint8, CAN_BUSOFF_PRIVATE_DATA) nubNmBusOffCntAry[CAN_USED_CONTROLLER_NUM];
STATIC VAR(uint8, CAN_BUSOFF_PRIVATE_DATA) nmStatusErrRestoringAry[CAN_USED_CONTROLLER_NUM];
STATIC VAR(uint8, CAN_BUSOFF_PRIVATE_DATA) nmStatusSlowRecoveryAry[CAN_USED_CONTROLLER_NUM];
STATIC VAR(uint8, CAN_BUSOFF_PRIVATE_DATA) NMBusErrorAry[CAN_USED_CONTROLLER_NUM];
STATIC VAR(nmTimerCntType, CAN_BUSOFF_PRIVATE_DATA) nmTimerCntTbusoffAry[CAN_USED_CONTROLLER_NUM];

static FUNC(void, CAN_BUSOFF_PRIVATE_CODE) NmCanBusOffCheckFun(const uint16_t CurChannel);



/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: CAN_BusOff_Init
*
* Description:   bus-off
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
void CAN_BusOff_Init(void)
{
    uint8_t i;

    for(i = 0; i < CAN_USED_CONTROLLER_NUM; i ++)
    {
        BusOffFlagAry[i] = 0;
        nubNmBusOffCntAry[i] = 0;
        nmStatusErrRestoringAry[i] = 0;
        nmStatusSlowRecoveryAry[i] = 0;
        NMBusErrorAry[i] = 0;
        nmTimerCntTbusoffAry[i] = 0;
    }
}

/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: ApplNmBusOff
*
* Description:   bus-off
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
void ApplNmBusOff(const uint16_t CurChannel)/*indicates bus off error occured*/
{

    (void)CurChannel;
    Com_TxStop();
    Com_RxStop();
}


/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: ApplNmBusOffEnd
*
* Description:   bus-off
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
void ApplNmBusOffEnd(const uint16_t CurChannel)/*indicates bus off error occured*/
{

    (void)CurChannel;
    Com_TxStart();
    Com_RxStart();
}

/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: Can_BusOff
*
* Description:   bus-off
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
FUNC(void, CAN_BUSOFF_PRIVATE_CODE) Can_BusOff(const uint16_t CanControllerId)
{
    

    uint16_t CurChannel;

    CurChannel = CanControllerId;

    nmStatusNMBusOffFlag = 1u;

}
/*This callback function is performed when busOff recovery successed.*/
void ApplNmBusOffRecoverySuccess(const uint16_t nmChannelHandle)
{
    uint16_t CurChannel;
    CurChannel = nmChannelHandle;
    if(1 == nmStatusErrRestoring)
    {
        /*OsekNm_008*/
        nubNmBusOffCnt = 0; 
        nmStatusSlowRecovery = 0;
        nmStatusErrRestoring = 0;

    }    
}

void ApplNmCanBusOffRecoveryFail(const uint16_t nmChannelHandle)
{
    /*Bus Off recovery failed */
    



}

/* BEGIN_FUNCTION_HDR
********************************************************************************
* Function Name: BusErrorRecover
*
* Description:   Process the NM when BusOff.
*             
* Inputs:        initMode
* 
* Outputs:       None
* 
* Limitations:   None
********************************************************************************
END_FUNCTION_HDR*/
STATIC FUNC(void, CAN_BUSOFF_PRIVATE_CODE) NmBusErrorRecover
(
    const uint16_t CurChannel
)
{

    /*OsekNm_008*/
    (void)CanNm_PassiveStartUp(0);

    nubNmBusOffCnt++;

    nmStatusErrRestoring = 1u;
      
#if ( NM_BUSOFF_FAST_RECOVERY_ENABLE != STD_OFF)

    if((nubNmBusOffCnt <= NM_BUSOFF_FAST_RECOVERY_TIMES)&&(0 == nmStatusSlowRecovery))    
    {
        if(nubNmBusOffCnt == NM_BUSOFF_FAST_RECOVERY_TIMES)
        {
            /* 1:Fast recover will  try last one time,Slow recover will be processed*/
            nmStatusSlowRecovery = 1u;
            nubNmBusOffCnt = 0;
        }
        else
        {

        }
        nmTimerCntTbusoff = NM_COUNT_FAST_TBUSOFF;
        /*CallBack function, inform Application Bus off*/
        ApplNmBusOff(CurChannel);    

    }
    else if(nubNmBusOffCnt <= NM_BUSOFF_SLOW_RECOVERY_TIMES)
#else
	if(nubNmBusOffCnt <= NM_BUSOFF_SLOW_RECOVERY_TIMES)
#endif
    {
        /*OsekNm_006*/
        nmTimerCntTbusoff = NM_COUNT_SLOW_TBUSOFF;

        /*CallBack function, inform Application Bus off*/
        ApplNmBusOff(CurChannel);    
    }
    else
    {
        nubNmBusOffCnt = 0;
        /*process fast recover first*/
        nmStatusSlowRecovery = 0u;
        ApplNmCanBusOffRecoveryFail(CurChannel);
    }

}
/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: NmTerrTimeOutProc
*
* Description:   Carry out this event Function when Time-out Terr
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
STATIC FUNC(void, CAN_BUSOFF_PRIVATE_CODE) NmTerrTimeOutProc    
(
    const uint16_t CurChannel
)
{
    Nm_StateType nmCurState_Par;
    Nm_ModeType  nmCurMode_Par;

    uint32_t primask;
    BusOffCanInterruptDisable();


    /*OsekNm_004 end*/
    if(1u == nmStatusNMBusError )
    {
        nmStatusNMBusError = 0;
        /*clear CAN driver buffer*/
        NmCanClearBuffer(CurChannel);
        /*OsekNm_008 start*/
        NMBusErrorCanInit(CurChannel);
        NMBusErrorCanStart(CurChannel);
        ApplNmBusOffEnd(CurChannel);   

        /* enable application communication (D_online) */
        (void)NmCanTxOnline(CurChannel);
        /*OsekNm_008 end*/
    }
    else
    {
        /*nothing to do*/
    }

    Com_Transmit(0,&COM_TxDataPtr[0]); 
        

    BusOffCanInterruptRestore();
}

/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: NmTbusOffRecoveryTimeOutProc
*
* Description:   BusOff recovery process
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
/*OsekNm_006*/
STATIC FUNC(void, CAN_BUSOFF_PRIVATE_CODE) NmTBusOffRecoveryTimeOutProc
(
    const uint16_t CurChannel
)
{
    NmTerrTimeOutProc(CurChannel);
}
/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: NmTimerTTxCntFun
*
* Description:   bus-off timer function
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
/*OsekNm_006*/
STATIC FUNC(void, CAN_BUSOFF_PRIVATE_CODE) NmTimerTBusOffCntFun
(
    const uint16_t CurChannel
)
{
    uint32_t primask;
    BusOffCanInterruptDisable();

    if(nmTimerCntTbusoff != 0)
    {
        nmTimerCntTbusoff--;
        
        if(0 == nmTimerCntTbusoff)
        {
            NmTBusOffRecoveryTimeOutProc(CurChannel);
        }
        else
        {
            /* do nothing */
        }
    }
    else
    {
        /* do nothing */
    }
    BusOffCanInterruptRestore();
}
/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: CanBusOffMainFunction
*
* Description:   bus-off
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
FUNC(void, CAN_BUSOFF_PRIVATE_CODE) CanBusOffMainFunction(void)
{
    NmCanBusOffCheckFun(0);
    NmTimerTBusOffCntFun(0);
}



/* BEGIN_FUNCTION_HDR
******************************************************************************** 
* Function Name: CanBusOffCheckFun
*
* Description:   bus-off
*                
* Inputs:        None
* 
* Outputs:       None
* 
* Limitations:   None
******************************************************************************** 
END_FUNCTION_HDR*/
static FUNC(void, CAN_BUSOFF_PRIVATE_CODE) NmCanBusOffCheckFun(const uint16_t CurChannel)
{
    uint32_t primask;

    if(1 == nmStatusNMBusOffFlag)
    {
        BusOffCanInterruptDisable();
   
        (void)NmCanTxOffline(CurChannel);
         
        nmStatusNMBusOffFlag = 0;
        nmStatusNMBusError = 1;
     
        NmCanClearBuffer(CurChannel);
//        NMBusErrorCanInit(CurChannel);
//        NMBusErrorCanStart(CurChannel);
        /*Bus off recovery*/
        NmBusErrorRecover(CurChannel);

        BusOffCanInterruptRestore();
    }
    else
    {
        /*do nothing*/
    }

}
