view src/cs/layer1/cfile/l1_drive.c @ 701:35e7f9d0379f

targets: add TARGET_HAS_BUZZER to c11x, c139 and dsample This new target config preprocessor symbol was introduced in Tourmaline in connection with the new approach to playing buzzer melodies via PWT, properly omitting the responsible code on targets where BU output controls the vibrator instead. That code is not present in Magnetite and we have no plans to backport it here, but target header files should be kept consistent between the two trees, especially given that we plan to support FC Venus target in Magnetite.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 26 Mar 2022 19:51:34 +0000
parents 50a15a54801e
children
line wrap: on
line source

/************* Revision Controle System Header *************
 *                  GSM Layer 1 software
 * L1_DRIVE.C
 *
 *        Filename l1_drive.c
 *  Copyright 2003 (C) Texas Instruments
 *
 ************* Revision Controle System Header *************/

#define  L1_DRIVE_C

#include "l1_confg.h"

#if (RF_FAM == 61)
#include "apc.h"
#endif

#define	W_A_DSP_PR20037	1	/* FreeCalypso */

#if ((L1M_WAIT_DSP_RESTART_AFTER_VOCODER_ENABLE ==1)&&(W_A_DSP_PR20037 == 1))
  #include "nucleus.h"
#endif
#include "l1_macro.h"
#if (CODE_VERSION == SIMULATION)
  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.h"
  #include "l1_time.h"
  #if TESTMODE
    #include "l1tm_defty.h"
  #endif
  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_defty.h"
  #endif
  #if (L1_GTT == 1)
    #include "l1gtt_const.h"
    #include "l1gtt_defty.h"
  #endif
  #if (L1_MP3 == 1)
    #include "l1mp3_defty.h"
  #endif
  #if (L1_MIDI == 1)
    #include "l1midi_defty.h"
  #endif
//ADDED FOR AAC
  #if (L1_AAC == 1)
    #include "l1aac_defty.h"
  #endif
  #include "l1_defty.h"
  #include "l1_varex.h"
  #include "cust_os.h"
  #include "l1_msgty.h"
  #if TESTMODE
    #include "l1tm_varex.h"
  #endif
  #if L2_L3_SIMUL
    #include "hw_debug.h"
  #endif

  #if L1_GPRS
    #include "l1p_cons.h"
    #include "l1p_msgt.h"
    #include "l1p_deft.h"
    #include "l1p_vare.h"
    #include "l1p_sign.h"
  #endif

  #include <stdio.h>
  #include "sim_cfg.h"
  #include "sim_cons.h"
  #include "sim_def.h"
  #include "sim_var.h"

  #include "l1_ctl.h"

#else

  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.h"
  #include "l1_time.h"
  #if TESTMODE
    #include "l1tm_defty.h"
  #endif
  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_defty.h"
  #endif
  #if (L1_GTT == 1)
    #include "l1gtt_const.h"
    #include "l1gtt_defty.h"
  #endif
  #if (L1_MP3 == 1)
    #include "l1mp3_defty.h"
  #endif
  #if (L1_MIDI == 1)
    #include "l1midi_defty.h"
  #endif
//ADDED FOR AAC
  #if (L1_AAC == 1)
    #include "l1aac_defty.h"
  #endif
  #include "l1_defty.h"
  #include "l1_varex.h"
  #include "cust_os.h"
  #include "l1_msgty.h"
  #if TESTMODE
    #include "l1tm_varex.h"
  #endif
  #if L2_L3_SIMUL
    #include "hw_debug.h"
  #endif
  #include "tpudrv.h"

  #if L1_GPRS
    #include "l1p_cons.h"
    #include "l1p_msgt.h"
    #include "l1p_deft.h"
    #include "l1p_vare.h"
    #include "l1p_sign.h"
  #endif

  #include "l1_ctl.h"

#endif

#if (RF_FAM == 61)
  #include "tpudrv61.h"
#endif



/*
 * Prototypes of external functions used in this file.
 *
 * FreeCalypso change: removed all those prototypes which appear
 * in tpudrv.h, and kept only the additional ones.
 */

#if ((REL99 == 1) && (FF_BHO == 1))
#if (L1_MADC_ON == 1)
  void  l1dmacro_rx_fbsb (SYS_UWORD16 radio_freq,UWORD8 adc_active);
#else
  void  l1dmacro_rx_fbsb (SYS_UWORD16 radio_freq);
#endif
#endif//#if ((REL99 == 1) && (FF_BHO == 1))

void Cust_get_ramp_tab(API *a_ramp, UWORD8 txpwr_ramp_up, UWORD8 txpwr_ramp_down, UWORD16 radio_freq);
#if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3) || (RF_FAM == 61))
  UWORD16 Cust_get_pwr_data(UWORD8 txpwr, UWORD16 radio_freq
  										  #if(REL99 && FF_PRF)
  										  ,UWORD8 number_uplink_timeslot
  										  #endif
  										  );
#endif

#if L1_GPRS
  void l1ps_reset_db_mcu_to_dsp(T_DB_MCU_TO_DSP_GPRS *page_ptr);
#endif

/*-------------------------------------------------------*/
/* l1ddsp_load_info()                                    */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_info(UWORD32 task, API *info_ptr, UWORD8 *data)
{
  if(task == RACH_DSP_TASK)
  // RACH info. format is only 2 words...
  {
    info_ptr[0] = ((API)(data[0])) | ((API)(data[1])<<8);
  }
  else
  // Fill mcu-dsp comm. buffer.
  {
    UWORD8 i,j;

    // Fill data block Header...
    info_ptr[0] = (1 << B_BLUD);     // 1st word: Set B_BLU bit.
    info_ptr[1] = 0;                 // 2nd word: cleared.
    info_ptr[2] = 0;                 // 3rd word: cleared.

    if((info_ptr == l1s_dsp_com.dsp_ndb_ptr->a_du_0) ||
       (info_ptr == l1s_dsp_com.dsp_ndb_ptr->a_du_1))
    // DATA traffic buffers: size of buffer is 260 bit -> 17 words but DATA traffic uses
    // only a max of 240 bit (30 bytes) -> 15 words.
    {
      for (i=0, j=(3+0); j<(3+15); j++)
      {
        info_ptr[j] = ((API)(data[i])) | ((API)(data[i+1]) << 8);
        i += 2;
      }
      #if (TRACE_TYPE==3)
        if (l1_stats.type == PLAY_UL)
        {
          for (i=0, j=(3+0); j<(3+17); j++)
          {
            info_ptr[j] = ((API)(data[i])) |
                          ((API)(data[i]) << 8);
            i ++;
          }
        }
     #endif
    }
    else
    // Data block for control purpose is 184 bit length: 23 bytes: 12 words (16 bit/word).
    {
      // Copy first 22 bytes in the first 11 words after header.
      for (i=0, j=(3+0); j<(3+11); j++)
      {
        info_ptr[j] = ((API)(data[i])) | ((API)(data[i+1]) << 8);
        i += 2;
      }

      // Copy last UWORD8 (23rd) in the 12th word after header.
      info_ptr[14] = data[22];
    }
  }
}

/*-------------------------------------------------------*/
/* l1ddsp_load_monit_task()                              */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_monit_task(API monit_task, API fb_mode)
{
  l1s_dsp_com.dsp_db_w_ptr->d_task_md   = monit_task;  // Write number of measurements

  if(l1a_l1s_com.mode == CS_MODE)
    l1s_dsp_com.dsp_ndb_ptr->d_fb_mode  = fb_mode;     // Write FB detection algo. mode.
  else
    l1s_dsp_com.dsp_ndb_ptr->d_fb_mode  = 1;
}


/* --------------------------------------------------- */

/* Locosto Changes....*/

// Parameters: UWORD16 afcval
// Return       :Void
//Functionality: TPU to accept the afcvalue from the MCU and copy it
//to the mem_xtal before triggering of AFC Script in DRP

#if(RF_FAM == 61)
void l1dtpu_load_afc(UWORD16 afc)
{
   l1dmacro_afc(afc, 0);
}

/* --------------------------------------------------- */

/* Locosto Changes....*/

/* Parameters: API dco_algo_ctl_sb */
/* Functionality: Loads the API  d_dco_ctl_algo_sb in the API
     This should be called after updating the value in the API via cust_Get_dco_algo_ctl(...) */

/* --------------------------------------------------- */

void l1ddsp_load_dco_ctl_algo_sb (UWORD16 dco_ctl_algo)
{
#if (DSP == 38) || (DSP == 39)
  l1s_dsp_com.dsp_db_common_w_ptr->d_dco_algo_ctrl_sb = (API) dco_ctl_algo;
#endif
}

/* --------------------------------------------------- */

/* Locosto Changes....*/

/* Parameters: API dco_algo_ctl_nb */
/* Functionality: Loads the API  d_dco_ctl_algo_nb in the API
     This should be called after updating the value in the API via cust_Get_dco_algo_ctl(...) */

/* --------------------------------------------------- */

void l1ddsp_load_dco_ctl_algo_nb (UWORD16 dco_ctl_algo)
{
#if (DSP == 38) || (DSP == 39)
  l1s_dsp_com.dsp_db_common_w_ptr->d_dco_algo_ctrl_nb = (API) dco_ctl_algo;
#endif

}
/* --------------------------------------------------- */

/* Locosto Changes....*/

/* Parameters: API dco_algo_ctl_pw  */
/* Functionality: Loads the API  d_dco_ctl_algo_pw in the API
     This should be called after updating the value in the API via cust_Get_dco_algo_ctl(...) */

/* --------------------------------------------------- */

void l1ddsp_load_dco_ctl_algo_pw (UWORD16 dco_ctl_algo)
{
#if (DSP == 38) || (DSP == 39)
  l1s_dsp_com.dsp_db_common_w_ptr->d_dco_algo_ctrl_pw = (API) dco_ctl_algo;
#endif
}

#endif

/*-------------------------------------------------------*/
/* l1ddsp_load_afc()                                     */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_afc(API afc)
{
#if (L1_EOTD==1)
  // NEW !!! For EOTD measurements in IDLE mode only, cut AFC updates....
  #if (L1_GPRS)
   if ( (l1a_l1s_com.nsync.eotd_meas_session == FALSE) ||
        (l1a_l1s_com.mode == DEDIC_MODE)||
        (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED))
  #else
   if ( (l1a_l1s_com.nsync.eotd_meas_session == FALSE) ||
        (l1a_l1s_com.mode == DEDIC_MODE))
  #endif

  {
#endif
    //######################## For DSP Rom #################################
    l1s_dsp_com.dsp_db_w_ptr->d_afc = afc;                      // Write new afc command.
    #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3) || (RF_FAM == 61))
    // NOTE: In Locosto AFC loading is w.r.t DRP not in ABB
      l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= (1 << B_AFC);     // Validate new afc value.
    #endif
 #if (L1_EOTD==1)
 }
#endif

}

/*-------------------------------------------------------*/
/* l1ddsp_load_txpwr()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*Notes:

While Programming APC Ramp always Program the APCDEL also
Cal+:
APCDEL1: LSB Dwn(9:5):Up(4:0)
APCDEL2: MSB Dwn(9:5):Up(4:0)

Locosto:
APCDEL1: LSB Dwn(9:5):Up(4:0)
APCDEL2: MSB Dwn(9:5):Up(4:0)
-----
Cal+
APCRAM : Dwn(51:11)Up(10:6)Forced(0)
Locosto:
APCRAM: Dwn(9:5)Up(4:0)

For AFC, APCDEL1, APCDEL2, APCRAMP the Control word d_ctl_abb is checked
i f they are reqd to be updated.

For AUXAPC (Cal+), the last bit = 1 would mean the DSP would pick it at Tx
For APCLEV (Loc), it is picked at every Tx, for dummy burst DSP would make it 0
*/

/*-------------------------------------------------------*/
void l1ddsp_load_txpwr(UWORD8 txpwr, UWORD16 radio_freq)
{
  #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3) || (RF_FAM == 61))
    UWORD16 pwr_data;
  #endif

  //config
  if (l1_config.tx_pwr_code ==0)
  {
    // Fixed TXPWR.
    l1s_dsp_com.dsp_db_w_ptr->d_power_ctl = l1_config.params.fixed_txpwr;     // GSM management disabled: Fixed TXPWR used.


    #if(RF_FAM == 61)
    //Locosto has new API for Ramp
       #if (DSP == 38) || (DSP == 39)
         Cust_get_ramp_tab(l1s_dsp_com.dsp_ndb_ptr->a_drp_ramp, txpwr, txpwr, radio_freq);
       #endif
    #else
       #if (CODE_VERSION != SIMULATION)
    /*** Reference to real ramp array (GSM: 15 power levels, 5-19, DCS: 16 power levels, 0-15) ***/
       Cust_get_ramp_tab(l1s_dsp_com.dsp_ndb_ptr->a_ramp, txpwr, txpwr, radio_freq);
       #endif
    #endif

    #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3))
      l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (1 << B_BULRAMPDEL) | (1 << B_BULRAMPDEL2));
    #endif

   #if(RF_FAM == 61)
      l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (1 << B_BULRAMPDEL) | (1 << B_BULRAMPDEL2));
   #endif

  }
  else
  {
    static UWORD8 last_used_freq_band = 0;
    UWORD8 freq_band;

#if (L1_FF_MULTIBAND == 0)
    // Check whether band has changed
    // This will be used to reload ramps
    if ((l1_config.std.id == DUAL)     ||
        (l1_config.std.id == DUALEXT) ||
        (l1_config.std.id == DUAL_US))
    {
      if (radio_freq < l1_config.std.first_radio_freq_band2)
        freq_band = BAND1;
      else
        freq_band = BAND2;
    }
    else
      freq_band = BAND1;
#else

freq_band = l1_multiband_radio_freq_convert_into_effective_band_id(radio_freq);

#endif 

    // Note: txpwr = NO_TXPWR is reserved for forcing the transmitter off
    // -----           (to suppress SACCH during handover, for example)

    /*** Check to see if the TXPWR is to be suppressed (txpwr = NO_TXPWR)   ***/

    if(txpwr == NO_TXPWR)
    {
       /*** No transmit ***/
       #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3))
         l1s_dsp_com.dsp_db_w_ptr->d_power_ctl = 0x12; // AUXAPC initialization addr 9 pg 0 Omega
         l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (1 << B_BULRAMPDEL)  | (1 << B_BULRAMPDEL2));
       #endif

       #if(RF_FAM == 61 ) //Locosto without Syren Format
           l1s_dsp_com.dsp_db_w_ptr->d_power_ctl = (API) 0; // APCLEV
           l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (1 << B_BULRAMPDEL)  | (1 << B_BULRAMPDEL2));
       #endif

       l1s.last_used_txpwr = NO_TXPWR;
       return;
    }
    else
    {
      /*** Get power data according to clipped TXPWR ***/
      pwr_data = Cust_get_pwr_data(txpwr, radio_freq
      									  #if(REL99 && FF_PRF)
      									  ,1
      									  #endif
      									  );

      /*** Load power control level adding the APC address register ***/
      #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3))
        l1s_dsp_com.dsp_db_w_ptr->d_power_ctl = ((pwr_data << 6) | 0x12);
        // AUXAPC initialization addr 9 pg 0 Omega
      #endif

      #if(RF_FAM == 61)
        l1s_dsp_com.dsp_db_w_ptr->d_power_ctl = (API)(pwr_data);
      #endif
    }

      #if TESTMODE
       #if(RF_FAM == 61)
         // Currently for RF_FAM=61 Enabling APC-Ramp, APCDEL1 and APCDEL2 writing always i.e. in every TDMA frame
	 // TODO: Check whether this is okay
         if ((l1_config.TestMode) && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK))
       #else
         if ((l1_config.TestMode) && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK) &&
            ((l1s.last_used_txpwr != txpwr) || (l1_config.tmode.rf_params.reload_ramps_flag)))
       #endif
        {
          #if(RF_FAM == 61)
            #if (DSP == 38) || (DSP == 39)
              Cust_get_ramp_tab(l1s_dsp_com.dsp_ndb_ptr->a_drp_ramp, txpwr, txpwr, radio_freq);
            #endif
          #else
		    #if (CODE_VERSION != SIMULATION)
	    Cust_get_ramp_tab(l1s_dsp_com.dsp_ndb_ptr->a_ramp, txpwr, txpwr, radio_freq);
		    #endif
          #endif

          #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3))
	    // Setting bit 3 of this register causes DSP to write to APCDEL1 register in Omega. However,
            // we are controlling this register from MCU through the SPI. Therefore, set it to 0.
            l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (0 << B_BULRAMPDEL)  | (1 << B_BULRAMPDEL2));
          #endif

          #if (RF_FAM == 61)
            l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (1 << B_BULRAMPDEL)  | (1 << B_BULRAMPDEL2));
          #endif

          l1s.last_used_txpwr = txpwr;
          l1_config.tmode.rf_params.reload_ramps_flag = 0;
        }
       else
      #endif

      if ((l1s.last_used_txpwr != txpwr) || (last_used_freq_band != freq_band))
      {
        /*** Power level or band has changed, so update the ramp, and trigger the data send to ABB ***/

        l1s.last_used_txpwr = txpwr;
        last_used_freq_band = freq_band;

        /*** Reference to real ramp array (GSM: 15 power levels, 5-19, DCS: 16 power levels, 0-15) ***/
      #if(RF_FAM == 61)
       #if (DSP == 38) || (DSP == 39)
          Cust_get_ramp_tab(l1s_dsp_com.dsp_ndb_ptr->a_drp_ramp, txpwr, txpwr, radio_freq);
       #endif
      #else
       #if (CODE_VERSION != SIMULATION)
          Cust_get_ramp_tab(l1s_dsp_com.dsp_ndb_ptr->a_ramp, txpwr, txpwr, radio_freq);
       #endif
      #endif

      #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3) ||(RF_FAM == 61))
        l1s_dsp_com.dsp_db_w_ptr->d_ctrl_abb |= ( (1 << B_RAMP) | (1 << B_BULRAMPDEL)  | (1 << B_BULRAMPDEL2));
      #endif
    }
  }
}

#if (FF_L1_FAST_DECODING == 1)
/*-------------------------------------------------------*/
/* l1ddsp_load_fp_task()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_fast_dec_task(API task, UWORD8 burst_id)
{
  if (l1s_check_fast_decoding_authorized(task))
  {
    //l1s_dsp_com.dsp_db_w_ptr->d_fast_paging_ctrl = 0x0001
    l1s_dsp_com.dsp_db_common_w_ptr->d_fast_paging_ctrl =  0x00001;
    if(burst_id == BURST_1)
    {
      l1s_dsp_com.dsp_db_common_w_ptr->d_fast_paging_ctrl |=  0x8000;
    }
  }
}
#endif /* FF_L1_FAST_DECODING */

/*-------------------------------------------------------*/
/* l1ddsp_load_rx_task()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_rx_task(API rx_task, UWORD8 burst_id, UWORD8 tsq)
{
  l1s_dsp_com.dsp_db_w_ptr->d_task_d       = rx_task;      // Write RX task Identifier.
  l1s_dsp_com.dsp_db_w_ptr->d_burst_d      = burst_id;     // Write RX burst Identifier.
  l1s_dsp_com.dsp_db_w_ptr->d_ctrl_system |= tsq << B_TSQ; // Write end of task DSP state.
}

/*-------------------------------------------------------*/
/* l1ddsp_load_tx_task()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_tx_task(API tx_task, UWORD8 burst_id, UWORD8 tsq)
{
  l1s_dsp_com.dsp_db_w_ptr->d_task_u       = tx_task;      // write TX task Identifier.
  l1s_dsp_com.dsp_db_w_ptr->d_burst_u      = burst_id;     // write TX burst Identifier.
  l1s_dsp_com.dsp_db_w_ptr->d_ctrl_system |= tsq << B_TSQ; // Write end of task DSP state.
}

/*-------------------------------------------------------*/
/* l1ddsp_load_ra_task()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_ra_task(API ra_task)
{
  l1s_dsp_com.dsp_db_w_ptr->d_task_ra   = ra_task;   // write RA task Identifier.
}

/*-------------------------------------------------------*/
/* l1ddsp_load_tch_mode()                                */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_tch_mode(UWORD8 dai_mode, BOOL dtx_allowed)
{
  // TCH mode register.
  //        bit[0]      -> b_eotd.
  //        bit[1]      -> b_audio_async only for WCP
  //        bit [2]     -> b_dtx.
  //        bit[3]      -> play_ul when set to 1
  //        bit[4]      -> play_dl when set to 1
  //        bit[5]      -> DTX selection for voice memo
  //        bit[6]      -> Reserved for ciphering debug
  //        bit[7..10]  -> Reserved for ramp up control
  //        bit[11]     -> Reserved for analog device selection

  #if (DSP == 32)
    UWORD16 mask = 0xfffb;
  #else // NO OP_WCP
    UWORD16 mask = 0xfff8;
  #endif

  l1s_dsp_com.dsp_ndb_ptr->d_tch_mode = (l1s_dsp_com.dsp_ndb_ptr->d_tch_mode & mask)
                                        | (dtx_allowed<<2);
#if (L1_EOTD == 1)
  l1s_dsp_com.dsp_ndb_ptr->d_tch_mode |= B_EOTD;
#endif
}

#if (AMR == 1)
  /*-------------------------------------------------------*/
  /* l1ddsp_load_tch_param()                               */
  /*-------------------------------------------------------*/
  /* Parameters :                                          */
  /* Return     :                                          */
  /* Functionality :                                       */
  /*-------------------------------------------------------*/
#if (FF_L1_TCH_VOCODER_CONTROL == 1)
  void l1ddsp_load_tch_param(T_TIME_INFO *next_time, UWORD8 chan_mode,
                             UWORD8       chan_type, UWORD8 subchannel,
                             UWORD8       tch_loop,  UWORD8 sync_tch,
                             UWORD8       sync_amr,
                             UWORD8       reset_sacch,
                           #if !FF_L1_IT_DSP_DTX
                             UWORD8       vocoder_on)
			   #else
                             UWORD8       vocoder_on,
                             BOOL         dtx_dsp_interrupt)
                           #endif
#else
  void l1ddsp_load_tch_param(T_TIME_INFO *next_time, UWORD8 chan_mode,
                             UWORD8       chan_type, UWORD8 subchannel,
                             UWORD8       tch_loop,  UWORD8 sync_tch,
                           #if !FF_L1_IT_DSP_DTX
                             UWORD8       sync_amr)
                           #else
                             UWORD8       sync_amr,  BOOL   dtx_dsp_interrupt)
                           #endif
#endif
  {
    UWORD32  count_0;
    UWORD32  count_1;
    UWORD32  d_ctrl_tch;
    UWORD32  d_fn;

    // d_ctrl_tch
    // ----------
    //   bit [0..3]   -> b_chan_mode
    //   bit [4..7]   -> b_chan_type
    //   bit [8]      -> b_sync_tch_ul
    //   bit [9]      -> b_sync_amr
    //   bit [10]     -> b_stop_tch_ul
    //   bit [11]     -> b_stop_tch_dl
    //   bit [12..14] -> b_tch_loop
    //   bit [15]     -> b_subchannel
  #if (FF_L1_TCH_VOCODER_CONTROL == 1)
    d_ctrl_tch = (chan_mode<<B_CHAN_MODE)  | (chan_type<<B_CHAN_TYPE)  | (subchannel<<B_SUBCHANNEL) |
                 (sync_tch<<B_SYNC_TCH_UL) | (sync_amr<<B_SYNC_AMR)    |
                 (tch_loop<<B_TCH_LOOP) | (reset_sacch<<B_RESET_SACCH) | (vocoder_on<<B_VOCODER_ON);
  #else
    d_ctrl_tch = (chan_mode<<B_CHAN_MODE)  | (chan_type<<B_CHAN_TYPE)  | (subchannel<<B_SUBCHANNEL) |
                 (sync_tch<<B_SYNC_TCH_UL) | (sync_amr<<B_SYNC_AMR)    |
                 (tch_loop<<B_TCH_LOOP);
  #endif

    // d_fn
    // ----
    //   bit [0..7]  -> b_fn_report
    //   bit [8..15] -> b_fn_sid
    d_fn = (next_time->fn_in_report) | ((next_time->fn%104)<<8);

    // a_a5fn
    // ------
    //   count_0 (a_a5fn[0]), bit [0..4]  -> T2.
    //   count_0 (a_a5fn[1]), bit [5..10] -> T3.
    //   count_1 (a_a5fn[0]), bit [0..10] -> T1.
    count_0 = ((UWORD16)next_time->t3 << 5) | (next_time->t2);
    count_1 = (next_time->t1);

    l1s_dsp_com.dsp_db_w_ptr->d_fn         = d_fn;         // write both Fn_sid, Fn_report.
    l1s_dsp_com.dsp_db_w_ptr->a_a5fn[0]    = count_0;      // cyphering FN part 1.
    l1s_dsp_com.dsp_db_w_ptr->a_a5fn[1]    = count_1;      // cyphering FN part 2.
    l1s_dsp_com.dsp_db_w_ptr->d_ctrl_tch   = d_ctrl_tch;   // Channel config.
  #if FF_L1_IT_DSP_DTX
    // ### TBD: report this block below in the other instance of this function
    // DTX interrupt request is latched by DSP in TDMA3 (TCH-AFS, TCH-AHS0) or TDMA0 (TCH-AHS1)
    if ((chan_mode == TCH_AFS_MODE) || (chan_mode == TCH_AHS_MODE))
    {
      if (((next_time->fn_mod13_mod4 == 3) &&
           ((chan_mode == TCH_AFS_MODE) || ((subchannel == 0)))) ||
          ((next_time->fn_mod13_mod4 == 0) &&
           ((chan_mode == TCH_AHS_MODE) && (subchannel == 1)))
         )
      {
        if (dtx_dsp_interrupt)
          l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enable=1;
        else
          l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enable=0;

      }
    }
    // Fast DTX not supported
    else
    {
      // No interrupt genaration
      l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enable=0;
    }
  #endif
  }
#else
  /*-------------------------------------------------------*/
  /* l1ddsp_load_tch_param()                               */
  /*-------------------------------------------------------*/
  /* Parameters :                                          */
  /*  Return     :                                         */
  /* Functionality :                                       */
  /*-------------------------------------------------------*/
#if (FF_L1_TCH_VOCODER_CONTROL == 1)
  void l1ddsp_load_tch_param(T_TIME_INFO *next_time,   UWORD8 chan_mode,
                             UWORD8       chan_type,   UWORD8 subchannel,
                             UWORD8       tch_loop,    UWORD8 sync_tch,
                           #if !FF_L1_IT_DSP_DTX
                             UWORD8       reset_sacch, UWORD8 vocoder_on)
			   #else
                             UWORD8       reset_sacch, UWORD8 vocoder_on,
                             BOOL         dtx_dsp_interrupt)
                           #endif
#else
  void l1ddsp_load_tch_param(T_TIME_INFO *next_time, UWORD8 chan_mode,
                             UWORD8       chan_type, UWORD8 subchannel,
                           #if !FF_L1_IT_DSP_DTX
                             UWORD8       tch_loop,  UWORD8 sync_tch)
                           #else
                             UWORD8       tch_loop,  UWORD8 sync_tch,
                             BOOL         dtx_dsp_interrupt)
                           #endif
#endif
  {
    UWORD32  count_0;
    UWORD32  count_1;
    UWORD32  d_ctrl_tch;
    UWORD32  d_fn;

    // d_ctrl_tch
    // ----------
    //   bit [0..3]   -> b_chan_mode
    //   bit [4..7]   -> b_chan_type
    //   bit [8]      -> b_sync_tch_ul
    //   bit [9]      -> b_sync_tch_dl
    //   bit [10]     -> b_stop_tch_ul
    //   bit [11]     -> b_stop_tch_dl
    //   bit [12..14] -> b_tch_loop
    //   bit [15]     -> b_subchannel
  #if (FF_L1_TCH_VOCODER_CONTROL == 1)
    d_ctrl_tch = (chan_mode<<B_CHAN_MODE)  | (chan_type<<B_CHAN_TYPE)  | (subchannel<<B_SUBCHANNEL) |
                 (sync_tch<<B_SYNC_TCH_UL) | (sync_tch<<B_SYNC_TCH_DL) |
                 (tch_loop<<B_TCH_LOOP) | (reset_sacch<<B_RESET_SACCH) | (vocoder_on<<B_VOCODER_ON);
  #else
    d_ctrl_tch = (chan_mode<<B_CHAN_MODE)  | (chan_type<<B_CHAN_TYPE)  | (subchannel<<B_SUBCHANNEL) |
                 (sync_tch<<B_SYNC_TCH_UL) | (sync_tch<<B_SYNC_TCH_DL) |
                 (tch_loop<<B_TCH_LOOP);
  #endif

    // d_fn
    // ----
    //   bit [0..7]  -> b_fn_report
    //   bit [8..15] -> b_fn_sid
    d_fn = (next_time->fn_in_report) | ((next_time->fn%104)<<8);

    // a_a5fn
    // ------
    //   count_0 (a_a5fn[0]), bit [0..4]  -> T2.
    //   count_0 (a_a5fn[1]), bit [5..10] -> T3.
    //   count_1 (a_a5fn[0]), bit [0..10] -> T1.
    count_0 = ((UWORD16)next_time->t3 << 5) | (next_time->t2);
    count_1 = (next_time->t1);

    l1s_dsp_com.dsp_db_w_ptr->d_fn         = d_fn;         // write both Fn_sid, Fn_report.
    l1s_dsp_com.dsp_db_w_ptr->a_a5fn[0]    = count_0;      // cyphering FN part 1.
    l1s_dsp_com.dsp_db_w_ptr->a_a5fn[1]    = count_1;      // cyphering FN part 2.
    l1s_dsp_com.dsp_db_w_ptr->d_ctrl_tch   = d_ctrl_tch;   // Channel config.
  }
#endif

#if (L1_VOCODER_IF_CHANGE == 0)
// TODO: to be moved in API file (see BUG3093)
BOOL enable_tch_vocoder(BOOL vocoder)
{
  #if (FF_L1_TCH_VOCODER_CONTROL == 1)
    // To enable the vocoder, we set the trigger => then handled in l1s_dedicated_mode_manager
    #if (W_A_DSP_PR20037 == 1)
      if ((vocoder==TRUE) && (l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_DISABLED))
      {
        l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_ENABLE_REQ;

        #if ( L1M_WAIT_DSP_RESTART_AFTER_VOCODER_ENABLE ==1)
          NU_Sleep(DSP_VOCODER_ON_TRANSITION); // DSP transition
        #endif
      }
      // When vocoder_on = FALSE, vocoder module is not executed
      else if ((vocoder==FALSE) && (l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_ENABLED))
      {
        l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_DISABLE_REQ;
      }
    #else // W_A_DSP_PR20037 == 0
      if (vocoder)
      {
        l1a_l1s_com.dedic_set.start_vocoder = TRUE;
      }
      // When vocoder_on = FALSE, vocoder module is not executed
      else
      {
        l1a_l1s_com.dedic_set.vocoder_on = FALSE;
      }
    #endif // W_A_DSP_PR20037

    return TRUE;
  #else
    return FALSE;
  #endif
  }
#endif // L1_VOCODER_IF_CHANGE
BOOL l1_select_mcsi_port(UWORD8 port)
{
  #if (  (CHIPSET == 12) && (RF_FAM != 61) )
    l1s_dsp_com.dsp_ndb_ptr->d_mcsi_select = (API)port;
    return TRUE;
  #else
    return FALSE;
  #endif
}

// TODO: to be moved in API file

/*-------------------------------------------------------*/
/* l1ddsp_load_ciph_param()                              */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_load_ciph_param(UWORD8 a5mode,
                            T_ENCRYPTION_KEY      *ciph_key)
{
  // Store ciphering mode (0 for no ciphering) in MCU-DSP com.
  l1s_dsp_com.dsp_ndb_ptr->d_a5mode = a5mode;  // A5 algorithm (0 for none).
  // Store ciphering key.

#if (L1_A5_3 == 1)

  if(a5mode == 3)
  {
  #if(OP_L1_STANDALONE != 1)
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[0]  = (ciph_key->A[0]) | (ciph_key->A[1] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[1]  = (ciph_key->A[2]) | (ciph_key->A[3] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[2]  = (ciph_key->A[4]) | (ciph_key->A[5] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[3]  = (ciph_key->A[6]) | (ciph_key->A[7] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[4]  = (ciph_key->A[8]) | (ciph_key->A[9] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[5]  = (ciph_key->A[10]) | (ciph_key->A[11] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[6]  = (ciph_key->A[12]) | (ciph_key->A[13] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[7]  = (ciph_key->A[14]) | (ciph_key->A[15] << 8);
  #else // (OP_L1_STANDALONE == 1)
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[0]  = (ciph_key->A[0]) | (ciph_key->A[1] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[1]  = (ciph_key->A[2]) | (ciph_key->A[3] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[2]  = (ciph_key->A[4]) | (ciph_key->A[5] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[3]  = (ciph_key->A[6]) | (ciph_key->A[7] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[4]  = (ciph_key->A[8]) | (ciph_key->A[1] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[5]  = (ciph_key->A[10]) | (ciph_key->A[3] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[6]  = (ciph_key->A[12]) | (ciph_key->A[5] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[7]  = (ciph_key->A[14]) | (ciph_key->A[7] << 8);
  #endif
  }
  else // a5mode == 1 or 2
  {
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[0]  = (ciph_key->A[0]) | (ciph_key->A[1] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[1]  = (ciph_key->A[2]) | (ciph_key->A[3] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[2]  = (ciph_key->A[4]) | (ciph_key->A[5] << 8);
    l1s_dsp_com.dsp_ndb_ptr->a_a5_kc[3]  = (ciph_key->A[6]) | (ciph_key->A[7] << 8);
  }

#else

  l1s_dsp_com.dsp_ndb_ptr->a_kc[0]  = (ciph_key->A[0]) | (ciph_key->A[1] << 8);
  l1s_dsp_com.dsp_ndb_ptr->a_kc[1]  = (ciph_key->A[2]) | (ciph_key->A[3] << 8);
  l1s_dsp_com.dsp_ndb_ptr->a_kc[2]  = (ciph_key->A[4]) | (ciph_key->A[5] << 8);
  l1s_dsp_com.dsp_ndb_ptr->a_kc[3]  = (ciph_key->A[6]) | (ciph_key->A[7] << 8);

#endif
}

/*-------------------------------------------------------*/
/* l1ddsp_stop_tch()                                     */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_stop_tch(void)
{
  // Tch channel description.
  //        bit [10]    -> b_stop_tch_ul,  stop TCH/UL.
  //        bit [11]    -> b_stop_tch_dl,  stop TCH/DL.

  l1s_dsp_com.dsp_db_w_ptr->d_ctrl_tch |= 3 << B_STOP_TCH_UL;
}

/*-------------------------------------------------------*/
/* l1ddsp_meas_read()                                    */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_meas_read(UWORD8 nbmeas, UWORD8 *pm)
{
  UWORD8 i;

  for (i= 0; i < nbmeas; i++)
  {
    pm[i] = ((l1s_dsp_com.dsp_db_r_ptr->a_pm[i] & 0xffff) >> 5);
  }

  #if TESTMODE
    if(l1_config.TestMode)
      l1tm.tmode_stats.pm_recent = l1s_dsp_com.dsp_db_r_ptr->a_pm[0] & 0xffff;
  #endif
}

#if (AMR == 1)
  /*-------------------------------------------------------*/
  /* l1ddsp_load_amr_param()                               */
  /*-------------------------------------------------------*/
  /* Parameters : AMR configuration                        */
  /* Return     : none                                     */
  /* Functionality : Download the AMR configuration to the */
  /*                 DSP via API                           */
  /*-------------------------------------------------------*/
  void l1ddsp_load_amr_param(T_AMR_CONFIGURATION amr_param, UWORD8 cmip)
  {
    // Clear the AMR API buffer
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[0] = (API)0;
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[1] = (API)0;
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[2] = (API)0;
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[3] = (API)0;

    // Set the AMR parameters
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSCB_INDEX]   |= (API)((amr_param.noise_suppression_bit & NSCB_MASK ) << NSCB_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[ICMUL_INDEX]  |= (API)((amr_param.initial_codec_mode & ICM_MASK ) << ICMUL_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[ICMDL_INDEX]  |= (API)((amr_param.initial_codec_mode & ICM_MASK ) << ICMDL_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[ICMIUL_INDEX] |= (API)((amr_param.initial_codec_mode_indicator & ICMI_MASK ) << ICMIUL_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[ICMIDL_INDEX] |= (API)((amr_param.initial_codec_mode_indicator & ICMI_MASK ) << ICMIDL_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[ACSUL_INDEX]  |= (API)((amr_param.active_codec_set & ACS_MASK ) << ACSUL_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[ACSDL_INDEX]  |= (API)((amr_param.active_codec_set & ACS_MASK ) << ACSDL_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[THR1_INDEX]   |= (API)((amr_param.threshold[0] & THR_MASK ) << THR1_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[THR2_INDEX]   |= (API)((amr_param.threshold[1] & THR_MASK ) << THR2_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[THR3_INDEX]   |= (API)((amr_param.threshold[2] & THR_MASK ) << THR3_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[HYST1_INDEX]  |= (API)((amr_param.hysteresis[0] & HYST_MASK ) << HYST1_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[HYST2_INDEX]  |= (API)((amr_param.hysteresis[1] & HYST_MASK ) << HYST2_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[HYST3_INDEX]  |= (API)((amr_param.hysteresis[2] & HYST_MASK ) << HYST3_SHIFT);
    l1s_dsp_com.dsp_ndb_ptr->a_amr_config[CMIP_INDEX]   |= (API)((cmip & CMIP_MASK ) << CMIP_SHIFT);
  }
#endif

#if (L1_SAIC != 0)
  /*-------------------------------------------------------*/
  /* l1ddsp_load_swh_flag()                                */
  /*-------------------------------------------------------*/
  /* Parameters : SWH (Spatial Whitening) Flag             */
  /* Return     : none                                     */
  /* Functionality : To write the d_swh_ApplyWhitening flag*/
  /*-------------------------------------------------------*/
  void l1ddsp_load_swh_flag (UWORD16 SWH_flag, UWORD16 SAIC_flag)
  {

    if(SAIC_flag)
    {
      l1s_dsp_com.dsp_db_common_w_ptr->d_swh_ctrl_db = SAIC_ENABLE_DB;
     if(SWH_flag)
     {
        l1s_dsp_com.dsp_db_common_w_ptr->d_swh_ctrl_db |= (0x01<< B_SWH_DB);
     }
    }
    else
    {
      l1s_dsp_com.dsp_db_common_w_ptr->d_swh_ctrl_db = 0;
    }
  }
#endif

/*-------------------------------------------------------*/
/* l1ddsp_end_scenario()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ddsp_end_scenario(UWORD8 type)
{
  #if (CODE_VERSION == SIMULATION)
    #if (AUDIO_SIMULATION)
      switch(type)
      {
        case GSM_CTL:
        case GSM_MISC_CTL:
        // a DSP control for a GSM task or
        // a DSP control for a GSM and a MISC tasks
        //-----------------------------
        {
          // set DSP_ENB and DSP_PAG for communication interrupt
          l1s_tpu_com.reg_cmd->dsp_pag_bit = l1s_dsp_com.dsp_w_page;
          l1s_tpu_com.reg_cmd->dsp_enb_bit = ON;

          // change DSP page pointer for next controle
          l1s_dsp_com.dsp_w_page  ^= 1;
        }
        break;

        case MISC_CTL:
        // a DSP control for a MISC task
        //------------------------------
        {
          // set only MISC task and reset MISC page
          // (don't change GSM PAGE).
          // set DSP communication Interrupt.
          // set DSP_ENB and the same DSP_PAG for communication interrupt
          l1s_tpu_com.reg_cmd->dsp_pag_bit = l1s_dsp_com.dsp_w_page^1;
          l1s_tpu_com.reg_cmd->dsp_enb_bit = ON;
        }
        break;
      }
    #else // NO AUDIO_SIMULATION
      // set DSP_ENB and DSP_PAG for communication interrupt
      l1s_tpu_com.reg_cmd->dsp_pag_bit = l1s_dsp_com.dsp_w_page;
      l1s_tpu_com.reg_cmd->dsp_enb_bit = ON;

      // change DSP page pointer for next control
      l1s_dsp_com.dsp_w_page  ^= 1;
    #endif // AUDIO_SIMULATION

  #else // NOT_SIMULATION
    UWORD32 dsp_task;
    switch(type)
    {
      case GSM_CTL:
      // a DSP control for a GSM task
      //-----------------------------
      {
        // set only GSM task and GSM page
        dsp_task = B_GSM_TASK | l1s_dsp_com.dsp_w_page;
        // change DSP page pointer for next controle
        l1s_dsp_com.dsp_w_page  ^= 1;
      }
      break;

      case MISC_CTL:
      // a DSP control for a MISC task
      //------------------------------
      {
        UWORD32  previous_page = l1s_dsp_com.dsp_w_page ^ 1;

        // set only MISC task and reset MISC page
        // (don't change GSM PAGE).
        // set DSP communication Interrupt.
        dsp_task = B_MISC_TASK | previous_page;

        // Rem: DSP makes the DB header feedback even in case
        //      of MISC task (like TONES). This created some
        //      side effect which are "work-around" passing
        //      the correct DB page to the DSP.
      }
      break;

      case GSM_MISC_CTL:
      // a DSP control for a GSM and a MISC tasks
      //-----------------------------------------
      {
        // set GSM task, MISC task and GSM page bit.....
        dsp_task =  B_GSM_TASK | B_MISC_TASK | l1s_dsp_com.dsp_w_page;
        // change DSP page pointer for next controle
        l1s_dsp_com.dsp_w_page  ^= 1;
      }
      break;

      #if 0	/* enable this after TCS211 reconstruction */
      default:
	dsp_task = 0;
      #endif
    }

    // write dsp tasks.....
    #if (DSP >= 33)
      l1s_dsp_com.dsp_ndb_ptr->d_dsp_page = (API) dsp_task;
    #else
      l1s_dsp_com.dsp_param_ptr->d_dsp_page = (API) dsp_task;
    #endif

    // Enable frame IT on next TDMA
    l1dmacro_set_frame_it();

    #if (DSP >= 38)
    // DSP CPU load measurement - write logic (provide TDMA frame number to DSP)
    (*((volatile UWORD16 *)(DSP_CPU_LOAD_MCU_W_TDMA_FN))) = (API)l1s.actual_time.fn_mod42432;
    #endif

  #endif // NOT_SIMULATION
}

/*-------------------------------------------------------*/
/* l1dtpu_meas()                                         */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */

/* Locosto : should take additional Param of task */

/*-------------------------------------------------------*/
void l1dtpu_meas(UWORD16 radio_freq,
                 WORD8   agc,
                 UWORD8  lna_off,
                 UWORD16 win_id,
                 UWORD16 tpu_synchro, UWORD8 adc_active
#if(RF_FAM == 61)
                 ,UWORD8 afc_mode
                 ,UWORD8 if_ctl
#endif
                              )

{

  WORD16  offset;
  WORD16  when;
  UWORD16 offset_chg;

  #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif // TESTMODE

  // Compute offset
  offset_chg = ((win_id  * BP_DURATION) >> BP_SPLIT_PW2);
  offset     = tpu_synchro + offset_chg;
  if(offset >= TPU_CLOCK_RANGE) offset -= TPU_CLOCK_RANGE;

  // Compute offset change timing
  when = offset_chg + PROVISION_TIME - (l1_config.params.rx_synth_setup_time + EPSILON_OFFS);
  if(when < 0) when += TPU_CLOCK_RANGE;

  // Program TPU scenario
  l1dmacro_offset   (offset, when);            // change TPU offset according to win_id
  l1dmacro_rx_synth (radio_freq);              // pgme SYNTH.
  if(adc_active == ACTIVE)
     l1dmacro_adc_read_rx();                   // pgme ADC measurement

  l1dmacro_agc      (radio_freq, agc,lna_off
                               #if (RF_FAM == 61)
					 ,if_ctl
				   #endif
                                   ); // pgme AGC.
  #if (CODE_VERSION == SIMULATION)
    l1dmacro_rx_ms    (radio_freq, 0);           // pgm  PWR acquisition.
  #else
  #if (L1_MADC_ON == 1)
  #if (RF_FAM == 61)
   l1dmacro_rx_ms    (radio_freq,adc_active);              // pgm  PWR acquisition.
   #endif
  #else
    l1dmacro_rx_ms    (radio_freq);              // pgm  PWR acquisition.
   #endif
  #endif
  l1dmacro_offset   (tpu_synchro, IMM);        // restore offset

  //Locosto
  #if(RF_FAM == 61)
    // L1_AFC_SCRIPT_MODE - This is specific to Locosto to make AFC script run after
    // the second power measurement during FBNEW
    if ((win_id == 0)  ||  (afc_mode == L1_AFC_SCRIPT_MODE))
  #else
    if (win_id == 0)
  #endif
  {
    #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3))
    // NOTE: In Locosto AFC is in DRP not in triton
        l1ddsp_load_afc(l1s.afc);
    #endif

    //Locosto
    #if(RF_FAM == 61)
    if(afc_mode != L1_AFC_NONE)
    {
      if(afc_mode == L1_AFC_SCRIPT_MODE)
      {
        l1dtpu_load_afc(l1s.afc);  //Load the Initial afc value to the TPU. TPU would copy it to the DRP Wrapper Mem.
      }
      else
      {
        l1ddsp_load_afc(l1s.afc);
      }
    }
    #endif
    // end Locosto
  }
}

/*-------------------------------------------------------*/
/* l1dtpu_neig_fb()                                      */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_neig_fb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off)
{
   #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif

  l1dmacro_rx_synth (radio_freq);               // pgme SYNTH.
  l1dmacro_agc      (radio_freq,agc, lna_off
  	                         #if (RF_FAM == 61)
                                ,IF_120KHZ_DSP
                                 #endif
					 );  // pgme AGC.
#if (L1_MADC_ON == 1)
#if (RF_FAM == 61)
   l1dmacro_rx_fb    (radio_freq,INACTIVE);               // pgm  FB acquisition.
#endif
#else
  l1dmacro_rx_fb    (radio_freq);               // pgm  FB acquisition.
#endif
}

/*-------------------------------------------------------*/
/* l1dtpu_neig_fb26()                                    */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_neig_fb26(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off, UWORD32 offset_serv)
{
  WORD16  offset;

  #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif

  // Compute offset
  offset = offset_serv + l1_config.params.fb26_anchoring_time;
  if(offset >= TPU_CLOCK_RANGE) offset -= TPU_CLOCK_RANGE;

  // Program TPU scenario
  l1dmacro_offset   (offset, l1_config.params.fb26_change_offset_time);
  l1dmacro_rx_synth (radio_freq);               // pgme SYNTH.
  l1dmacro_agc      (radio_freq,agc, lna_off
  	                         #if (RF_FAM == 61)
                                ,IF_120KHZ_DSP
                                 #endif
                                 );  // pgme AGC.
#if (L1_MADC_ON == 1)
#if (RF_FAM == 61)
  l1dmacro_rx_fb26  (radio_freq, INACTIVE);               // pgm  FB acquisition.
#endif
#else
  l1dmacro_rx_fb26  (radio_freq);               // pgm  FB acquisition.
#endif
  l1dmacro_offset   (offset_serv, IMM);         // restore offset
}

/*-------------------------------------------------------*/
/* l1dtpu_neig_sb()                                      */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_neig_sb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off,
                    UWORD32 time_alignmt, UWORD32 offset_serv, UWORD8 reload_flag,
                    UWORD8 attempt
                   #if (RF_FAM == 61)
                   ,UWORD8 if_ctl
                   #endif
                    )
{
  UWORD16 offset_neigh;

  #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif

  // compute offset neighbour...
  offset_neigh = offset_serv + time_alignmt;
  if(offset_neigh >= TPU_CLOCK_RANGE) offset_neigh -= TPU_CLOCK_RANGE;

  // load OFFSET with NEIGHBOUR value.
  l1dmacro_offset  (offset_neigh, l1_config.params.rx_change_offset_time);

  // Insert 1 NOP to correct the EPSILON_SYNC side effect.
  if(attempt != 2)
  if(time_alignmt >= (TPU_CLOCK_RANGE - EPSILON_SYNC))
    l1dmacro_offset  (offset_neigh, 0);  // load OFFSET with NEIGHBOUR value.

  l1dmacro_rx_synth(radio_freq);               // pgme SYNTH.
  l1dmacro_agc     (radio_freq, agc, lna_off
#if (RF_FAM == 61)
                                ,if_ctl
#endif
                                  ); // pgme AGC.
 #if (L1_MADC_ON == 1)
 #if (RF_FAM == 61)
  l1dmacro_rx_sb   (radio_freq,INACTIVE);               // pgm  SB acquisition.
 #endif
 #else
  l1dmacro_rx_sb   (radio_freq);               // pgm  SB acquisition.
 #endif

  // Restore offset with serving value.
  if(reload_flag == TRUE)
  {
    l1dmacro_offset  (offset_serv, IMM);
  }
}
/*-------------------------------------------------------*/
/* l1dtpu_neig_fbsb()                                      */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
#if ((REL99 == 1) && (FF_BHO == 1))
/*void l1dtpu_neig_fbsb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off
                   #if (RF_FAM == 61)
			,UWORD8 if_ctl
  		   #endif
			)*/
void l1dtpu_neig_fbsb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off)
{
#if TESTMODE
  if (!l1_config.agc_enable)
  {
    // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
    // corresponds to the lna_off bit
    agc = l1_config.tmode.rx_params.agc;
    lna_off = l1_config.tmode.rx_params.lna_off;
  }
#endif // TESTMODE

  l1dmacro_rx_synth (radio_freq);               // pgme SYNTH.
  /*l1dmacro_agc(radio_freq, agc, lna_off
                         #if (RF_FAM == 61)
                         ,if_ctl
                         #endif
                         );     // pgme AGC.
 */
 l1dmacro_agc      (radio_freq,agc, lna_off
  	                         #if (RF_FAM == 61)
                                ,L1_CTL_LOW_IF
                                 #endif
					 );  // pgme AGC.
#if (L1_MADC_ON == 1)
#if (RF_FAM == 61)
  l1dmacro_rx_fbsb(radio_freq,INACTIVE);               // pgm  FB acquisition.
#endif
#else
  l1dmacro_rx_fbsb(radio_freq);             // pgm  FB acquisition.- sajal commented
#endif
}
#endif  // #if ((REL99 == 1) && (FF_BHO == 1))
/*-------------------------------------------------------*/
/* l1dtpu_neig_sb26()                                    */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_neig_sb26(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off, UWORD32 time_alignmt,
                      UWORD32 fn_offset, UWORD32 offset_serv
                 #if (RF_FAM == 61)
			,UWORD8 if_ctl
  		   #endif
					  )
{
  UWORD16 offset_neigh;

  #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif

  // compute offset neighbour...
  offset_neigh = offset_serv + time_alignmt;
  if(offset_neigh >= TPU_CLOCK_RANGE) offset_neigh -= TPU_CLOCK_RANGE;

  if(fn_offset != 0)
    l1dmacro_offset  (offset_neigh, 0);       // 1 NOP in some case
  else
    l1dmacro_offset  (offset_neigh, l1_config.params.fb26_change_offset_time);

  l1dmacro_rx_synth(radio_freq);              // pgme SYNTH.
  l1dmacro_agc(radio_freq, agc, lna_off
                         #if (RF_FAM == 61)
                         ,if_ctl
                         #endif
                         );     // pgme AGC.
#if (L1_MADC_ON == 1)
#if (RF_FAM == 61)
 l1dmacro_rx_sb   (radio_freq, INACTIVE);              // pgm  SB acquisition.
#endif
#else
  l1dmacro_rx_sb   (radio_freq);              // pgm  SB acquisition.
#endif
  l1dmacro_offset  (offset_serv, IMM);        // Restore offset with serving value.
}

/*-------------------------------------------------------*/
/* l1dtpu_serv_rx_nb()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_serv_rx_nb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off,
                       UWORD32 synchro_serv,UWORD32 new_offset,BOOL change_offset,
                       UWORD8 adc_active
                      #if(RF_FAM == 61)
                     , UWORD8 csf_filter_choice
                     , UWORD8 if_ctl
                      #endif
                      #if (NEW_SNR_THRESHOLD == 1)
                     , UWORD8 saic_flag
                      #endif/* NEW_SNR_THRESHOLD == 1*/
                         )
{

  #if (CODE_VERSION == SIMULATION)
    UWORD32 tpu_w_page;

    if (hw.tpu_r_page==0)
       tpu_w_page=1;
    else
       tpu_w_page=0;

    // Give the Ts related to the L1s
    hw.rx_id[tpu_w_page][0]= ((TPU_CLOCK_RANGE+new_offset-synchro_serv)%TPU_CLOCK_RANGE)/TN_WIDTH;
    hw.num_rx[tpu_w_page][0]=1;
    hw.rx_group_id[tpu_w_page]=1;
  #endif

  #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif

  l1dmacro_synchro (l1_config.params.rx_change_synchro_time, synchro_serv); // Adjust serving OFFSET.

  #if L2_L3_SIMUL
    #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET)
      buffer_trace(3, 0x43, synchro_serv,l1s.actual_time.fn,0);
    #endif
  #endif

  // Need to slide offset to cope with the new synchro.
  if(change_offset)
    l1dmacro_offset(new_offset, l1_config.params.rx_change_offset_time);

  l1dmacro_rx_synth(radio_freq);                   // load SYNTH.
  if(adc_active == ACTIVE)
     l1dmacro_adc_read_rx();                       // pgme ADC measurement

  l1dmacro_agc     (radio_freq, agc, lna_off
                               #if (RF_FAM == 61)
                               ,if_ctl
                               #endif
                                );

  #if TESTMODE && (CODE_VERSION != SIMULATION)
    // Continuous mode: Rx continuous scenario only on START_RX state.
    if ((l1_config.TestMode) &&
        (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS))
   #if (L1_MADC_ON == 1)
   #if (RF_FAM == 61)
      l1dmacro_rx_cont   (FALSE, radio_freq,adc_active,csf_filter_choice
    #if (NEW_SNR_THRESHOLD == 1)
        ,saic_flag
    #endif /* NEW_SNR_THRESHOLD*/
          );
   #endif /* RF_FAM == 61*/
   #else  /* L1_MADC_ON == 1 */
    #if (RF_FAM == 61)
      l1dmacro_rx_cont   (FALSE, radio_freq,csf_filter_choice);
    #else
      l1dmacro_rx_cont   (FALSE, radio_freq);
    #endif
   #endif
	//TBD Danny New MAcro for Cont Tx reqd, to use only External Trigger
    else
  #endif
 #if ( L1_MADC_ON == 1)
 #if (RF_FAM == 61)
    l1dmacro_rx_nb   (radio_freq, adc_active, csf_filter_choice
 #if (NEW_SNR_THRESHOLD == 1)
        ,saic_flag
 #endif /* NEW_SNR_THRESHOLD*/
        );  // RX window for NB.
 #endif /* RF_FAM == 61*/
 #else /* L1_MADC_ON == 1*/
   #if (RF_FAM == 61)
     l1dmacro_rx_nb   (radio_freq, csf_filter_choice);	// RX window for NB.
   #else
     l1dmacro_rx_nb   (radio_freq);			// RX window for NB.
   #endif
 #endif

  #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3))
      l1ddsp_load_afc(l1s.afc);
  #endif
  #if (RF_FAM == 61)
      l1dtpu_load_afc(l1s.afc);
  #endif


  if(change_offset)
    l1dmacro_offset(synchro_serv, IMM); // Restore offset.
}

/*-------------------------------------------------------*/
/* l1dtpu_serv_tx_nb()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_serv_tx_nb(UWORD16 radio_freq, UWORD8 timing_advance,
                       UWORD32 offset_serv, UWORD8 txpwr, UWORD8 adc_active)
{
  WORD32    time;
  UWORD32   offset_tx;
  UWORD32   timing_advance_in_qbit = (UWORD32)timing_advance << 2;

  #if (CODE_VERSION == SIMULATION)
    UWORD32 tpu_w_page;

    if (hw.tpu_r_page==0)
       tpu_w_page=1;
    else
       tpu_w_page=0;

    hw.tx_id[tpu_w_page][0]=3;// MS synchronized on TN=0 for RX => TN=3 for TX
    hw.num_tx[tpu_w_page][0]=1;
    hw.tx_group_id[tpu_w_page]=1;
  #endif

  // Reset timing advance if TA_ALGO not enabled.
  #if !TA_ALGO
    timing_advance_in_qbit = 0;
  #endif

  // Compute offset value for TX.
  // PRG_TX has become variable, no longer contained in TIME_OFFSET_TX !
  offset_tx = (offset_serv + TIME_OFFSET_TX-l1_config.params.prg_tx_gsm - timing_advance_in_qbit) ;
  if (offset_tx >= TPU_CLOCK_RANGE) offset_tx -= TPU_CLOCK_RANGE;

  // Check that RX controle has been already installed.
  // Offset for TX must be set an immediately if RX is there else
  // it must be performed EPSILON_SYNC before current offset time.
  if( l1s.tpu_ctrl_reg & CTRL_RX )
    time = l1_config.params.tx_change_offset_time - l1_config.params.prg_tx_gsm;
  else
    time = TPU_CLOCK_RANGE - EPSILON_SYNC;

  l1dmacro_offset  (offset_tx, time);  // load OFFSET for TX before each burst.

  #if L2_L3_SIMUL
    #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET)
      buffer_trace(2, offset_tx,l1s.actual_time.fn,0,0);
    #endif
  #endif

  l1dmacro_tx_synth(radio_freq);         // load SYNTH.
  #if TESTMODE && (CODE_VERSION != SIMULATION)
    // Continuous mode: Tx continuous scenario only on START_TX state.
    #if (RF_FAM != 61)
      if ((l1_config.TestMode) &&
          (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS))
        l1dmacro_tx_cont   (radio_freq, txpwr);     // TX window for NB.
      else
    #endif // RF_FAM != 61
    #if (RF_FAM == 61)
      // NOTE: In Test Mode and in TX Continuous, APC control is in manual mode
      // This is done in l1tm_async.c
      if ((l1_config.TestMode) &&
          (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS))
      {
	 // NOTE: APC is set in manual mode from l1tm_async.c
	 l1dmacro_tx_cont   (radio_freq, txpwr);     // TX window for NB.
      }
      else
    #endif // RF_FAM == 61
  #endif
  l1dmacro_tx_nb   (radio_freq, txpwr, adc_active);  // TX window for NB.
  // TX window for NB.
  l1dmacro_offset  (offset_serv, IMM);   // Restore offset with serving value.

  #if L2_L3_SIMUL
    #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET)
      buffer_trace(2, offset_serv,l1s.actual_time.fn,0,0);
    #endif
  #endif
}

/*-------------------------------------------------------*/
/* l1dtpu_neig_rx_nb()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_neig_rx_nb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off,
                       UWORD32 time_alignmt, UWORD32 offset_serv, UWORD8 reload_flag,
                       UWORD8 nop
                     #if (RF_FAM == 61)
			    ,UWORD8 if_ctl
			 #endif
#if (NEW_SNR_THRESHOLD == 1)
                                  ,UWORD8 saic_flag
#endif /* NEW_SNR_THRESHOLD*/
					      )
{
  UWORD32 offset_neigh;
#if (RF_FAM == 61)
  // By default we choose the hardware filter for neighbour Normal Bursts
  UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER;
#endif

  #if TESTMODE
    if (!l1_config.agc_enable)
    {
      // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero)
      // corresponds to the lna_off bit
      agc = l1_config.tmode.rx_params.agc;
      lna_off = l1_config.tmode.rx_params.lna_off;
    }
  #endif

 // compute offset neighbour...
  offset_neigh = (offset_serv + time_alignmt) ;
  if (offset_neigh >= TPU_CLOCK_RANGE) offset_neigh -= TPU_CLOCK_RANGE;

  l1dmacro_offset  (offset_neigh, l1_config.params.rx_change_offset_time);  // load OFFSET with NEIGHBOUR value.
  // Insert 1 NOP to correct the EPSILON_SYNC side effect
  if (nop ==1) l1dmacro_offset  (offset_neigh,0);


  l1dmacro_rx_synth(radio_freq);               // load SYNTH.
  l1dmacro_agc     (radio_freq, agc, lna_off
  	                    #if (RF_FAM == 61)
				   ,if_ctl
				#endif
				    );
#if (L1_MADC_ON == 1)
#if (RF_FAM == 61)
  l1dmacro_rx_nb   (radio_freq, INACTIVE, csf_filter_choice
#if (NEW_SNR_THRESHOLD == 1)
        ,saic_flag
#endif /* NEW_SNR_THRESHOLD*/
      )  ;     // RX window for NB.
#endif  /* RF_FAM == 61*/
#else /* L1_MADC_ON == 1*/
  #if (RF_FAM == 61)
    l1dmacro_rx_nb   (radio_freq, csf_filter_choice);	// RX window for NB.
  #else
    l1dmacro_rx_nb   (radio_freq);			// RX window for NB.
  #endif
#endif

  // Restore offset with serving value.
  if(reload_flag == TRUE)
    l1dmacro_offset  (offset_serv, IMM);

}

/*-------------------------------------------------------*/
/* l1dtpu_serv_tx_ra()                                   */
/*-------------------------------------------------------*/
/* Parameters : "burst_id" gives the burst identifier    */
/*              which is used for offset management.     */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_serv_tx_ra(UWORD16 radio_freq, UWORD32 offset_serv, UWORD8 txpwr, UWORD8 adc_active)
{
  WORD32    time;
  UWORD32   offset_tx;

  // Compute offset value for TX.
  // Rem: Timing Advance is always 0 for a RA.
  // PRG_TX has become variable, no longer contained in TIME_OFFSET_TX !
  offset_tx = (offset_serv + TIME_OFFSET_TX-l1_config.params.prg_tx_gsm);
  if (offset_tx >= TPU_CLOCK_RANGE) offset_tx -= TPU_CLOCK_RANGE;

  // Check that RX controle has been already installed.
  // Offset for TX must be set an immediately if RX is there else
  // it must be performed EPSILON_SYNC before current offset time.
  if( l1s.tpu_ctrl_reg & CTRL_RX )
    time = l1_config.params.tx_change_offset_time - l1_config.params.prg_tx_gsm;
  else
    time = TPU_CLOCK_RANGE - EPSILON_SYNC;

  l1dmacro_offset  (offset_tx, time);  // load OFFSET for TX before each burst.
  #if L2_L3_SIMUL
    #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET)
      buffer_trace(2, offset_tx,l1s.actual_time.fn,0,0);
    #endif
  #endif
  l1dmacro_tx_synth(radio_freq);            // load SYNTH.
  l1dmacro_tx_ra   (radio_freq, txpwr,adc_active);     // TX window for RA.
  l1dmacro_offset  (offset_serv, IMM); // Restore offset with serving value.
  #if L2_L3_SIMUL
    #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET)
      buffer_trace(2, offset_serv,l1s.actual_time.fn,0,0);
    #endif
  #endif
}

/*-------------------------------------------------------*/
/* l1dtpu_end_scenario()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1dtpu_end_scenario(void)
{

  // write IDLE at end of TPU page
  // TPU_ENB and TPU_PAG are set in L1DMACRO_IDLE(). The TPU change
  // is executed by the TPU itself and the TPU pointer is reset to
  // start of page by l1dmacro_idle();
  l1dmacro_idle();

  #if (CODE_VERSION == SIMULATION)
    #if LOGTPU_TRACE
      log_macro();
    #endif
  #endif
  // init pointer within new TPU page at 1st line
  #if (CODE_VERSION == SIMULATION)
    // set TPU_ENB, TPU_PAG for communication interrupt
    l1s_tpu_com.reg_cmd->tpu_pag_bit = l1s_tpu_com.tpu_w_page;
    l1s_tpu_com.reg_cmd->tpu_enb_bit = ON;

    // change TPU and DSP page pointer for next control
    l1s_tpu_com.tpu_w_page  ^= 1;

    // points on new "write TPU page"...
    l1s_tpu_com.tpu_page_ptr=&(tpu.buf[l1s_tpu_com.tpu_w_page].line[0]);

  #endif

}

/*-------------------------------------------------------*/
/* l1d_reset_hw()                                        */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1d_reset_hw(UWORD32 offset_value)
{
  #if (CODE_VERSION == SIMULATION)
  // Reset DSP write/read page, Reset TPU write page, reset "used" flag.
  l1s_dsp_com.dsp_w_page      = 0;
  l1s_dsp_com.dsp_r_page      = 0;
  l1s_tpu_com.tpu_w_page      = 0;
  l1s_dsp_com.dsp_r_page_used = 0;

  // Reset communication pointers.
    l1s_dsp_com.dsp_ndb_ptr  = &(buf.ndb);                            // MCU<->DSP comm. read/write (Non Double Buffered comm. memory).
    l1s_dsp_com.dsp_db_r_ptr = &(buf.mcu_rd[l1s_dsp_com.dsp_r_page]); // MCU<->DSP comm. read  page (Double Buffered comm. memory).
    l1s_dsp_com.dsp_db_w_ptr = &(buf.mcu_wr[l1s_dsp_com.dsp_w_page]); // MCU<->DSP comm. write page (Double Buffered comm. memory).

  // Reset task commands.
  l1s_dsp_com.dsp_db_w_ptr->d_task_d  = NO_DSP_TASK; // Init. RX task to NO TASK.
  l1s_dsp_com.dsp_db_w_ptr->d_task_u  = NO_DSP_TASK; // Init. TX task to NO TASK.
  l1s_dsp_com.dsp_db_w_ptr->d_task_ra = NO_DSP_TASK; // Init. RA task to NO TASK.
  l1s_dsp_com.dsp_db_w_ptr->d_task_md = NO_DSP_TASK; // Init. MONITORING task to NO TASK.


  //Reset the TCH channel description
  l1s_dsp_com.dsp_db_w_ptr->d_ctrl_tch = 0;

    #if (L1_GPRS)
      // Reset communication pointers.
      l1ps_dsp_com.pdsp_db_r_ptr = &(buf.mcu_rd_gprs[l1s_dsp_com.dsp_r_page]);
      l1ps_dsp_com.pdsp_db_w_ptr = &(buf.mcu_wr_gprs[l1s_dsp_com.dsp_w_page]);

      // Reset MCU->DSP page.
      l1ps_reset_db_mcu_to_dsp(l1ps_dsp_com.pdsp_db_w_ptr);
    #endif // L1_GPRS

    // Direct access to TPU_RESET_BIT.
    l1s_tpu_com.reg_cmd->tpu_reset_bit = ON;           // Reset TPU.

    // Reset TPU_ENB, DSP_ENB and TPU_PAG, DSP_PAG for communication interrupt
    l1s_tpu_com.reg_cmd->tpu_pag_bit = 0;
    l1s_tpu_com.reg_cmd->dsp_pag_bit = 0;
    l1s_tpu_com.reg_cmd->tpu_enb_bit = OFF;
    l1s_tpu_com.reg_cmd->dsp_enb_bit = OFF;

    // Init pointer within TPU page 0 at 1st line
    l1s_tpu_com.tpu_page_ptr = &(tpu.buf[0].line[0]);

    // Load offset register according to serving cell.
    l1dmacro_offset(offset_value, IMM);

  #else // NOT_SIMULATION

    // Reset DSP write/read page, Reset TPU write page, reset "used" flag.
    l1s_dsp_com.dsp_w_page      = 0;
    l1s_dsp_com.dsp_r_page      = 0;
    l1s_tpu_com.tpu_w_page      = 0;
    l1s_dsp_com.dsp_r_page_used = 0;

    // Reset communication pointers.
    l1s_dsp_com.dsp_ndb_ptr  = (T_NDB_MCU_DSP *)   NDB_ADR;      // MCU<->DSP comm. read/write (Non Double Buffered comm. memory).
    l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) DB_R_PAGE_0;  // MCU<->DSP comm. read  page (Double Buffered comm. memory).
    l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) DB_W_PAGE_0;  // MCU<->DSP comm. write page (Double Buffered comm. memory).
    l1s_dsp_com.dsp_param_ptr= (T_PARAM_MCU_DSP *) PARAM_ADR;

    #if (DSP == 38) || (DSP == 39)
    l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP *) DB_COMMON_W_PAGE_0;
    #endif

    // Reset task commands.
    l1s_dsp_com.dsp_db_w_ptr->d_task_d  = NO_DSP_TASK; // Init. RX task to NO TASK.
    l1s_dsp_com.dsp_db_w_ptr->d_task_u  = NO_DSP_TASK; // Init. TX task to NO TASK.
    l1s_dsp_com.dsp_db_w_ptr->d_task_ra = NO_DSP_TASK; // Init. RA task to NO TASK.
    l1s_dsp_com.dsp_db_w_ptr->d_task_md = NO_DSP_TASK; // Init. MONITORING task to NO TASK.

    //Reset the TCH channel description
    l1s_dsp_com.dsp_db_w_ptr->d_ctrl_tch = 0;

    // Clear DSP_PAG bit
    #if (DSP == 33) || (DSP == 34) || (DSP == 35) || (DSP == 36) || (DSP == 37) || (DSP == 38) || (DSP == 39)
      l1s_dsp_com.dsp_ndb_ptr->d_dsp_page = 0;
    #else
      l1s_dsp_com.dsp_param_ptr->d_dsp_page = 0;
    #endif

    #if (L1_GPRS)
      // Reset communication pointers.
      l1ps_dsp_com.pdsp_ndb_ptr  = (T_NDB_MCU_DSP_GPRS *)   NDB_ADR_GPRS;
      l1ps_dsp_com.pdsp_db_r_ptr = (T_DB_DSP_TO_MCU_GPRS *) DB_R_PAGE_0_GPRS;
      l1ps_dsp_com.pdsp_db_w_ptr = (T_DB_MCU_TO_DSP_GPRS *) DB_W_PAGE_0_GPRS;
      l1ps_dsp_com.pdsp_param_ptr= (T_PARAM_MCU_DSP_GPRS *) PARAM_ADR_GPRS;

      // Reset MCU->DSP page.
      l1ps_reset_db_mcu_to_dsp(l1ps_dsp_com.pdsp_db_w_ptr);
    #endif // L1_GPRS

    #if (DSP_DEBUG_TRACE_ENABLE == 1)
      l1s_dsp_com.dsp_db2_current_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_0;
      l1s_dsp_com.dsp_db2_other_r_ptr   = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_1;
    #endif

    // Reset TPU and Reload offset register with Serving value.
    // Clear TPU_PAG
    l1dmacro_reset_hw(offset_value);
  #endif // NOT_SIMULATION
}


#if(RF_FAM == 61)

/*-------------------------------------------------------*/
/* l1apc_init_ramp_tables()                              */
/*-------------------------------------------------------*/
/* Parameters :        void                              */
/* Return     :        void                              */
/* Functionality :     This would copy the Ramp table    */
/*                     values to the MCU DSP API         */
/*-------------------------------------------------------*/
void l1dapc_init_ramp_tables(void)
{

#if (CODE_VERSION == SIMULATION)
// Do Nothing there is no APC task
 #else
   #if ( DSP == 38) || (DSP == 39)
      // Load RAMP up/down in NDB memory...
      if (l1_config.tx_pwr_code == 0)
      {
        Cust_get_ramp_tab( l1s_dsp_com.dsp_ndb_ptr->a_drp_ramp,
                          0 /* not used */,
                          0 /* not used */,
                          1 /* arbitrary value for arfcn*/);

      }
      else
      {
        Cust_get_ramp_tab( l1s_dsp_com.dsp_ndb_ptr->a_drp_ramp,
                          5 /* arbitrary value working in any case */,
                          5 /* arbitrary value working in any case */,
                          1 /* arbitrary value for arfcn*/);
      }
  #endif
   // Is it required to load ramptables for GPRS a_drp2_ramp_gprs

#endif

}



/*-------------------------------------------------------*/
/* l1ddsp_apc_load_apcctrl2                              */
/*-------------------------------------------------------*/
/* Parameters :        void                              */
/* Return     :        void                              */
/* Functionality :     This would copy the Ramp table    */
/*                     values to the MCU DSP API         */
/*-------------------------------------------------------*/
void l1ddsp_apc_load_apcctrl2(UWORD16 apcctrl2)
{
  l1s_dsp_com.dsp_ndb_ptr->d_apcctrl2 = ((apcctrl2) | (0x8000));
}

/*-------------------------------------------------------*/
/* l1ddsp_apc_set_manual_mode                            */
/*-------------------------------------------------------*/
/* Parameters :        void                              */
/* Return     :        void                              */
/* Functionality :     This would set the APC in manual  */
/*                     OR external trigger mode          */
/*-------------------------------------------------------*/
void l1ddsp_apc_set_manual_mode(void)
{
  l1s_dsp_com.dsp_ndb_ptr->d_apcctrl2 |= ((APC_APC_MODE) | (0x8000));
}

/*-------------------------------------------------------*/
/* l1ddsp_apc_set_automatic_mode                         */
/*-------------------------------------------------------*/
/* Parameters :        void                              */
/* Return     :        void                              */
/* Functionality :     This would set APC in automatic   */
/*                     OR internal sequencer mode        */
/*-------------------------------------------------------*/
void l1ddsp_apc_set_automatic_mode(void)
{
  l1s_dsp_com.dsp_ndb_ptr->d_apcctrl2 &=  ~(APC_APC_MODE);
  l1s_dsp_com.dsp_ndb_ptr->d_apcctrl2 |=    (0x8000);
}

#ifdef TESTMODE

/*-------------------------------------------------------*/
/* l1ddsp_apc_load_apclev                                */
/*-------------------------------------------------------*/
/* Parameters :    void                                  */
/* Return     :    void                                  */
/* Functionality : This function writes the apclev       */
/*                 val into the APCLEV register via DSP  */
/* NOTE:  Used only in TESTMODE and only when            */
/* l1_config.tmode.rf_params.down_up == TMODE_UPLINK;    */
/*-------------------------------------------------------*/
void l1ddsp_apc_load_apclev(UWORD16 apclev)
{
  l1s_dsp_com.dsp_ndb_ptr->d_apclev = ((apclev) | (0x8000));
}


#endif // TESTMODE

#endif
#if FF_L1_IT_DSP_DTX
/*-------------------------------------------------------*/
/* l1ddsp_dtx_interrupt_pending()                        */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :    DTX interrupt status                  */
/* Functionality : Test and clear the DTX IT pending     */
/*                 flag for DSP ISR screening purpose    */
/*-------------------------------------------------------*/
BOOL l1ddsp_dtx_interrupt_pending(void)
{
  if (l1s_dsp_com.dsp_ndb_ptr->d_dsp_hint_flag & (2 << B_DTX_HINT_ISSUED))
  {
    // Flag HISR to be scheduled
    l1a_apihisr_com.dtx.pending = TRUE;
    // Clear API ISR condition
    l1s_dsp_com.dsp_ndb_ptr->d_dsp_hint_flag &= ~(2 << B_DTX_HINT_ISSUED);
    return TRUE;
  }
  else
    return FALSE;
}
#endif


#define L1_DEBUG_IQ_DUMP  0

#if (L1_DEBUG_IQ_DUMP == 1)

#define IQ_DUMP_MAX_LOG_SIZE  (400) /* i.e. 200 I-Q Sample Pair */
#define IQ_DUMP_BUFFER_SIZE  (1280)
#define L1_DSP_DUMP_IQ_BUFFER_PAGE0 (0xFFD00000 + ((0x2000 - 0x800)*2))
#define L1_DSP_DUMP_IQ_BUFFER_PAGE1 (0xFFD00000 + ((0x2190 - 0x800)*2))

typedef struct
{
  UWORD8  task;
  UWORD8  hole;
  UWORD16 size;
  UWORD16 fn_mod42432;
  UWORD16 iq_sample[IQ_DUMP_MAX_LOG_SIZE];
}T_IQ_LOG_BUFFER;

#pragma DATA_SECTION(iq_dump_buffer,".debug_data");
T_IQ_LOG_BUFFER iq_dump_buffer[IQ_DUMP_BUFFER_SIZE];

UWORD32         iq_dump_buffer_log_index = 0;
UWORD32         iq_overflow_ind=0;

void l1ddsp_read_iq_dump(UWORD8 task)
{
  UWORD16 *p_dsp_iq_buffer_ptr;
  UWORD16 size;
  int i;

  /* get the page logic*/
  p_dsp_iq_buffer_ptr = (UWORD16 *)(L1_DSP_DUMP_IQ_BUFFER_PAGE0);
  if(l1s_dsp_com.dsp_r_page){
    p_dsp_iq_buffer_ptr = (UWORD16 *)(L1_DSP_DUMP_IQ_BUFFER_PAGE1);
  }

  /* */
  size = *p_dsp_iq_buffer_ptr;

  if(size == 0)
    return;

  /* size given by DSP is in units of I-Q sample pair */
  if(size > (IQ_DUMP_MAX_LOG_SIZE /2)){
    size = (IQ_DUMP_MAX_LOG_SIZE/2);
  }

  /* make size as zero again */
  *p_dsp_iq_buffer_ptr++ = 0;

  if(iq_dump_buffer_log_index >= IQ_DUMP_BUFFER_SIZE){
    iq_overflow_ind=1;
    iq_dump_buffer_log_index = 0;
  }

  iq_dump_buffer[iq_dump_buffer_log_index].task = task;
  iq_dump_buffer[iq_dump_buffer_log_index].hole = 0;
  iq_dump_buffer[iq_dump_buffer_log_index].size = size;
  iq_dump_buffer[iq_dump_buffer_log_index].fn_mod42432 = l1s.actual_time.fn_mod42432;

  memcpy(&iq_dump_buffer[iq_dump_buffer_log_index].iq_sample[0],
      p_dsp_iq_buffer_ptr,
      size*2*2); /* size * 2 (as size is in IQsample pair) * 2 (to convert to bytes) */

  iq_dump_buffer_log_index = iq_dump_buffer_log_index + 1;
}
#endif