/***************  COPYRIGHT (c) 2002-2007 FICOSA INTERNATIONAL   **************
| Language:       |  MISRA C
| Controller:     |  Generic
| Spec. Document: |  ISO15765-2-E.pdf
|-----------------|------------------------------------------------------------
| Project:        |  ISO15765-2
| Reference:      |
|------------------------------------------------------------------------------
|    Date  - Cod. - Rev. - App. -             Description
| 12/09/02   AM                 Implementation of the kwp2000 for PSA.
| 19/08/04   DT                 Split ISO15765_2 protocol from the KWP2000
|                               because they are different modules.
| 24/04/09   DC                 Modification to guarantee the requirements SR1431,
|                               SR1438, SR1681.
| 15/07/09   AC                 Corrected bug in ReadCF because it didn't count
|                               correctly the blocks
| 15/12/10   AC                 Converted ISO15765_2 protocol to multi-instance.
| 13/11/11   AC                 Converted ISO15765_2 to full-duplex
| 09/01/11   AC                 Changed file, routines and variable naming to
|                               make it a standard component and to have a
|                               similar naming style with MPDT.
|------------------------------------------------------------------------------
| DESCRIPTION:
|   User interface for the transport protocol ISO15765_2 on CAN.
|   ISO15765_2 protocol is a transport protocol that permits the sending and
|   reception of frames until 4096 bytes on a network protocol with frames of
|   lower size. The original frame is segemented and sent with flow control
|   data that allows to the reception node to mount again the original frame.
| GENERAL CONSIDERATIONS
|   - This implementation allows full duplex communications.
|   - This implementation allows for each instance a communication channel
|     with physical address in which both transmission and receptions could
|     be done and a funcional address for only receptions.
|   - The functional address channel only supports frames with less than
|     8 bytes of data.
******************************************************************************/

/*----------------------------- INCLUDES ---------------------------------*/
//#include "Global.h"
//#include "Timer.h"
#include "Std_Types.h"
#include "DiagnosticL/Comp_HAL_Autosar_Wrappers/Timer.h"
#include "DiagnosticL/UDS/Iso15765_layer2/TP_CFG.h"
#include "DiagnosticL/Comp_ISO_15765_2/TP.h"
#include "TP_Task.h"
#include "TP_Functions.h"
#include "DiagnosticL/FicOsek/FicOsekCom.h"

/*----------------------------- DEFINES ----------------------------------*/

/* Constant that define the maximum value that could have the segment number */
#define MAX_NUM_SEG ((UI_8)15)

/* Possible values of the first 4 bits of the first transport protocol byte */
/* which define the type of TP frame */
#define SF_TYPE     ((UI_8)0)
#define FF_TYPE     ((UI_8)1)
#define CF_TYPE     ((UI_8)2)
#define FC_TYPE     ((UI_8)3)

/*------------------------------ DATA TYPES ------------------------------*/

/*--------------------------- GLOBAL VARIABLES ---------------------------*/

/* Declaration of the TP data structure */
t_tp_data tp_data[TP_NUM_INSTANCES];

/* Declaration of the tp_frm phisical structure */
t_tp_frm tp_frm[TP_NUM_INSTANCES];

/* Declaration of the tp_frm functional structure */
t_tp_fun_frm tp_fun_frm[TP_NUM_INSTANCES];


/*--------------------------- ROUTINE PROTOTYPES -------------------------*/

/*-------------------------------- ROUTINES ------------------------------*/

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to initialize the transport protocol strucutres.
|  This routine must be called once from Initializations of main
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: TP handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void InicialitzaTPTask(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* INITIALIZE FLOW CONTROL DATA STRUCTURE */
#ifdef TP_MODE_FULL
		/* Flow control status */
		tp_data[tp_hdl].fc_data.flow_status = TP_FLOW_STS_CTS;
		/* BS received by the FC of the tool */
		tp_data[tp_hdl].fc_data.rx_bs = 0xFF;
		/* STMIN time received by the FC of the tool */
		tp_data[tp_hdl].fc_data.stmin = 0x7F;
		/* Flag that indicates if it is the first FC */
		tp_data[tp_hdl].fc_data.first_fc = TRUE;
		/* Flag that indicates the reception of a FC */
		tp_data[tp_hdl].fc_data.fc_rx = FALSE;
		/* Counter of the current block size sent in order to know when a FC must expected */
		tp_data[tp_hdl].fc_data.block_size_cnt = 0xFF;
		/* Counter of the consecutive frames sent before waiting a FC */
		tp_data[tp_hdl].fc_data.num_fc_wait = 0;
#endif
		/* INITIALIZE THE TP_FRM STRUCTURE */
		tp_frm[tp_hdl].size_tx = (UI_16)0;
		tp_frm[tp_hdl].size_rx = (UI_16)0;
		tp_frm[tp_hdl].sts_tx = TP_FRM_TX_IDLE;
		tp_frm[tp_hdl].sts_rx = TP_FRM_RX_IDLE;
		tp_frm[tp_hdl].unblock_after_tx = FALSE;
		tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
		tp_frm[tp_hdl].iso15765_2_block_tx = FALSE;
		/* INITIALIZE THE TP_FUN_FRM STRUCTURE */
		tp_fun_frm[tp_hdl].size = (UI_8)0;
		tp_fun_frm[tp_hdl].sts_rx = TP_FRM_RX_IDLE;
		/* INITIALIZE THE TX RX STATUS STRUCTURE */
		tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_NO_FRM;
		tp_data[tp_hdl].tx_st.ack_tx = FALSE;
		tp_data[tp_hdl].tx_st.frame_tx_sts = TP_TX_CONFIRMED;
#ifdef TP_MODE_FULL
		tp_data[tp_hdl].rx_st.byte_actual_rx = (UI_16)0;
		tp_data[tp_hdl].tx_st.byte_actual_tx = (UI_16)0;
		tp_data[tp_hdl].rx_st.frame_fc_type = TP_NO_FC_FRM;
		tp_data[tp_hdl].rx_st.next_segm_num_rx = (UI_8)0;
		tp_data[tp_hdl].tx_st.next_segm_num_tx = (UI_8)0;
		tp_data[tp_hdl].rx_st.num_frames_before_fc = (UI_16)0;
		tp_data[tp_hdl].tx_st.frame_tx_fc_sts = TP_TX_CONFIRMED;
#endif

		/* INITIALIZE THE TP TIMERS */
		tp_data[tp_hdl].timers.n_as = (t_clock)0;
#ifdef TP_MODE_FULL
		tp_data[tp_hdl].timers.n_cr = (t_clock)0;
		tp_data[tp_hdl].timers.n_ar = (t_clock)0;
		tp_data[tp_hdl].timers.n_bs = (t_clock)0;
		tp_data[tp_hdl].timers.n_cs = (t_clock)0;
#endif

		/* Initialize the TP user dynamic configuration parameters */
		TPDynamicParametersInitCallback(tp_hdl);

#ifdef TP_MODE_FULL
		/* Initialize the TP task to receive the CAN frames */
		TP_NetworkLayerLowerInterface_RxInicialitza(tp_hdl);
		/* Initialize the TP TX FSM */
		TP_Tx_FullInicialitza(tp_hdl);
		/* Initialize the TP RX FSM */
		TP_Rx_FullInicialitza(tp_hdl);
		/* Initialize the TP funtional RX FSM */
		TP_RxFunInicialitza(tp_hdl);
		/* Initialize the TP task to transmit the CAN frames */
		TP_NetworkLayerLowerInterface_TxInicialitza(tp_hdl);
#else
		/* Initialize the TP task to receive the CAN frames */
		TP_NetworkLayerLowerInterface_RxInicialitza(tp_hdl);
		/* Initialize the TP TX FSM */
		TP_Tx_LiteInicialitza(tp_hdl);
		/* Initialize the TP RX FSM */
		TP_Rx_LiteInicialitza(tp_hdl);
		/* Initialize the TP funtional RX FSM */
		TP_RxFunInicialitza(tp_hdl);
		/* Initialize the TP task to transmit the CAN frames */
		TP_NetworkLayerLowerInterface_TxInicialitza(tp_hdl);
#endif

	}
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine that execute all the FSM tasks that are involved in the transport
|  protocol sending and reception.
|  This routine must be called at each program cycle in main.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: TP handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPTask(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

#ifdef TP_MODE_FULL
		/* Execute the TP task to receive the CAN frames */
		TP_NetworkLayerLowerInterface_Rx(tp_hdl);
		/* Execute the TP TX task */
		TP_Tx_Full(tp_hdl);
		/* Execute the TP RX task */
		TP_Rx_Full(tp_hdl);
		/* Execute the TP RX functional task */
		TP_RxFun(tp_hdl);
		/* Execute the TP task to transmit the CAN frames */
		TP_NetworkLayerLowerInterface_Tx(tp_hdl);
#else
		/* Execute the TP task to receive the CAN frames */
		TP_NetworkLayerLowerInterface_Rx(tp_hdl);
		/* Execute the TP TX task */
		TP_Tx_Lite(tp_hdl);
		/* Execute the TP RX task */
		TP_Rx_Lite(tp_hdl);
		/* Execute the TP RX functional task */
		TP_RxFun(tp_hdl);
		/* Execute the TP task to transmit the CAN frames */
		TP_NetworkLayerLowerInterface_Tx(tp_hdl);
#endif

	}
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to initialize an ISO15765_2 instance with the configuration
|  parameters needed by the application.
|  This routine must be called from the callback routine in which the user
|  must configure the dynamic parameters that must be called
|  TPDynamicParametersInitCallback
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     init_data: ISO15765_2 configuration parameters to be taken by the
|                given handler
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPInitData(UI_8 tp_hdl, t_tp_init * init_data)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Initialize the dynamic parameters with the init value given by the user */
#ifdef TP_MODE_FULL
		tp_data[tp_hdl].cfg.np_max_frm_size = init_data->max_frm_size;
		tp_data[tp_hdl].cfg.n_cr_max = init_data->cr_timer;
		tp_data[tp_hdl].cfg.n_bs_max = init_data->bs_timer;
		tp_data[tp_hdl].cfg.stmin = init_data->stmin_timer;
		tp_data[tp_hdl].cfg.block_size = init_data->block_size;
		tp_data[tp_hdl].cfg.n_wftmax = init_data->max_fc_wait;
#endif
		tp_data[tp_hdl].cfg.np_can_frm_size_fixed = init_data->frm_size_fixed;
		tp_data[tp_hdl].cfg.np_rx_padding_sensitive = init_data->rx_padding_sensitive;
		tp_data[tp_hdl].cfg.np_tx_padding_value = init_data->tx_padding_value;
		tp_data[tp_hdl].can_phy.can_handler = init_data->can_handler;
		tp_data[tp_hdl].can_phy.sig_np_rx = init_data->sig_np_rx_phy;
		tp_data[tp_hdl].can_phy.sig_np_tx = init_data->sig_np_tx_phy;
		tp_data[tp_hdl].can_fun.sig_np_rx = init_data->sig_np_rx_fun;
		tp_frm[tp_hdl].data_tx = init_data->tx_phy_buffer;
		tp_frm[tp_hdl].data_rx = init_data->rx_phy_buffer;
		tp_fun_frm[tp_hdl].data_rx = init_data->rx_fun_buffer;

	}
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to process the last received physical CAN frame. This routine
|  will get the data bytes, the length and the type of transport protocol
|  frame using the CAN interfaces.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPProcessRxCanPhyFrame(UI_8 tp_hdl)
{     // uint8 index;
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		BOOL test_can_frm_size;
		UI_8 rx_can_frame[CAN_FRM_MAX_SIZE];
		UI_8 rx_can_len, type, i;

		/* Receive the physical CAN frame */

           
	   
		(void)ReceiveDynamicMessage(tp_data[tp_hdl].can_phy.sig_np_rx,
				(t_application_data_ref)rx_can_frame,
				(t_length_ref)&rx_can_len);

		//<<
		//AlwaysEntry
		//>>

		/* Check if TP is configured with fixed size and RX length case sensitive */
		if((tp_data[tp_hdl].cfg.np_can_frm_size_fixed == TRUE) &&
				(tp_data[tp_hdl].cfg.np_rx_padding_sensitive == TRUE)) {
			/* Check that the received frame has 8 bytes of length */
			test_can_frm_size = (rx_can_len == CAN_FRM_MAX_SIZE);
		}
		else {
			/* Check that the frame at least has one byte of data */
			test_can_frm_size = (rx_can_len > 0);
		}

		/* Check that we received a frame with correct data size according configuration of TP */
		if(test_can_frm_size == TRUE) {
			/* Get the TP frame type */
			type = rx_can_frame[0] >> (UI_8)4;
			/* Check if the frame is a valid TP frame type */
			switch(type) {
			case SF_TYPE:
				/* Set the SINGLE FRAME type */
				tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_SF;
				/* Copy the received data to the structure */
				for(i=0; i<8; i++) {
					tp_data[tp_hdl].rx_st.frame_rx_data[i] = rx_can_frame[i];
				}
				/* Copy the received data length to the structure */
				tp_data[tp_hdl].rx_st.frame_rx_len = rx_can_len;
				break;
#ifdef TP_MODE_FULL
			case FF_TYPE:
				/* A first frame must have maximum CAN length */
				if(rx_can_len == CAN_FRM_MAX_SIZE) {
					/* Set the FIRST FRAME type */
					tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_FF;
					/* Copy the received data to the structure */
					for(i=0; i<8; i++) {
						tp_data[tp_hdl].rx_st.frame_rx_data[i] = rx_can_frame[i];
					}
					/* Copy the received data length to the structure */
					tp_data[tp_hdl].rx_st.frame_rx_len = rx_can_len;
				}
				else {
					/* Non valid FF */
					tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_NO_FRM;
				}
				break;
			case CF_TYPE:
				/* Check if the length is valid according to CF. It shall be 8 bytes */
				/* except for the case of last CF */
				if((rx_can_len != CAN_FRM_MAX_SIZE) && ((tp_data[tp_hdl].rx_st.byte_actual_rx + (UI_16)(rx_can_len-(UI_8)1)) < tp_frm[tp_hdl].size_rx)) {
					/* Ignore CF as it is not the last CF and length is different from 8 bytes */
					tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_NO_FRM;
				}
				else {
					/* Set the CONSECUTIVE FRAME type */
					tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_CF;
					/* Copy the received data to the structure */
					for(i=0; i<8; i++) {
						tp_data[tp_hdl].rx_st.frame_rx_data[i] = rx_can_frame[i];
					}
					/* Copy the received data length to the structure */
					tp_data[tp_hdl].rx_st.frame_rx_len = rx_can_len;
				}
				break;
			case FC_TYPE:
				/* Set the FLOW CONTROL type */
				tp_data[tp_hdl].rx_st.frame_fc_type = TP_FC;
				/* Copy the received data to the structure */
				for(i=0; i<8; i++) {
					tp_data[tp_hdl].rx_st.frame_rx_fc_data[i] = rx_can_frame[i];
				}
				/* Copy the received data length to the structure */
				tp_data[tp_hdl].rx_st.frame_rx_fc_len = rx_can_len;
				break;
#endif
			default:
				/* No valid frame has been received */
				break;
			}
		}
		else {
			/* Do nothing */
		}
	}
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine that checks if any of the possible pending transport protocol
|  transmission frames are pending to be transmitted.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     result: boolean that indicates if transmission is pending
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPCheckTxCanFrame(UI_8 tp_hdl, t_tp_tx_type *tp_tx_type)
{
	BOOL result = FALSE;
	//uint8 index_3;

	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

#ifdef TP_MODE_FULL
		/* Check if a FC will be the next TP frame to be sent */
		if(tp_data[tp_hdl].tx_st.frame_tx_fc_sts == TP_TX_REQUESTED) {
			/* Notify that FC frame will be the next */
			result = TRUE;
			*tp_tx_type = TP_TX_TYPE_FC;
		}
		/* Check if a SF, FF or CF will be the next TP frame to be sent */
		else if(tp_data[tp_hdl].tx_st.frame_tx_sts == TP_TX_REQUESTED) {
			/* Notify that SF, FF or CF frame will be the next */
			result = TRUE;
			*tp_tx_type = TP_TX_TYPE_SF_FF_CF;
		}
		else {
			/* Notify that no frame is pending */
			result = FALSE;
			*tp_tx_type = TP_TX_TYPE_NONE;
		}
#else
		/* Check if a SF will be the next TP frame to be sent */
		if(tp_data[tp_hdl].tx_st.frame_tx_sts == TP_TX_REQUESTED) {
			/* Notify that SF frame will be the next */
			result = TRUE;
			*tp_tx_type = TP_TX_TYPE_SF_FF_CF;
		}
		else {
			/* Notify that no frame is pending */
			result = FALSE;
			*tp_tx_type = TP_TX_TYPE_NONE;
		}
#endif

	}
	return result;
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine that triggers the sending of a transport protocol frame (SF, FF, CF
|  or flow control). The priority of the transmission frames will be given by
|  the order of checking each of the flags in the IF condition.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPProcessTxCanFrame(UI_8 tp_hdl)
{
	//uint8 index_1;
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	/* Test here*/
	if (tp_hdl < TP_NUM_INSTANCES){

#ifdef TP_MODE_FULL
		if(tp_data[tp_hdl].tx_st.frame_tx_fc_sts == TP_TX_REQUESTED) {
			//<<Not Enter here>>
			
			/* Send the flow control on CAN */
			(void)SendDynamicMessage(tp_data[tp_hdl].can_phy.sig_np_tx,
					(t_application_data_ref)&tp_data[tp_hdl].tx_st.frame_tx_fc_data[0],
					(t_length_ref)&tp_data[tp_hdl].tx_st.frame_tx_fc_len);
			/* Update the FC status of transmission */
			tp_data[tp_hdl].tx_st.frame_tx_fc_sts = TP_TX_ON_GOING;
		}
		/* Check if any of the transmission frames are pending */
		else if(tp_data[tp_hdl].tx_st.frame_tx_sts == TP_TX_REQUESTED) {
#else
			/* Check if any of the transmission frames are pending */
			if(tp_data[tp_hdl].tx_st.frame_tx_sts == TP_TX_REQUESTED) {
#endif
				

				//<<OnlyOnceHere>>	
				/* Send the TX frame on CAN */
				(void)SendDynamicMessage(tp_data[tp_hdl].can_phy.sig_np_tx,
						(t_application_data_ref)&tp_data[tp_hdl].tx_st.frame_tx_data[0],
						(t_length_ref)&tp_data[tp_hdl].tx_st.frame_tx_len);
				/* Update the status of frame the transmission */
				tp_data[tp_hdl].tx_st.frame_tx_sts = TP_TX_ON_GOING;
			}
			else {
				/* Do nothing */
			}
		}

		//<<OnlyOnceHere>>	
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine that checks if Osekcom notified the transmission of the TX last
|  frame
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     result: TRUE if transmission has been confirmed, FALSE otherwise
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPCheckCanFrameConfirmation(UI_8 tp_hdl)
{
	t_flag_value tx_phy_notif;
	BOOL result = FALSE;

	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Check if transmission has been confirmed */
		tx_phy_notif = ReadFlagTxSig(tp_data[tp_hdl].can_phy.sig_np_tx);
		/* Check if has been confirmed */
		if(tx_phy_notif == COM_TRUE) {
			/* Notify the TX confirmation */
			result = TRUE;
		}
		else {
			/* Do nothing */
		}
	}

	return result;
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine that checks if for a given transmission frame (which could be
|  a "Flow Control", a "First Frame, a "Consecutive Frame" or a "Single Frame")
|  his transmission has been confirmed.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     tx_sts: current transmission status of the requested frame
|     result: TRUE if transmission has been confirmed, FALSE otherwise
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPCheckTxConfirmed(UI_8 tp_hdl, t_tp_tx_sts tx_sts)
{
	BOOL result = TRUE;
	BOOL can_conf;

	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Check if the frame TX status has been already confirmed */
		if(tx_sts == TP_TX_CONFIRMED) {
			/* Do nothing */
		}
		else {
			/* Get CAN frame confirmation */
			can_conf = TPCheckCanFrameConfirmation(tp_hdl);
			/* Check if CAN frame has been confirmed after last execution of NetworkLayerLowerInterface */
			/* and we let the TP_Tx_Full FSM to continue in order to avoid waiting 5 ms */
			if((tx_sts == TP_TX_ON_GOING) && (can_conf == TRUE)) {
				/* Do nothing */
			}
			else {
				/* Notify that transmission is still not confirmed */
				result = FALSE;
			}
		}
	}
	return result;
}

/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to notify a new transmission frame status for a transmission
|  which still has his status as ongoing
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     tx_sts: new status to be set instead of ongoing
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPNotifyCanFrmTx(UI_8 tp_hdl, t_tp_tx_sts tx_sts)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Check which frame was being sent */
		if(tp_data[tp_hdl].tx_st.frame_tx_sts == TP_TX_ON_GOING) {
			/* Update TX frame status as confirmed */
			tp_data[tp_hdl].tx_st.frame_tx_sts = tx_sts;
			//<<Not enter here>>//
		}
#ifdef TP_MODE_FULL
		else if(tp_data[tp_hdl].tx_st.frame_tx_fc_sts == TP_TX_ON_GOING) {
			/* Update TX FC status as confirmed */
			tp_data[tp_hdl].tx_st.frame_tx_fc_sts = tx_sts;
		}
#endif
		else {
			/* Do nothing */
		}
	}
}

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine that checks if there are still more frames pending to be sent.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     result: TRUE if there are not more pending frames to be sent.
|             FALSE if there are still more pending frames to be sent
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPTestEndFrame(UI_8 tp_hdl)
{
	BOOL test_value = FALSE;

	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

#ifdef TP_MODE_FULL
		/* Check if the requested TP TX size has been already requested */
		/* to be transmitted to the low layer (OSEKCOM) */
		if(tp_frm[tp_hdl].size_tx <= tp_data[tp_hdl].tx_st.byte_actual_tx) {
			/* Notify that the frame TX is finished */
			test_value = TRUE;
		}
		else {
			/* Notify that the frame TX is not finished */
			test_value = FALSE;
		}
#else
		/* In lite mode only single frames are transmitted so once the frame is sent */
		/* we are sure that the whole length of data has been sent */
		test_value = TRUE;
#endif

	}
	return test_value;
}

/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to request the sending of a single frame. Remember that a SF is
|  used only to sent network frames with equal ore less than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPSendSF(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){
        #ifdef TP_MODE_FULL
		/* Reset flow control reception notification */
		tp_data[tp_hdl].rx_st.frame_fc_type = TP_NO_FC_FRM;
        #endif

		/* Indicacio de que es tracta d'un single frame i volcat de la mida de les dades */
		/* NPCI = 0x0X; (0x00 = SingleFrame) or (0x0X = numero de bytes de datos) */
		tp_data[tp_hdl].tx_st.frame_tx_data[0] = (UI_8)tp_frm[tp_hdl].size_tx;

		/* Volcat de les dades */
		tp_data[tp_hdl].tx_st.frame_tx_data[1] = tp_frm[tp_hdl].data_tx[0];
		tp_data[tp_hdl].tx_st.frame_tx_data[2] = tp_frm[tp_hdl].data_tx[1];
		tp_data[tp_hdl].tx_st.frame_tx_data[3] = tp_frm[tp_hdl].data_tx[2];
		tp_data[tp_hdl].tx_st.frame_tx_data[4] = tp_frm[tp_hdl].data_tx[3];
		tp_data[tp_hdl].tx_st.frame_tx_data[5] = tp_frm[tp_hdl].data_tx[4];
		tp_data[tp_hdl].tx_st.frame_tx_data[6] = tp_frm[tp_hdl].data_tx[5];
		tp_data[tp_hdl].tx_st.frame_tx_data[7] = tp_frm[tp_hdl].data_tx[6];

#ifdef TP_MODE_FULL
		/* Set the size of the single frame data sent */
		tp_data[tp_hdl].tx_st.byte_actual_tx = tp_frm[tp_hdl].size_tx;
#endif

		/* Check if the size of the diagnostic frames must be fixed (8 bytes) */
		if(tp_data[tp_hdl].cfg.np_can_frm_size_fixed == TRUE) {
			UI_8 aux;
			/* Omplenat amb zeros dels bytes no utils i indicacio de la mida de les dades */
			for (aux=(UI_8)tp_frm[tp_hdl].size_tx + (UI_8)1; aux < CAN_FRM_MAX_SIZE; aux++) {
				tp_data[tp_hdl].tx_st.frame_tx_data[aux] = tp_data[tp_hdl].cfg.np_tx_padding_value;
			}
			/* Set the maximum CAN frame length */
			tp_data[tp_hdl].tx_st.frame_tx_len = CAN_FRM_MAX_SIZE;
		}
		else {
			/* Set the SF length */
			tp_data[tp_hdl].tx_st.frame_tx_len = (UI_8)(tp_frm[tp_hdl].size_tx + (UI_8)1);
		}

		/* Check if TP must be unblocked */
		if(tp_frm[tp_hdl].unblock_after_tx == TRUE) {
			/* Allow new requests */
			tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
		}
		else {
			/* Do nothing */
		}

		/* Request the transmission of the frame */
		//<<HereIs: tp_data[tp_hdl].tx_st.frame_tx_sts = TP_TX_CONFIRMED;>>//
		tp_data[tp_hdl].tx_st.frame_tx_sts = TP_TX_REQUESTED;

	}
}

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to request the sending of a first frame. Remember that a first
|  frame is used to send the initial network frame with more than 8 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPSendFF(UI_8 tp_hdl)
{
	UI_16 npci;

	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Reset flow control reception notification */
		tp_data[tp_hdl].rx_st.frame_fc_type = TP_NO_FC_FRM;

		/* Indicacio de que es tracta d'un first frame i volcat de la mida de les dades */
		/* NPCI = 0x1XXX; (0x10 = FirstFrame) or (0x0XXX = numero de bytes de datos) */
		npci = tp_frm[tp_hdl].size_tx | (UI_16)0x1000;
		/* La parte alta en el byte 0 */
		tp_data[tp_hdl].tx_st.frame_tx_data[0] = (UI_8)(npci >> 8);
		/* La parte baja del NPCI ira en el byte 1. */
		tp_data[tp_hdl].tx_st.frame_tx_data[1] = (UI_8)npci;
		/* Apuntador al byte actual */
		tp_data[tp_hdl].tx_st.byte_actual_tx = (UI_8)6;
		/* Num del proxim segment */
		tp_data[tp_hdl].tx_st.next_segm_num_tx = (UI_8)1;
		/* Volcat de les dades */
		tp_data[tp_hdl].tx_st.frame_tx_data[2] = tp_frm[tp_hdl].data_tx[0];
		tp_data[tp_hdl].tx_st.frame_tx_data[3] = tp_frm[tp_hdl].data_tx[1];
		tp_data[tp_hdl].tx_st.frame_tx_data[4] = tp_frm[tp_hdl].data_tx[2];
		tp_data[tp_hdl].tx_st.frame_tx_data[5] = tp_frm[tp_hdl].data_tx[3];
		tp_data[tp_hdl].tx_st.frame_tx_data[6] = tp_frm[tp_hdl].data_tx[4];
		tp_data[tp_hdl].tx_st.frame_tx_data[7] = tp_frm[tp_hdl].data_tx[5];
		/* Set the maximum CAN length frame */
		tp_data[tp_hdl].tx_st.frame_tx_len = CAN_FRM_MAX_SIZE;

		/* Request the transmission of the frame */
		tp_data[tp_hdl].tx_st.frame_tx_sts = TP_TX_REQUESTED;
	}
}
#endif

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to request the sending of a consecutive frame. Remember that CF
|  are used after sending a FF when the network frame has more than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPSendCF(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Reset flow control reception notification */
		tp_data[tp_hdl].rx_st.frame_fc_type = TP_NO_FC_FRM;

		/* Indicacio de que es tracta d'un cosecutive frame i volcat del numero de segment */
		/* NPCI = 0x2X; (0x20 = ConsecutiveFrame) or (0x0X = numero de segmento)   */
		tp_data[tp_hdl].tx_st.frame_tx_data[0] = tp_data[tp_hdl].tx_st.next_segm_num_tx | (UI_8)0x20;
		if (tp_data[tp_hdl].tx_st.next_segm_num_tx >= MAX_NUM_SEG) {
			tp_data[tp_hdl].tx_st.next_segm_num_tx = (UI_8)0;
		}
		else {
			tp_data[tp_hdl].tx_st.next_segm_num_tx++;
		}

		/* Volcat de les dades */
		tp_data[tp_hdl].tx_st.frame_tx_data[1] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;
		tp_data[tp_hdl].tx_st.frame_tx_data[2] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;
		tp_data[tp_hdl].tx_st.frame_tx_data[3] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;
		tp_data[tp_hdl].tx_st.frame_tx_data[4] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;
		tp_data[tp_hdl].tx_st.frame_tx_data[5] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;
		tp_data[tp_hdl].tx_st.frame_tx_data[6] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;
		tp_data[tp_hdl].tx_st.frame_tx_data[7] = tp_frm[tp_hdl].data_tx[tp_data[tp_hdl].tx_st.byte_actual_tx];
		tp_data[tp_hdl].tx_st.byte_actual_tx++;

		if (tp_frm[tp_hdl].size_tx <= tp_data[tp_hdl].tx_st.byte_actual_tx) {
			/* Check if the size of the diagnostic frames must be fixed (8 bytes) */
			if(tp_data[tp_hdl].cfg.np_can_frm_size_fixed == TRUE) {
				UI_8 aux;
				/* Omplenat amb zeros dels bytes no utils i indicacio de la mida de les dades */
				for (aux=(UI_8)0 ; aux < tp_data[tp_hdl].tx_st.byte_actual_tx - tp_frm[tp_hdl].size_tx ; aux++) {
                    /* Polyspace Defensive code to make the tool to understand that padding is only applicable to last frame. */
					if (aux < 6) {
					    tp_data[tp_hdl].tx_st.frame_tx_data[CAN_FRM_MAX_SIZE - ((UI_8)1) - aux] = tp_data[tp_hdl].cfg.np_tx_padding_value;
					}
					else {
					   /* Do nothing */
					}
				}
				/* Set the maximum CAN length frame */
				tp_data[tp_hdl].tx_st.frame_tx_len = CAN_FRM_MAX_SIZE;
			}
			else {
				/* Set the consecutive frame length */
				tp_data[tp_hdl].tx_st.frame_tx_len = (UI_8)(CAN_FRM_MAX_SIZE + tp_frm[tp_hdl].size_tx - tp_data[tp_hdl].tx_st.byte_actual_tx);
			}

			/* Check if TP must be unblocked */
			if(tp_frm[tp_hdl].unblock_after_tx==TRUE) {
				/* Allow new requests */
				tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
			}
			else {
				/* Do nothing */
			}
		}
		else {
			/* Set the maximum CAN frame length size */
			tp_data[tp_hdl].tx_st.frame_tx_len = CAN_FRM_MAX_SIZE;
		}

		/* Request the transmission of the frame */
		tp_data[tp_hdl].tx_st.frame_tx_sts = TP_TX_REQUESTED;
	}
}
#endif

/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to read a CAN frame of the type "Single Frame" with physical
|  address. Remember that a SF is a frame with equal or less than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPReadSF(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		UI_8 rx_sf_size;

		/* Reset the frame reception type */
		tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_NO_FRM;

		/* Get the received SF length */
		rx_sf_size = tp_data[tp_hdl].rx_st.frame_rx_data[0] & ((UI_8)(0x0F));

		/* Check if the size is correct and the ISO_2 is not blocked */
		if ((tp_frm[tp_hdl].iso15765_2_block_rx == FALSE) &&
				(rx_sf_size < tp_data[tp_hdl].rx_st.frame_rx_len) &&
				(rx_sf_size > (UI_8)0) &&
				(rx_sf_size <= NP_SF_MAX_SIZE)) {
			/* Volcat de la mida de les dades */
			tp_frm[tp_hdl].size_rx = rx_sf_size;
			/* Comprovacio de que la mida de les dades indicada a la trama no es igual a 0 seguint SR1431 */
			if ((tp_frm[tp_hdl].size_rx != (UI_8)(0x00)) && (tp_frm[tp_hdl].size_rx <= NP_SF_MAX_SIZE)) {
				/* Volcat de les dades */
				tp_frm[tp_hdl].data_rx[0] = tp_data[tp_hdl].rx_st.frame_rx_data[1];
				tp_frm[tp_hdl].data_rx[1] = tp_data[tp_hdl].rx_st.frame_rx_data[2];
				tp_frm[tp_hdl].data_rx[2] = tp_data[tp_hdl].rx_st.frame_rx_data[3];
				tp_frm[tp_hdl].data_rx[3] = tp_data[tp_hdl].rx_st.frame_rx_data[4];
				tp_frm[tp_hdl].data_rx[4] = tp_data[tp_hdl].rx_st.frame_rx_data[5];
				tp_frm[tp_hdl].data_rx[5] = tp_data[tp_hdl].rx_st.frame_rx_data[6];
				tp_frm[tp_hdl].data_rx[6] = tp_data[tp_hdl].rx_st.frame_rx_data[7];

				/* Notificacio a la capa superior de l'arribada d'una nova trama */
				tp_frm[tp_hdl].sts_rx = TP_FRM_RX_NOTIF;
				/* Block TP reception */
				tp_frm[tp_hdl].iso15765_2_block_rx = TRUE;
			}
			else {
				/* Ignorar la trama */
				tp_frm[tp_hdl].sts_rx = TP_FRM_RX_ERR_NOTIF;
			}
		}
		else {
			/* Ignorar la trama */
			tp_frm[tp_hdl].sts_rx = TP_FRM_RX_ERR_NOTIF;
		}
	}
}

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to read a CAN frame of the type "First Frame" and request directly
|  the sending of a Flow Control as always after receiving a FF a FC must
|  be sent by protocol. Remember that a FF is a frame with more than 7
|  bytes. Remember that a FC is used to control the flow of the reception
|  of a frame with more than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPReadFFSendFC(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Reset the frame reception type */
		tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_NO_FRM;

		/* Check that conditions are correct to receive a FF */
		if (tp_data[tp_hdl].rx_st.frame_rx_len == CAN_FRM_MAX_SIZE) {
			/* Volcat de la mida de les dades */
			tp_frm[tp_hdl].size_rx =(UI_8)(tp_data[tp_hdl].rx_st.frame_rx_data[0] & ((UI_8)(0x0F)));
			tp_frm[tp_hdl].size_rx <<= (UI_8)8;
			tp_frm[tp_hdl].size_rx |= tp_data[tp_hdl].rx_st.frame_rx_data[1];
			tp_data[tp_hdl].rx_st.byte_actual_rx = (UI_8)6;

			/* Comprovacio que la trama en proces de recepcio cap */
			/* dins del buffer de recepcio                        */
			if (tp_frm[tp_hdl].size_rx <= tp_data[tp_hdl].cfg.np_max_frm_size) {
				/* Comprovacio que la mida de la trama es major que el */
				/* tamany maxim d'un SF seguint SR1681                 */
				if(tp_frm[tp_hdl].size_rx > NP_SF_MAX_SIZE) {

					/* Volcat del num del proxim segment */
					tp_data[tp_hdl].rx_st.next_segm_num_rx = (UI_8)1;

					/* Volcat de les dades */
					tp_frm[tp_hdl].data_rx[0] = tp_data[tp_hdl].rx_st.frame_rx_data[2];
					tp_frm[tp_hdl].data_rx[1] = tp_data[tp_hdl].rx_st.frame_rx_data[3];
					tp_frm[tp_hdl].data_rx[2] = tp_data[tp_hdl].rx_st.frame_rx_data[4];
					tp_frm[tp_hdl].data_rx[3] = tp_data[tp_hdl].rx_st.frame_rx_data[5];
					tp_frm[tp_hdl].data_rx[4] = tp_data[tp_hdl].rx_st.frame_rx_data[6];
					tp_frm[tp_hdl].data_rx[5] = tp_data[tp_hdl].rx_st.frame_rx_data[7];

					/* Notificacio a la capa superior de l'arribada d'una nova trama */
					tp_frm[tp_hdl].sts_rx = TP_FRM_RX_IN_PRG;

					/* Enviar FC positivament */
					TPSendFC(tp_hdl, TP_FLOW_STS_CTS);
				}
				else {
					/* Ignorar la trama */
				}
			}
			else {
				/* Notificacio a la capa superior de l'arribada d'una nova trama amb error */
				tp_frm[tp_hdl].sts_rx = TP_FRM_RX_ERR_FINISHED;
				/* Enviar FC notificant l'overflow en el tamany de dades */
				TPSendFC(tp_hdl, TP_FLOW_STS_OVFLW);
			}
		}
		else {
			/* Ignorar la trama */
		}
	}
}
#endif

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to request the sending of a flow control. Remember that a FC is
|  used to control the flow of the reception of a frame with more than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     flow_control_type: type of the flow control that must be sent
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPSendFC(UI_8 tp_hdl, t_tp_flow_sts flow_control_type)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Enviament de de la trama flow control */
		/* Indicacio de que es tracta d'un flow control */
		/* frame i volcat Flow control status           */
		tp_data[tp_hdl].tx_st.frame_tx_fc_data[0]= (UI_8)flow_control_type | ((UI_8)0x30);
		/* Volcat del BS */
		tp_data[tp_hdl].tx_st.frame_tx_fc_data[1]=tp_data[tp_hdl].cfg.block_size;
		/* Volcat del ST_MIN */
		tp_data[tp_hdl].tx_st.frame_tx_fc_data[2]=(UI_8)tp_data[tp_hdl].cfg.stmin;

		/* Check if the size of the frame shall be fixed to 8 bytes */
		if(tp_data[tp_hdl].cfg.np_can_frm_size_fixed == TRUE) {
			/* Omplenat amb zeros dels bytes no utils i */
			/* indicacio de la mida de les dades        */
			tp_data[tp_hdl].tx_st.frame_tx_fc_data[3] = tp_data[tp_hdl].cfg.np_tx_padding_value;
			tp_data[tp_hdl].tx_st.frame_tx_fc_data[4] = tp_data[tp_hdl].cfg.np_tx_padding_value;
			tp_data[tp_hdl].tx_st.frame_tx_fc_data[5] = tp_data[tp_hdl].cfg.np_tx_padding_value;
			tp_data[tp_hdl].tx_st.frame_tx_fc_data[6] = tp_data[tp_hdl].cfg.np_tx_padding_value;
			tp_data[tp_hdl].tx_st.frame_tx_fc_data[7] = tp_data[tp_hdl].cfg.np_tx_padding_value;
			/* Set the length to the maximum CAN frame size */
			tp_data[tp_hdl].tx_st.frame_tx_fc_len = CAN_FRM_MAX_SIZE;
		}
		else {
			/* Set the flow control length */
			tp_data[tp_hdl].tx_st.frame_tx_fc_len = (UI_8)3;
		}

		/* Request the transmission of the frame */
		tp_data[tp_hdl].tx_st.frame_tx_fc_sts = TP_TX_REQUESTED;
	}
}
#endif

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to read a CAN frame of the type "Consecutive Frame". Remember
|  that consecutive frames are received after receiving the first frame
|  with network frames with more than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPReadCF(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		UI_8 segm_num;
		UI_8 aux;

		/* Reset the frame reception type */
		tp_data[tp_hdl].rx_st.frame_rx_type = TP_RX_NO_FRM;

		/* Check if the received length of the frame is correct */
		if (tp_frm[tp_hdl].iso15765_2_block_rx == FALSE) {
			segm_num = (UI_8)(tp_data[tp_hdl].rx_st.frame_rx_data[0] & ((UI_8)0x0F));
			if (segm_num == tp_data[tp_hdl].rx_st.next_segm_num_rx) {
				if (tp_data[tp_hdl].rx_st.next_segm_num_rx >= MAX_NUM_SEG) {
					tp_data[tp_hdl].rx_st.next_segm_num_rx = (UI_8)0;
				}
				else {
					tp_data[tp_hdl].rx_st.next_segm_num_rx++;
				}

				/* Volcat de les dades */
				for (aux=(UI_8)1; aux < tp_data[tp_hdl].rx_st.frame_rx_len; aux++) {
					tp_frm[tp_hdl].data_rx[tp_data[tp_hdl].rx_st.byte_actual_rx] = tp_data[tp_hdl].rx_st.frame_rx_data[aux];
					tp_data[tp_hdl].rx_st.byte_actual_rx++;
				}

				if (tp_frm[tp_hdl].size_rx <= tp_data[tp_hdl].rx_st.byte_actual_rx) {
					/* Notificacio a la capa superior de l'arribada d'una nova trama */
					tp_frm[tp_hdl].sts_rx = TP_FRM_RX_FINISHED;
					/* Block TP reception */
					tp_frm[tp_hdl].iso15765_2_block_rx = TRUE;
				}
				else if (tp_data[tp_hdl].rx_st.frame_rx_len != CAN_FRM_MAX_SIZE) {
					/* Notificacio a la capa superior de l'arribada d'una nova trama amb error */
					tp_frm[tp_hdl].sts_rx = TP_FRM_RX_ERR_FINISHED;
				}
				else {
					/* No fer res */
				}
			}
			else {
				tp_frm[tp_hdl].sts_rx = TP_FRM_RX_ERR_FINISHED;
			}
		}
		else {
			/* Ignorar la trama */
		}
	}
}
#endif

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to read a CAN frame of the type "Consecutive Frame". Remember
|  that consecutive frames are received after receiving the first frame
|  with network frames with more than 7 bytes. This routine in case that
|  the received frame is consistent and has the correct format will request
|  the sending of a flow control.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPReadCFSendFC(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Read the consecutive frame */
		TPReadCF(tp_hdl);

		/* Check if the consecutive frame have the correct format */
		if(tp_frm[tp_hdl].sts_rx != TP_FRM_RX_ERR_FINISHED) {
			/* Send a flow control */
			TPSendFC(tp_hdl, TP_FLOW_STS_CTS);
		}
		else {
			/* Do nothing */
		}
	}
}
#endif

#ifdef TP_MODE_FULL
/*****************************************************************************
| Portability:  Generic
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to read a CAN frame of the type "Flow Control" and request
|  the sending of a "Consecutive Frame". Remember that "Flow Control" frames
|  are used to control the flow of the transmission in case of network
|  frames with more than 7 bytes.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
/---------------------------------------------------------------------------*/
void TPReadFCSendCF(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Reset the frame reception type */
		tp_data[tp_hdl].rx_st.frame_fc_type = TP_NO_FC_FRM;

		/* Check if the size of the received frame is correct */
		if (tp_data[tp_hdl].rx_st.frame_rx_fc_len >= CAN_FRM_FC_SIZE) {
			tp_data[tp_hdl].fc_data.flow_status = (t_tp_flow_sts)(tp_data[tp_hdl].rx_st.frame_rx_fc_data[0] & ((UI_8)0x0F));

			/* Aixequem el flag de recepcio de flow control */
			tp_data[tp_hdl].fc_data.fc_rx = TRUE;

			/* Check if the flow control type is correct */
			if ((tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_CTS) ||
					(tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_WT) ||
					(tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_OVFLW)) {

				/* Check if this is the first flow control */
				if (tp_data[tp_hdl].fc_data.first_fc == TRUE) {
					tp_data[tp_hdl].fc_data.first_fc = FALSE;
					tp_data[tp_hdl].fc_data.rx_bs = tp_data[tp_hdl].rx_st.frame_rx_fc_data[1];
					/* Cas valors 0..127 */
					if (tp_data[tp_hdl].rx_st.frame_rx_fc_data[2] <= (UI_8)0x7F) {
						tp_data[tp_hdl].fc_data.stmin = tp_data[tp_hdl].rx_st.frame_rx_fc_data[2];
					}
					/* Cas valors F1..F9 i valors reservats */
					else {
						/* Renault specification in document 36-02-031--A_Gb.pdf page 15 */
						tp_data[tp_hdl].fc_data.stmin = (UI_8)0x7F;
					}
				}
				else {
					/* Ignorar bs i stmin */
				}
				/* Cas en que el Flow Control indica ClearToSend */
				if (tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_CTS) {
					/* Enviar el primer Consecutive Frame */
					TPSendCF(tp_hdl);
				}
				/* Cas en que el Flow Control no indica ClearToSend */
				else {
					/* Esperar proxim Flow Control */
				}
			}
			else {
				/* Do nothing */
			}
		}
		else {
			/* Ignorar la trama */
		}
	}
}
#endif

/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to read a functional CAN frame. Remember that in functional
|  channel any frame with a type different from SF will be ignored as the
|  maximum allowed size for this channel is 7.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
void TPReadFunFrm(UI_8 tp_hdl)
{
	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		UI_8 rx_can_frame[CAN_FRM_MAX_SIZE];
		UI_8 rx_can_len,rx_sf_size;
		//BOOL test_can_frm_size;

		/* Receive the CAN frame */
		(void)ReceiveDynamicMessage(tp_data[tp_hdl].can_fun.sig_np_rx,
				(t_application_data_ref)rx_can_frame,
				(t_length_ref)&rx_can_len);

		/* Check that the notified RX length is correct according to the received CAN frame length */
		/* Longitud 0 Payload shall be rejected */
		rx_sf_size = rx_can_frame[0] & ((UI_8)(0x0F));

		/* Verificacio de la mida i del tipus de trama */
		if (((rx_can_frame[0] >> (UI_8)4) == TP_RX_SF)  &&
				(rx_sf_size > (UI_8)0) &&
				((rx_can_frame[0] & (UI_8)0x0F) <= NP_SF_MAX_SIZE)) {
			/* Volcat de la mida de les dades */
			tp_fun_frm[tp_hdl].size = (UI_8)(rx_can_frame[0] & (UI_8)0x0F);
			/* Save the received data */
			tp_fun_frm[tp_hdl].data_rx[0] = rx_can_frame[1];
			tp_fun_frm[tp_hdl].data_rx[1] = rx_can_frame[2];
			tp_fun_frm[tp_hdl].data_rx[2] = rx_can_frame[3];
			tp_fun_frm[tp_hdl].data_rx[3] = rx_can_frame[4];
			tp_fun_frm[tp_hdl].data_rx[4] = rx_can_frame[5];
			tp_fun_frm[tp_hdl].data_rx[5] = rx_can_frame[6];
			tp_fun_frm[tp_hdl].data_rx[6] = rx_can_frame[7];
			/* Notificacio a la capa superior de l'arribada d'una nova trama */
			tp_fun_frm[tp_hdl].sts_rx = TP_FRM_RX_NOTIF;
		}
		else {
			/* Ignorar la trama */
		}
	}
}

/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to check if the timeout of the transmission frame has been notfied.
|  Remember that this timeout must be configured in the OSEKCOM database with
|  the specified AX timeout defined.
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     return: TRUE if timeout has been confirmed, FALSE otherwise
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPCheckAxTimeout(UI_8 tp_hdl)
{
	t_flag_value ax_timeout = 0;
	BOOL result =FALSE;

	/* To avoid Polyspace warning : "pointer may be outside its bounds" */
	if (tp_hdl < TP_NUM_INSTANCES){

		/* Get the AX timeout from OSEKCOM */
		//ax_timeout = ReadFlagTxErrorSig(tp_data[tp_hdl].can_phy.sig_np_tx);

		/* Check if the timeout is confirmed */
		if(ax_timeout == COM_TRUE) {
			result = TRUE;
		}
		else {
			result = FALSE;
		}
	}
	return result;
}

/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to check that all the physical interface routines with OSEKCOM layer
|  are correctly initialized
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     return: TRUE if configuration is correct, FALSE otherwise
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPCheckPhyCfgData(UI_8 tp_hdl)
{
    BOOL result;

	/* Check that CAN interface routines are correctly initialized */
    result = ((BOOL)GetComApplicationMode() == (BOOL)COM_NORMAL_MODE);

	return result;
}

/*****************************************************************************
| Portability:  Generica
|----------------------------------------------------------------------------
| Functionalities Contract Description:
|  Routine to check that all the functional interface routines with OSEKCOM layer
|  are correctly initialized
|---------------------------------------------------------------------------
| Parameters Explanation:
|     tp_hdl: ISO15765_2 handler to be used
|     return: TRUE if configuration is correct, FALSE otherwise
|---------------------------------------------------------------------------
| Timing:
| Tmax Int Dis:   ? CPU cycles | O(n): CTE
| Tmax Int En :   ? CPU cycles | O(n): CTE
| Tmax Total  :   ? CPU cycles | O(n): CTE
/---------------------------------------------------------------------------*/
BOOL TPCheckFunCfgData(UI_8 tp_hdl)
{
    BOOL result;

	/* Check that CAN interface routines are correctly initialized */
    result = ((BOOL)GetComApplicationMode() == (BOOL)COM_NORMAL_MODE);

	return result;
}

