
/**************   FICOSA COMMAND AND CONTROL SYSTEMS DIVISION  ****************
| File:              | TP_Tx.c
|-----------------------------------------------------------------------------
| Author:            | Author
|-----------------------------------------------------------------------------
| Project:           | TP
| System:            | TP_Task
| Diagram:           | TP_Tx
| Model Version:     | 1.0
| Model Date:        | Thursday, February 26, 2009 - 14:47:56
|-----------------------------------------------------------------------------
| CodeC Version:     | 1.0
| Codification Date: | 18/10/2010
|-----------------------------------------------------------------------------
| Description:
|    Codificacio automatica d'un diagrama d'estats
|
|    ++++ Informacio del Diagrama d'Estats +++++
|
|    Numero d'estats:       3
|    Numero de transicions: 12
|    Estats inicials:       1
|  
|    Variables d'entrada:
|           tp_frm (t_tp_frm)
|           fc_data (t_fc_data)
|    Variables de sortida:
|           NP_CAN_TX_DATA (UI_8)
|           NP_CAN_TX_SIZE (UI_8)
|    Variables d'entrada/sortida:
|    Variables locals:
|           block_size (UI_8)
|           timer_n_bs (t_clock)
|           timer_n_cs (t_clock)
|           timer_n_as (t_clock)
|           ack_tx (BOOL)
|
|    ++++ Descripcio del proces implementat ++++
|
|     Maquina 0x2 
 ISO 15765: KWP -> CAN 
|
**************************   FI DE LA CAPCALERA  ****************************/

/*------------------------------- includes --------------------------------*/
#include "Std_Types.h"
#include "DiagnosticL/Comp_HAL_Autosar_Wrappers/Timer.h"
#include "TP_Task.h"
#include "TP.h"


/*------------------------------ user code --------------------------------*/

#include "DiagnosticL/UDS/Iso15765_layer2/TP_CFG.h"
#include "TP_Functions.h"
#include "DiagnosticL/FicOsek/FicOsekCom.h"

/*-------------------------------- macros ---------------------------------*/





/*------------------------------- defines ---------------------------------*/
/* Maxim valor del compteig del temps */
#define MAX_COMPTADOR_TEMPS ((UI_16)65000)

/*---------------------------- tipus de dades -----------------------------*/

/*------------------------------ variables --------------------------------*/

/*------------------------- capcaleres de funcions ------------------------*/

static void TP_Tx_Full0(UI_8 tp_hdl);
static void Inici(UI_8 tp_hdl);
static void EsperaFC(UI_8 tp_hdl);
static void ConfirmaTx(UI_8 tp_hdl);
void TP_Tx_Full(UI_8 tp_hdl);


/*----------------------- funcions d'inicialitzacio -----------------------*/
 
/**************************************************************************** 
| Funcionalitat:                                                              
|   Inicialitzacio del diagrama d estats TP_Tx 
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades: - 
|   Sortides:
|       
|       NP_CAN_TX_DATA
|       NP_CAN_TX_SIZE 
****************************************************************************/
#if 1
void TP_Tx_FullInicialitza(UI_8 tp_hdl)
{
    /* Inicialitzacio de la variable d estat */
    tp_data[tp_hdl].state_tx = ESTAT_0_TP_TX_FULL;

    /* Execucio del cicle inicial de la maquina d estats */
    TP_Tx_Full(tp_hdl);
}
#endif

/*------------------------- rutines principals ---------------------------*/
 
/**************************************************************************** 
| Funcionalitat:                                                              
|   Rutina principal del diagrama d estats TP_Tx. 
|   Invoca a la funcio corresponent a l estat actual. 
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       
|       tp_frm
|       fc_data 
|   Sortides:
|       
|       NP_CAN_TX_DATA
|       NP_CAN_TX_SIZE 
****************************************************************************/
void TP_Tx_Full(UI_8 tp_hdl)
{
    /* Estudi per casos del estat actual */
    switch (tp_data[tp_hdl].state_tx){
    case ESTAT_0_TP_TX_FULL:
        TP_Tx_Full0(tp_hdl);
        break;
    case ESTAT_TP_TX_FULL_INICI:
        Inici(tp_hdl);
        break;
    case ESTAT_TP_TX_FULL_ESPERAFC:
        EsperaFC(tp_hdl);
        break;
    case ESTAT_TP_TX_FULL_CONFIRMATX:
        ConfirmaTx(tp_hdl);
        break;
    default:
        tp_data[tp_hdl].state_tx = ESTAT_0_TP_TX_FULL;
        break;
    }

    /* Increment del temps de cicle als timers */
    if (tp_data[tp_hdl].timers.n_bs < MAX_COMPTADOR_TEMPS) {
        tp_data[tp_hdl].timers.n_bs += TP_TASK_TICKS;
    }
    if (tp_data[tp_hdl].timers.n_cs < MAX_COMPTADOR_TEMPS) {
        tp_data[tp_hdl].timers.n_cs += TP_TASK_TICKS;
    }
}

#ifdef ENABLE_INCREMENT_EXTERNAL_TIMERS
void TPTxIncrTimers(UI_8 tp_hdl, UI_16 ticks)
{
    if (tp_data[tp_hdl].timers.n_bs < MAX_COMPTADOR_TEMPS) {
        tp_data[tp_hdl].timers.n_bs += ticks;
    }
    if (tp_data[tp_hdl].timers.n_cs < MAX_COMPTADOR_TEMPS) {
        tp_data[tp_hdl].timers.n_cs += ticks;
    }
}
#endif

/*------------------------- funcions d'estats -----------------------------*/

 
/**************************************************************************** 
| Funcionalitat: 
|   Funcio corresponent a l estat inicial del proces TP_Tx 
|---------------------------------------------------------------------------- 
| Interficie: -                                                                
****************************************************************************/
static void TP_Tx_Full0(UI_8 tp_hdl)
{
    /* -- reset dels timers t_clock -- */
    tp_data[tp_hdl].timers.n_bs= (t_clock)0;
    tp_data[tp_hdl].timers.n_cs= (t_clock)0;
    
    if (TPCheckPhyCfgData(tp_hdl) == TRUE) {
        /* Canviem l estat inicial */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
    }
    else {
        /* No s ha activat cap condicio inicial: ens quedem a l estat actual */
        tp_data[tp_hdl].state_tx = ESTAT_0_TP_TX_FULL;
    }
}
 
/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat Inici.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       
|       tp_frm
|       fc_data 
|   Sortides:
|       
|       NP_CAN_TX_DATA
|       NP_CAN_TX_SIZE 
****************************************************************************/
static void Inici(UI_8 tp_hdl)
{
    if ((tp_frm[tp_hdl].sts_tx == TP_FRM_TX_REQ) && (tp_frm[tp_hdl].size_tx <= NP_SF_MAX_SIZE) && (tp_frm[tp_hdl].iso15765_2_block_tx == FALSE)) {
        /* Cas en que executem la transicio TxSF */

        /* -- action de la transicio -- */
        TPSendSF(tp_hdl);

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_CONFIRMATX;
    }
    else if ((tp_frm[tp_hdl].sts_tx == TP_FRM_TX_REQ) && (tp_frm[tp_hdl].size_tx > NP_SF_MAX_SIZE) && (tp_frm[tp_hdl].iso15765_2_block_tx == FALSE)) {
        /* Cas en que executem la transicio TxFF */

        /* -- action de la transicio -- */
        TPSendFF(tp_hdl);
        tp_data[tp_hdl].fc_data.first_fc = TRUE;
        tp_data[tp_hdl].fc_data.block_size_cnt = 0xFF;
        tp_data[tp_hdl].fc_data.rx_bs = 0xFF;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_CONFIRMATX;
    }
    else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
    }
}
 
/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat EsperaFC.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       
|       tp_frm
|       fc_data 
|   Sortides:
|       
|       NP_CAN_TX_DATA
|       NP_CAN_TX_SIZE 
****************************************************************************/
static void EsperaFC(UI_8 tp_hdl)
{
    /* -- codi de l estat actual -- */
    if (tp_data[tp_hdl].rx_st.frame_fc_type == TP_FC) {
        TPReadFCSendCF(tp_hdl);
    }
    else {
        /* Do nothing */
    }

    if ((tp_data[tp_hdl].fc_data.fc_rx == TRUE) && (tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_WT) && (tp_data[tp_hdl].fc_data.num_fc_wait < tp_data[tp_hdl].cfg.n_wftmax)) {
        /* Cas en que executem la transicio ArribaFCWaitAccepted */

        /* -- action de la transicio -- */
		/* Reset the FC reception flag */
        tp_data[tp_hdl].fc_data.fc_rx = FALSE;
		/* Increment number of FC wait received */
		tp_data[tp_hdl].fc_data.num_fc_wait++;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_ESPERAFC;
    }
    else if ((tp_data[tp_hdl].fc_data.fc_rx == TRUE) && (tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_WT) && (tp_data[tp_hdl].fc_data.num_fc_wait >= tp_data[tp_hdl].cfg.n_wftmax)) {
        /* Cas en que executem la transicio ArribaFCWaitRejected */
        /* -- action de la transicio -- */
        tp_data[tp_hdl].fc_data.fc_rx = FALSE;
        tp_frm[tp_hdl].sts_tx = TP_FRM_TX_ERR_NOTIF;
        tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
		tp_data[tp_hdl].fc_data.num_fc_wait = 0;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
	}
    else if ((tp_data[tp_hdl].fc_data.fc_rx == FALSE) && (tp_data[tp_hdl].timers.n_bs >= TIMER_MS_TO_TICKS(tp_data[tp_hdl].cfg.n_bs_max) )) {
        /* Cas en que executem la transicio TimeOutFC */
        /* -- action de la transicio -- */
        tp_data[tp_hdl].fc_data.fc_rx = FALSE;
        tp_frm[tp_hdl].sts_tx = TP_FRM_TX_ERR_NOTIF;
        tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
		tp_data[tp_hdl].fc_data.num_fc_wait = 0;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
    }
    else if ((tp_data[tp_hdl].fc_data.fc_rx == TRUE) && (tp_data[tp_hdl].fc_data.flow_status != TP_FLOW_STS_WT) && (tp_data[tp_hdl].fc_data.flow_status != TP_FLOW_STS_CTS)) {
        /* Cas en que executem la transicio ArribaFCError */
        /* -- action de la transicio -- */
        tp_data[tp_hdl].fc_data.fc_rx = FALSE;
        tp_frm[tp_hdl].sts_tx = TP_FRM_TX_ERR_NOTIF;
        tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
		tp_data[tp_hdl].fc_data.num_fc_wait = 0;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
    }
    else if ((tp_data[tp_hdl].fc_data.fc_rx == TRUE) && (tp_data[tp_hdl].fc_data.flow_status == TP_FLOW_STS_CTS)) {
        /* Cas en que executem la transicio TxPrimerCF */

        /* -- action de la transicio -- */
        tp_data[tp_hdl].fc_data.block_size_cnt = (UI_8)1;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_CONFIRMATX;
    }
    else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_ESPERAFC;
    }
}
 
/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat ConfirmaTx.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       
|       tp_frm
|       fc_data 
|   Sortides:
|       
|       NP_CAN_TX_DATA
|       NP_CAN_TX_SIZE 
****************************************************************************/
static void ConfirmaTx(UI_8 tp_hdl)
{
    BOOL tx_confirmed, end_frame;
    
    /* Check if the transmission has been confirmed */
    tx_confirmed = TPCheckTxConfirmed(tp_hdl, tp_data[tp_hdl].tx_st.frame_tx_sts);
    
    /* -- codi de l estat actual -- */
    if (tx_confirmed == TRUE) {
        tp_data[tp_hdl].tx_st.ack_tx = TRUE;
    }
    else {
        tp_data[tp_hdl].tx_st.ack_tx = FALSE;
        tp_data[tp_hdl].timers.n_cs = 0;
    }
    
    /* Check if the TX is finished */
    end_frame = TPTestEndFrame(tp_hdl);

    if ((tp_data[tp_hdl].tx_st.ack_tx == FALSE) && (tp_data[tp_hdl].tx_st.frame_tx_sts == TP_TX_ERROR)) {
        /* Cas en que executem la transicio TimeOutTxCF */
        /* -- action de la transicio -- */
        tp_frm[tp_hdl].sts_tx = TP_FRM_TX_ERR_NOTIF;
        tp_frm[tp_hdl].iso15765_2_block_rx = FALSE;
		tp_data[tp_hdl].fc_data.num_fc_wait = 0;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
    }
    else if ((tp_data[tp_hdl].tx_st.ack_tx == TRUE) && (end_frame == TRUE)) {
        /* Cas en que executem la transicio TxAcabada */
        /* -- action de la transicio -- */
        tp_frm[tp_hdl].sts_tx = TP_FRM_TX_IDLE;
		tp_data[tp_hdl].fc_data.num_fc_wait = 0;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_INICI;
    }
    else if ((tp_data[tp_hdl].tx_st.ack_tx == TRUE) && (end_frame == FALSE) && (tp_data[tp_hdl].fc_data.rx_bs > (UI_8)0) && (tp_data[tp_hdl].fc_data.block_size_cnt >= tp_data[tp_hdl].fc_data.rx_bs)) {
        /* Cas en que executem la transicio EndBlockSize */

        /* -- action de la transicio -- */
        tp_data[tp_hdl].fc_data.fc_rx = FALSE;

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_ESPERAFC;
    }
    else if ((tp_data[tp_hdl].tx_st.ack_tx == TRUE) && (end_frame == FALSE) && (tp_data[tp_hdl].timers.n_cs >= TIMER_MS_TO_TIME_RESTRICTIVE((t_clock)(tp_data[tp_hdl].fc_data.stmin))) && ((tp_data[tp_hdl].fc_data.block_size_cnt < tp_data[tp_hdl].fc_data.rx_bs) || (tp_data[tp_hdl].fc_data.rx_bs == 0))) {
        /* Cas en que executem la transicio TxSeguentCF */

        /* -- action de la transicio -- */
        tp_data[tp_hdl].fc_data.block_size_cnt++;
        TPSendCF(tp_hdl);

        /* -- reset del timer -- */
        tp_data[tp_hdl].timers.n_bs = (t_clock)0;
        tp_data[tp_hdl].timers.n_cs = (t_clock)0;

        /* -- canviem l estat -- */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_CONFIRMATX;
    }
    else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        tp_data[tp_hdl].state_tx = ESTAT_TP_TX_FULL_CONFIRMATX;
    }
}


/********************************** FI **************************************/
