view src/g23m-fad/ra/ra_fax.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 90eb61ecd093
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :  GSM-F&D (8411)
|  Modul   :  RA_FAX
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This Modul defines the functions for the faxnsparent
|             data model for the component RA of the mobile station
+-----------------------------------------------------------------------------
*/

#ifndef RA_FAX_C
#define RA_FAX_C
#endif

#define ENTITY_RA

/*==== INCLUDES ===================================================*/

#include <string.h>
#include "typedefs.h"
#include "vsi.h"
#include "macdef.h"
#include "pconst.cdg"
#include "custom.h"
#include "gsm.h"
#include "cnf_ra.h"
#include "prim.h"
#include "pei.h"
#include "tok.h"
#include "ccdapi.h"
#include "ra.h"

/*==== CONST ======================================================*/

LOCAL const T_SKIP skip_F14400 [4] =
{
  /* T4DATA same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* T4DATA other */  {0, 1, 0, 1, 0, 1, 0, 1}},
  /* STATUS same  */ {{0, 0, 1, 0, 0, 0, 1, 0},
  /* STATUS other */  {1, 1, 1, 0, 1, 1, 1, 0}},
  /* SYNC   same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* SYNC   other */  {1, 0, 1, 0, 1, 0, 1, 0}},
  /* TRAIN  same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* TRAIN  other */  {1, 1, 1, 0, 1, 1, 1, 0}}
};

LOCAL const UBYTE request_F14400 [4] =
{
  5,4,5,4
};

LOCAL const T_SKIP skip_F9600 [4] =
{
  /* T4DATA same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* T4DATA other */  {0, 0, 0, 0, 0, 0, 0, 0}},
  /* STATUS same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* STATUS other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* SYNC   same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* SYNC   other */  {0, 0, 0, 0, 0, 0, 0, 0}},
  /* TRAIN  same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* TRAIN  other */  {0, 1, 0, 1, 0, 1, 0, 1}}
};

LOCAL const UBYTE request_F9600 [4] =
{
  3,3,3,3
};

LOCAL const T_SKIP skip_F4800 [4] =
{
  /* T4DATA same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* T4DATA other */  {0, 1, 0, 1, 0, 1, 0, 1}},
  /* STATUS same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* STATUS other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* SYNC   same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* SYNC   other */  {0, 1, 0, 1, 0, 1, 0, 1}},
  /* TRAIN  same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* TRAIN  other */  {0, 1, 1, 1, 0, 1, 1, 1}}
};

LOCAL const UBYTE request_F4800 [4] =
{
  2,1,2,1
};

LOCAL const T_SKIP skip_F2400 [4] =
{
  /* T4DATA same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* T4DATA other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* STATUS same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* STATUS other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* SYNC   same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* SYNC   other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* TRAIN  same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* TRAIN  other */  {0, 1, 1, 1, 1, 1, 1, 1}}
};

LOCAL const UBYTE request_F2400 [4] =
{
  1,1,1,1
};

LOCAL const T_SKIP skip_H4800 [4] =
{
  /* T4DATA same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* T4DATA other */  {0, 1, 0, 1, 0, 1, 0, 1}},
  /* STATUS same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* STATUS other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* SYNC   same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* SYNC   other */  {0, 1, 0, 1, 0, 1, 0, 1}},
  /* TRAIN  same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* TRAIN  other */  {0, 1, 1, 1, 0, 1, 1, 1}}
};

LOCAL const UBYTE request_H4800 [4] =
{
  2,1,2,1
};

LOCAL const T_SKIP skip_H2400 [4] =
{
  /* T4DATA same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* T4DATA other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* STATUS same  */ {{0, 0, 0, 1, 0, 0, 0, 1},
  /* STATUS other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* SYNC   same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* SYNC   other */  {0, 1, 1, 1, 0, 1, 1, 1}},
  /* TRAIN  same  */ {{0, 0, 0, 0, 0, 0, 0, 0},
  /* TRAIN  other */  {0, 1, 1, 1, 1, 1, 1, 1}}
};

LOCAL const UBYTE request_H2400 [4] =
{
  1,1,1,1
};

/*==== TYPES ======================================================*/
/*==== VARIABLES ==================================================*/
/*==== FUNCTIONS ==================================================*/

#if defined TRACE_RA_FAX_UL_FRAME_TYPE || defined _SIMULATION_

LOCAL void trace_ra_fax_ul_frame_type(USHORT cus_frame_type, UBYTE* buf1, USHORT bytes_to_write)
{
  const char type[5] = "DSYT";
  char buf[15] = "TISx:0x00-0x00";

  if (cus_frame_type < 4)
    buf[3] = type[cus_frame_type];

  if (buf1)
    BYTE2HEXSTR(*(buf1+1), &buf[7]);

  BYTE2HEXSTR((UBYTE)bytes_to_write, &buf[12]);
  TRACE_EVENT (buf);
}

#endif

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_

LOCAL void trace_ra_fax_dl_frame_type(U8 *last, U8 current, USHORT bytes_read)
{
  void t30_ker_debug(CHAR *header, UBYTE *buf, USHORT len);

  const char type[5] = "DSYT";
  char buf[15] = "TIRx:0x00-0x__";

  if (*last NEQ current)
  {
    if (current < 4)
      buf[3] = type[current];

    TRACE_EVENT (buf);

   *last = current;
  }
  else if (bytes_read)
  {
    if (current EQ 0)
    {
      t30_ker_debug("TIRD", ra_data->fax->dl_pFD->buf, bytes_read);
    }
    else
    {
      if (current < 4)
        buf[3] = type[current];

      BYTE2HEXSTR((UBYTE)bytes_read, &buf[7]);

      if (current EQ 1)
        BYTE2HEXSTR(ra_data->fax->dl_pFD->buf[1], &buf[12]);

      TRACE_EVENT (buf);
    }
  }
}

#endif

LOCAL void fax_init_data(BOOL CMM_flag)
{
  T_FAX *dfax = ra_data->fax;
  /*
   * initialize the fax mode data
   */
  ra_data->sync_timer               = 0L;
  ra_data->cycle_time               = 0L;

  dfax->CMM_flag            = CMM_flag;
  dfax->ul_frame_type_last  = FR_SYNC;
  dfax->ul_frame_type       = FR_SYNC;
  dfax->ul_pFD = NULL;

  cl_ribu_init(&dfax->ul_ribu->idx, RA_FIFO_DEPTH);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
  dfax->dl_frame_type_last  = 0xFF;
  dfax->dl_state_last = 0xFF;
#endif

  dfax->req_idx = 0;
  dfax->seq_idx = 0;

  dfax->ul_train_FD.buf = dfax->train_seq;
  dfax->ul_train_FD.len = 2;

  ra_data->ra_data_ind.fr_type        = FR_INVALID;
  ra_data->ra_data_ind.sdu.o_buf      = 0;
  ra_data->ra_data_ind.sdu.l_buf      = 0;
  ra_data->ra_ready_ind[0].req_frames = 0;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_init                 |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_init(void)
{
  TRACE_FUNCTION("fax_init");

  fax_init_data(FALSE); /* no CMM */

  hCommFAD = vsi_c_open ( VSI_CALLER FAD_NAME );
  hCommMMI = vsi_c_open ( VSI_CALLER ACI_NAME );
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_ul_modify            |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_ul_modify(void)
{
  TRACE_EVENT("fax_ul_modify()");

  fax_init_data(TRUE); /* CMM */
  fax_ul_null();
  return;
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_idle                 |
+--------------------------------------------------------------------+

  PURPOSE : IDLE processing for uplink and downlink fax mode
*/

GLOBAL void fax_idle(void)
{
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_ul_null              |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_ul_null(void)
{
  T_FAX *dfax = ra_data->fax;

  TRACE_FUNCTION("fax_ul_null");

  if (ra_data->activated)
  {
    /*
     * setup the communication parameters
     */
    shm_set_dsp_value (conf_b_itc, V_ITC_FAX);

    switch (ra_data->nsb)
    {
    case 1:
      shm_set_dsp_value (conf_b_nsb, V_NSB_ONE_STOP);
      break;
    case 2:
      shm_set_dsp_value (conf_b_nsb, V_NSB_TWO_STOP);
      break;
    default:
      break;
    }

    switch (ra_data->ndb)
    {
    case 7:
      shm_set_dsp_value (conf_b_ndb, V_NDMSK_B_7_DBITS);
      break;
    case 8:
      shm_set_dsp_value (conf_b_ndb, V_NDMSK_B_8_DBITS);
      break;
    default:
      break;
    }

    shm_set_dsp_value (conf_b_ce, V_CE_TRANSP);

    switch (ra_data->tra_rate)
    {
    case TRA_FULLRATE_14400:
      dfax->skip_seq = &skip_F14400[0];
      dfax->req_seq  = &request_F14400[0];
      shm_set_dsp_value (conf_b_ct, V_CT_FR);
      shm_set_dsp_value (conf_b_ur, V_UR_14400);
      ra_data->cycle_time = 20;
      break;

    case TRA_FULLRATE_9600:
      dfax->skip_seq = &skip_F9600[0];
      dfax->req_seq  = &request_F9600[0];
      shm_set_dsp_value (conf_b_ur, V_UR_9600);
      shm_set_dsp_value (conf_b_ct, V_CT_FR);
      ra_data->cycle_time = 20;
      break;

    case TRA_FULLRATE_4800:
      dfax->skip_seq = &skip_F4800[0];
      dfax->req_seq  = &request_F4800[0];
      shm_set_dsp_value (conf_b_ur, V_UR_4800);
      shm_set_dsp_value (conf_b_ct, V_CT_FR);
      ra_data->cycle_time = 20;
      break;

    case TRA_FULLRATE_2400:
      dfax->skip_seq = &skip_F2400[0];
      dfax->req_seq  = &request_F2400[0];
      shm_set_dsp_value (conf_b_ur, V_UR_2400);
      shm_set_dsp_value (conf_b_ct, V_CT_FR);
      ra_data->cycle_time = 20;
      break;

    case TRA_HALFRATE_4800:
      dfax->skip_seq = &skip_H4800[0];
      dfax->req_seq  = &request_H4800[0];
      shm_set_dsp_value (conf_b_ur, V_UR_4800);
      shm_set_dsp_value (conf_b_ct, V_CT_HR);
      ra_data->cycle_time = 40;
      break;

    case TRA_HALFRATE_2400:
      dfax->skip_seq = &skip_H2400[0];
      dfax->req_seq  = &request_H2400[0];
      shm_set_dsp_value (conf_b_ur, V_UR_2400);
      shm_set_dsp_value (conf_b_ct, V_CT_HR);
      ra_data->cycle_time = 40;
      break;

    default:
      TRACE_EVENT ("Unknown transmission rate");

      ra_data->cycle_time = 20;
      break;
    }

    shm_set_dsp_value (fax_b_data_receive, 1);

    /*
     * set uplink buffer to empty values
     */
    shm_set_dsp_value (faxd_byte_cnt, 0);
    shm_set_dsp_value (faxu_byte_cnt, 0);
    shm_set_dsp_value (faxu_control, V_CTRL_SYNC);

    /*
     * start initialisation process in F&D L1
     */

    /*
     * enable status frame detection in L1
     * and set the biterror thresholds for the status frame detection
     */
    shm_set_dsp_value (fax_b_status_stop,    0);
    shm_set_dsp_value (fax_b_status_detect,  1);
    shm_set_dsp_value (fax_b_ident_thres,    3);
    shm_set_dsp_value (fax_b_info_thres,     3);
    shm_set_dsp_value (fax_b_status_receive, 0);
    shm_set_dsp_value (fax_b_byte_interface, 1);
    shm_set_dsp_value (faxu_byte_cnt, 0);

    shm_set_dsp_value (act_b_init,    1);
    shm_set_dsp_value (act_b_syncul,  1);
    shm_set_dsp_value (act_b_syncdl,  1);

    INIT_STATE (KER, FAX_INIT_L1);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    if (dfax->dl_state_last NEQ ra_data->ker.state)
    {
      TRACE_EVENT_P2("KER:FAX_%d -> FAX_%d", dfax->dl_state_last, ra_data->ker.state);
      dfax->dl_state_last = ra_data->ker.state;
    }
#endif

#ifdef HO_WORKAROUND /* fax_ul_null */
    _act_d_ra_conf = *ra_data->shm.shm_addr[d_ra_conf];
    TRACE_EVENT_P1("d_ra_conf saved; rate=%d", ra_data->tra_rate);
#endif
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_ul_init_l1           |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_ul_init_l1(void)
{
  TRACE_FUNCTION("fax_ul_init_l1");

  if (shm_get_dsp_value(act_b_init) EQ 0) /* Indicates initialization of IDS module */
  {
    /*
     * L1 F&D initialized; start ul/dl synchronisation
     */
    SET_STATE (KER, FAX_SYNCH_TCH_START);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    if (ra_data->fax->dl_state_last NEQ ra_data->ker.state)
    {
      TRACE_EVENT_P2("KER:FAX_%d -> FAX_%d", ra_data->fax->dl_state_last, ra_data->ker.state);
      ra_data->fax->dl_state_last = ra_data->ker.state;
    }
#endif
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_dl_sync_tch_start    |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_dl_sync_tch_start(void)
{
  TRACE_FUNCTION("fax_dl_sync_tch_start");

  if (shm_get_dsp_value (statd_b_syncdet) EQ 1)
  {
    /*
     * Detection of sync frames, synchro. on M1 sequence.
     * Start a pseudo timer with 500 ms.
     * The value is decremented by cycle_time
     * each time the L1 calls the dll_data_ul function
     */
    ra_data->sync_timer = 500L;

    SET_STATE (KER, FAX_SYNCH_TCH_FOUND);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    if (ra_data->fax->dl_state_last NEQ ra_data->ker.state)
    {
      TRACE_EVENT_P2("KER:FAX_%d -> FAX_%d", ra_data->fax->dl_state_last, ra_data->ker.state);
      ra_data->fax->dl_state_last = ra_data->ker.state;
    }
#endif

  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_ul_sync_tch_found    |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_ul_sync_tch_found(void)
{
  T_FAX *dfax = ra_data->fax;

  TRACE_FUNCTION("fax_ul_sync_tch_found");

  if (TimeOut(&ra_data->sync_timer) NEQ TRUE)
    return;

  /*
   * timeout of the sync timer - reset the sync-detection flags
   */
  shm_set_dsp_value (act_b_syncul,  0);
  shm_set_dsp_value (act_b_syncdl,  0);

  if (ra_data->tra_rate NEQ TRA_FULLRATE_14400)
  {
    /*
     * setup uplink buffer to send SYNC frames
     */
    shm_set_dsp_value (faxu_byte_cnt, 0);
    shm_set_dsp_value (faxu_control, V_CTRL_SYNC);
    dfax->seq_idx = 0;
    SET_STATE (KER, FAX_WAIT_SYNC_LOST);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    if (dfax->dl_state_last NEQ ra_data->ker.state)
    {
      TRACE_EVENT_P2("KER:FAX_%d -> FAX_%d", dfax->dl_state_last, ra_data->ker.state);
      dfax->dl_state_last = ra_data->ker.state;
    }
#endif

  }
  else /* ra_data->tra_rate EQ TRA_FULLRATE_14400 */
  {
    /*
     * sync detection finished -> enter the data transmission (pre-) state
     */
    if (dfax->CMM_flag)
    {
      l1i_ra_modify_cnf();
      SET_STATE (KER, FAX_DATA_TRANS);
    }
    else
    {
      l1i_ra_activate_cnf();
      SET_STATE (KER, FAX_DATA_TRANS_PRE);
    }

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    if (dfax->dl_state_last NEQ ra_data->ker.state)
    {
      TRACE_EVENT_P2("KER:FAX_%d -> FAX_%d", dfax->dl_state_last, ra_data->ker.state);
      dfax->dl_state_last = ra_data->ker.state;
    }
#endif

#ifdef HO_WORKAROUND /* fax_ul_sync_tch_found */
    if (*ra_data->shm.shm_addr[d_ra_conf] NEQ _act_d_ra_conf)
    {
      *ra_data->shm.shm_addr[d_ra_conf] = _act_d_ra_conf;
      TRACE_EVENT("HO_REFRESH fax_ul_sync_tch_found");
    }
#endif

  }
}

LOCAL void IncIndex(UBYTE *idx, UBYTE idxMax)
{
  if (++(*idx) EQ idxMax)
    *idx = 0;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_dl_wait_sync_lost    |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_dl_wait_sync_lost(void)
{
  T_FAX *dfax = ra_data->fax;

  TRACE_FUNCTION("fax_dl_wait_sync_lost");

  IncIndex(&dfax->seq_idx, 8);

  if (shm_get_dsp_value (statd_b_syncdet) EQ 0)
  {
    /*
     * sync detection finished -> enter the data transmission (pre-) state
     */
    if (dfax->CMM_flag)
    {
      l1i_ra_modify_cnf();
      SET_STATE (KER, FAX_DATA_TRANS);
    }
    else
    {
      l1i_ra_activate_cnf();
      SET_STATE (KER, FAX_DATA_TRANS_PRE);
    }

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    if (dfax->dl_state_last NEQ ra_data->ker.state)
    {
      TRACE_EVENT_P2("KER:FAX_%d -> FAX_%d", dfax->dl_state_last, ra_data->ker.state);
      dfax->dl_state_last = ra_data->ker.state;
    }
#endif

#ifdef HO_WORKAROUND /* fax_dl_wait_sync_lost */
    if (*ra_data->shm.shm_addr[d_ra_conf] NEQ _act_d_ra_conf)
    {
      *ra_data->shm.shm_addr[d_ra_conf] = _act_d_ra_conf;
      TRACE_EVENT("HO_REFRESH fax_dl_wait_sync_lost");
    }
#endif

  }
}

#ifndef _SIMULATION_
LOCAL void check_skip(USHORT fed_ul, BOOL *skip)
{
  if (*skip AND !fed_ul)
  {
    *skip = FALSE;
#ifdef TRACE_RA_FAX_UL_SKIP
    TRACE_EVENT_P1("fed_ul=%d -> skip -> FALSE", fed_ul);
#endif
  }
  else if (!*skip AND fed_ul)
  {
    *skip = TRUE;
#ifdef TRACE_RA_FAX_UL_SKIP
    TRACE_EVENT_P1("fed_ul=%d-> skip -> TRUE", fed_ul);
#endif
  }
}
#endif

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_ul_data_trans        |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_ul_data_trans(void)
{
  T_FAX *dfax = ra_data->fax;
  USHORT bytes_used_after = 0;
  BOOL skip;

  USHORT fed_ul = shm_get_dsp_value(statu_b_fed_ul);

  TRACE_FUNCTION ("fax_ul_data_trans");

#if defined TRACE_RA_FAX_UL_FRAME_TYPE || defined _SIMULATION_
  if (dfax->ul_ribu->idx.filled > 1)
    TRACE_EVENT_P1("dfax->ul_ribu->idx.filled=%d", dfax->ul_ribu->idx.filled);
#endif

  if (dfax->ul_ribu->idx.filled)
  {
    dfax->ul_pFD = cl_ribu_get(dfax->ul_ribu);
    dfax->ul_frame_type = dfax->ul_pFD->type;
  }

#if defined TRACE_RA_FAX_UL_FRAME_TYPE || defined _SIMULATION_
  else
  {
    TRACE_EVENT_P1("dfax->ul_ribu->idx.filled=%d", dfax->ul_ribu->idx.filled);
  }
#endif

  /*
   * Check if we must skip this cycle.
   * For status frames this is done every third status frame,
   * because L1 sends more data (1,2,4,6) * 64 bit status frames.
   * for T4DATA frames this also happens in 2400 bps mode
   */
  /*
   * check if the frame type has changed
   */
  if (dfax->ul_frame_type_last NEQ dfax->ul_frame_type)
  {
    skip = (dfax->skip_seq[dfax->ul_frame_type_last].skip_seq_other[dfax->seq_idx] NEQ 0);

#ifndef _SIMULATION_
    check_skip(fed_ul, &skip);
#endif

    if ((dfax->ul_frame_type_last EQ FR_TRAIN) AND (dfax->train_len > 0))
    {
      /* Training is stopped only after a minimum length */
      dfax->train_len--;
      skip = TRUE;
    }

    if (!skip)
    {
      /*
       * we are on a 64 bit boundary so we can write into the new frame. Reset all sequencers.
       */
      dfax->ul_frame_type_last = dfax->ul_frame_type;
      dfax->seq_idx = 1;

      /*
       * start the request sequencer for T4DATA
       */
      if (dfax->ul_frame_type EQ FR_T4DATA)
      {
        dfax->req_idx = 1;
      }
      else
      {
        dfax->req_idx = 0;

        /*
         * Store training sequence. It will be used later, when changing
         * to T4 data, in order to avoid insertion of sync frames.
         */
        if (dfax->ul_frame_type EQ FR_TRAIN)
        {
          dfax->train_seq[0] = dfax->ul_pFD->buf[0];
          dfax->train_seq[1] = dfax->ul_pFD->buf[1];
          dfax->train_len = MIN_FR_TRAIN_LEN - 1; /* Minimum length of training */
        }
      }
    }
    else /* skip */
    {
      IncIndex(&dfax->seq_idx, 8);

      if (dfax->ul_frame_type_last EQ FR_T4DATA)
      {
        IncIndex(&dfax->req_idx, 4);
      }
    }
  }
  else /* frame type not changed */
  {
    skip = (dfax->skip_seq[dfax->ul_frame_type_last].skip_seq_same[dfax->seq_idx] NEQ 0);

#ifndef _SIMULATION_
    check_skip(fed_ul, &skip);
#endif

    IncIndex(&dfax->seq_idx, 8);

    if (dfax->ul_frame_type EQ FR_T4DATA)
    {
      IncIndex(&dfax->req_idx, 4);
    }
    else if ((dfax->ul_frame_type_last EQ FR_TRAIN) AND (dfax->train_len > 0))
    {
      /* Training is stopped only after a minimum length */
      dfax->train_len--;
    }
  }

  if (!skip)
  {
    switch (dfax->ul_frame_type)
    {
      case FR_T4DATA:
        shm_set_dsp_value (faxu_control, V_CTRL_DATA);
        break;

      case FR_STATUS:
        shm_set_dsp_value (faxu_control, V_CTRL_STATUS);
        break;

      case FR_TRAIN:
        shm_set_dsp_value (faxu_control, V_CTRL_TRAIN);
        break;

      case FR_SYNC:
        shm_set_dsp_value (faxu_control, V_CTRL_SYNC);
        shm_set_dsp_value (faxu_byte_cnt, 0);
        break;
    }
    if (dfax->ul_frame_type NEQ FR_SYNC)
    {
      bytes_used_after = shm_set_dsp_buffer_new(dfax->ul_pFD, ra_data->shm.shm_addr[adr_faxu_data]+wof_faxu_data, 0, (USHORT)MAX_FAX_BUFFER_UL);
      shm_set_dsp_value (faxu_byte_cnt, bytes_used_after);
    }

#if defined TRACE_RA_FAX_UL_FRAME_TYPE || defined _SIMULATION_
    if (dfax->ul_pFD)
      trace_ra_fax_ul_frame_type(dfax->ul_frame_type, dfax->ul_pFD->buf, bytes_used_after);
#endif

    ra_data->ra_ready_ind[0].req_frames = dfax->req_seq[dfax->req_idx];
    l1i_ra_ready_ind(hCommFAD, 0);
  }
  else if (dfax->ul_frame_type_last EQ FR_TRAIN) /* skip AND train*/
  {
    shm_set_dsp_value (faxu_control, V_CTRL_TRAIN);
    bytes_used_after = shm_set_dsp_buffer_new(&dfax->ul_train_FD, ra_data->shm.shm_addr[adr_faxu_data]+wof_faxu_data, 0, (USHORT)MAX_FAX_BUFFER_UL);
    shm_set_dsp_value (faxu_byte_cnt, bytes_used_after);

#if defined TRACE_RA_FAX_UL_FRAME_TYPE || defined _SIMULATION_
    trace_ra_fax_ul_frame_type(V_CTRL_TRAIN, dfax->ul_train_FD.buf, bytes_used_after);
#endif

  }
  else /* skip */
  {
    shm_set_dsp_value (faxu_byte_cnt, 0);

#if defined TRACE_RA_FAX_UL_FRAME_TYPE || defined _SIMULATION_
    trace_ra_fax_ul_frame_type(4, NULL, 0);
#endif

  }
}

LOCAL U8 get_frame_descriptor(U8 bytes_to_read)
{
  T_FAX *dfax = ra_data->fax;

  U8 bytes_read;

#ifdef _SIMULATION_
  dfax->dl_pFD = cl_ribu_get_new_frame_desc(ra_data->dl_ribu);
#else
  dfax->dl_pFD = fad_rbm_get_next_FrameDesc();
#endif

  dfax->dl_pFD->len = FAD_DESCBUF_LEN;
  bytes_read = shm_get_dsp_buffer_new(ra_data->shm.shm_addr[adr_faxd_data]+wof_faxd_data, bytes_to_read, dfax->dl_pFD);

  return bytes_read;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)        MODULE  : RA_FAX                   |
| STATE   : code                  ROUTINE : fax_dl_data_trans        |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL void fax_dl_data_trans(void)
{
  UBYTE bytes_to_read, bytes_read = 0;
  UBYTE dl_frame_type;

  T_FAX *dfax = ra_data->fax;

  TRACE_FUNCTION ("fax_dl_data_trans");

#ifdef HO_WORKAROUND /* fax_dl_data_trans */
  if (*ra_data->shm.shm_addr[d_ra_conf] NEQ _act_d_ra_conf)
  {
    *ra_data->shm.shm_addr[d_ra_conf] = _act_d_ra_conf;
    TRACE_EVENT("HO_REFRESH fax_dl_data_trans");
  }
#endif

  dl_frame_type = shm_get_dsp_value (faxd_control);

  if (dl_frame_type EQ V_CTRL_SYNC)
  {
    bytes_read = get_frame_descriptor(0);
    dfax->dl_pFD->len = bytes_read;
    dfax->dl_pFD->type = dl_frame_type;
    l1i_ra_data_ind(hCommFAD);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
    trace_ra_fax_dl_frame_type(&dfax->dl_frame_type_last, dl_frame_type, bytes_read);
#endif

  }
  else
  {
    bytes_to_read = shm_get_dsp_value (faxd_byte_cnt);

    if (bytes_to_read > 0)
    {
      bytes_read = get_frame_descriptor(bytes_to_read);
      shm_set_dsp_value (faxd_byte_cnt, 0);
    }

    if (bytes_read)
    {
      dfax->dl_pFD->len = bytes_read;
      dfax->dl_pFD->type = dl_frame_type;
      l1i_ra_data_ind(hCommFAD);

#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
      trace_ra_fax_dl_frame_type(&dfax->dl_frame_type_last, dl_frame_type, bytes_read);
#endif

    }
  }
#if defined TRACE_RA_FAX_DL_FRAME_TYPE || defined _SIMULATION_
  dfax->dl_frame_type_last = dl_frame_type;
#endif
}