view src/cs/layer1/cfile/l1_cmplx.c @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents edcb8364d45b
children
line wrap: on
line source

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

#define  L1_CMPLX_C

//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

#include "l1_macro.h"
#include "l1_confg.h"

#if (CODE_VERSION == SIMULATION)
  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.h"
  #include "l1_time.h"
  #include "l1_signa.h"
  #include <l1_trace.h>

  #if TESTMODE
    #include "l1tm_defty.h"
  #endif
  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_signa.h"
    #include "l1audio_defty.h"
    #include "l1audio_msgty.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 "cust_os.h"
  #include "l1_msgty.h"
  #include "l1_varex.h"
  #include "l1_proto.h"
  #include "l1_mftab.h"
  #include "l1_tabs.h"
  #include "l1_ver.h"
  #if L2_L3_SIMUL
    #include "l2_l3.h"
    #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 "sim_cons.h"
  #include "sim_def.h"
  extern T_hw FAR hw;

#else
  #include "abb.h"
  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.h"
  #include "l1_time.h"
  #include "l1_signa.h"
  #if TESTMODE
    #include "l1tm_defty.h"
    #if (RF_FAM == 60)
      #include "pld.h"
    #endif
  #endif
  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_signa.h"
    #include "l1audio_defty.h"
    #include "l1audio_msgty.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 "cust_os.h"
  #include "l1_msgty.h"
  #include "l1_varex.h"
  #include "l1_proto.h"
  #include "l1_mftab.h"
  #include "l1_tabs.h"
  #include "l1_ver.h"
  #include "l1_trace.h"
  #include "l1_ctl.h"
  #if L2_L3_SIMUL
    #include "l2_l3.h"
    #include "hw_debug.h"
    #include "l2_simul.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
#endif

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

#if W_A_DSP1
extern UWORD8 old_sacch_DSP_bug;
#endif

#if TESTMODE
  #include "l1tm_msgty.h"
  #include "l1tm_signa.h"
  #include "l1tm_varex.h"
  void l1tm_fill_burst (UWORD16 pattern, UWORD16 *TM_ul_data);
  #if (ANLG_FAM != 11)
  void ABB_Write_Uplink_Data(SYS_UWORD16 *TM_ul_data);
  #else
  // TODO
  #endif
#endif

#if ((TRACE_TYPE==2) || (TRACE_TYPE==3))
  extern void L1_trace_string(char *s);
  extern void L1_trace_char  (char s);
#endif

#if (GSM_IDLE_RAM != 0)
#if (OP_L1_STANDALONE == 1)
#include "csmi_simul.h"
#else
#include "csmi/sleep.h"
#endif
#endif

#if (RF_FAM == 61)
  #include "l1_rf61.h"
#if (DRP_FW_EXT==1)
  #include "l1_drp_inc.h"
#else
  #include "drp_drive.h"
#endif
#endif

/*-------------------------------------------------------*/
/* Prototypes of external functions used in this file.   */
/*-------------------------------------------------------*/
void l1dmacro_synchro        (UWORD32 when, UWORD32 value);

void l1dmacro_offset         (UWORD32 offset_value, WORD32 relative_time);
void l1dmacro_rx_synth       (UWORD16 arfcn);
void l1dmacro_agc            (UWORD16 arfcn,WORD8 gain, UWORD8 lna
	                                   #if (RF_FAM == 61)
                                            ,UWORD8 if_ctl
						#endif
							   );
void l1dmacro_rx_nb          (UWORD16 arfcn);
void l1dmacro_afc            (UWORD16 afc_value, UWORD8 win_id);
void l1dmacro_adc_read_rx    (void);
#if (CODE_VERSION != SIMULATION)
#if (L1_MADC_ON ==1)
void l1dmacro_adc_read_rx_cs_mode0(void);
#endif
#endif

#if (RF_FAM != 61)
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);
#endif

#if (RF_FAM == 61)
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, UWORD8 csf_filter_choice, UWORD8 if_ctl
#if (NEW_SNR_THRESHOLD == 1)
                                  ,UWORD8 saic_flag
#endif /* NEW_SNR_THRESHOLD*/
                              );
#endif /* RF_FAM == 61*/

void l1ddsp_meas_read        (UWORD8 nbmeas, UWORD8 *pm);

#if L1_GPRS
void l1pddsp_synchro         (UWORD8 switch_mode, UWORD8  camp_timeslot);
void l1pddsp_load_bcchn_task (UWORD8 tsq,UWORD16 radio_freq);
void l1pddsp_meas_ctrl       (UWORD8 nbmeas, UWORD8 pm_pos);
void l1pddsp_meas_read       (UWORD8 nbmeas, UWORD8 *a_pm);
#if FF_L1_IT_DSP_USF
void l1pddsp_idle_rx_nb      (UWORD8 burst_nb, UWORD8 tsq, UWORD16 radio_freq,
                              UWORD8 timeslot_no, BOOL ptcch_dl, BOOL usf_interrupt);
#else
void l1pddsp_idle_rx_nb      (UWORD8 burst_nb, UWORD8 tsq, UWORD16 radio_freq,
                              UWORD8 timeslot_no, BOOL ptcch_dl);
#endif
#endif

#if (RF_FAM == 61)
void   cust_get_if_dco_ctl_algo (UWORD16* dco_algo_ctl, UWORD8* if_ctl,
  UWORD8 input_level_flag, UWORD8 input_level, UWORD16 radio_freq, UWORD8 if_threshold);
#endif

/* FreeCalypso added feature: TCH tap */
extern BOOL tch_dl_sniff_mode, tch_ul_play_mode;
extern void tch_send_downlink_bits(API *dsp_buffer, UWORD8 nwords,
				   UWORD8 chan_mode, UWORD8 fn_mod_104);
extern void tchf_substitute_uplink(API *dsp_buffer);

//#pragma DUPLICATE_FOR_INTERNAL_RAM_END

extern UWORD16 toa_tab[4];


#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise
  UWORD16 toa_tab[4];
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif


#if TESTMODE
  UWORD16 TM_ul_data[16]; //Uplink data to be stored into Omega Uplink buffer
#endif
#if ((REL99 == 1) && (FF_BHO == 1))
  void l1dtpu_neig_fbsb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off); // Blind handover
#endif

/*-------------------------------------------------------*/
/* l1s_ctrl_hwtest()                                     */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* task HWTEST. This function check the checksum of the  */
/* DSP.                                                  */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_TEST bit in the register.               */
/*-------------------------------------------------------*/
void l1s_ctrl_hwtest(UWORD8 task, UWORD8 param2)
{
  // Flag DSP programmation.
  // ************************
  l1ddsp_load_monit_task(DSP_TASK_CODE[task],0);

  // Set "CTRL_TEST" flag in the controle flag register.
  l1s.dsp_ctrl_reg |= CTRL_TEST;
}

/*-------------------------------------------------------*/
/* l1s_read_hwtest()                                     */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* task HWTEST. This function read the checksum of the   */
/* DSP.                                                  */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register.                       */
/*   -> disable HWTEST task.                             */
/*                                                       */
/* "l1s.task_status[HWTEST].current_status"              */
/*   current task status for HWTEST task.                */
/*   -> disactivate HWTEST task.                         */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_read_hwtest(UWORD8 task, UWORD8 param2)
{
  #if (TRACE_TYPE==2) || (TRACE_TYPE==3)//OMAPS00090550
  UWORD32 flash_type = 0;
  #endif
  xSignalHeaderRec *msg;

  #if (CODE_VERSION != SIMULATION)
    #if (DSP == 33) || (DSP == 34) || (DSP == 35) || (DSP == 36) || (DSP == 37) || (DSP == 38) || (DSP == 39)
      l1s.version.dsp_code_version  = l1s_dsp_com.dsp_ndb_ptr->d_version_number1;
      l1s.version.dsp_checksum      = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[1] & 0xffff);
      l1s.version.dsp_patch_version = l1s_dsp_com.dsp_ndb_ptr->d_version_number2;
    #else
      l1s.version.dsp_code_version  = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[0] & 0xffff);
      l1s.version.dsp_checksum      = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[1] & 0xffff);
    //l1s.version.dsp_patch_version = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[2] & 0xffff);
      l1s.version.dsp_patch_version = (UWORD32) *((API *) SC_CHKSUM_VER);
      //NOTE: dsp_patch_version is duplicated in d_version_number
    #endif
  #endif // NOT_SIMULATION

  // send L1_INIT_HW_CON to L1A...
  msg = os_alloc_sig(sizeof(T_TST_TEST_HW_CON));
  DEBUGMSG(status,NU_ALLOC_ERR)
  msg->SignalCode = L1_TEST_HW_INFO;

  // added for the new naming convention
  ((T_TST_TEST_HW_CON*)(msg->SigP))->dsp_code_version  = l1s.version.dsp_code_version;
  ((T_TST_TEST_HW_CON*)(msg->SigP))->dsp_checksum      = l1s.version.dsp_checksum;
  ((T_TST_TEST_HW_CON*)(msg->SigP))->dsp_patch_version = l1s.version.dsp_patch_version;
  ((T_TST_TEST_HW_CON*)(msg->SigP))->mcu_tcs_program_release = l1s.version.mcu_tcs_program_release;
  ((T_TST_TEST_HW_CON*)(msg->SigP))->mcu_tcs_official        = l1s.version.mcu_tcs_official;
  ((T_TST_TEST_HW_CON*)(msg->SigP))->mcu_tcs_internal        = l1s.version.mcu_tcs_internal;

  os_send_sig(msg, L1C1_QUEUE);

  DEBUGMSG(status,NU_SEND_QUEUE_ERR)

  #if (TRACE_TYPE==2) || (TRACE_TYPE==3)
    uart_trace_checksum(flash_type);
  #endif

  // HWTEST task is completed, make it INACTIVE.
  // It is a 1 shot task, it must be also disabled in L1S.
  l1s.task_status[task].current_status = INACTIVE;
  l1a_l1s_com.l1s_en_task[HWTEST] = TASK_DISABLED;

  // Flag the use of the MCU/DSP dual page read interface.
  // ******************************************************

  // Set flag used to change the read page at the end of "l1_synch" only.
  l1s_dsp_com.dsp_r_page_used = TRUE;
}

/*-------------------------------------------------------*/
/* l1s_new_synchro()                                     */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* task SYNCHRO. This function mainly adapts the L1/TPU  */
/* timebase to a new setting. This new setting can come  */
/* from a timeslot change or a full change of serving    */
/* cell. This change is a big discontinuity, it requires */
/* some global variable reset. Here is a summary of the  */
/* execution:                                            */
/*                                                       */
/*  - Traces for debug.                                  */
/*  - Disables the L1S task SYNCHRO (SYNCHRO is 1 shot)  */
/*    and make it inactive (current status set to        */
/*    INACTIVE).                                         */
/*  - Compute timeshift.                                 */
/*  - Program serving cell fine timeshift for TPU.       */
/*  - Execute serving cell frame number timeshift.       */
/*  - Flag TPU programmation.                            */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1a_l1s_com.tn_difference"                           */
/*   timeslot difference between new and old setting.    */
/*   This is used when timeshift is due to a change of   */
/*   timeslot but on the same serving cell.              */
/*   -> reset to 0.                                      */
/*                                                       */
/* "l1a_l1s_com.Scell_inf.time_alignmt"                  */
/*   fine time difference between current setting and    */
/*   new setting to achieve.                             */
/*   -> reset to 0.                                      */
/*                                                       */
/* "l1a_l1s_com.Scell_inf.fn_offset"                     */
/*   frame number offset between current setting and new */
/*   setting to achieve.                                 */
/*   -> reset to 0.                                      */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for SYNCHRO and OFFSET register in the TPU    */
/*   for current serving cell setting.                   */
/*   -> set to the new setting.                          */
/*                                                       */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register.                       */
/*   -> disable SYNCHRO task.                            */
/*                                                       */
/* "l1s.task_status[SYNCHRO].current_status"             */
/*   current task status for SYNCHRO task.               */
/*   -> disactivate SYNCHRO task.                        */
/*                                                       */
/* "l1s.actual_time, l1s.next_time"                      */
/*   frame number and derived numbers for current frame  */
/*   and next frame.                                     */
/*   -> update to new setting.                           */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_SYNC bit in the register.               */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_new_synchro(UWORD8 param1, UWORD8 param2)
{
  WORD32       offset;
  UWORD32      tpu_offset_shift;
  T_CELL_INFO *sptr = &(l1a_l1s_com.Scell_info);

  // Traces for debug mainly used during L1 simulation.
  // ***************************************************

  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_NEW_SYNCHRO, l1a_l1s_com.Scell_info.radio_freq);
  #endif

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_tpu(dltsk_trace[SYNCHRO].name);
  #endif

  // Disable SYNCHRO task.
  // **********************

  // SYNCHRO task is a one shot task enabled by L1A and
  // disables after its execution in L1S. Here is the disabling.
  l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_DISABLED;
  l1s.task_status[SYNCHRO].current_status = INACTIVE;

  #if 0	/* FreeCalypso TCS211 reconstruction */
  #if L1_GPRS
  //Change of mode when synchro is executed when switching from idle to transfer
  //In this case, PDTCH task has been enabled in transfer mode manager, but the mode is still not PACKET_TRANSFER_MODE
  if((l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) && (l1a_l1s_com.mode != PACKET_TRANSFER_MODE))
    l1a_l1s_com.mode = PACKET_TRANSFER_MODE;
  #endif
  #endif

  // Compute timeshift.
  // *******************

  if(l1a_l1s_com.tn_difference < 0)
  // "tn_difference" field is not 0 only when the new serving cell is the same
  // as the old one. Therefore, we are just changing the timeslot.
  // If the new timeslot if lower than the old one then the serving FN must
  // be incremented by 1. To do so, we use the "fn_offset" field which is
  // loaded with "1".
  {
    sptr->fn_offset += 1;
    l1a_l1s_com.tn_difference += 8;
  }

  // update the TPU with the new TOA if necessary
  l1ctl_update_TPU_with_toa();

  // Manage shifting value for TPU offset register...
  // if staying on the same serving cell but changing the RX timeslot (CCCH_GROUP or timeslot),
  // then the "timeslot difference" between old and new configuration is given in "tn_difference",
  // else "tn_difference" must contain 0.
  tpu_offset_shift = (sptr->time_alignmt) + (l1a_l1s_com.tn_difference * BP_DURATION);

  // Clear "timeslot difference" parameter.
  l1a_l1s_com.tn_difference = 0;

  // Get FN difference between actual synchro and the one we are going to switch to.
  // The switch (slide of OFFSET and REG_COM_INT) is performed at the time "OFFSET - epsilon".
  // If "tpu_offset_shift" is greater than "OFFSET - epsilon (called SWITCH_TIME)" then
  // the next interrupt is going to occur very soon after the switch, and new FN comes directly
  // from current FN + the "fn_offset" (minus 1 since FN has just been incremented). Else 1 frame
  // is missed and new FN comes from "fn_offset + 1" (minus 1 since FN has just been incremented).
  offset = sptr->fn_offset - 1;
  if(tpu_offset_shift <= SWITCH_TIME) offset++;
  #if L1_FF_WA_OMAPS00099442
    if(l1a_l1s_com.change_tpu_offset_flag == TRUE){
      l1s.tpu_offset = (l1s.tpu_offset + (TPU_CLOCK_RANGE >> 1) ) % TPU_CLOCK_RANGE;
      l1a_l1s_com.change_tpu_offset_flag = FALSE;
    }
  #endif

  // Shift "tpu_offset" accordingly to the computed "tpu_offset_shift" value.
  // Rem: "%" is required since the result value can be greater than 2*TPU_CLOCK_RANGE.
  l1s.tpu_offset = (l1s.tpu_offset + tpu_offset_shift) % TPU_CLOCK_RANGE;

  // Program serving cell fine timeshift for TPU.
  // *********************************************

  // Store the fine time shifting program in the MCU/TPU com.
  l1dmacro_synchro(SWITCH_TIME, l1s.tpu_offset);

  // Execute serving cell frame number timeshift.
  // *********************************************

  // Slide frame numbers and derived numbers to jump on new setting.
  l1s_increment_time(&(l1s.actual_time), offset); // Update actual_time.

  l1s.next_time      = l1s.actual_time;
  l1s_increment_time(&(l1s.next_time), 1);        // Next time is actual_time + 1

  #if L1_GPRS
    l1s.next_plus_time = l1s.next_time;
    l1s_increment_time(&(l1s.next_plus_time), 1); // Next_plus time is next_time + 1
  #endif

  #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
    trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550
  #endif

  #if (TOA_ALGO == 2)
    // Fix in case of handovers and Test Mode
    l1s.toa_var.toa_update_fn = l1s.toa_var.toa_update_fn + offset;
    if(l1s.toa_var.toa_update_fn >= MAX_FN)
    {
      l1s.toa_var.toa_update_fn-= MAX_FN;
    }
  #endif



  // the FN was changed: it could have an impact on the gauging algorithm
        //Nina modify to save power, not forbid deep sleep, only force gauging in next paging
	/* FreeCalypso Frankenstein: see l1_async.c regarding Nina's change */
#define	NINA_ADDED	0
#if NINA_ADDED
if(l1s.force_gauging_next_paging_due_to_CCHR != 1)
#endif
{
l1s.pw_mgr.enough_gaug = FALSE;  // forbid Deep sleep until next gauging
}


  // Clear Serving offset and bob.
  sptr->fn_offset    = 0;
  sptr->time_alignmt = 0;

  // Flag TPU programmation.
  // ************************

  // Set "CTRL_SYNC" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_SYNC;

  #if (CODE_VERSION == SIMULATION)
    si_scheduling(MPHC_SCELL_NBCCH_REQ, NULL, TRUE);
    si_scheduling(MPHC_SCELL_EBCCH_REQ, NULL, TRUE);
  #endif

  #if TESTMODE
    // Continuous mode: if we are in continuous mode: return to the no continuous mode.
    if ((l1_config.TestMode) && (l1_config.tmode.rf_params.tmode_continuous == TM_CONTINUOUS))
      l1_config.tmode.rf_params.tmode_continuous = TM_NO_CONTINUOUS;
  #endif

  #if L1_GPRS
    // Signals the GSM->GPRS or GPRS->GSM switch to the DSP.
    // ******************************************************
    l1pddsp_synchro(l1a_l1s_com.dsp_scheduler_mode, l1a_l1s_com.dl_tn);

    // Flag DSP programmation.
    // Set "CTRL_SYNC" flag in the controle flag register.
    l1s.dsp_ctrl_reg |= CTRL_SYNC;
  #endif

  #if (CODE_VERSION == SIMULATION)
    si_scheduling(MPHC_SCELL_NBCCH_REQ, NULL, TRUE);
    si_scheduling(MPHC_SCELL_EBCCH_REQ, NULL, TRUE);
  #endif
}

/*-------------------------------------------------------*/
/* l1s_ctrl_ADC()                                        */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* task ADC. This function program the L1/TPU in order   */
/* to perform an ADC measurement in CS_MODE0             */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_ADC(UWORD8 param1, UWORD8 param2)
{
  // Traces and debug.
  // ******************

  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_CTRL_ADC, (UWORD32)(-1));//OMAPS00090550
  #endif

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[task].name);
  #endif

  //  In CS_MODE0, MPHC_RXLEV_REQ is not received periodically. In case network is not found,
  //the period between 2 MPHC_RXLEV_REQ increases and can be as high as 360 seconds (Max Value)
  // To enable MADC periodically, the function l1dmacro_adc_read_rx_cs_mode0; is called
  #if (CODE_VERSION != SIMULATION)
     #if (L1_MADC_ON ==1)
            if (l1a_l1s_com.mode == CS_MODE0)
                    l1dmacro_adc_read_rx_cs_mode0();
          else
                 l1dmacro_adc_read_rx(); // ADC performed into a rx scenario to have BULON and BULENA signals off so maintaining
                         // low power consumption on ABB
     #else
           l1dmacro_adc_read_rx(); // ADC performed into a rx scenario to have BULON and BULENA signals off so maintaining
                         // low power consumption on ABB
      #endif  // End of L1_MADC_ON == 1
  #else
            l1dmacro_adc_read_rx(); // ADC performed into a rx scenario to have BULON and BULENA signals off so maintaining
                         // low power consumption on ABB
  #endif


  l1s.task_status[ADC_CSMODE0].current_status = INACTIVE;

  if (l1a_l1s_com.adc_mode & ADC_NEXT_CS_MODE0)  // performe ADC only one time
  {
     l1a_l1s_com.adc_mode &= ADC_MASK_RESET_IDLE; // reset in order to have only one ADC measurement in CS_MODE0
     l1a_l1s_com.l1s_en_task[ADC_CSMODE0] = TASK_DISABLED; // disable the ADC task in case of one shot
  }

  // Set "CTRL_MS" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_ADC;
}

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise

/*-------------------------------------------------------*/
/* l1s_abort()                                           */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* task ABORT. When the L1S merge manager routine,       */
/* "l1s_merge_manager()", finds a conflict between a     */
/* running task and a pending task, it can come to       */
/* aborting the running one to start executing the       */
/* pending. Here is the routine which resets the comm.   */
/* between the MCU and the DSP and TPU. The DSP is also  */
/* signaled to abort any ongoing task. Here is a summary */
/* of the execution:                                     */
/*                                                       */
/*  - Traces for debug.                                  */
/*  - Reset MCU/DSP and MCU/TPU communications.          */
/*  - Signals the ABORT process to the DSP.              */
/*  - Flag DSP programmation.                            */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1s.tpu_offset"                                      */
/*   OFFSET/SYNCHRO registers value for current serving  */
/*   cell setting.                                       */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_ABORT bit in the register.              */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_abort(UWORD8 param1, UWORD8 param2)
{
  // Traces for debug.
  // ******************

  #if (TRACE_TYPE==5)
    trace_fct(CST_L1S_ABORT, l1a_l1s_com.Scell_info.radio_freq);
  #endif

  #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
    trace_fct(CST_L1S_ABORT_W0_R0, (UWORD32)(-1));//OMAPS00090550
  #endif

  #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
    if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_L1S_DEBUG)
      Trace_L1s_Abort(trace_info.abort_task);
  #endif

  // Reset MCU/DSP and MCU/TPU communications.
  // ******************************************

  // Reset Hardware...
  // Set "tpu_reset_bit" to 1.
  // Reset DSP write/read page.
  // Reset communication pointers.
  // Immediate Reload offset with Serving one.
  l1d_reset_hw(l1s.tpu_offset);

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  // Signals the ABORT process to the DSP.
  // **************************************

  // Set "b_abort" to TRUE, dsp will reset current and pending tasks.
  l1s_dsp_com.dsp_db_w_ptr->d_ctrl_system |= (1 << B_TASK_ABORT);


  // Tasks are aborted on DSP side => forbid measurements during ABORT
  l1s.forbid_meas = 1;

  // Flag DSP programmation.
  // ************************

  // Set "CTRL_ABORT" flag in the controle flag register.
  l1s.dsp_ctrl_reg |= CTRL_ABORT;
#if (FF_L1_FAST_DECODING == 1)
  /* Reset fast decoding */
  l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE;
  l1a_apihisr_com.fast_decoding.contiguous_decoding = FALSE;
#endif /* #if (FF_L1_FAST_DECODING == 1) */
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif

/*-------------------------------------------------------*/
/* l1s_ctrl_msagc()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: BCCHN,FBNEW,SB1,SB2,SBCONF. This function is   */
/* the control function for making a power measurement   */
/* for refreshing the AGC for those tasks. It programs   */
/* the DSP and the TPU for making 1 measurement in the   */
/* next frame. Here is a summary of the execution:       */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Get the cell information structure.              */
/*    - Traces and debug.                                */
/*    - Programs DSP for measurement task.               */
/*    - Programs TPU for measurement task.               */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   BCCHN, BCCH Neighbor reading task.                  */
/*   FBNEW, Frequency Burst detection task in Idle mode. */
/*   SB1, Synchro Burst reading task in Idle mode.       */
/*   SB2, Synchro Burst detection task in Idle mode.     */
/*   SBCONF, Synchro Burst confirmation task in Idle     */
/*   mode.                                               */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for FBNEW and SB2   */
/*   tasks in Cell Selection only.                       */
/*                                                       */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip this      */
/*   control if L1A has changed or is changing some of   */
/*   the task parameters.                                */
/*                                                       */
/* "l1a_l1s_com.Ncell_info.bcch"                         */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/* "l1a_l1s_com.Ncell_info.conf"                         */
/*   cell information structure used for BCCHN,FBNEW,    */
/*   SB1/SB2,SBCONF respectively.                        */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> incremented.                                     */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_msagc(UWORD8 task, UWORD8 param2)
{
  #if (RF_FAM == 61)
      UWORD16 dco_algo_ctl_pw = 0;
      UWORD8 if_ctl = 0;
//OMAPS00090550	  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  #endif

  if(!(l1a_l1s_com.task_param[task]))
  // Check the task semaphore. The control body is executed only
  // when the task semaphore is 0. This semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters.
  {
    T_NCELL_SINGLE *cell_info_ptr = NULL;
#if (L1_GPRS)
    T_NCELL_SINGLE pbcchn_cell_info;
#endif
#if ((REL99 == 1) && (FF_BHO == 1))
    T_NCELL_SINGLE bho_cell_info;
#endif

    // Get the cell information structure.
    // ************************************

    switch(task)
    {
      case BCCHN:    cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm];break;
      case BCCHN_TOP:cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top];break;
      case FBNEW:    cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id];    break;
      case SB2:      cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id];    break;
      case SBCONF:   cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id];break;

#if ((REL99 == 1) && (FF_BHO == 1))
      case FBSB:
      {
        cell_info_ptr = &bho_cell_info;
        bho_cell_info.radio_freq = l1a_l1s_com.nsync_fbsb.radio_freq;
        bho_cell_info.fn_offset  = l1a_l1s_com.nsync_fbsb.fn_offset;
      }
      break;
#endif

      #if (L1_GPRS)
        case PBCCHN_IDLE:
        {
          cell_info_ptr               = &pbcchn_cell_info;
          pbcchn_cell_info.radio_freq = l1pa_l1ps_com.pbcchn.bcch_carrier;
          pbcchn_cell_info.fn_offset  = l1pa_l1ps_com.pbcchn.fn_offset;
        }
        break;
      #endif
      default: return;
    }

    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_MSAGC, cell_info_ptr->radio_freq);
    #endif

    l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;


    // Programs DSP for measurement task.
    // ***********************************

    // Dsp pgm... (2 measurement).
    #if L1_GPRS
      switch (l1a_l1s_com.dsp_scheduler_mode)
      {
        case GPRS_SCHEDULER:
        {
          l1pddsp_meas_ctrl(2,0);
        } break;

        case GSM_SCHEDULER:
        {
          l1ddsp_load_monit_task(2, 0);
        } break;
      }
    #else
      l1ddsp_load_monit_task(2, 0);
    #endif

  #if (RF_FAM == 61)
   #if (PWMEAS_IF_MODE_FORCE == 0)
      cust_get_if_dco_ctl_algo (&dco_algo_ctl_pw, &if_ctl,
          (UWORD8) L1_IL_INVALID, 0,
          cell_info_ptr->radio_freq,C_IF_ZERO_LOW_THRESHOLD_GSM);//OMAPS00090550
    #else
      if_ctl = IF_120KHZ_DSP;
      dco_algo_ctl_pw = DCO_IF_0KHZ;
    #endif

    // Duplicate the outcome of DCO control as there are 2 PM
    dco_algo_ctl_pw = (((dco_algo_ctl_pw<<2) & 0x0C) | (dco_algo_ctl_pw & 0x03)); // 0000ZLZL
    l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
  #endif

    // Programs TPU for measurement task.
    // ***********************************
         // tpu pgm: measurement only.
     if (task == FBNEW)
     {
         l1dtpu_meas(cell_info_ptr->radio_freq,
                     l1_config.params.high_agc,
                     0,                                 // 0 is set for lna_off = 0
                     l1s.tpu_win,
                     l1s.tpu_offset, INACTIVE
     #if(RF_FAM == 61)
                    ,L1_AFC_NONE
                    ,if_ctl
     #endif
     	                      );
     }
     else
     {
    	     l1dtpu_meas(cell_info_ptr->radio_freq,
                     l1_config.params.high_agc,
                     0,                                 // 0 is set for lna_off = 0
                     l1s.tpu_win,
                     l1s.tpu_offset, INACTIVE
     #if(RF_FAM == 61)
                    ,L1_AFC_SCRIPT_MODE
                    ,if_ctl
     #endif
     	                      );
     }

    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
        buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq,
                        cell_info_ptr->fn_offset, l1s.tpu_win);
      #endif
    #endif

if (task == FBNEW)
{
    // Increment tpu window identifier.
    l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);

    // tpu pgm: measurement only.
    l1dtpu_meas(cell_info_ptr->radio_freq,
                l1_config.params.low_agc,
                0,                          // 0 is set for lna_off = 0
                l1s.tpu_win,
                l1s.tpu_offset,
                INACTIVE
#if(RF_FAM == 61)
                ,L1_AFC_SCRIPT_MODE
                ,if_ctl
#endif
	);
}
else
{
    // Increment tpu window identifier.
    l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);

    // tpu pgm: measurement only.
    l1dtpu_meas(cell_info_ptr->radio_freq,
                l1_config.params.low_agc,
                0,                          // 0 is set for lna_off = 0
                l1s.tpu_win,
                l1s.tpu_offset,
                INACTIVE
#if(RF_FAM == 61)
                ,L1_AFC_SCRIPT_MODE
                ,if_ctl
#endif
	);
}
    // Increment tpu window identifier.
    l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_MS" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_MS;
  l1s.dsp_ctrl_reg |= CTRL_MS;

  // This task is not compatible with Neigh. Measurement. Store task length
  // in "forbid_meas" to indicate when the task will last.
  l1s.forbid_meas = TASK_ROM_MFTAB[task].size;
}

/*-------------------------------------------------------*/
/* l1s_ctrl_fb()                                         */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: FBNEW,FB51. This function is the control       */
/* function for making a frequency burst acquisition on  */
/* a neighbor cell. It programs the DSP and the TPU for  */
/* making 1 attempt in reading the frequency burst.Here  */
/* is a summary of the execution:                        */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Traces and debug.                                */
/*    - Programs DSP for FB acquisition task.            */
/*    - Programs TPU for FB acquisition task.            */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   FBNEW, Frequency Burst detection task in Idle mode. */
/*   FB51, Frequency Burst detection task in Dedicated   */
/*   mode.                                               */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip this      */
/*   control if L1A has changed or is changing some of   */
/*   the task parameters.                                */
/*                                                       */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/*   cell information structure used for FBNEW and FB51  */
/*   tasks.                                              */
/*                                                       */
/* "l1a_l1s_com.fb_mode"                                 */
/*   the frequency burst detection algorithm implemented */
/*   in the DSP uses 2 different modes. The mode to use  */
/*   is indicated by this global variable and is passed  */
/*   to the DSP.                                         */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_fb(UWORD8 task, UWORD8 param2)
{
  WORD8    agc;
  UWORD8   lna_off;
  BOOL     en_task;
  BOOL     task_param;
  UWORD32  dsp_task;
#if (L1_FF_MULTIBAND == 1)
  UWORD16  operative_radio_freq;
#endif


  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

  if((en_task) && !(task_param))
  // Check the task semaphore and enable flag. The control body is executed only
  // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters. The enable can be
  // reset to 0 when the task is no more enabled.
  {
    T_NCELL_SINGLE  *cell_info_ptr = NULL;

    // Get the cell information structure.
    // ************************************
    cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id];

    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_FB, cell_info_ptr->radio_freq);
    #endif

    #if (TRACE_TYPE==5) && FLOWCHART
      trace_flowchart_dsp_tpu(dltsk_trace[task].name);
    #endif

    l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 13) ;

    // Programs DSP for required task.
    // ********************************

    // dsp pgm...

    dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task);

    l1ddsp_load_monit_task(dsp_task, l1a_l1s_com.fb_mode);

    // Programs TPU for required task.
    // ********************************
#if (L1_FF_MULTIBAND == 0)

    // Get AGC to be applied.
    agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq,l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID);
    // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo
    lna_off = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 1 below

    operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq );
    // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo
    lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
    // Get AGC to be applied.
    agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq,l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID);
    
#endif // #if (L1_FF_MULTIBAND == 0) else


    // tpu pgm...
    l1dtpu_neig_fb(cell_info_ptr->radio_freq, agc, lna_off);
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;

  // This task is not compatible with Neigh. Measurement. Store task length
  // in "forbid_meas" to indicate when the task will last.
  // Rem: Only FB51 task starts from this ctrl function.
  if(task==FB51) l1s.forbid_meas = TASK_ROM_MFTAB[task].size;
}


/*-------------------------------------------------------*/
/* l1s_ctrl_fbsb()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: FBSB. This function is the control             */
/* function for making a frequency + synchro burst       */
/* on a neighbor cell in case of blind handover          */
/* It programs the DSP and the TPU for                   */
/* making 1 attempt in reading the frequency & synchro   */
/* burst                                                 */
/* Here is a summary of the execution:                   */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Traces and debug.                                */
/*    - Programs DSP for FB+SB acquisition task.         */
/*    - Programs TPU for FB+SB acquisition task.         */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   FBSB, Frequency + Synchro burst detection task in   */
/*        blind handover                                 */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip this      */
/*   control if L1A has changed or is changing some of   */
/*   the task parameters.                                */
/*                                                       */
/* "l1a_l1s_com.nsync_fbsb"                              */
/*   cell information structure used for FBSB tasks.     */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP        */
/*   interface. This is used mainly to swap then the     */
/*   com. page at the end of a control frame.            */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
#if ((REL99 == 1) && (FF_BHO == 1))
void l1s_ctrl_fbsb(UWORD8 task, UWORD8 param2)
{

  WORD8    agc;
  UWORD8   lna_off;
  UWORD32  dsp_task;
  //added by sajal for DCXO
  UWORD8 input_level;
  #if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_sb = 0;
  UWORD8 if_ctl = 0;
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  #endif
#if (L1_FF_MULTIBAND == 1)
  UWORD16 operative_radio_freq;
#endif
  


  // Traces and debug.
  // ******************

#if (TRACE_TYPE!=0)
  //  trace_fct(CST_L1S_CTRL_FBSB, l1a_l1s_com.nsync_fbsb.radio_freq);
#endif

#if (TRACE_TYPE==5) && FLOWCHART
  trace_flowchart_dsp_tpu(dltsk_trace[task].name);
#endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 13) ;

  // Programs DSP for required task.
  // ********************************

  // dsp pgm...

  dsp_task = l1s_swap_iq_dl(l1a_l1s_com.nsync_fbsb.radio_freq, task);

  l1ddsp_load_monit_task(dsp_task, 1);
#if (L1_FF_MULTIBAND == 0)
  input_level = l1a_l1s_com.last_input_level[l1a_l1s_com.nsync_fbsb.radio_freq - l1_config.std.radio_freq_index_offset].input_level;
#else
	operative_radio_freq = 
	  l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.nsync_fbsb.radio_freq);
	input_level = 
	  l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
#endif

   #if (RF_FAM == 61)   // Locosto DCO
        cust_get_if_dco_ctl_algo(&dco_algo_ctl_sb, &if_ctl, (UWORD8) L1_IL_VALID ,
                                           input_level,
                                             l1a_l1s_com.nsync_fbsb.radio_freq,if_threshold);

	l1ddsp_load_dco_ctl_algo_sb(dco_algo_ctl_sb);
   #endif

  // Programs TPU for required task.
  // ********************************
#if (L1_FF_MULTIBAND == 0)
  
  // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo
  lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.nsync_fbsb.radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

  // Get AGC to be applied.
  agc = Cust_get_agc_from_IL(l1a_l1s_com.nsync_fbsb.radio_freq, l1a_l1s_com.last_input_level[l1a_l1s_com.nsync_fbsb.radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID);

#else // L1_FF_MULTIBAND = 1 below

  /*operative_radio_freq = 
    l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.nsync_fbsb.radio_freq);*/

  // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo
  lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;

  // Get AGC to be applied.
  agc = 
    Cust_get_agc_from_IL(l1a_l1s_com.nsync_fbsb.radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID);

#endif // #if (L1_FF_MULTIBAND == 0) else 

  // tpu pgm...

  l1dtpu_neig_fbsb(l1a_l1s_com.nsync_fbsb.radio_freq, agc, lna_off);

  // Disable Task
// FTH  l1a_l1s_com.l1s_en_task[FBSB] = TASK_DISABLED;

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;
}
#endif //#if ((REL99 == 1) && (FF_BHO == 1))



/*-------------------------------------------------------*/
/* l1s_ctrl_sbgen()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: SB1,SB2,SB51,SBCONF,SBCNF51. This function is  */
/* the control function for making a synchro burst       */
/* reading on a neighbor cell in Cell Selection, Idle    */
/* mode and dedicated mode SDCCH. It programs the DSP    */
/* and the TPU for making 1 attempt in reading the       */
/* synchro burst. Here is a summary of the execution:    */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Get the cell information structure.              */
/*    - Traces and debug.                                */
/*    - Programs DSP for SB reading task.                */
/*    - Programs TPU for SB reading task.                */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   SB1, Synchro Burst reading task in Idle mode.       */
/*   SB2, Synchro Burst detection task in Idle mode.     */
/*   SBCONF, Synchro Burst confirmation task in Idle     */
/*   mode.                                               */
/*   SB51, Synchro Burst reading task in Dedicated mode. */
/*   SBCNF51, Synchro Burst confirmation task in         */
/*   Dedicated mode.                                     */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip this      */
/*   control if L1A has changed or is changing some of   */
/*   the task parameters.                                */
/*                                                       */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/*   cell information structure used for SB1, SB2 and    */
/*   SB51 tasks.                                         */
/*                                                       */
/* "l1a_l1s_com.Ncell_info.conf"                         */
/*   cell information structure used for SBCONF and      */
/*   SBCNF51 tasks.                                      */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for SYNCHRO and OFFSET register in the TPU    */
/*   for current serving cell setting. It is used here   */
/*   by the synchro burst reading TPU driver since this  */
/*   driver changes the OFFSET register. At the end of   */
/*   the task it restores the serving cell offset value. */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_sbgen(UWORD8 task, UWORD8 attempt)
{
  UWORD8   reload_serv_offset = TRUE;   // Default: offset serving reloaded.
  WORD8    agc;
  UWORD8   lna_off;
  BOOL     en_task;
  BOOL     task_param;
  UWORD32  dsp_task;
  UWORD8 input_level;
  #if (RF_FAM == 61)
      UWORD16 dco_algo_ctl_sb = 0;
      UWORD8 if_ctl = 0;
	  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  #endif
#if (L1_FF_MULTIBAND == 1)
  UWORD16 operative_radio_freq;
#endif


  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

  if((en_task) && !(task_param))
  // Check the task semaphore and enable flag. The control body is executed only
  // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters. The enable can be
  // reset to 0 when the task is no more enabled.
  {
    T_NCELL_SINGLE *cell_info_ptr = NULL;

    switch(task)
    {
      case SB2:
      {
        // Get the cell information structure.
        // ************************************
        cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id];

        if(attempt == 1) reload_serv_offset = FALSE; // Offset serving not reloaded on 1st CTRL.

        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1S_CTRL_SB2, cell_info_ptr->radio_freq);
        #endif
      }
      break;

      case SB51:
      {
        // Get the cell information structure.
        // ************************************
        cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id];

        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1S_CTRL_SB51, cell_info_ptr->radio_freq);
        #endif
      }
      break;

      case SBCONF:
      case SBCNF51:
      {
        // Get the cell information structure.
        // ************************************
        cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id];

        #if (TRACE_TYPE!=0)
          if(task == SBCONF)
            trace_fct(CST_L1S_CTRL_SBCONF, cell_info_ptr->radio_freq);
          else
            trace_fct(CST_L1S_CTRL_SBCNF51, cell_info_ptr->radio_freq);
        #endif
#if (L1_EOTD==1)
        // We need to trigger the TOA tracking / adjustment period
        // which logs all TOA updates after E-OTD has started...

        if(l1a_l1s_com.nsync.eotd_meas_session == TRUE)
        {
          if(    (l1a_l1s_com.nsync.eotd_toa_phase == 0)
              && (l1a_l1s_com.nsync.active_sbconf_id == 12) )
          {
            l1a_l1s_com.nsync.eotd_toa_tracking = 0;
            l1a_l1s_com.nsync.eotd_toa_phase = 1;
          }

          l1a_l1s_com.nsync.eotd_cache_toa_tracking = l1a_l1s_com.nsync.eotd_toa_tracking;
        }
#endif


      }
      break;

      default: return;
    }

    // Traces and debug.
    // ******************

    #if (TRACE_TYPE==5) && FLOWCHART
      trace_flowchart_dsp_tpu(dltsk_trace[task].name);
    #endif

    l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 3) ;

    // Programs DSP for required task.
    // ********************************

    // dsp pgm...
    dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task);
    l1ddsp_load_monit_task(dsp_task, 0);

#if (L1_FF_MULTIBAND == 0)
    input_level = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level;
#else // L1_FF_MULTIBAND = 1 below
    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq); 
    input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
#endif //#if (L1_FF_MULTIBAND == 0) else

   #if (RF_FAM == 61)   // Locosto DCO
        cust_get_if_dco_ctl_algo(&dco_algo_ctl_sb, &if_ctl, (UWORD8) L1_IL_VALID ,
                                           input_level,
                                             cell_info_ptr->radio_freq,if_threshold);

     // This is a work-around for a DSP problem (OMAPS00117845)
     // The problem happens during neighbor FB/SB, when there is an
     // IDLE frame between neighbor FB and SB. 
     // Neighbor cell SB(SB2) is different from other kind of SB decode.
     // For SB2 we open the RF window for 2 frames (2 C W W R)
     // For both Control, l1s_dsp_com.dsp_db_common_w_ptr->d_dco_algo_ctrl_sb is updated.
     // However DSP copies DB value to NDB and this value is copied only once.
     // At the end of the first SB, DSP right shifts the NDB variable.
     // The fix below replicates the DCO control information 4 times
     // so that DSP has correct information even after right shifting during first SB.
   
        if(task == SB2)
	 {
	   dco_algo_ctl_sb *= 0x55;
	 }
    



	l1ddsp_load_dco_ctl_algo_sb(dco_algo_ctl_sb);
   #endif

    // Programs TPU for required task.
    // ********************************
#if (L1_FF_MULTIBAND == 0)
    
    // Get AGC to be applied.
    agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, input_level >> 1, AV_ID);
    // lna_off flag is ONLY updated in case of l1ctl_pgc2 control algorithm
    lna_off = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 0 below

    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq); 
    // lna_off flag is ONLY updated in case of l1ctl_pgc2 control algorithm
    lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
    // Get AGC to be applied.
    agc = 
      Cust_get_agc_from_IL(cell_info_ptr->radio_freq, input_level >> 1, AV_ID);

#endif // #if (L1_FF_MULTIBAND == 0) else

    // tpu pgm...
    l1dtpu_neig_sb(cell_info_ptr->radio_freq,
                   agc,
                   lna_off,
                   cell_info_ptr->time_alignmt,
                   l1s.tpu_offset,
                   reload_serv_offset,
                   attempt
                #if (RF_FAM == 61)
                   ,if_ctl
                #endif
	                         );

    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
        buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq,
                        cell_info_ptr->time_alignmt,l1s.tpu_offset);
      #endif
    #endif
  }
  else
  // The task has been disabled or some parameters have changed, the serving tpu offset
  // must be restored.
  {
    if(attempt==2)
    {
      l1dmacro_offset(l1s.tpu_offset,IMM);
    }
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;

  // This task is not compatible with Neigh. Measurement. Store task length
  // in "forbid_meas" to indicate when the task will last.
  // Rem: Only SB51/SBCNF51 tasks start from this ctrl function.
  if((task==SB51)||(task==SBCNF51)) l1s.forbid_meas = TASK_ROM_MFTAB[task].size;
}

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_ctrl_fb26()                                       */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: FB26. This function is the control function    */
/* for making a frequency burst acquisition attempt on   */
/* a neighbor cell in dedicated mode TCH. It programs    */
/* the DSP and the TPU for making 1 attempt in reading   */
/* the frequency burst.Here is a summary of the          */
/* execution:                                            */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Traces and debug.                                */
/*    - Programs DSP for FB acquisition task.            */
/*    - Programs TPU for FB acquisition task.            */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/*   cell information structure used for FB26 task.      */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for SYNCHRO and OFFSET register in the TPU    */
/*   for current serving cell setting. It is used here   */
/*   by the frequency burst reading TPU driver since     */
/*   this driver changes the OFFSET register. At the end */
/*   of the task it restores the serving cell offset     */
/*   value.                                              */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_fb26(UWORD8 param1, UWORD8 param2)
{
  WORD8    agc;
  BOOL     lna_off;
  UWORD32  dsp_task;
  UWORD16  radio_freq = 0;
#if (L1_FF_MULTIBAND == 1)
  UWORD16 operative_radio_freq;
#endif
  
#if (L1_12NEIGH ==1)
  BOOL     en_task;
  BOOL     task_param;

  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[param1];
  task_param = l1a_l1s_com.task_param[param1];

  if((en_task) && !(task_param))
  // Check the task semaphore and enable flag. The control body is executed only
  // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters. The enable can be
  // reset to 0 when the task is no more enabled.
#else
  if(!(l1a_l1s_com.task_param[FB26] == SEMAPHORE_SET))
#endif
  // Check the task semaphore. The control body is executed only
  // when the task semaphore is 0. This semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters.
  {
#if (L1_12NEIGH ==1)
    T_NCELL_SINGLE *cell_info_ptr = NULL;

    cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id];
    radio_freq = cell_info_ptr->radio_freq;
#else
    radio_freq = l1a_l1s_com.nsync.list[0].radio_freq;
#endif
    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_FB26, radio_freq);
    #endif

    #if (TRACE_TYPE==5) && FLOWCHART
      trace_flowchart_dsp_tpu(dltsk_trace[FB26].name);
    #endif

    // Programs DSP for FB26 task.
    // ****************************

    // dsp pgm...

    dsp_task = l1s_swap_iq_dl(radio_freq,FB26);

    l1ddsp_load_monit_task(dsp_task, 1);

    // Programs TPU for FB26 task.
    // ****************************
#if (L1_FF_MULTIBAND == 0)
    
    // agc is just computed from last stored IL
    agc     = Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID);
    lna_off = l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 1 below

    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq);
    lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
    // agc is just computed from last stored IL
    agc     = 
    Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID);

#endif // #if (L1_FF_MULTIBAND == 1) else


    // tpu pgm...
    l1dtpu_neig_fb26(radio_freq,
                     agc,
                     lna_off,
                     l1s.tpu_offset);
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;

  // This task is not compatible with Neigh. Measurement. Store task length
  // in "forbid_meas" to indicate when the task will last.
  // Special case: we set forbid_meas to skip the measurements in the frames
  // FN%26=24 or 25.
  l1s.forbid_meas = 3;
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_ctrl_sb26()                                       */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: SB1,SB2,SB51,SBCONF,SBCNF51. This function is  */
/* the control function for making a synchro burst       */
/* reading on a neighbor cell in Cell Selection, Idle    */
/* mode and dedicated mode SDCCH. It programs the DSP    */
/* and the TPU for making 1 attempt in reading the       */
/* synchro burst. Here is a summary of the execution:    */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Get the cell information structure.              */
/*    - Traces and debug.                                */
/*    - Programs DSP for SB reading task.                */
/*    - Programs TPU for SB reading task.                */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   SB26, Synchro Burst reading task in Dedicated mode, */
/*   TCH.                                                */
/*   SBCNF26, Synchro Burst confirmation task in Dedic.  */
/*   mode TCH.                                           */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/*   cell information structure used for SB26 task.      */
/*                                                       */
/* "l1a_l1s_com.Ncell_info.conf"                         */
/*   cell information structure used for SBCNF26 task.   */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for SYNCHRO and OFFSET register in the TPU    */
/*   for current serving cell setting. It is used here   */
/*   by the synchro burst reading TPU driver since this  */
/*   driver changes the OFFSET register. At the end of   */
/*   the task it restores the serving cell offset value. */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_sb26(UWORD8 task, UWORD8 param2)
{
  UWORD32  nb_nop = 0;
  WORD8    agc;
  BOOL     lna_off;
  UWORD32  dsp_task;
  UWORD8 input_level;
  UWORD32 temp;
#if (L1_FF_MULTIBAND == 1)
  UWORD16 operative_radio_freq;
#endif

#if (L1_12NEIGH ==1)
  BOOL     en_task;
  BOOL     task_param;
#if (RF_FAM == 61)
      UWORD16 dco_algo_ctl_sb = 0;
      UWORD8   if_ctl = 0 ;
	  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
#endif

   // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

 if((en_task) && !(task_param))
#else
  if(!(l1a_l1s_com.task_param[task]))
#endif
  // Check the task semaphore. The control body is executed only
  // when the task semaphore is 0. This semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters.
  {
    UWORD16  radio_freq = 0;
    UWORD32  time_alignmt = 0;
#if (L1_12NEIGH ==1)
    T_NCELL_SINGLE *cell_info_ptr;

    if (task == SB26)
       cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id];
    if (task == SBCNF26)
    {

#if (L1_EOTD==1)
       // We need to trigger the TOA tracking / adjustment period
       // which logs all TOA updates after E-OTD has started...

       if(l1a_l1s_com.nsync.eotd_meas_session == TRUE)
       {
         if(    (l1a_l1s_com.nsync.eotd_toa_phase == 0)
             && (l1a_l1s_com.nsync.active_sbconf_id == 12) )
         {
           l1a_l1s_com.nsync.eotd_toa_tracking = 0;
           l1a_l1s_com.nsync.eotd_toa_phase = 1;
         }

         l1a_l1s_com.nsync.eotd_cache_toa_tracking = l1a_l1s_com.nsync.eotd_toa_tracking;
       }
#endif

       cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id];

    }
    radio_freq   = cell_info_ptr->radio_freq;
    time_alignmt = cell_info_ptr->time_alignmt;

#else
    // Get the cell information.
    // **************************
    radio_freq   = l1a_l1s_com.nsync.list[0].radio_freq;
    time_alignmt = l1a_l1s_com.nsync.list[0].time_alignmt;
#endif
    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0)
      switch(task)
      {
        case SB26:    trace_fct(CST_L1S_CTRL_SB26, radio_freq);    break;
        case SBCNF26: trace_fct(CST_L1S_CTRL_SBCNF26, radio_freq); break;
      }
    #endif

    #if (TRACE_TYPE==5) && FLOWCHART
      trace_flowchart_dsp_tpu(dltsk_trace[task].name);
    #endif

    // Programs DSP for required task.
    // ********************************
    // dsp pgm...

    dsp_task = l1s_swap_iq_dl(radio_freq,task);
    l1ddsp_load_monit_task(dsp_task, 0);

    // Programs TPU for required task.
    // ********************************
  temp = (UWORD32)(l1_config.params.fb26_anchoring_time - EPSILON_SYNC);
  #if (L1_12NEIGH ==1)
      if((cell_info_ptr->sb26_offset == 1) &&
         (time_alignmt >= temp)) //omaps00090550
  #else
      if((l1a_l1s_com.nsync.list[0].sb26_offset == 1) &&
         (time_alignmt >= temp)) //omaps00090550
  #endif
    // SB is in the 2nd frame of the search slot...
    // ...and SB is at the very end of the slot.
    // We insert a nop in the tpu scenario to
    // be able to jump the 1st frame.
    {
      nb_nop = 1;
    }

#if (L1_FF_MULTIBAND == 0)

    // agc is just computed from last stored IL
    input_level = l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].input_level;
    agc     = Cust_get_agc_from_IL(radio_freq, input_level >> 1, AV_ID);
    lna_off = l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 1 below

    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); 
    // agc is just computed from last stored IL
    input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
    lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;    
    agc     = Cust_get_agc_from_IL(radio_freq, input_level >> 1, AV_ID);    

#endif // #if (L1_FF_MULTIBAND == 0) else

    #if (RF_FAM == 61)   // Locosto DCO
       cust_get_if_dco_ctl_algo(&dco_algo_ctl_sb, &if_ctl, (UWORD8) L1_IL_VALID,
                                          input_level,
                                           radio_freq,if_threshold);
      	l1ddsp_load_dco_ctl_algo_sb(dco_algo_ctl_sb);
    #endif

    // tpu pgm...
    l1dtpu_neig_sb26(radio_freq,
                     agc,
                     lna_off,
                     time_alignmt,
                     nb_nop,
                     l1s.tpu_offset
                    #if (RF_FAM == 61)
                    ,if_ctl
                    #endif
                               	);
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;

  // This task is not compatible with Neigh. Measurement. Store task length
  // in "forbid_meas" to indicate when the task will last.
  // Special case: we set forbid_meas to skip the measurements in the frames
  // FN%26=24 or 25.
  l1s.forbid_meas = 3;
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

/*-------------------------------------------------------*/
/* l1s_ctrl_smscb()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: SMSCB. This function is the control function   */
/* for reading a CBCH burst on the serving cell. It      */
/* shifts the OFFSET register to match the normal burst  */
/* receive task with the CBCH timeslot number (0,1,2 or  */
/* 3), programs a normal burst reading and restores the  */
/* OFFSET to the serving cell timeslot 0. On the last    */
/* control (4th burst), the SYNCHRO/OFFSET registers are */
/* shifted back to the normal idle mode PCH reading      */
/* setting. Here is a summary of the execution:          */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Traces and debug.                                */
/*    - Programs DSP for SMSCB task, reading 1 burst.    */
/*    - Programs TPU for SMSCB task, reading 1 burst.    */
/*    - Shift TPU SYNCHRO/OFFSET registers back to the   */
/*      PAGING TASK timeslot.                            */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   SMSCB, Short Message Service Cell Broadcast.        */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.cbch_desc"                               */
/*   Cell Broadcast CHannel description structure.       */
/*                                                       */
/* "l1a_l1s_com.Scell_info.bsic"                         */
/*   BSIC of the serving cell. It is used here to pass   */
/*   the training sequence number (part of BSIC) to the  */
/*   DSP.                                                */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for SMSCB reading   */
/*   task.                                               */
/*                                                       */
/* "l1a_l1s_com.offset_tn0"                              */
/*   value to load in the OFFSET register to shift then  */
/*   any receive task to the timeslot 0 of the serving   */
/*   cell. This is the default setting to restore after  */
/*   any CBCH burst reading.                             */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting. It is used here   */
/*   at the end of the CBCH task controls to restore the */
/*   SYNCHRO/OFFSET registers to the normal setting in   */
/*   idle mode.                                          */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.actual_time, l1s.next_time"                      */
/*   frame number and derived numbers for current frame  */
/*   and next frame.                                     */
/*   -> update to cope with side effect due to synchro.  */
/*      changes/restores.                                */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_smscb(UWORD8 task, UWORD8 burst_id)
{
  UWORD16  rx_radio_freq;
  UWORD32  offset_smscb;
  WORD8    agc;
  UWORD8   lna_off;
  UWORD32  dsp_task;
  static   WORD32 new_tpu_offset;
  static   BOOL   change_synchro;
#if 0	/* FreeCalypso TCS211 reconstruction */
  UWORD8 input_level;
#endif
#if (L1_FF_MULTIBAND == 1)
  UWORD16 operative_radio_freq;
#endif

#if (NEW_SNR_THRESHOLD == 1)
  UWORD8 saic_flag=0;
#endif /* NEW_SNR_THRESHOLD */
#if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_nb = 0;
  UWORD8 if_ctl = 0;
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  // By default we choose the hardware filter
  UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER;
#endif

  // Needed for simulated DSP GRPS scheduler
  #if (CODE_VERSION == SIMULATION)
    UWORD32 tpu_w_page;

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

    hw.rx_id[tpu_w_page][0]=0;
    hw.num_rx[tpu_w_page][0]=1;
    hw.rx_group_id[tpu_w_page]=1;
  #endif


  if((l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) &&
    !(l1a_l1s_com.task_param[task] == SEMAPHORE_SET))
  // Check the task semaphore. The control body is executed only
  // when the task semaphore is 0. This semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters.
  {
    // Get ARFCN to be used for current control. Output of the hopping algorithm.
    rx_radio_freq = l1a_l1s_com.dedic_set.radio_freq;

    // Traces and debug.
    // ******************

    #if (TRACE_TYPE==5) && FLOWCHART
      trace_flowchart_dsp_tpu(dltsk_trace[task].name);
    #endif

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_SMSCB, rx_radio_freq);
    #endif

    l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

    // Programs DSP for SMSCB task according to the DSP scheduler used
    // ****************************************************************

  #if L1_GPRS
    switch(l1a_l1s_com.dsp_scheduler_mode)
    {
      // dsp pgm is made using GSM scheduler...
      case GSM_SCHEDULER:
      {
        dsp_task = l1s_swap_iq_dl(rx_radio_freq, task);

        // dsp pgm...
        l1ddsp_load_rx_task(dsp_task,burst_id,l1a_l1s_com.cbch_desc.tsc);
      }
      break;

      // dsp pgm is made using GPRS scheduler...
      case GPRS_SCHEDULER:
      {
      #if FF_L1_IT_DSP_USF
        l1pddsp_idle_rx_nb(burst_id,l1a_l1s_com.cbch_desc.tsc,rx_radio_freq,0,FALSE,FALSE);
      #else
        l1pddsp_idle_rx_nb(burst_id,l1a_l1s_com.cbch_desc.tsc,rx_radio_freq,0,FALSE);
      #endif
      }
      break;
    }
  #else
    dsp_task = l1s_swap_iq_dl(rx_radio_freq, task);

    // dsp pgm...
    l1ddsp_load_rx_task(dsp_task,burst_id,l1a_l1s_com.cbch_desc.tsc);
 #endif

    // Check if "Synchro" change is needed.
    // *************************************

    // If so the synchro is changed by 4 timeslots.
    if(burst_id == BURST_1)
    {
      // This task is not compatible with Neigh. Measurement. Store task length
      // in "forbid_meas" to indicate when the task will last.
      l1s.forbid_meas = TASK_ROM_MFTAB[task].size;

      change_synchro = l1a_l1s_com.change_synchro_cbch;

      if(change_synchro)
      {
        // compute TPU offset for "current timeslot + 4 timeslot"
        new_tpu_offset = l1s.tpu_offset + (4 * TN_WIDTH);

        if(new_tpu_offset >= TPU_CLOCK_RANGE)
          new_tpu_offset -= TPU_CLOCK_RANGE;

        // Slide synchro to match current timeslot + 4 timeslot.
        l1dmacro_synchro(l1_config.params.rx_change_synchro_time, new_tpu_offset);
      }
      else
      {
        new_tpu_offset = l1s.tpu_offset;
      }
    }

    // Programs TPU for SMSCB task, reading 1 burst.
    // **********************************************

    offset_smscb = new_tpu_offset + l1a_l1s_com.tn_smscb * TN_WIDTH;
    if (offset_smscb >= TPU_CLOCK_RANGE)
      offset_smscb -= TPU_CLOCK_RANGE;

#if 1	/* FreeCalypso match TCS211 */

    // agc is set with the input_level computed from PAGC algo
    agc     = Cust_get_agc_from_IL(l1a_l1s_com.Scell_info.radio_freq, l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, MAX_ID);
    lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#elif (L1_FF_MULTIBAND == 0)

    // agc is set with the input_level computed from PAGC algo
    input_level =  l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].input_level;
    agc     = Cust_get_agc_from_IL(l1a_l1s_com.Scell_info.radio_freq,input_level >> 1, MAX_ID);
    lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 1 below

    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); 
    input_level =  l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
    lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
    agc     = Cust_get_agc_from_IL(l1a_l1s_com.Scell_info.radio_freq,input_level >> 1, MAX_ID);


#endif // #if (L1_FF_MULTIBAND == 0) else

    #if(RF_FAM == 61)   // Locosto DCO
       cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID,
                                                 input_level,
                                                 l1a_l1s_com.Scell_info.radio_freq,if_threshold);

        l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb);
    #endif

    // Store IL used for current CTRL in order to be able to buil IL from pm
    // in READ phase.
#if 1	/* FreeCalypso match TCS211 */

    l1a_l1s_com.Scell_used_IL.input_level = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].input_level;
    l1a_l1s_com.Scell_used_IL.lna_off     = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#elif (L1_FF_MULTIBAND == 0)

    l1a_l1s_com.Scell_used_IL.input_level = input_level;
    l1a_l1s_com.Scell_used_IL.lna_off     = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 1 below    
    
    operative_radio_freq = 
        l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq);
    l1a_l1s_com.Scell_used_IL.input_level = input_level;
    l1a_l1s_com.Scell_used_IL.lna_off     = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;

#endif // #if (L1_FF_MULTIBAND == 1) else    

    #if (L1_SAIC != 0)
      // If SAIC is enabled, call the low level SAIC control function
      csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode
    #if (NEW_SNR_THRESHOLD == 1)
          ,task
          ,&saic_flag
    #endif
          );
    #endif

    // tpu pgm...
    l1dtpu_serv_rx_nb(rx_radio_freq,
                      agc,
                      lna_off,
                      new_tpu_offset,
                      offset_smscb,
                      TRUE,
                      FALSE
                    #if (RF_FAM == 61)
                      ,csf_filter_choice
                      ,if_ctl
                    #endif
                    #if (NEW_SNR_THRESHOLD == 1)
                      ,saic_flag
                    #endif   /* NEW_SNR_THRESHOLD */
      	                            );

  } // End if(task enabled and semaphore false)

  // Remark:
  //--------
  // When the task is aborted, we must continue to make dummy
  // DSP programming to avoid communication mismatch due
  // to C/W/R pipelining.

  // We must also ensure the Synchro back since synchro change has surely be done
  // in the 1st CTRL phase.

  // Shift TPU SYNCHRO/OFFSET registers back to the default timeslot (normally (P)CCCH one).
  // ****************************************************************************************
  // When the CBCH reading control is completed (4 burst controled),
  // the SYNCHRO/OFFSET registers are shifted back to the normal idle
  // setting used for (P)CCCH reading on the serving cell.

  // Check if "Synchro" change was needed.
  // If so the synchro is changed to recover normal synchro.
  if(burst_id == BURST_4)
  {
    if(change_synchro)
    {
      // Slide synchro back to mach current serving timeslot.
      l1dmacro_synchro(SWITCH_TIME, l1s.tpu_offset);

      // Increment frame number.
      #if L1_GPRS
        l1s.actual_time    = l1s.next_time;
        l1s.next_time      = l1s.next_plus_time;
        l1s_increment_time(&(l1s.next_plus_time), 1);  // Increment "next_plus time".
      #else
        l1s.actual_time = l1s.next_time;
        l1s_increment_time(&(l1s.next_time), 1);  // Increment "next time".
      #endif

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550
      #endif

      l1s.tpu_ctrl_reg |= CTRL_SYCB;
      l1s.dsp_ctrl_reg |= CTRL_SYNC;
    }
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;
}

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise

#if 0	/* FreeCalypso TCS211 reconstruction */
UWORD32 qual_acc_idle1[2];
#endif

/*-------------------------------------------------------*/
/* l1s_ctrl_snb_dl()                                     */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* serving cell normal burst reading tasks: NP, EP,      */
/* BCCHS, ALLC, DDL and ADL. This function is the control*/
/* function for reading a normal burst on the serving    */
/* cell. It programs the DSP and the TPU for reading a   */
/* normal burst without change on the TPU OFFSET         */
/* register and flags the reading of the normal paging   */
/* burst. This flag is used by the measurement manager   */
/* "l1s_meas_manager()" at the end of L1S. Here is a     */
/* summary of the execution:                             */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*      - Catch ARFCN and set CIPHERING reduced frame    */
/*        number.                                        */
/*      - Traces and debug.                              */
/*      - Programs DSP for required task.                */
/*      - Programs TPU for required task.                */
/*      - Flag the reading of a Normal Paging burst.     */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   NP, Normal paging reading task.                     */
/*   EP, Extended paging reading task.                   */
/*   BCCHS, BCCH Serving reading task.                   */
/*   ALLC, All serving cell CCCH reading task.           */
/*                                                       */
/*   DDL, SDCCH DOWNLINK reading task.                   */
/*   ADL, SACCH DOWNLINK (associated with SDCCH)reading  */
/*   task.                                               */
/*                                                       */
/* "burst_id"                                            */
/*   BURST_1, 1st burst of the task.                     */
/*   BURST_2, 2nd burst of the task.                     */
/*   BURST_3, 3rd burst of the task.                     */
/*   BURST_4, 4th burst of the task.                     */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.dedic_set"                               */
/*   Dedicated channel parameter structure. It is used   */
/*   to get the ARFCN to use for SDCCH (DDL, ADL). This  */
/*   ARFCN comes from the HOPPING algorithm called just  */
/*   before calling this function.                       */
/*                                                       */
/* "l1a_l1s_com.Scell_info"                              */
/*  Serving cell information structure.                  */
/*    .radio_freq, serving cell beacon frequency.             */
/*    .bsic, BSIC of the serving cell. It is used here   */
/*           to pass the training sequence number (part  */
/*           of BSIC) to the DSP.                        */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for the given task. */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting. It is used here   */
/*   to refresh the TPU SYNCHRO and OFFSET registers     */
/*   with a corrected (time tracking of the serving)     */
/*   value prior to reading a serving cell normal burst. */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.np_ctrl"                                         */
/*   Flag set when a normal paging burst reading is      */
/*   controled. This flag is used by the measurement     */
/*   manager "l1s_meas_manager()", at the end of L1S, to */
/*   scheduling the neighbor cell measurements.          */
/*   -> set to 1.                                        */
/*                                                       */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> incremented.                                     */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_snb_dl(UWORD8 task, UWORD8 burst_id)
{
  UWORD8          lna_off;
  WORD8           agc;
  UWORD16         rx_radio_freq;
  UWORD8          tsc;
  T_INPUT_LEVEL  *IL_info_ptr;
  UWORD32         dsp_task;
  static  BOOL    change_synchro;
  UWORD8          adc_active = INACTIVE;
#if (L1_FF_MULTIBAND == 1)
  UWORD16 operative_radio_freq;
#endif /*L1_FF_MULTIBAND*/
  
#if L1_GPRS
  static  BOOL    algo_change_synchro_active = FALSE;
  static  BOOL    BCCHS_in_transfert = FALSE;
#endif
#if 0	/* FreeCalypso match TCS211 */
  UWORD8 input_level = 0; //omaps00090550
#endif
#if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_nb = 0;
  UWORD8 if_ctl = 0;
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  // By default we choose the hardware filter
  UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER;
#endif
#if (NEW_SNR_THRESHOLD == 1)
  UWORD8 saic_flag=0;
#endif /* NEW_SNR_THRESHOLD */

#if (FF_L1_FAST_DECODING == 1)
  BOOL fast_decoding_authorized = FALSE;

  if ( (burst_id == BURST_1) && (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_FORBIDDEN) )
  {
    l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE;
  }

  fast_decoding_authorized = l1s_check_fast_decoding_authorized(task);

  if ( fast_decoding_authorized && l1s_check_deferred_control(task,burst_id) )
  {
    /* Control is deferred until the upcoming fast decoding IT */
    return;
  } /* if (fast_decoding_authorized)*/

  /* In all other cases, control must be performed now. */
#endif /* FF_L1_FAST_DECODING == 1 */

  if(!(l1a_l1s_com.task_param[task] == SEMAPHORE_SET))
    // Check the task semaphore. The control body is executed only
    // when the task semaphore is 0. This semaphore can be set to
    // 1 whenever L1A makes some changes to the task parameters.
  {
    // Catch ARFCN and set CIPHERING reduced frame number.
    // Catch Training sequence.
    // ****************************************************

    if((task == DDL) || (task == ADL))
      // Dedicated mode SDCCH downlink.
    {
      // Get ARFCN to be used for current control.
      rx_radio_freq = l1a_l1s_com.dedic_set.radio_freq;

      if (rx_radio_freq==l1a_l1s_com.Scell_info.radio_freq) // we are working on a beacon freq.
        IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon;
      else
        IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas;// we are working on a daughter freq

      // Catch training sequence code from the channel description.
      tsc = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->tsc;

      // Set CIPHERING reduced frame number.
#if (AMR == 1)
  #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
        SIG_ONLY_MODE,
        l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
        #if !FF_L1_IT_DSP_DTX
          0, 0, 0, 0, 0, 0);
        #else
          0, 0, 0, 0, 0, 0, 0);
        #endif
  #else
      l1ddsp_load_tch_param(&(l1s.next_time),
        SIG_ONLY_MODE,
        l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
        #if !FF_L1_IT_DSP_DTX
          0, 0, 0, 0);
        #else
          0, 0, 0, 0, 0);
        #endif
  #endif
#else
  #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
        SIG_ONLY_MODE,
        l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
        #if !FF_L1_IT_DSP_DTX
          0, 0, 0, 0, 0);
        #else
          0, 0, 0, 0, 0, 0);
        #endif
  #else
      l1ddsp_load_tch_param(&(l1s.next_time),
        SIG_ONLY_MODE,
        l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
        #if !FF_L1_IT_DSP_DTX
          0, 0, 0);
        #else
          0, 0, 0, 0);
        #endif
  #endif
#endif
      // for SDCCH we use DPAGC algorithm.
#if DPAGC_MAX_FLAG
      agc = Cust_get_agc_from_IL(rx_radio_freq, IL_info_ptr->input_level >> 1, MAX_ID);
#else
      agc = Cust_get_agc_from_IL(rx_radio_freq, IL_info_ptr->input_level >> 1, AV_ID);
#endif
      lna_off = IL_info_ptr->lna_off;



      // Store input_level and lna_off field  used for current CTRL in order to be able to build IL
      // from pm in READ phase.
      l1a_l1s_com.Scell_used_IL = *IL_info_ptr;
    } // end if (task == DDL) || (task == ADL)
    else
    {
      rx_radio_freq = l1a_l1s_com.Scell_info.radio_freq;

      // Catch training sequence code from serving cell BCC (part of BSIC).
      tsc = l1a_l1s_com.Scell_info.bsic & 0x0007;

      // for PCH/E_PCH/Serving BCCH and All CCCH we use
      // PAGC algorithm.
#if 1	/* FreeCalypso match TCS211 */

      agc     = Cust_get_agc_from_IL(rx_radio_freq, l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, MAX_ID);
      lna_off = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

      // Store input_level and lna_off fields used for current CTRL in order to be able
      // to build IL from pm in READ phase.
      l1a_l1s_com.Scell_used_IL = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset];

#elif (L1_FF_MULTIBAND == 0)

      input_level = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].input_level ;
      lna_off = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].lna_off;
      agc     = Cust_get_agc_from_IL(rx_radio_freq, input_level >> 1, MAX_ID);


      // Store input_level and lna_off fields used for current CTRL in order to be able
      // to build IL from pm in READ phase.
      l1a_l1s_com.Scell_used_IL = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset];

#else // L1_FF_MULTIBAND = 1 below

    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(rx_radio_freq);

      input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level ;
      lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
      agc     = Cust_get_agc_from_IL(rx_radio_freq, input_level >> 1, MAX_ID);


      // Store input_level and lna_off fields used for current CTRL in order to be able
      // to build IL from pm in READ phase.
      l1a_l1s_com.Scell_used_IL = l1a_l1s_com.last_input_level[operative_radio_freq];


#endif // #if (L1_FF_MULTIBAND == 0) else

      
    }

   #if(RF_FAM == 61)   // Locosto DCO
          cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID ,
                                                    input_level,
                                                    rx_radio_freq,if_threshold);
          l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb);
   #endif //RF_FAM =61

    #if (L1_SAIC != 0)
      // If SAIC is enabled, call the low level SAIC control function
      csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode
      #if (NEW_SNR_THRESHOLD == 1)
          ,task
          ,&saic_flag
      #endif
          );
   #endif  //L1_SAIC != 0

    // ADC measurement
    // ***************
    // check if during the 1st burst of the bloc an ADC measurement must be performed
    if ((burst_id == BURST_1) && (task == NP))
    {
#if L1_GPRS
      //In case of network mode of operation II or III, CCCH reading is possible
      //in packet idle mode and in packet transfer mode.
      //ADC measurements are already managed by comlex function of Packet idle tasks
      if (!((l1a_l1s_com.l1s_en_task[PNP]    == TASK_ENABLED) ||
        (l1a_l1s_com.l1s_en_task[PEP]    == TASK_ENABLED) ||
        (l1a_l1s_com.l1s_en_task[PALLC]  == TASK_ENABLED) ||
        (l1a_l1s_com.l1s_en_task[PDTCH]  == TASK_ENABLED) ||
        (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED)))
#endif
      {
        adc_active = l1s_ADC_decision_on_NP();
      }
    } // end if (burst_id == BURST_1) && (task == NP)

    if (task == ADL)
    {
      // ADC measurement for SACCH DL
      // ****************************

      // check if during the SACCH burst an ADC measurement must be performed
      if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_DL)  // perform ADC only one time
      {
        adc_active = ACTIVE;
        l1a_l1s_com.adc_mode &= ADC_MASK_RESET_TRAFFIC; // reset in order to have only one ADC measurement in Traffic
      }
      else
      if (l1a_l1s_com.adc_mode & ADC_EACH_TRAFFIC_DL) // perform ADC on each period bloc
      {
        if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period
        {
          adc_active = ACTIVE;
          l1a_l1s_com.adc_cpt = 0;
        }
      }
    }

    // Traces and debug.
    // ******************

#if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[task].name);
#endif

#if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
    trace_fct(CST_L1S_CTRL_SNB_DL_BURST0 + burst_id, (UWORD32)(-1));//OMAPS00090550
#endif

#if (TRACE_TYPE==5)
    trace_fct(CST_L1S_CTRL_SNB_DL, rx_radio_freq);
#endif

    l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

    // the l1a_l1s_com.mode variable could change during the block: So test this variable only on the 1st block
    // See BUG2237 (mode change from Idle to Transfert during BCCHS task)
#if (L1_GPRS)
    if (burst_id == BURST_1)
      BCCHS_in_transfert = ((l1a_l1s_com.mode == PACKET_TRANSFER_MODE) && ((task == EBCCHS) || (task == NBCCHS)));
#endif

    // Programs DSP according to the DSP scheduler used
    // *************************************************


#if (L1_GPRS)
    switch(l1a_l1s_com.dsp_scheduler_mode)
    {
      // dsp pgm is made using GSM scheduler...
    case GSM_SCHEDULER:
#if (FF_L1_FAST_DECODING == 1)
      l1ddsp_load_fast_dec_task(task,burst_id);
#endif
      dsp_task = l1s_swap_iq_dl(rx_radio_freq,task);
      l1ddsp_load_rx_task(dsp_task, burst_id, tsc);
      break;

      // dsp pgm is made using GPRS scheduler...
    case GPRS_SCHEDULER:
#if (FF_L1_FAST_DECODING == 1)
          l1ddsp_load_fast_dec_task(task,burst_id);
#endif
        #if FF_L1_IT_DSP_USF
          l1pddsp_idle_rx_nb(burst_id,tsc,rx_radio_freq,0,FALSE,FALSE);
        #else
          l1pddsp_idle_rx_nb(burst_id,tsc,rx_radio_freq,0,FALSE);
        #endif
      break;
    }
#else
#if (FF_L1_FAST_DECODING == 1)
    l1ddsp_load_fast_dec_task(task,burst_id);
#endif
    dsp_task = l1s_swap_iq_dl(rx_radio_freq,task);
    l1ddsp_load_rx_task(dsp_task, burst_id, tsc);
#endif

    // update the TPU with the new TOA if necessary
    l1ctl_update_TPU_with_toa();

    // Programs TPU for required task.
    // ********************************
#if (L1_GPRS)

    //In case of network mode of operation II or III, CCCH reading is possible
    //in packet idle mode and in packet transfer mode.
    // if (TS(CCCH) - TS(current task))%8 >= 4    synchro change is required
    // if not, OFFSET change is required
    //
    if (((task == EP) || (task == NP)) &&
      ((l1a_l1s_com.l1s_en_task[PNP]    == TASK_ENABLED) ||
      (l1a_l1s_com.l1s_en_task[PEP]    == TASK_ENABLED) ||
      (l1a_l1s_com.l1s_en_task[PALLC]  == TASK_ENABLED) ||
      (l1a_l1s_com.l1s_en_task[PDTCH]  == TASK_ENABLED) ||
      (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED)))
    {
      UWORD32  new_offset;
      WORD32   new_synchro;
      UWORD32  ts_ccch;

      ts_ccch =  (l1a_l1s_com.ccch_group * 2);                //timeslot CCCH burts
      new_offset = (ts_ccch  - l1a_l1s_com.dl_tn + 8) % 8;    //dl_tn is the current time slot from previous task

      if (burst_id == BURST_1)
        l1s.forbid_meas = TASK_ROM_MFTAB[task].size;

      if (new_offset >= 4)
        algo_change_synchro_active = TRUE;

      if (algo_change_synchro_active)
      {
        // compute TPU offset for "current timeslot + 4 timeslot"
        new_synchro = l1s.tpu_offset + (4 * TN_WIDTH);

        if(new_synchro >= TPU_CLOCK_RANGE)
          new_synchro -= TPU_CLOCK_RANGE;

        //compute new offset
        new_offset = (((ts_ccch + 4 - l1a_l1s_com.dl_tn)%8) * TN_WIDTH) + new_synchro;
      }
      //no synchro change required, but new offset is computed
      else
      {
        new_synchro = l1s.tpu_offset;
        new_offset = (new_offset * TN_WIDTH) + new_synchro;
      }

      if (new_offset >= TPU_CLOCK_RANGE)
        new_offset -= TPU_CLOCK_RANGE;

      // tpu pgm...
      l1dtpu_serv_rx_nb(rx_radio_freq,
        agc,
        lna_off,
        new_synchro,
        new_offset,
        TRUE,
        adc_active
        #if (RF_FAM == 61)
	   ,csf_filter_choice
	   ,if_ctl
	#endif
    #if (NEW_SNR_THRESHOLD == 1)
     ,saic_flag
    #endif /*NEW_SNR_THRESHOLD */
        );
    } // end if (task == EP) || (task == NP) in packet Idle

    // in case of EBCCHS and NBCCHS in packet transfer a change synchro is performed
    else if (BCCHS_in_transfert)
    {
      UWORD32  new_offset;
      WORD32   new_synchro;

      change_synchro = ((l1a_l1s_com.dl_tn > 0) && (l1a_l1s_com.dl_tn < 5 ));

      // if change synchro is needed
      if(change_synchro) // TS= [1,2,3,4]
      {
        // the synchro is changed by 4 timeslots.
        new_synchro = l1s.tpu_offset + (4 * TN_WIDTH);
        if(new_synchro >= TPU_CLOCK_RANGE)
          new_synchro -= TPU_CLOCK_RANGE;

        // the TPU offset is changed according to the PDTCH time slot
        // because of the new synchro above with a shift of 4TS,
        // 4TS are substract to the offset
        new_offset  = (8 - 4 - l1a_l1s_com.dl_tn) * TN_WIDTH;
      }
      else
      {
        // the synchro is unchanged
        new_synchro = l1s.tpu_offset;

        // the TPU offset is changed according to the PDTCH time slot
        new_offset  = (8 - l1a_l1s_com.dl_tn) * TN_WIDTH;
      }

      new_offset += new_synchro;
      if (new_offset >= TPU_CLOCK_RANGE)
        new_offset -= TPU_CLOCK_RANGE;

      // tpu pgm...
      #if (RF_FAM == 61)
        l1dtpu_serv_rx_nb(rx_radio_freq,
          agc,
          lna_off,
          new_synchro,
          new_offset,
          TRUE,
          adc_active,
          csf_filter_choice,
          if_ctl
          #if (NEW_SNR_THRESHOLD == 1)
          ,saic_flag
          #endif /*NEW_SNR_THRESHOLD */
          );
	#endif

	#if(RF_FAM != 61)
         l1dtpu_serv_rx_nb(rx_radio_freq,
           agc,
           lna_off,
           new_synchro,
           new_offset,
           TRUE,
           adc_active);
	#endif

    } // end if (task == EBCCHS) || (task == NBCCHS) in packet Idle
    else
#endif
    {
      // tpu pgm...
      #if (RF_FAM == 61)
        l1dtpu_serv_rx_nb(rx_radio_freq,
          agc,
          lna_off,
          l1s.tpu_offset,
          l1s.tpu_offset,
          FALSE,
          adc_active,
          csf_filter_choice,
          if_ctl
          #if (NEW_SNR_THRESHOLD == 1)
          ,saic_flag
          #endif /*NEW_SNR_THRESHOLD */
          );
	#endif
       #if (RF_FAM != 61)
         l1dtpu_serv_rx_nb(rx_radio_freq,
           agc,
           lna_off,
           l1s.tpu_offset,
           l1s.tpu_offset,
           FALSE,
           adc_active);
	#endif
    }

    // Increment tpu window identifier.
    l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD);

    // GSM DSP scheduler is not able to handle PWR too close to RX normal burst.
    // We have to oblige a min of 1 burst period between RX and PWR
    if(l1_config.params.rx_synth_load_split < BP_SPLIT)
      l1s.tpu_win += BP_SPLIT - l1_config.params.rx_synth_load_split;

   #if L2_L3_SIMUL
   #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
       buffer_trace(4, l1s.actual_time.fn, rx_radio_freq,
         l1s.tpu_win,l1s.tpu_offset);
   #endif
   #endif
  }

    #if (L1_GPRS)

    //In case of network mode of operation II or III, CCCH reading is possible
    //in packet idle mode and in packet transfer mode.

    if (((task == EP) || (task == NP)) &&
        ((l1a_l1s_com.l1s_en_task[PNP]    == TASK_ENABLED) ||
         (l1a_l1s_com.l1s_en_task[PEP]    == TASK_ENABLED) ||
         (l1a_l1s_com.l1s_en_task[PALLC]  == TASK_ENABLED) ||
         (l1a_l1s_com.l1s_en_task[PDTCH]  == TASK_ENABLED) ||
         (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED)))
    {
        if((burst_id == BURST_4) && algo_change_synchro_active)
        {

            // Slide synchro back to mach current serving timeslot.
            l1dmacro_synchro(SWITCH_TIME, l1s.tpu_offset);


            // Increment frame number.
            l1s.actual_time    = l1s.next_time;
            l1s.next_time      = l1s.next_plus_time;
            l1s_increment_time (&(l1s.next_plus_time), 1);  // Increment "next_plus time".

            l1s.tpu_ctrl_reg |= CTRL_SYCB;
            l1s.dsp_ctrl_reg |= CTRL_SYNC;
            l1s.ctrl_synch_before = FALSE;
            algo_change_synchro_active = FALSE;

            #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
              trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550
            #endif
        }
    }

    // in case of EBCCHS and NBCCHS in packet transfer a change synchro is performed
    else if (BCCHS_in_transfert)
    {
      // Shift TPU SYNCHRO/OFFSET registers back to the default timeslot .
      // ****************************************************************
      // When the E/NBCCHS reading control is completed ,
      // the SYNCHRO/OFFSET registers are shifted back to the normal
      // setting used for PCCH reading on the serving cell.
      // Check if "Synchro" change was needed.
      // If so the synchro is changed to recover normal synchro.
      if(burst_id == BURST_4)
      {
        if(change_synchro) // TS= [1,2,3,4]
        {
          // Slide synchro back to mach current serving timeslot.
          l1dmacro_synchro(SWITCH_TIME, l1s.tpu_offset);

          // Increment frame number.
          l1s.actual_time    = l1s.next_time;
          l1s.next_time      = l1s.next_plus_time;
          l1s_increment_time(&(l1s.next_plus_time), 1);  // Increment "next_plus time".

          #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
            trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550
          #endif

          l1s.tpu_ctrl_reg |= CTRL_SYCB;
          l1s.dsp_ctrl_reg |= CTRL_SYNC;
        }
      }

      // This task is not compatible with Neigh. Measurement. Store task length
      // in "forbid_meas" to indicate when the task will last.
      if(burst_id == BURST_1)
        l1s.forbid_meas = TASK_ROM_MFTAB[task].size;
    }
  #endif

  // Flag the reading of a Normal Paging burst.
  // *******************************************

  // Set flag "NP contoled !!". Used in "l1_synch()" to generate meas. controles.
  if(task == NP)
     l1a_l1s_com.ba_list.np_ctrl = burst_id+1;

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif

/*-------------------------------------------------------*/
/* l1s_ctrl_snb_ul()                                     */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* serving cell normal burst sending tasks: DUL, AUL.    */
/* This function is the control function for sending a   */
/* burst on a SDCCH channel. It programs the DSP and the */
/* TPU for sending a normal burst taking into account    */
/* the timing adavance. Here is a summary of the         */
/* execution:                                            */
/*                                                       */
/*  - Catch ARFCN.                                       */
/*  - Traces and debug.                                  */
/*  - Programs DSP for required task.                    */
/*  - Catch UL data block from DLL and gives it to DSP.  */
/*  - Programs TPU for required task.                    */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   DUL, SDCCH UPLINK sending task.                     */
/*   AUL, SACCH UPLINK (associated with SDCCH)sending    */
/*   task.                                               */
/*                                                       */
/* "burst_id"                                            */
/*   BURST_1, 1st burst of the task.                     */
/*   BURST_2, 2nd burst of the task.                     */
/*   BURST_3, 3rd burst of the task.                     */
/*   BURST_4, 4th burst of the task.                     */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.dedic_set"                               */
/*   Dedicated channel parameter structure. It is used   */
/*   to get the ARFCN to use for SDCCH (DUL, AUL). This  */
/*   ARFCN comes from the HOPPING algorithm called just  */
/*   before calling this function.                       */
/*                                                       */
/* "l1a_l1s_com.Scell_info"                              */
/*  Serving cell information structure.                  */
/*    .bsic, BSIC of the serving cell. It is used here   */
/*           to pass the training sequence number (part  */
/*           of BSIC) to the DSP.                        */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for the given task. */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting. It is used here   */
/*   to restore this value in the OFFSET register after  */
/*   the TX burst programming.                           */
/*                                                       */
/* "l1s.applied_txpwr"                                   */
/*   Applied transmit power.                             */
/*                                                       */
/* "l1s.reported_txpwr"                                  */
/*   Transmit power to report in the L1 header of the    */
/*   SACCH data block.                                   */
/*                                                       */
/* "l1a_l1s_com.dedic_set.aset"                          */
/*   Active dedicated mode parameter set.                */
/*    .timing_advance, Timing advance to apply to the UL */
/*                     burst transmission.               */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> set to TDMA_WIN3.                                */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_snb_ul(UWORD8 task, UWORD8 burst_id)
{
  T_RADIO_FRAME  *tx_data = NULL;
  UWORD16         tx_radio_freq;
  UWORD32         dsp_task;
  UWORD8          adc_active_ul = INACTIVE;

  // Catch ARFCN.
  // *************

  // Get ARFCN to be used for current control.
  tx_radio_freq = l1a_l1s_com.dedic_set.radio_freq;

  // Traces and debug.
  // ******************

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[task].name);
    if(burst_id == BURST_1) trace_flowchart_dsptx(dltsk_trace[task].name);
  #endif

  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_CTRL_SNB_UL, tx_radio_freq);
  #endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  // Programs DSP for required task.
  // ********************************

  // Set CIPHERING reduced frame number.
  #if (AMR == 1)
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            SIG_ONLY_MODE,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
                          #if !FF_L1_IT_DSP_DTX
                            0, 0, 0, 0, 0, 0);
    #else
                            0, 0, 0, 0, 0, 0, 0);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            SIG_ONLY_MODE,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
                          #if !FF_L1_IT_DSP_DTX
                            0, 0, 0, 0);
                          #else
                            0, 0, 0, 0, 0);
                          #endif
    #endif
  #else
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            SIG_ONLY_MODE,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
                          #if !FF_L1_IT_DSP_DTX
                            0, 0, 0, 0, 0);
                          #else
                            0, 0, 0, 0, 0, 0);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            SIG_ONLY_MODE,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type,
                          #if !FF_L1_IT_DSP_DTX
                            0, 0, 0);
                          #else
                            0, 0, 0, 0);
                          #endif
    #endif
  #endif

  if(task == DUL)
  // SDCCH/UL task.
  {
    if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0)
    // "ho_acc_to_send" is a counter of Handover Access burst still to send.
    // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a
    // Handover command is received from L3 through L1A.
    {
      // TX burst is a RACH.
      // ********************
      // dsp and tpu pgm...
      l1s_ctrl_rach(RAHO,NO_PAR);

      // Decrement number of HO ACCESS burst still to be sent.
      // Rem: (-1) is used for Async. HO.
      if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != -1)
        l1a_l1s_com.dedic_set.aset->ho_acc_to_send --;

      if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0)
      // Handover access procedure is completed.
      // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A.
      {
        l1s_send_ho_finished(HO_COMPLETE);
      }
    }

    else
    {
      // TX burst is a Normal Burst.
      // ****************************
      // dsp pgm...

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr)
      #endif

      dsp_task = l1s_swap_iq_ul(tx_radio_freq,task);

      l1ddsp_load_tx_task(dsp_task,
                          burst_id,
                          l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->tsc);

      // tpu pgm...
      l1dtpu_serv_tx_nb(tx_radio_freq,
                        l1a_l1s_com.dedic_set.aset->timing_advance,
                        l1s.tpu_offset,
                        l1s.applied_txpwr,INACTIVE);

      // Catch UL data block from DLL and gives it to DSP.
      // **************************************************
      // SDCCH info.
      if(burst_id == BURST_1)
      // perform "PH_DATA_REQ" from L2...
      {
        // Get SDCCH/UL data block from L2.
        tx_data = dll_read_dcch(SIG_ONLY_MODE);

        // Store the UL data block in MCU/DSP interface.
        if(tx_data != NULL)  // NULL should never occur !!!
        {
          #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
            RTTL1_FILL_UL_DCCH
            trace_info.facch_ul_count ++;
          #endif

          l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, &(tx_data->A[0]));
        }
      }
    }

    // In any case set TXPWR.
    l1ddsp_load_txpwr(l1s.applied_txpwr, tx_radio_freq);

  }  // End if(task == DUL)

  else
  // SACCH/UL task.
  {

    if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0)
    // "ho_acc_to_send" is a counter of Handover Access burst still to send.
    // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a
    // Handover command is received from L3 through L1A.
    // Rem: it is not allowed to send HO ACCESS burst on SACCH/UL. We must
    // then avoid any normal burst transmission by setting txpwr=NO_TXPWR. The DSP
    // and TPU are controled normally.
    {
      // Set TXPWR.
      l1ddsp_load_txpwr(NO_TXPWR, tx_radio_freq);

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, NO_TXPWR)
      #endif
    }

    else
    {
      // Set TXPWR.
      l1ddsp_load_txpwr(l1s.applied_txpwr, tx_radio_freq);

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr)
      #endif
    }

    //ADC Measurements
    //

    // Check if during the SACCH burst an ADC measurement shall be performed

    if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_UL)  // perform ADC only one time
    {
       adc_active_ul = ACTIVE;
       l1a_l1s_com.adc_mode &= ADC_MASK_RESET_TRAFFIC; // reset in order to have only one ADC measurement in Traffic
    }
    else
    {
      if (l1a_l1s_com.adc_mode & ADC_EACH_TRAFFIC_UL) // perform ADC on each period bloc
      {
        if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period
        {
          adc_active_ul = ACTIVE;
          l1a_l1s_com.adc_cpt = 0;
        }
      }
    }


    // In any case TX burst is a Normal Burst.
    // ****************************************
    // dsp pgm...

    dsp_task = l1s_swap_iq_ul(tx_radio_freq,task);

    l1ddsp_load_tx_task(dsp_task,
                        burst_id,
                        l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->tsc);

    // tpu pgm...
    l1dtpu_serv_tx_nb(tx_radio_freq,
                      l1a_l1s_com.dedic_set.aset->timing_advance,
                      l1s.tpu_offset,
                      l1s.applied_txpwr,adc_active_ul);


    // Catch UL data block from DLL and gives it to DSP.
    // **************************************************
    // SACCH info.
    if(burst_id == BURST_1)
    // perform "PH_DATA_REQ" from L2...
    {

      #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4))
      BOOL tx_data_flag = FALSE; //omaps00090550
      #endif

          #if (FF_REPEATED_SACCH == 1)
	  	    #if TESTMODE
	  	        if(l1_config.repeat_sacch_enable != REPEATED_SACCH_ENABLE) /* disable the repeated sacch mode  */
	  	         {
	  	             l1s.repeated_sacch.sro = 0; /* set no repetition order */
	  	             l1s.repeated_sacch.buffer_empty = TRUE; /* set no buffer */
	  	         }
	  	    #endif /* TESTMODE */
	  #endif /* (FF_REPEATED_SACCH == 1) */
    #if (FF_REPEATED_SACCH == 1)
      /* Get data from PS if only no repetition order is required (1st condition)
         or no repetition candidate exists (2nd condition) */
      if(    (l1s.repeated_sacch.sro == 0) || (l1s.repeated_sacch.buffer_empty == TRUE)    )
{
    #endif  /* (FF_REPEATED_SACCH == 1) */
      tx_data = dll_read_sacch(SIG_ONLY_MODE);

      if(tx_data != NULL)  // NULL should never occur !!!
      {
#if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        tx_data_flag =TRUE;  //omaps00090550
#endif
        // Set L1 Header...
        tx_data->A[0] = l1s.reported_txpwr;
    #if (FF_REPEATED_SACCH == 1)
		/* Include the SACCH Repetition Request (SRR) in the L1 Header */
		tx_data->A[0] |= (l1s.repeated_sacch.srr <<6);

   #endif  /* FF_REPEATED_SACCH */
        tx_data->A[1] = l1a_l1s_com.dedic_set.aset->timing_advance;

        // Store the UL data block in MCU/DSP interface.
        l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, &(tx_data->A[0]));
           #if (FF_REPEATED_SACCH == 1 )
		        /* Store the block data in case of a retransmission order */
		        /* Retransmission is done in case of a SAPI0 and not 3    */
		          if(((tx_data->A[2]&0x1C) >> 2) == SAPI_0)
		          {
		              l1s_store_sacch_buffer( &(l1s.repeated_sacch), &(tx_data->A[0]));
		           }
		          else // FIXME FIXME NOT sure whether this needs to be done
		          {
		            /* the SACCH repetition block occurrence will always come as a consecutive pair */
		            /* To handle DL UL | DL  UL  | DL UL                                             */
		            /*            -               0 | SRO  3  | -   new data should be asked from PS old 0 cannot be repeated */
		                 l1s.repeated_sacch.buffer_empty=TRUE;
		          }
		  #endif /* FF_REPEATED_SACCH */

       }/*  end of   if(tx_data != NULL) */
#if (FF_REPEATED_SACCH == 1)
     }

      else if ((l1s.repeated_sacch.sro == 1) && (l1s.repeated_sacch.buffer_empty == FALSE))
      {
         /*  Put data block in MCU/DSP com.  */
         l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, l1s.repeated_sacch.buffer );
         l1s.repeated_sacch.buffer_empty = TRUE;   /* Set that the buffer is now empty (only one repetition) */
      }
#endif /* FF_REPEATED_SACCH */

      #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4))
          RTTL1_FILL_UL_SACCH(tx_data_flag,l1a_l1s_com.dedic_set.aset->timing_advance, l1s.reported_txpwr)   //omaps00090550
      #endif

    }
  }

  // Set tpu window identifier for Power meas after TX.
  l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split;

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_TX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_TX;
  l1s.dsp_ctrl_reg |= CTRL_TX;
}

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_ctrl_nnb()                                        */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* neigbor cell normal burst reading tasks: BCCHN.       */
/* This function is the control function for reading 4   */
/* normal bursts on a neighbor cell. It programs the DSP */
/* and the TPU for reading the 4 bursts taking into      */
/* account the time difference between the serving and   */
/* the neighbor cells. To this avail, it shifts the TPU  */
/* OFFSET register according to this time difference and */
/* restores the serving offset value when the 4 burst    */
/* reading are completed. Here is a summary of the       */
/* execution:                                            */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*      - Traces and debug.                              */
/*      - Programs DSP for required task.                */
/*      - Programs TPU for required task.                */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   BCCHN, BCCH Neighbor reading task.                  */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.Ncell_info.bcch"                         */
/*   cell information structure used for BCCHN task.     */
/*                                                       */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register. Used here to check if */
/*   the Full BCCH Reading task is enabled and then to   */
/*   take the decision to reloading the serving value    */
/*   in the TPU OFFSET register.                         */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for SYNCHRO and OFFSET register in the TPU    */
/*   for current serving cell setting. At the end of     */
/*   the task this value is restored in the OFFSET       */
/*   register.                                           */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_nnb(UWORD8 task, UWORD8 param2)
{
  UWORD8           lna_off;
  WORD8            agc;
  T_NCELL_SINGLE  *cell_info_ptr = NULL;
  BOOL             en_task;
  BOOL             task_param;
  UWORD32          dsp_task;
#if(L1_FF_MULTIBAND == 1)
 UWORD16 operative_radio_freq;
 UWORD8  input_level;
#endif
  
#if (RF_FAM == 61)
       UWORD16 dco_algo_ctl_nb = 0;
       UWORD8 if_ctl = 0;
	   UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
#endif

  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];



  if((en_task) && !(task_param))
  // Check the task semaphore and enable flag. The control body is executed only
  // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to
  // 1 whenever L1A makes some changes to the task parameters. The enable can be
  // reset to 0 when the task is no more enabled.
  {
    // Get the cell information structure.
    // ************************************
    if (task == BCCHN)
      cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm];
    else // BCCHN_TOP and BCCHN_TRAN tasks
      cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top];

    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_NNB, cell_info_ptr->radio_freq);
    #endif

    #if (TRACE_TYPE==5) && FLOWCHART
      trace_flowchart_dsp_tpu(dltsk_trace[task].name);
    #endif

    l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 6) ;

    // Programs DSP for required task.
    // ********************************

    #if L1_GPRS
      switch(l1a_l1s_com.dsp_scheduler_mode)
      {
        // dsp pgm is made using GSM scheduler...
        case GSM_SCHEDULER:
          dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task);
          l1ddsp_load_rx_task(dsp_task,
                              0,
                              cell_info_ptr->tsc);
        break;

        // dsp pgm is made using GPRS scheduler...
        case GPRS_SCHEDULER:
          l1pddsp_load_bcchn_task(cell_info_ptr->tsc, cell_info_ptr->radio_freq);
        break;
      }
    #else
      // dsp pgm...
      dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task);
      l1ddsp_load_rx_task(dsp_task,
                          0,
                          cell_info_ptr->tsc);
    #endif

    // Programs TPU for required task.
    // ********************************

    // We program 4 burst reading. The OFFSET register is used to
    // cope with the time difference between the serving and the
    // neighbor cells. The serving cell offset value (l1s.tpu_offset)
    // is restored at the end of the 4 burst reading.
#if (L1_FF_MULTIBAND == 0)

    // agc is computed from PGC2 algo result.
    agc     = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID);
    lna_off = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off;

#else // L1_FF_MULTIBAND = 1 below

    operative_radio_freq = 
      l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq);
    lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
    input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
    // agc is computed from PGC2 algo result.
    agc     = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID);

#endif // #if (L1_FF_MULTIBAND == 0) else



    #if(RF_FAM == 61)  // Locosto DCO
        cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID,
#if (L1_FF_MULTIBAND == 0)        
                                       l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level,
#else
                                       input_level,
#endif                                        
                                        cell_info_ptr->radio_freq,if_threshold);

        //dco_algo_ctl has 0000 00ZL
         dco_algo_ctl_nb *= 0x55;   // replicate 0000 00zL as ZLZL ZLZL

        l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb);
    #endif

    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
        buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq,
                        cell_info_ptr->time_alignmt, cell_info_ptr->fn_offset);
      #endif
    #endif

  #if (RF_FAM == 61)
      if ( cell_info_ptr->time_alignmt >= TPU_CLOCK_RANGE - EPSILON_SYNC)
      {
        // Insert 1 NOP to correct the EPSILON_SYNC side effect
        l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                          agc,
                          lna_off,
                          cell_info_ptr->time_alignmt,
                          l1s.tpu_offset,
                          FALSE, 1,
   			     if_ctl
            #if (NEW_SNR_THRESHOLD == 1)
             ,SAIC_OFF
            #endif /* NEW_SNR_THRESHOLD == 1*/
             );
      }
      else
      {
        l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                          agc,
                          lna_off,
                          cell_info_ptr->time_alignmt,
                          l1s.tpu_offset,
                          FALSE, 0,
   			     if_ctl
             #if (NEW_SNR_THRESHOLD == 1)
             ,SAIC_OFF
            #endif /* NEW_SNR_THRESHOLD == 1*/
             );
      }

      l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                        agc,
                        lna_off,
                        cell_info_ptr->time_alignmt,
                        l1s.tpu_offset,
                        FALSE, 0,
   			     if_ctl
             #if (NEW_SNR_THRESHOLD == 1)
             ,SAIC_OFF
            #endif /* NEW_SNR_THRESHOLD == 1*/
             );
      l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                        agc,
                        lna_off,
                        cell_info_ptr->time_alignmt,
                        l1s.tpu_offset,
                        FALSE, 0,
   			     if_ctl
            #if (NEW_SNR_THRESHOLD == 1)
             ,SAIC_OFF
            #endif /* NEW_SNR_THRESHOLD == 1*/
             );
      l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                        agc,
                        lna_off,
                        cell_info_ptr->time_alignmt,
                        l1s.tpu_offset,
                        TRUE, 0,
   			     if_ctl
            #if (NEW_SNR_THRESHOLD == 1)
             ,SAIC_OFF
            #endif /* NEW_SNR_THRESHOLD == 1*/
             );
  #endif // RF_FAM == 61

  #if (RF_FAM != 61)
      if ( cell_info_ptr->time_alignmt >= TPU_CLOCK_RANGE - EPSILON_SYNC)
      {
        // Insert 1 NOP to correct the EPSILON_SYNC side effect
        l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                          agc,
                          lna_off,
                          cell_info_ptr->time_alignmt,
                          l1s.tpu_offset,
                          FALSE, 1);
      }
      else
      {
        l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                          agc,
                          lna_off,
                          cell_info_ptr->time_alignmt,
                          l1s.tpu_offset,
                          FALSE, 0);
      }

      l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                        agc,
                        lna_off,
                        cell_info_ptr->time_alignmt,
                        l1s.tpu_offset,
                        FALSE, 0);
      l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                        agc,
                        lna_off,
                        cell_info_ptr->time_alignmt,
                        l1s.tpu_offset,
                        FALSE, 0);
      l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq,
                        agc,
                        lna_off,
                        cell_info_ptr->time_alignmt,
                        l1s.tpu_offset,
                        TRUE, 0);
  #endif // RF_FAM != 61
  }

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;

  #if L1_GPRS
  // This task is not compatible with Neigh. Measurement. Store task length
  // in "forbid_meas" to indicate when the task will last.
  if(task == BCCHN_TRAN)
  {
    // In IDLE mode, l1s.forbid_meas is setted by the AGC ctrl
    l1s.forbid_meas = TASK_ROM_MFTAB[task].size;
  }
  #endif
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

/*-------------------------------------------------------*/
/* l1s_ctrl_rach()                                       */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* serving cell Random Access burst sending tasks: RAAC, */
/* RAHO. This function is the control function for       */
/* sending a random access burst to the serving cell.    */
/* This sending is either a Channel Request (connection  */
/* establishment) or a Handover Access burst (dedicated  */
/* mode). It programs the DSP and the TPU for sending a  */
/* random access burst with a null timing advance.       */
/* Here is a summary of the execution:                   */
/*                                                       */
/*  - Traces and debug.                                  */
/*  - Programs DSP for required task.                    */
/*  - Build RACH data block and store in MCU/DSP com.    */
/*  - Programs TPU for required task.                    */
/*  - Send confirmation msg to L1A.                      */
/*  - Flag DSP and TPU programmation.                    */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   RAAC, RACH sending task for Channel Request.        */
/*   RAHO, RACH sending task for Handover Access.        */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.Scell_info"                              */
/*  Serving cell information structure.                  */
/*    .bsic, BSIC of the serving cell. It is used here   */
/*           to pass the training sequence number (part  */
/*           of BSIC) to the DSP.                        */
/*    .radio_freq, serving cell beacon frequency.             */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for the given task. */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting. It is used here   */
/*   to restore this value in the OFFSET register after  */
/*   the TX burst programming.                           */
/*                                                       */
/* "l1s.applied_txpwr"                                   */
/*   Applied transmit power.                             */
/*                                                       */
/* "l1a_l1s_com.ra_info"                                 */
/*   random access task parameters.                      */
/*   .channel_request, random number sent in the case    */
/*      of Channel Request (RAAC).                       */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> set to TDMA_WIN3.                                */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_rach(UWORD8 task, UWORD8 param2)
{
  UWORD8   tx_data[2];
  UWORD16  radio_freq=0;
  UWORD32  dsp_task;
  UWORD8   adc_active=INACTIVE;

  // Get ARFCN to be used for current control.
  // *******************************************

  if(task == RAHO)
  // Handover Access...
  {
    // The ARFCN comes from the HOPPING algorithm called
    // prior to calling any CTRL function in the current frame.
    radio_freq = l1a_l1s_com.dedic_set.radio_freq;
  }
  else
  // Network Access...
  {
    #if TESTMODE
      if (l1_config.TestMode)
      {
        // A TX_TCH task has been enabled in TestMode with burst_type=access burst.
        // Thus set radio_freq to tch_arfcn .
        radio_freq = l1_config.tmode.rf_params.tch_arfcn;
      }
      else
    #endif
    {
      // The ARFCN is the BEACON frequency.
      radio_freq = l1a_l1s_com.Scell_info.radio_freq;
    }
  }


  // ADC measurement
  // ***************

  // check if during the RACH an ADC measurement must be performed
  if (task == RAACC)
   if (l1a_l1s_com.adc_mode & ADC_EACH_RACH)  // perform ADC on each burst
       adc_active = ACTIVE;


  // Traces and debug.
  // ******************

  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_CTRL_RACH, radio_freq);
  #endif

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[task].name);
  #endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  #if (CODE_VERSION!=SIMULATION)
    #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
      L1_trace_string("RA");
    #endif
  #endif

  // Programs DSP for required task.
  // ********************************

  // dsp pgm...

  dsp_task = l1s_swap_iq_ul(radio_freq,task);

  l1ddsp_load_ra_task(dsp_task);

  // Set TXPWR.
  l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq);

  // Build RACH data block and store in MCU/DSP com.
  // ************************************************

  // RACH info.
  if(task == RAACC)
  // RACH data is only the "channel_request". (BYTE format data).
  {
    tx_data[0] = (l1a_l1s_com.Scell_info.bsic << 2);
    tx_data[1] = l1a_l1s_com.ra_info.channel_request;

  }
  else
  // RACH data is only the "handover access" (BYTE format data).
  {
    tx_data[0] = (l1a_l1s_com.Scell_info.bsic << 2);
    tx_data[1] = l1a_l1s_com.dedic_set.aset->ho_acc;
  }

  // Store data block in MCU/DSP com.
  l1ddsp_load_info(DSP_TASK_CODE[task], &(l1s_dsp_com.dsp_ndb_ptr->d_rach), &(tx_data[0]));

  // Programs TPU for required task.
  // ********************************

  // tpu pgm...
  l1dtpu_serv_tx_ra(radio_freq, l1s.tpu_offset, l1s.applied_txpwr, adc_active);

  // Set tpu window identifier for Power meas if any.
  l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_ra_load_split + l1_config.params.rx_synth_load_split;

  #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
    RTTL1_FILL_UL_AB(task, l1s.applied_txpwr)
  #endif

  // Flag DSP and TPU programmation.
  // ********************************

  // Set "CTRL_TX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_TX;
  l1s.dsp_ctrl_reg |= CTRL_TX;
}

/*-------------------------------------------------------*/
/* l1s_ctrl_tchtd()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description: This function controls the non transmitting slot in case of Half Rate TCH  */
/* ------------                                          */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_tchtd(UWORD8 task, UWORD8 param2)
{
  T_CHANNEL_DESCRIPTION  *desc_ptr;
  #if FF_L1_IT_DSP_DTX
    BOOL dtx_dsp_interrupt = FALSE;
  #endif

  // Traces and debug.
  // ******************

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[TCHD].name);
  #endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  // Catch channel description.
  // ***************************

  // Catch the active channel description used along the routine.
  // It contains:
  //    "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}.
  //    "subchannel", {0, 1}. 0 is the default value for TCH_F.
  desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

  /**************************************************************************/
  /* TCH/Dummy Receive...                                                   */
  /**************************************************************************/
  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_CTRL_TCHT_DUMMY__DL, l1a_l1s_com.dedic_set.radio_freq);
  #endif

  #if FF_L1_IT_DSP_DTX
    // Fast DTX active only in TCH AHS
    if ((l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE)
        && (l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE))
    {
      // AHS0
      if (desc_ptr->subchannel == 0)
      {
        // DTX interrupt request for B1 and B2 (no DTX uncertainty on B0 thanks to idle frame)
        if (l1s.next_time.fn_mod13 <= 7)
          dtx_dsp_interrupt = TRUE;
      }

      // AHS1
      else
      {
        // DTX interrupt requested for ALL blocks (idle frame does not help)
        dtx_dsp_interrupt = TRUE;
      }
    }
  #endif

  /*--------------------------------------------*/
  /* Program DSP...                             */
  /*--------------------------------------------*/
  // dsp pgm.
  l1ddsp_load_rx_task(DSP_TASK_CODE[task], 0, desc_ptr->tsc);

  /*--------------------------------------------*/
  /* Flag DSP and TPU programmation...          */
  /*--------------------------------------------*/

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.dsp_ctrl_reg |= CTRL_RX;


  /*----------------------------------------------*/
  /* Common for Dedicated mode: DSP parameters... */
  /*----------------------------------------------*/
  #if (AMR == 1)
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            0,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
    #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            dtx_dsp_interrupt);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                          #if !FF_L1_IT_DSP_DTX
                            0);
  #else
                            0,
                            dtx_dsp_interrupt);
                          #endif
    #endif
  #else
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
                          #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            dtx_dsp_interrupt);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_tch);
                          #else
                            l1a_l1s_com.dedic_set.sync_tch,
                            dtx_dsp_interrupt);
                          #endif
    #endif
  #endif

  // Clear "sync_tch" and "reset_sacch" flag to maintain normal TCH process.
  l1a_l1s_com.dedic_set.sync_tch = FALSE;
#if (FF_L1_TCH_VOCODER_CONTROL == 1)
  l1a_l1s_com.dedic_set.reset_sacch = FALSE;
#endif

  // Set tpu window identifier for Power meas in case of dummy burst in Half-rate
  l1s.tpu_win = 0;
}

/*-------------------------------------------------------*/
/* l1s_ctrl_tchth()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* dedicated mode TCH task: TCHTH. This function is the  */
/* control function for reading the DL burst and sending */
/* the UL burst. The UL burst can be a Normal Burst in   */
/* normal case or an Access Burst when starting a        */
/* Handover procedure. Both Half rate and Full rate TCH  */
/* channel are handled. The DSP and the TPU are          */
/* programmed for both the DL and UL bursts. The timing  */
/* advance is taken into account for positionning the UL */
/* burst.                                                */
/*                                                       */
/* This function accesses the L1/DLL and L1/DATA         */
/* interface ("dll_read_dcch()", "tx_tch_data()"         */
/* functions respectively) and passes then the returned  */
/* data blocks to the DSP.                               */
/*                                                       */
/* Here is a summary of the execution:                   */
/*                                                       */
/*  - Traces and debug.                                  */
/*  - Catch channel description and ARFCN.               */
/*  - TCH/T Receive...                                   */
/*      - Program DSP for RX.                            */
/*      - Program TPU for RX.                            */
/*      - Flag DSP and TPU programmation.                */
/*  - TCH/T Transmit...                                  */
/*      - If Any Handover Access burst to send           */
/*          - Call "l1s_ctrl_rach()".                    */
/*      - Else                                           */
/*          - Get DATA block if required for TCH.        */
/*          - Program DSP for TX.                        */
/*          - Program TPU for TX.                        */
/*          - Flag DSP and TPU programmation.            */
/*  - Common for DL/UL: DSP parameters.                  */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   TCHTH, Traffic Channel TCH Half rate.               */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.dedic_set"                               */
/*   Dedicated channel parameter structure.              */
/*     .radio_freq, ARFCN value set by the Hopping algo.      */
/*     .aset, active dedicated parameter set.            */
/*                                                       */
/* "l1a_l1s_com.Scell_info"                              */
/*  Serving cell information structure.                  */
/*    .bsic, BSIC of the serving cell. It is used here   */
/*           to pass the training sequence number (part  */
/*           of BSIC) to the DSP.                        */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for the given task. */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting.                   */
/*                                                       */
/* "l1s.applied_txpwr"                                   */
/*   Applied transmit power.                             */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> set to TDMA_WIN3.                                */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_tchth(UWORD8 task, UWORD8 param2)
{
  UWORD16                 radio_freq=0;
  T_CHANNEL_DESCRIPTION  *desc_ptr;
  UWORD8                  lna_off;
  WORD8                   agc;
  T_INPUT_LEVEL          *IL_info_ptr;
  UWORD32                 dsp_task;
  UWORD32                 fn_mod_52;
  UWORD8 input_level;
#if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_nb = 0;
  UWORD8 if_ctl = 0;
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  // By default we choose the hardware filter
  UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER;
#endif
#if FF_L1_IT_DSP_DTX
  BOOL                    dtx_dsp_interrupt=FALSE; //omaps00090550
#endif
#if (NEW_SNR_THRESHOLD == 1)
  UWORD8 saic_flag=0;
#endif /* NEW_SNR_THRESHOLD */
  // Traces and debug.
  // ******************

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[TCHTH].name);
  #endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  // Catch channel description and ARFCN.
  // *************************************

  // Catch the active channel description used along the routine.
  // It contains:
  //    "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}.
  //    "subchannel", {0, 1}. 0 is the default value for TCH_F.
  desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

  // Get ARFCN to be used for current control. This  ARFCN comes from
  // the HOPPING algorithm called just before calling this function.
  radio_freq = l1a_l1s_com.dedic_set.radio_freq;

  if (radio_freq == l1a_l1s_com.Scell_info.radio_freq)
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon;
                       // we are working on a beacon freq.
  else
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas;
                       // we are working on a daughter freq.

#if FF_L1_IT_DSP_DTX
  // Skip RX DSP/RF programming part during DTX HISR
  if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  {
#endif

  /**************************************************************************/
  /* TCH/T Receive...                                                       */
  /**************************************************************************/
  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_CTRL_TCHTH__DL, radio_freq);
  #endif

  /*--------------------------------------------*/
  /* Program DSP...                             */
  /*--------------------------------------------*/

  dsp_task = l1s_swap_iq_dl(radio_freq,task);

  // dsp pgm.
  l1ddsp_load_rx_task(dsp_task, 0, desc_ptr->tsc);

  // Set TXPWR.
  l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq);

 input_level =  IL_info_ptr->input_level ;

  #if(RF_FAM == 61)   // Locosto DCO
    cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID,
                                              input_level ,
                                              radio_freq,if_threshold);
    l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb);
  #endif

  /*--------------------------------------------*/
  /* Program TPU...                             */
  /*--------------------------------------------*/
  // for TCHTH we use DPAGC algorithm.
  #if DPAGC_MAX_FLAG
    agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, MAX_ID);
  #else
    agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, AV_ID);
  #endif
  lna_off = IL_info_ptr->lna_off;


  // Store input_level and lna_off fields used for current CTRL in order to be able
  // to build IL from pm in READ phase.
  l1a_l1s_com.Scell_used_IL = *IL_info_ptr;

  #if (L1_SAIC != 0)
    // If SAIC is enabled, call the low level SAIC control function
    csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode
    #if (NEW_SNR_THRESHOLD == 1)
        ,task
        ,&saic_flag
    #endif
    );
  #endif

  // update the TPU with the new TOA if necessary
  l1ctl_update_TPU_with_toa();

  // Program a serving cell normal burst reading in TPU.
  #if (RF_FAM == 61)
    l1dtpu_serv_rx_nb(radio_freq,
                    agc,
                    lna_off,
                    l1s.tpu_offset,
                    l1s.tpu_offset,
                    FALSE,INACTIVE, csf_filter_choice, if_ctl
                    #if (NEW_SNR_THRESHOLD == 1)
                    ,saic_flag
                    #endif /*NEW_SNR_THRESHOLD */
                    );
  #endif
  #if (RF_FAM != 61)
    l1dtpu_serv_rx_nb(radio_freq,
                      agc,
                      lna_off,
                      l1s.tpu_offset,
                      l1s.tpu_offset,
                      FALSE,INACTIVE);
  #endif

  // Increment tpu window identifier.
  l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD);

  /*--------------------------------------------*/
  /* Flag DSP and TPU programmation...          */
  /*--------------------------------------------*/

  // Set "CTRL_RX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_RX;
  l1s.dsp_ctrl_reg |= CTRL_RX;
#if FF_L1_IT_DSP_DTX
  } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
#endif

  /**************************************************************************/
  /* TCH/T Transmit...                                                      */
  /**************************************************************************/

  // Any Handover Access burst to send ?
  // ************************************

  if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0)
  // "ho_acc_to_send" is a counter of Handover Access burst still to send.
  // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a
  // Handover command is received from L3 through L1A.
  // We must then replace the TCH UL normal burst by a RACH and decrement
  // this counter.
  {
    if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != -1)
      l1a_l1s_com.dedic_set.aset->ho_acc_to_send --;
    l1s_ctrl_rach(RAHO,NO_PAR);

    if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0)
    // Handover access procedure is completed.
    // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A.
    {
      l1s_send_ho_finished(HO_COMPLETE);
    }
  }
  else
  // TCH/UL is a normal burst.
  {
    UWORD8 channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode;
    //omaps00090550 UWORD8 channel_type = desc_ptr->channel_type;
    UWORD8  subchannel = desc_ptr->subchannel;

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_TCHTH__UL, radio_freq);
    #endif

#if FF_L1_IT_DSP_DTX
  // FACCH and IDS handled during L1S, have to be skipped during DTX HISR
  if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  {
    #endif

    /*--------------------------------------------*/
    /* Get DATA block if required for TCH.        */
    /*--------------------------------------------*/
    // Half rate traffic channel...
    {
      // Rem: time to get data block is
      //      Subchannel 0: FN%26 in {0, 8, 17}.
      //      Subchannel 1: FN%26 in {1, 9, 18}.
      //   => normalised time: FN_normalised = FN%26 - subchannel, in {0, 8, 17}.
      // so CTL: must occur 2 TDMAs before, on
      //      Subchannel 0: FN%26 in {23, 6, 15}.
      //      Subchannel 1: FN%26 in {24, 7, 16}.
      UWORD8  normalised_fn = l1s.next_time.t2 - subchannel;  // FN%26 - subchannel

      if((normalised_fn == 23) || (normalised_fn == 6) || (normalised_fn == 15))
      // It is time to check if a FACCH/UL data block is available from DLL or
      // if a data block is available from the DATA interface.
      {
        T_RADIO_FRAME  *tx_data = NULL;

        // Check if any FACCH to transmit.
        // Rem: when mode is "SIGNALLING ONLY" the "dll_read_dcch()" function
        // always give back a block of FACCH (true block or dummy one).
        tx_data = dll_read_dcch(channel_mode);
        if(tx_data != NULL)
        {
          // In DTX mode in HS, all 6 FACCH 1/2 bursts must always be transmitted.
          // Note: FACCH presence is checked 1 "control" before "control" of 1st burst of FACCH due to a DSP constraint
          // i.e. 3 bursts before FACCH interleaving boundary
          // So we must wait 1 control before controlling the transmission of 6 FACCH 1/2 bursts
          l1s.facch_bursts = 7;

          #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
            RTTL1_FILL_UL_DCCH
            trace_info.facch_ul_count ++;
          #endif

          l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_fu, &(tx_data->A[0]));
          #if (TRACE_TYPE==5) && FLOWCHART
            trace_flowchart_dsptx(dltsk_trace[TCHTH].name);
          #endif
        }

        #if (AMR == 1)
          // Check if any DATA traffic info frame available.
          // This check is used for all full rate channels except when
          // this channel is in SIGNALLING ONLY mode or in Half Rate
          // Speech mode or in adaptative Half Rate mode.
          if((channel_mode != TCH_HS_MODE)  &&
             (channel_mode != TCH_AHS_MODE) &&
             (channel_mode != SIG_ONLY_MODE))
        #else
          // Check if any DATA traffic info frame available.
          // This check is used for all full rate channels except when
          // this channel is in SIGNALLING ONLY mode or in Half Rate
          // Speech mode.
          if((channel_mode != TCH_HS_MODE) && (channel_mode != SIG_ONLY_MODE))
        #endif
        {
          UWORD8  *tx_data = NULL;

          tx_data = tx_tch_data();
          if(tx_data != NULL)
          {
            // Store the DATA/UL data block in the MCU/DSP com. according
            // to the "subchannel".
            if(subchannel == 0) l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_0, tx_data);
            else                l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_1, tx_data);
            #if (TRACE_TYPE==5) && FLOWCHART
              trace_flowchart_dsptx(dltsk_trace[TCHTH].name);
            #endif
          }
        }
      }
    }

#if FF_L1_IT_DSP_DTX
    // Fast DTX active only in TCH AHS
    if ((l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE)
        && (l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE))
    {
      // AHS0
      if (desc_ptr->subchannel == 0)
      {
        // DTX interrupt request for B1 and B2 (no DTX uncertainty on B0 thanks to idle frame)
        if (l1s.next_time.fn_mod13 <= 7)
          dtx_dsp_interrupt = TRUE;

        // DTX uncertainty check
        if  ((l1a_apihisr_com.dtx.fast_dtx_ready == TRUE) &&                   // Fast DTX can be used
             ((l1s.next_time.fn_mod13 == 4) || (l1s.next_time.fn_mod13 == 8))) // new block boundary
          l1a_apihisr_com.dtx.dtx_status = DTX_AWAITED;
      }

      // AHS1
      else
      {
        // DTX interrupt requested for ALL blocks (idle frame does not help)
        dtx_dsp_interrupt = TRUE;

        // DTX uncertainty check
        if  ((l1a_apihisr_com.dtx.fast_dtx_ready == TRUE) &&                   // Fast DTX can be used
             ((l1s.next_time.fn_mod13 == 1) || (l1s.next_time.fn_mod13 == 5)|| (l1s.next_time.fn_mod13 == 9))) // new block boundary
          l1a_apihisr_com.dtx.dtx_status = DTX_AWAITED;
      }
    }
    else
      l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE;
  } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)

  // Postpone TPU/DSP programming when DTX status not available from DSP
  if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
  {
    BOOL tx_active =FALSE; //omaps00090550
#endif
    /*--------------------------------------------*/
    /* Program DSP...                             */
    /*--------------------------------------------*/

    dsp_task = l1s_swap_iq_ul(radio_freq,task);

    l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc);

    /*--------------------------------------------*/
    /* Program TPU...                             */
    /*--------------------------------------------*/

    fn_mod_52   = l1s.actual_time.fn % 52;

    l1s.facch_bursts--;
    if (l1s.facch_bursts < 0)
      l1s.facch_bursts = -1;
  #if FF_L1_IT_DSP_DTX
    // Condition for TX TPU programming channel mode dependant
    switch (channel_mode)
    {
      case SIG_ONLY_MODE:
      case TCH_24H_MODE:
      case TCH_48H_MODE:
        // DTX not supported
        tx_active = TRUE;
        break;

      case TCH_HS_MODE:
        if ((l1s.dtx_ul_on == FALSE) ||                                // No DTX
            ((l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 5)) || // FACCH in progress
            ((subchannel == 0) && ((fn_mod_52 == 51) || (/*(fn_mod_52 >= 0) && omaps00090550*/(fn_mod_52 <= 5)))) || // SID HS0
            ((subchannel == 1) && (fn_mod_52 >= 13) && (fn_mod_52 <= 19)) // SID HS1
           )
          tx_active = TRUE;
        else
          tx_active = FALSE;
        break;

      case TCH_AHS_MODE:
        if (l1a_apihisr_com.dtx.tx_active) // DSP (Fast) DTX status
		tx_active = TRUE;
        else
          tx_active = FALSE;
        break;
    }

    // TPU TX burst programming
    if (tx_active)
  #else

    // In DTX mode, UL bursts should not be transmitted when no voice activity is detected
    // we must not call TPU scenario if dtx_on == TRUE in HS (See Technical Memo)
    // However, in DTX mode, several bursts must always be transmitted (See ETSI 05.08, 8.3)
    if ( (channel_mode != TCH_HS_MODE) ||
         (l1s.dtx_ul_on == FALSE) ||
         ( (l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 5) ) ||
         ( (subchannel == 0) && ((fn_mod_52 == 51) || ((fn_mod_52 >= 0) && (fn_mod_52 <= 5))) ) ||
         ( (subchannel == 1) && (fn_mod_52 >= 13) && (fn_mod_52 <= 19) ))
  #endif
    {
        l1dtpu_serv_tx_nb(radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr,INACTIVE);
    }

    #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
      RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr)
    #endif

  #if FF_L1_IT_DSP_DTX
    } // if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
  #endif
  } // TCH/UL is a normal burst.


#if FF_L1_IT_DSP_DTX
  // Postpone TPU/DSP programming when DTX status not available from DSP
  if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  {
#endif

  /*----------------------------------------------*/
  /* Common for Dedicated mode: DSP parameters... */
  /*----------------------------------------------*/
  #if (AMR == 1)
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.sync_amr,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
    #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            dtx_dsp_interrupt);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_amr);
                          #else
                            l1a_l1s_com.dedic_set.sync_amr,
                            dtx_dsp_interrupt);
                          #endif
    #endif

    // Clear "sync_amr" flag to maintain normal TCH process.
    l1a_l1s_com.dedic_set.sync_amr = FALSE;
  #else
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
    #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            dtx_dsp_interrupt);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_tch);
                          #else
                            l1a_l1s_com.dedic_set.sync_tch,
                            dtx_dsp_interrupt);
                          #endif
    #endif
  #endif

  // reset the FACCH header of the API buffer on the control following an ABORT to avoid decoding unwanted FACCH
  if (l1a_l1s_com.dedic_set.reset_facch == TRUE)
  {
    // Reset A_FD header.
    // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0
    l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1);
    l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff;
  }

  // Clear "sync_tch" and "reset_sacch" flag to maintain normal TCH process.
  l1a_l1s_com.dedic_set.sync_tch = FALSE;
  l1a_l1s_com.dedic_set.reset_facch = FALSE;
#if (FF_L1_TCH_VOCODER_CONTROL == 1)
  l1a_l1s_com.dedic_set.reset_sacch = FALSE;
#endif

  // Set tpu window identifier for Power meas.
  l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split;

  /*--------------------------------------------*/
  /* Flag DSP and TPU programmation...          */
  /*--------------------------------------------*/

  // Set "CTRL_TX" flag in the controle flag register.
  l1s.tpu_ctrl_reg |= CTRL_TX;
  l1s.dsp_ctrl_reg |= CTRL_TX;
#if FF_L1_IT_DSP_DTX
  } //if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
#endif
}

/*-------------------------------------------------------*/
/* l1s_ctrl_tchtf()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* dedicated mode TCH task: TCHTF. This function is the  */
/* control function for reading the DL burst and sending */
/* the UL burst. The UL burst can be a Normal Burst in   */
/* normal case or an Access Burst when starting a        */
/* Handover procedure. Both Half rate and Full rate TCH  */
/* channel are handled. The DSP and the TPU are          */
/* programmed for both the DL and UL bursts. The timing  */
/* advance is taken into account for positionning the UL */
/* burst.                                                */
/*                                                       */
/* This function accesses the L1/DLL and L1/DATA         */
/* interface ("dll_read_dcch()", "tx_tch_data()"         */
/* functions respectively) and passes then the returned  */
/* data blocks to the DSP.                               */
/*                                                       */
/* Here is a summary of the execution:                   */
/*                                                       */
/*  - Traces and debug.                                  */
/*  - Catch channel description and ARFCN.               */
/*  - TCH/T Receive...                                   */
/*      - Program DSP for RX.                            */
/*      - Program TPU for RX.                            */
/*      - Flag DSP and TPU programmation.                */
/*  - TCH/T Transmit...                                  */
/*      - If Any Handover Access burst to send           */
/*          - Call "l1s_ctrl_rach()".                    */
/*      - Else                                           */
/*          - Get DATA block if required for TCH.        */
/*          - Program DSP for TX.                        */
/*          - Program TPU for TX.                        */
/*          - Flag DSP and TPU programmation.            */
/*  - Common for DL/UL: DSP parameters.                  */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   TCHTF, Traffic Channel TCH Full rate.               */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.dedic_set"                               */
/*   Dedicated channel parameter structure.              */
/*     .radio_freq, ARFCN value set by the Hopping algo.      */
/*     .aset, active dedicated parameter set.            */
/*                                                       */
/* "l1a_l1s_com.Scell_info"                              */
/*  Serving cell information structure.                  */
/*    .bsic, BSIC of the serving cell. It is used here   */
/*           to pass the training sequence number (part  */
/*           of BSIC) to the DSP.                        */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for the given task. */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting.                   */
/*                                                       */
/* "l1s.applied_txpwr"                                   */
/*   Applied transmit power.                             */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> set to TDMA_WIN3.                                */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_tchtf(UWORD8 task, UWORD8 param2)
{
  UWORD16                 radio_freq=0;
  T_CHANNEL_DESCRIPTION  *desc_ptr;
  UWORD8                  lna_off;
  WORD8                   agc;
  T_INPUT_LEVEL          *IL_info_ptr;
  UWORD32                 dsp_task;
  UWORD32                 fn_mod_104;
#if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_nb;
  UWORD8 if_ctl =0 ; //omaps00090550
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  // By default we choose the hardware filter
  UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER;
#endif
#if FF_L1_IT_DSP_DTX
  BOOL                    dtx_dsp_interrupt = FALSE;
#endif
#if (NEW_SNR_THRESHOLD == 1)
  UWORD8 saic_flag;
#endif
  // Traces and debug.
  // ******************

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[TCHTF].name);
  #endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  // Catch channel description and ARFCN.
  // *************************************

  // Catch the active channel description used along the routine.
  // It contains:
  //    "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}.
  //    "subchannel", {0, 1}. 0 is the default value for TCH_F.
  desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

  // Get ARFCN to be used for current control. This  ARFCN comes from
  // the HOPPING algorithm called just before calling this function.
  radio_freq = l1a_l1s_com.dedic_set.radio_freq;

  if (radio_freq == l1a_l1s_com.Scell_info.radio_freq)
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon;
                       // we are working on a beacon freq.
  else
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas;
                       // we are working on a daughter freq.

#if FF_L1_IT_DSP_DTX
  // Skip RX DSP/RF programming part during DTX HISR
  if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  {
#endif

  /**************************************************************************/
  /* TCH/T Receive...                                                       */
  /**************************************************************************/
  #if (TRACE_TYPE!=0)
    trace_fct(CST_L1S_CTRL_TCHTF__DL, radio_freq);
  #endif

  /*--------------------------------------------*/
  /* Program DSP...                             */
  /*--------------------------------------------*/
  // dsp pgm.

  dsp_task = l1s_swap_iq_dl(radio_freq,task);

  l1ddsp_load_rx_task(dsp_task, 0, desc_ptr->tsc);

  #if(RF_FAM == 61)  // Locosto DCO
      cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID,
                                         IL_info_ptr->input_level ,
                                          radio_freq,if_threshold);
      l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb);
  #endif

  #if TESTMODE
    // if Normal Mode or
    // if TestMode DL+UL
    // NOTE: UL only true if DL is true in TCHTF!
    if ( !l1_config.TestMode ||
        (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK)))
  #endif
    {
      // Set TXPWR.
      l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq);
    }

  /*--------------------------------------------*/
  /* Program TPU...                             */
  /*--------------------------------------------*/

  // for TCHTF we use DPAGC algorithm.
  #if DPAGC_MAX_FLAG
    agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, MAX_ID);
  #else
    agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, AV_ID);
  #endif
  lna_off = IL_info_ptr->lna_off;


  // Store input_level and lna_off fields used for current CTRL in order to be able
  // to build IL from pm in READ phase.
  l1a_l1s_com.Scell_used_IL = *IL_info_ptr;

  #if (L1_SAIC != 0)
    // If SAIC is enabled, call the low level SAIC control function
    csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode
  #if (NEW_SNR_THRESHOLD == 1)
        ,task
        ,&saic_flag
  #endif
   );
  #endif

  #if TESTMODE
    // Continuous mode: Rx TPU programmation only in NO_CONTINUOUS or START_RX_CONTINUOUS mode.
    if ((!l1_config.TestMode)                                             ||
        (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS)        ||
        (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS))
  #endif
    {
      // update the TPU with the new TOA if necessary
      l1ctl_update_TPU_with_toa();

      // Program a serving cell normal burst reading in TPU.
      l1dtpu_serv_rx_nb(radio_freq,
                        agc,
                        lna_off,
                        l1s.tpu_offset,
                        l1s.tpu_offset,
                        FALSE,INACTIVE
                      #if (RF_FAM == 61)
			    ,csf_filter_choice
			    ,if_ctl
                      #endif
          #if (NEW_SNR_THRESHOLD == 1)
          ,saic_flag
          #endif /*NEW_SNR_THRESHOLD*/
			                 );
    }

  // Increment tpu window identifier.
  l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD);

  /*--------------------------------------------*/
  /* Flag DSP and TPU programmation...          */
  /*--------------------------------------------*/

  // Set "CTRL_RX" flag in the controle flag register.

  #if TESTMODE
    // Continuous mode: swap TPU page for Rx only in NO_CONTINUOUS or START_RX_CONTINUOUS mode.
    if ((!l1_config.TestMode)                                            ||
        (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS)       ||
        (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS))
  #endif
    {
  l1s.tpu_ctrl_reg |= CTRL_RX;
    }
  l1s.dsp_ctrl_reg |= CTRL_RX;
#if FF_L1_IT_DSP_DTX
  } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
#endif

  /**************************************************************************/
  /* TCH/T Transmit...                                                      */
  /**************************************************************************/

  // Any Handover Access burst to send ?
  // ************************************

  if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0)
  // "ho_acc_to_send" is a counter of Handover Access burst still to send.
  // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a
  // Handover command is received from L3 through L1A.
  // We must then replace the TCH UL normal burst by a RACH and decrement
  // this counter.
  {
    if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != -1)
      l1a_l1s_com.dedic_set.aset->ho_acc_to_send --;
    l1s_ctrl_rach(RAHO,NO_PAR);

    if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0)
    // Handover access procedure is completed.
    // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A.
    {
      l1s_send_ho_finished(HO_COMPLETE);
    }
  }
  else
  // TCH/UL is a normal burst.
  {
    UWORD8 channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode;
   //OMAPS00090550 UWORD8 channel_type = desc_ptr->channel_type;

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_CTRL_TCHTF__UL, radio_freq);
    #endif

#if FF_L1_IT_DSP_DTX
  // FACCH and IDS handled during L1S, have to be skipped during DTX HISR
  if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  {
#endif
    /*--------------------------------------------*/
    /* Get DATA block if required for TCH.        */
    /*--------------------------------------------*/
    // Full rate traffic channel...
    {
      UWORD8 fn_report_mod13_mod4 = (l1s.next_time.fn_in_report % 13) % 4;

      if(fn_report_mod13_mod4 == 3)
      // It is time to check if a FACCH/UL data block is available from DLL or
      // if a data block is available from the DATA interface.
      {
        T_RADIO_FRAME  *tx_data = NULL;

        // Check if any FACCH to transmit.
        // Rem: when mode is "SIGNALLING ONLY" the "dll_read_dcch()" function
        // always gives back a block of FACCH (true block or dummy one).
        // In ETM test mode, the protocol stack is not active and hence we do not require any FACCH data from L23
        // But this change is applicable only when ETM scripts are run with PS-builds. In case of L1-SA,
        // dll_read_dcch() is called which is just a stub function (It just returns a NULL ptr for L1 SA)
	/* FreeCalypso: this logic is not present in TCS211 */
	#if 0
        #if TESTMODE
        #if (OP_L1_STANDALONE == 0)
         if(!l1_config.TestMode)
        #endif // (OP_L1_STANDALONE == 0)
        #endif // TESTMODE
	#endif
         {
        tx_data = dll_read_dcch(channel_mode);
         }

        if(tx_data != NULL)
        {
          // In DTX mode in FR and EFR, all 8 FACCH 1/2 bursts must always be transmitted.
          // Note: FACCH presence is checked 1 "control" before "control" of 1st burst of FACCH due to a DSP constraint
          // i.e. 2 bursts before FACCH interleaving boundary
          //So we must wait 1 burst before controlling the transmission of 8 FACCH 1/2 bursts
          l1s.facch_bursts = 9;

          #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
            RTTL1_FILL_UL_DCCH
            trace_info.facch_ul_count ++;
          #endif

          // Store the FACCH/UL data block in the MCU/DSP com.
          #if TRACE_TYPE==3
            if (l1_stats.type == PLAY_UL)
            {
              // load A_DU_1 in PLAY Uplink mode.
              l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_1, &(tx_data->A[0]));


              if (channel_mode == TCH_EFR_MODE)
              {
                WORD32 bit5word14, bit2word14, bit12word15, bit15word15;

                 // clear CRC bits and repetition bits
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[7]  &= 0x807f;
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] &= 0xfc24;
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] &= 0x93ff;
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[19] &= 0xff00;

                // read repetition bits
                bit5word14  = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] >> 5)& 0x1;
                bit2word14  = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] >> 2)& 0x1;
                bit12word15  = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] >> 12) & 0x1;
                bit15word15 = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] >> 15)& 0x1;

                // copy repetition bits
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] |=
                         (bit5word14 << 4 | bit5word14 << 3 |
                          bit2word14 | bit2word14 << 1);

                l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] |=
                         (bit15word15 << 13 | bit12word15 << 14 |
                          bit12word15 << 10 | bit15word15 << 11);
              }
              else
              {
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] &= 0xfc3f;
                l1s_dsp_com.dsp_ndb_ptr->a_du_1[19] &= 0xff00;
              }

              // set PLAY Uplink bit .......
              l1s_dsp_com.dsp_ndb_ptr->d_tch_mode |= (1 << B_PLAY_UL);
            }
            else
              l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_fu, &(tx_data->A[0]));
          #else
            l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_fu, &(tx_data->A[0]));
          #endif
          #if (TRACE_TYPE==5) && FLOWCHART
            trace_flowchart_dsptx(dltsk_trace[TCHTF].name);
          #endif
        }

        #if (AMR == 1)
          // Check if any DATA traffic info frame available.
          // This check is used for all full rate channels except when
          // this channel is in SIGNALLING ONLY mode or in Full Rate
          // Speech mode or adaptative full rate mode.
          if((channel_mode != TCH_FS_MODE)   &&
             (channel_mode != SIG_ONLY_MODE) &&
             (channel_mode != TCH_EFR_MODE)  &&
             (channel_mode != TCH_AFS_MODE))
        #else
          // Check if any DATA traffic info frame available.
          // This check is used for all full rate channels except when
          // this channel is in SIGNALLING ONLY mode or in Full Rate
          // Speech mode.
          if((channel_mode != TCH_FS_MODE)   &&
             (channel_mode != SIG_ONLY_MODE) &&
             (channel_mode != TCH_EFR_MODE))
        #endif
        {
          #if IDS
          {
            UWORD8  fn_report_mod26;
            API *data_ul;

            data_ul = l1s_dsp_com.dsp_ndb_ptr->a_du_0;
            fn_report_mod26 = l1s.next_time.fn_in_report%26;

            // Set flag for UL/DL block information: for TCH/F48 mode only
            if((channel_mode == TCH_48F_MODE) && ((fn_report_mod26 == 7) || (fn_report_mod26 == 16)
                || (fn_report_mod26 == 24)))
              l1s_dsp_com.dsp_ndb_ptr->d_ra_act |= (3 << B_F48BLK);
            else
              l1s_dsp_com.dsp_ndb_ptr->d_ra_act &= ~(3 << B_F48BLK);
            dll_data_ul(l1s_dsp_com.dsp_ndb_ptr->a_data_buf_ul, &l1s_dsp_com.dsp_ndb_ptr->d_ra_conf,
                        &l1s_dsp_com.dsp_ndb_ptr->d_ra_act, &l1s_dsp_com.dsp_ndb_ptr->d_ra_test,
                        &l1s_dsp_com.dsp_ndb_ptr->d_ra_statu, &l1s_dsp_com.dsp_ndb_ptr->d_fax);

            // Fill a_du_0 data block Header.
      // Note: a_du_0 header is fill when dummy block is filled as well when data block
            //       is filled (buffer a_data_buf_ul
            data_ul[0] = (1 << B_BLUD);     // 1st word: Set B_BLU bit.
            data_ul[1] = 0;                 // 2nd word: cleared.
            data_ul[2] = 0;                 // 3rd word: cleared.

          }
          #else
          {
            UWORD8  *tx_data = NULL;

            tx_data = tx_tch_data();
            if(tx_data != NULL)
            {
              // Store the DATA/UL data block in the MCU/DSP com.
              #if TRACE_TYPE==3
                if (l1_stats.type == PLAY_UL)
                {
                  // load A_DU_1 in PLAY Uplink mode.
                  l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_1, tx_data);
                  if (channel_mode == TCH_48F_MODE)
                    l1s_dsp_com.dsp_ndb_ptr->a_du_1[10] &= 0x00ff;
                  if (channel_mode == TCH_24F_MODE)
                    l1s_dsp_com.dsp_ndb_ptr->a_du_1[7]  &= 0x00ff;
                  // set PLAY Uplink bit .......
                  l1s_dsp_com.dsp_ndb_ptr->d_tch_mode |= (1 << B_PLAY_UL);
                }
                else
                  l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_0, tx_data);
              #else
                l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_0, tx_data);
              #endif
            }

            #if (TRACE_TYPE==5) && FLOWCHART
              trace_flowchart_dsptx(dltsk_trace[TCHTF].name);
            #endif
          }
          #endif
        }
        else if (tch_ul_play_mode &&
                 (channel_mode == TCH_FS_MODE || channel_mode == TCH_EFR_MODE))
        {
          tchf_substitute_uplink(l1s_dsp_com.dsp_ndb_ptr->a_du_1);
        }
      }
    }

#if FF_L1_IT_DSP_DTX
    // Fast DTX active only in TCH AFS, for TDMA3 from speech block = 0, 1 [MOD 3]
    if ((l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AFS_MODE)
        && (l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE))
    {
      // DTX interrupt request for B1 and B2 (no DTX uncertainty on B0 thanks to idle frame)
      if (l1s.next_time.fn_mod13 <= 7)
        dtx_dsp_interrupt = TRUE;

      // DTX uncertainty check
      if  ((l1a_apihisr_com.dtx.fast_dtx_ready == TRUE) &&                   // Fast DTX can be used
           ((l1s.next_time.fn_mod13 == 4) || (l1s.next_time.fn_mod13 == 8))) // new block boundary
        l1a_apihisr_com.dtx.dtx_status = DTX_AWAITED;
    }
    else
      l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE;
  } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)

  // Postpone TPU/DSP programming when DTX status not available from DSP
  if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
  {
    BOOL tx_active =FALSE; //omaps00090550
#endif
    #if TESTMODE
      // if Normal Mode or
      // if TestMode and UL+DL
      // NOTE: UL only true if DL is true in TCHTF!
      if ( !l1_config.TestMode ||
          (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK)))
    #endif
      {
        /*--------------------------------------------*/
        /* Program DSP...                             */
        /*--------------------------------------------*/

        dsp_task = l1s_swap_iq_ul(radio_freq,task);

        l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc);

        /*--------------------------------------------*/
        /* Program TPU...                             */
        /*--------------------------------------------*/

        fn_mod_104   = l1s.actual_time.fn % 104;

        #if TESTMODE
          if ((!l1_config.TestMode)                                      ||
              (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) ||
              (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS))
        #endif
          {
            l1s.facch_bursts--;
	    if (l1s.facch_bursts < 0)
	      l1s.facch_bursts = -1;

      #if FF_L1_IT_DSP_DTX
        // Condition for TX TPU programming channel mode dependant
        switch (channel_mode)
        {
          case SIG_ONLY_MODE:
          case TCH_24F_MODE:
          case TCH_48F_MODE:
          case TCH_96_MODE:
          case TCH_144_MODE:
            // DTX not supported
            tx_active = TRUE;
            break;

          case TCH_FS_MODE:
          case TCH_EFR_MODE:
            if ((l1s.dtx_ul_on == FALSE) ||                                // No DTX
                ((l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 7)) || // FACCH in progress
                ((fn_mod_104 >= 51) && (fn_mod_104 <= 58))              // SID
               )
              tx_active = TRUE;
            else
              tx_active = FALSE;
            break;

          case TCH_AFS_MODE:
            if (l1a_apihisr_com.dtx.tx_active) // DSP (Fast) DTX status
	    tx_active = TRUE;
            else
	    tx_active = FALSE;
            break;
        }

        // TPU TX burst programming
        if (tx_active)
      #else
            // In DTX mode, UL bursts should not be transmitted when no voice activity is detected
	    // we must not call TPU scenario if dtx_on == TRUE in EFR and FR (See Technical Memo)
	    // However, in DTX mode, bursts 52 to 59 (modulo 104) must always be transmitted
	    // FACCH must also be transmitted but we must wait 1 bursts before transmitting 8 1/2 bursts
	    if ( ((channel_mode != TCH_FS_MODE) && (channel_mode != TCH_EFR_MODE)) ||
                 (l1s.dtx_ul_on == FALSE) ||
                 ( (l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 7) ) ||
		 ((fn_mod_104 >= 51) && (fn_mod_104 <= 58)) )
      #endif
            {
             l1dtpu_serv_tx_nb(radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr,INACTIVE);
            }
          }

        #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
          RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr)
        #endif

    }
  #if FF_L1_IT_DSP_DTX
    } // if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
  #endif
  } // TCH/UL is a normal burst.
#if FF_L1_IT_DSP_DTX
  // Postpone TPU/DSP programming when DTX status not available from DSP
  if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  {
#endif

  /*----------------------------------------------*/
  /* Common for Dedicated mode: DSP parameters... */
  /*----------------------------------------------*/
  #if (AMR == 1)
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            0,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.sync_amr,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
    #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            dtx_dsp_interrupt);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            0,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_amr);
                          #else
                            l1a_l1s_com.dedic_set.sync_amr,
                            dtx_dsp_interrupt);
                          #endif
    #endif

    // Clear "sync_amr" flag to maintain normal TCH process.
    l1a_l1s_com.dedic_set.sync_amr = FALSE;
  #else
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            0,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
    #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            dtx_dsp_interrupt);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            0,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_tch);
                          #else
                            l1a_l1s_com.dedic_set.sync_tch,
                            dtx_dsp_interrupt);
                          #endif
    #endif
  #endif

  // reset the FACCH header of the API buffer on the control following an ABORT to avoid decoding unwanted FACCH
  if (l1a_l1s_com.dedic_set.reset_facch == TRUE)
  {
    // Reset A_FD header.
    // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0
    l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1);
    l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff;
  }

  // Clear "sync_tch" and "reset_sacch" flag to maintain normal TCH process.
  l1a_l1s_com.dedic_set.sync_tch = FALSE;
  l1a_l1s_com.dedic_set.reset_facch = FALSE;
#if (FF_L1_TCH_VOCODER_CONTROL == 1)
  l1a_l1s_com.dedic_set.reset_sacch = FALSE;
#endif

  // Set tpu window identifier for Power meas or FS/SB search.
  l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split;

  /*--------------------------------------------*/
  /* Flag DSP and TPU programmation...          */
  /*--------------------------------------------*/

  #if TESTMODE
    // if Normal Mode or
    // if TestMode and UL+DL
    // NOTE: UL only true if DL is true in TCHTF!
    if ( !l1_config.TestMode ||
       (  l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK)))
  #endif
    {
      #if TESTMODE
        // Continuous mode: swap TPU page for Tx in NO_CONTINUOUS or START_TX_CONTINUOUS mode.
        if ((!l1_config.TestMode)                                      ||
            (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) ||
            (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS))
      #endif
        {
          l1s.tpu_ctrl_reg |= CTRL_TX;
        }
      l1s.dsp_ctrl_reg |= CTRL_TX;
    }

  #if TESTMODE
    // Continuous mode: if end of control of START_RX/TX: go to CONTINUOUS state
    if (l1_config.TestMode && (l1_config.tmode.rf_params.tmode_continuous != TM_NO_CONTINUOUS))
      l1_config.tmode.rf_params.tmode_continuous = TM_CONTINUOUS;
  #endif
#if FF_L1_IT_DSP_DTX
  } //if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
  #endif
}

/*-------------------------------------------------------*/
/* l1s_ctrl_tcha()                                       */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* dedicated mode TCH task: TCHA. This function is the   */
/* control function for reading the DL burst and sending */
/* the UL burst on the Slow Associated Channel (SACCH)   */
/* associated with the traffic channel. The UL burst can */
/* be a Normal Burst in normal case or an Access Burst   */
/* when starting a Handover procedure. Both Half rate    */
/* and Full rate TCH channel are handled. The DSP and    */
/* the TPU are programmed for both the DL and UL bursts. */
/* The timing advance is taken into account for          */
/* positionning the UL burst.                            */
/*                                                       */
/* This function accesses the L1/DLL interface           */
/* ("dll_read_sacch()" function) and passes then the     */
/* returned data blocks to the DSP after having set the  */
/* L1 header part of the block.                          */
/*                                                       */
/* Here is a summary of the execution:                   */
/*                                                       */
/*  - Traces and debug.                                  */
/*  - Catch channel description and ARFCN.               */
/*  - TCH/SACCH Receive...                               */
/*      - Program DSP for RX.                            */
/*      - Program TPU for RX.                            */
/*      - Flag DSP and TPU programmation.                */
/*  - TCH/SACCH Transmit...                              */
/*      - If Any Handover Access burst to send           */
/*          - Call "l1s_ctrl_rach()".                    */
/*      - Else                                           */
/*          - Get DATA block from DLL if required.       */
/*          - Program DSP for TX.                        */
/*          - Program TPU for TX.                        */
/*          - Flag DSP and TPU programmation.            */
/*  - Common for DL/UL: DSP parameters.                  */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   TCHA, Associated channel task when dedicated/TCH.   */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.dedic_set"                               */
/*   Dedicated channel parameter structure.              */
/*     .radio_freq, ARFCN value set by the Hopping algo.      */
/*     .aset, active dedicated parameter set.            */
/*                                                       */
/* "l1a_l1s_com.Scell_info"                              */
/*  Serving cell information structure.                  */
/*    .bsic, BSIC of the serving cell. It is used here   */
/*           to pass the training sequence number (part  */
/*           of BSIC) to the DSP.                        */
/*                                                       */
/* "l1s.afc"                                             */
/*   current AFC value to be applied for the given task. */
/*                                                       */
/* "l1s.tpu_offset"                                      */
/*   value for the TPU SYNCHRO and OFFSET registers      */
/*   for current serving cell setting.                   */
/*                                                       */
/* "l1s.applied_txpwr"                                   */
/*   Applied transmit power.                             */
/*                                                       */
/* "l1s.reported_txpwr"                                  */
/*   Transmit power to report in the L1 header of the    */
/*   SACCH data block.                                   */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.tpu_win"                                         */
/*   each frame is composed with a maximum of 3          */
/*   working/TPU windows (typically RX/TX/PW). This is   */
/*   a counter used to count the number of windows       */
/*   used.                                               */
/*   -> set to TDMA_WIN3.                                */
/*                                                       */
/* "l1s.tpu_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/TPU com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/* "l1s.dsp_ctrl_reg"                                    */
/*   bit register used to know at the end of L1S if      */
/*   something has been programmed on the MCU/DSP com.   */
/*   This is used mainly to swap then the com. page at   */
/*   the end of a control frame.                         */
/*   -> set CTRL_RX bit in the register.                 */
/*   -> set CTRL_TX bit in the register.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_ctrl_tcha(UWORD8 task, UWORD8 param2)
{
  UWORD16                radio_freq=0;
  T_CHANNEL_DESCRIPTION *desc_ptr;
  UWORD8                 lna_off =0;//omaps00090550
  WORD8                  agc =0; //omaps00090550
  T_INPUT_LEVEL         *IL_info_ptr;
  UWORD32                dsp_task;
  UWORD8                 adc_active_ul = INACTIVE;
  UWORD8                 adc_active_dl = INACTIVE;
#if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_nb = 0;
  UWORD8 if_ctl = 0;
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
  // By default we choose the hardware filter
  UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER;
#endif
#if (NEW_SNR_THRESHOLD == 1)
  UWORD8 saic_flag=0;
#endif /*NEW_SNR_THRESHOLD */
  // Traces and debug.
  // ******************

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dsp_tpu(dltsk_trace[TCHA].name);
  #endif

  l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;

  // Catch channel description and ARFCN.
  // *************************************

  // Catch the active channel description used along the routine.
  // It contains:
  //    "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}.
  //    "subchannel", {0, 1}. 0 is the default value for TCH_F.
  desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

  // Get ARFCN to be used for current control.
  radio_freq = l1a_l1s_com.dedic_set.radio_freq;

  if (radio_freq == l1a_l1s_com.Scell_info.radio_freq)
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon;
                          // we are working on a beacon freq.
  else
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas;
                          // we are working on a daughter freq.

  /**************************************************************************/
  /* SACCH Receive...                                                       */
  /**************************************************************************/

  // ADC measurement
  // ***************

  // check if during the SACCH burst an ADC measurement must be performed
   if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_DL)  // perform ADC only one time
   {
      adc_active_dl = ACTIVE;
      l1a_l1s_com.adc_mode &= ADC_MASK_RESET_TRAFFIC; // reset in order to have only one ADC measurement in Traffic
   }
   else
     if (l1a_l1s_com.adc_mode & ADC_EACH_TRAFFIC_DL) // perform ADC on each period bloc
       if (l1s.next_time.fn_in_report == 12) //periodic with each 1st SACCH burst
         if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period
         {
           adc_active_dl = ACTIVE;
           l1a_l1s_com.adc_cpt = 0;
         }

  #if TESTMODE
    // if Normal Mode or
    // if TestMode and DL-only or DL+UL
    if ( !l1_config.TestMode ||
         (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_DOWNLINK)))
  #endif
    {
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_CTRL_TCHA___DL, radio_freq);
      #endif

      /*--------------------------------------------*/
      /* Program DSP...                             */
      /*--------------------------------------------*/
      // dsp pgm.

      dsp_task = l1s_swap_iq_dl(radio_freq,task);
      l1ddsp_load_rx_task(dsp_task, 0, desc_ptr->tsc);

      #if(RF_FAM == 61)    // Locosto DCO
         cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID ,
                                         IL_info_ptr->input_level ,
                                          radio_freq,if_threshold);
   	l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb);
      #endif

      /*--------------------------------------------*/
      /* Program TPU...                             */
      /*--------------------------------------------*/
      // for TCHA we use DPAGC algorithm.
      #if DPAGC_MAX_FLAG
        agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, MAX_ID);
      #else
        agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, AV_ID);
      #endif
      lna_off = IL_info_ptr->lna_off;



      // Store input_level and lna_off fields used for current CTRL in order to be able
      // to build IL from pm in READ phase.
      l1a_l1s_com.Scell_used_IL = *IL_info_ptr;

      #if (L1_SAIC != 0)
        // If SAIC is enabled, call the low level SAIC control function
        csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode
        #if (NEW_SNR_THRESHOLD == 1)
            ,task
            ,&saic_flag
        #endif
        );
      #endif

      #if TESTMODE
        // Continuous mode: Rx TPU programmation only in NO_CONTINUOUS or START_RX_CONTINUOUS mode.
        if ((!l1_config.TestMode)                                           ||
            (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS)      ||
            (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS))
      #endif
        {
          // update the TPU with the new TOA if necessary
          l1ctl_update_TPU_with_toa();

          // Program a serving cell normal burst reading in TPU.
          l1dtpu_serv_rx_nb(radio_freq,
                            agc,
                            lna_off,
                            l1s.tpu_offset,
                            l1s.tpu_offset,
                            FALSE,adc_active_dl
                          #if (RF_FAM == 61)
				,csf_filter_choice
				,if_ctl
			  #endif
                          #if (NEW_SNR_THRESHOLD == 1)
                            ,saic_flag
                          #endif /* NEW_SNR_THRESHOLD */
					 );
        }

  // Increment tpu window identifier.
  l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD);

  // Set "CTRL_RX" flag in the control flag register.
  #if TESTMODE
    // Continuous mode: swap TPU page for Rx only in NO_CONTINUOUS or START_RX_CONTINUOUS mode.
    if ((!l1_config.TestMode)                                           ||
        (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS)      ||
        (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS))
  #endif
    {
      l1s.tpu_ctrl_reg |= CTRL_RX;
    }
    l1s.dsp_ctrl_reg |= CTRL_RX;

  }

  /**************************************************************************/
  /* TCH/T Transmit...                                                      */
  /**************************************************************************/

  // Any Handover Access burst to send ? --> TXPWR management
  // ************************************

  if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0)
  // "ho_acc_to_send" is a counter of Handover Access burst still to send.
  // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a
  // Handover command is received from L3 through L1A.
  // When Handover access is in progress, nothing but RACH can be transmitted.
  // RACH is not allowed on SACCH therefore TX is avoided by setting
  // the txpwr to NO_TXPWR !!!
  {
#if 0	/* LoCosto code */
    // NOTE: The spec says RACH bursts on SACCH UL is optional. hence it should not be counted
    // Refer spec 04.08
    l1s_ctrl_rach(RAHO,NO_PAR);
#else	/* TCS211 reconstruction, code taken from TSM30 */
    // Set TXPWR.
    l1ddsp_load_txpwr(NO_TXPWR, radio_freq);
 
    #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
      RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, NO_TXPWR)
    #endif
#endif
  }
  else
  // TCH/UL is a normal burst.
  // TX power must be the normal one
  {
    // Set TXPWR.
    l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq);

    #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
      RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr)
    #endif

    // ADC measurement
    // ***************

    // check if during the SACCH burst an ADC measurement must be performed
    if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_UL)  // perform ADC only one time
    {
       adc_active_ul = ACTIVE;
       l1a_l1s_com.adc_mode &= ADC_MASK_RESET_TRAFFIC; // reset in order to have only one ADC measurement in Traffic
    }
    else
      if (l1a_l1s_com.adc_mode & ADC_EACH_TRAFFIC_UL) // perform ADC on each period bloc
        if (l1s.next_time.fn_in_report == 12) //periodic with each 1st SACCH burst
          if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period
          {
            adc_active_ul = ACTIVE;
            l1a_l1s_com.adc_cpt = 0;
          }

#if 1	/* FreeCalypso TCS211 reconstruction */
  } // End of "TCH/UL is a normal burst"
#endif

    // In any case (normal TX or no TX due to Handover Access process)
    // the full TCHA task must be controled for TPU and DSP.
    {
      T_RADIO_FRAME   *tx_data = NULL;

      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_CTRL_TCHA___UL, radio_freq);
      #endif

      /*--------------------------------------------*/
      /* Get DATA block if required for SACCH.      */
      /*--------------------------------------------*/
      if(l1s.next_time.fn_in_report == 12)
      // It is time to get a SACCH data block from DLL.
      // Call "dll_read_sacch()" to perform "PH_DATA_REQ" and pass
      // the data block to the DSP..
      {
	  #if ((FF_REPEATED_SACCH)     && ( TESTMODE))
          if(l1_config.repeat_sacch_enable != REPEATED_SACCH_ENABLE)
        {
               l1s.repeated_sacch.sro = 0;
               l1s.repeated_sacch.buffer_empty = TRUE;
          }
      #endif /* #if ((FF_REPEATED_SACCH)     && ( TESTMODE)) */
#if FF_REPEATED_SACCH
        /* Get data from PS if only no repetition order is required (1st condition) */
        /* or no repetition candidate exists (2nd condition)                        */
     if((l1s.repeated_sacch.sro == 0)  ||  (l1s.repeated_sacch.buffer_empty == TRUE))
#endif /* FF_REPEATED_SACCH */
     {
        tx_data = dll_read_sacch(SIG_ONLY_MODE);
        if(tx_data != NULL)
        {
          // Set L1 Header...
          tx_data->A[0] = l1s.reported_txpwr;
          tx_data->A[1] = l1a_l1s_com.dedic_set.aset->timing_advance;

        #if FF_REPEATED_SACCH
                /* Include the SACCH Repetition Request (SRR) in the L1 Header */
           tx_data->A[0] |= (l1s.repeated_sacch.srr <<6);
        #endif  /* FF_REPEATED_SACCH */
          // Put data block in MCU/DSP com.
          l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, &(tx_data->A[0]));
          #if (FF_REPEATED_SACCH == 1 )
             if(((tx_data->A[2]&0x1C) >> 2) == SAPI_0)    /* Store the block data in case of a retransmission order */
            {
                 l1s_store_sacch_buffer( &(l1s.repeated_sacch), &(tx_data->A[0]));
                 /* Stores the buffer and turns of the buffer_empty flag as false */
             }
            else
            {
            /* the SACCH repetition block occurrence will always come as a consecutive pair   */
            /* To handle DL UL | DL  UL  | DL UL                                              */
            /*            -  0 | SRO  3  | -   new data should be asked from PS old 0 cannot be repeated */
                l1s.repeated_sacch.buffer_empty=TRUE;
            }
         #endif /* FF_REPEATED_SACCH */
         } /* if(tx_data != NULL) */

          #if (TRACE_TYPE==5) && FLOWCHART
            trace_flowchart_dsptx(dltsk_trace[TCHA].name);
          #endif
        }/* if((l1s.repeated_sacch.sro == 0)  ||  (l1s.repeated_sacch.buffer_empty == TRUE))*/
      #if FF_REPEATED_SACCH
	       else if ((l1s.repeated_sacch.sro == 1) && (l1s.repeated_sacch.buffer_empty == FALSE))
	       {
	            /* Put data block in MCU/DSP com. */
	            l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, l1s.repeated_sacch.buffer );
	            l1s.repeated_sacch.buffer_empty = TRUE;     /* Set that the buffer is now empty (only one repetition) */
	       } /* end else repetition */
	  #endif /* FF_REPEATED_SACCH */
        // check to be removed
      }

      /*--------------------------------------------*/
      /* Program DSP...                             */
      /*--------------------------------------------*/
      #if TESTMODE
        // UL-only...
        // Use SPI to write to Omega uplink buffer, do NOT use DSP
        if (l1_config.TestMode && l1_config.tmode.rf_params.down_up == TMODE_UPLINK)
          {
          #if (CODE_VERSION != SIMULATION)
            // For Calyso+ & Before...
            #if (RF_FAM == 12)
            ABB_Write_Register_on_page(PAGE0, AUXAPC, Cust_get_pwr_data(l1s.applied_txpwr, radio_freq
            																			   #if(REL99 && FF_PRF)
            																			   ,1
            																			   #endif
            																			   ));
            l1tm_fill_burst(l1_config.tmode.tx_params.burst_data, &TM_ul_data[0]);
            ABB_Write_Uplink_Data(&TM_ul_data[0]);
          #endif

            //For  UppCosto, Tx Data Write is via PLD to DRP & Ramp is via the ABB Driver
       #if (RF_FAM == 60)
         ABB_Write_Register_on_page(PAGE0, AUXAPC, Cust_get_pwr_data(l1s.applied_txpwr, radio_freq
																						#if(REL99 && FF_PRF)
																						,1
																						#endif
																						));
              l1tm_fill_burst(l1_config.tmode.tx_params.burst_data, &TM_ul_data[0]);
              PLD_Write_Uplink_Data(&TM_ul_data[0]);
            #endif

           #if (RF_FAM == 61)
              // For DRP we use the DSP to write the TX Power via a new variable apclev in API
        // A new variable is required in API as DSP copies the tx_power_ctl (which is
        // normally used to pass the APCLEV value to DSP) to APCLEV ONLY when there is a
        // burst to be transmitted
        l1ddsp_apc_load_apclev(Cust_get_pwr_data(l1s.applied_txpwr, radio_freq
        															#if(REL99 && FF_PRF)
        															,1
        															#endif
                                                                    ));
              l1tm_fill_burst(l1_config.tmode.tx_params.burst_data, &TM_ul_data[0]);
              DRP_Write_Uplink_Data(&TM_ul_data[0]);
            #endif

    #endif
          }
        // Use DSP...
        // if Normal Mode or
        // if TestMode and DL+UL
        else if ( !l1_config.TestMode ||
                (l1_config.TestMode && l1_config.tmode.rf_params.down_up == (TMODE_DOWNLINK|TMODE_UPLINK)))
          {
            dsp_task = l1s_swap_iq_ul(radio_freq,task);

            l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc);
          }
      #else
        dsp_task = l1s_swap_iq_ul(radio_freq,task);

        l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc);
      #endif

        /*--------------------------------------------*/
        /* Program TPU...                             */
        /*--------------------------------------------*/
      #if TESTMODE
        // if Normal Mode or
        // if TestMode and UL-only or DL+UL
        if ( !l1_config.TestMode ||
           (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK) &&
           (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS           ||
            l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS)))
      #endif
            {
               l1dtpu_serv_tx_nb(radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr, adc_active_ul);
            }
    }

#if 0	/* FreeCalypso TCS211 reconstruction */
  } // End of "TCH/UL is a normal burst"
#endif

  /*----------------------------------------------*/
  /* Common for Dedicated mode: DSP parameters... */
  /*----------------------------------------------*/

  #if (AMR == 1)
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.sync_amr,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
                          #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            0);
                          #endif
    #else // FF_L1_TCH_VOCODER_CONTROL
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_amr);
                          #else
                            l1a_l1s_com.dedic_set.sync_amr,
                            0);
                          #endif
    #endif // FF_L1_TCH_VOCODER_CONTROL

    l1a_l1s_com.dedic_set.sync_amr    = FALSE;

  #else // AMR
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                            l1a_l1s_com.dedic_set.sync_tch,
                            l1a_l1s_com.dedic_set.reset_sacch,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.vocoder_on);
    #else
                            l1a_l1s_com.dedic_set.vocoder_on,
                            0);
                          #endif
    #else
      l1ddsp_load_tch_param(&(l1s.next_time),
                            l1a_l1s_com.dedic_set.aset->achan_ptr->mode,
                            desc_ptr->channel_type,
                            desc_ptr->subchannel,
                            l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop,
                          #if !FF_L1_IT_DSP_DTX
                            l1a_l1s_com.dedic_set.sync_tch);
                          #else
                            l1a_l1s_com.dedic_set.sync_tch,
                            0);
                          #endif
    #endif
  #endif // AMR

  // Clear "sync_tch" flag to maintain normal TCH process.
  l1a_l1s_com.dedic_set.sync_tch = FALSE;
#if (FF_L1_TCH_VOCODER_CONTROL)
  l1a_l1s_com.dedic_set.reset_sacch = FALSE;
#endif

#if 0	/* FreeCalypso TCS211 reconstruction */
  if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0)
  {
#endif
    // Set tpu window identifier for Power meas or FS/SB search.
    l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split;

    /*--------------------------------------------*/
    /* Flag DSP and TPU programmation...          */
    /*--------------------------------------------*/
    #if TESTMODE
      // if Normal Mode or
      // if TestMode and UL-only or DL+UL
      if ( !l1_config.TestMode ||
         (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK)))
    #endif
      {
        #if TESTMODE
          // Continuous mode: swap TPU page for Tx in NO_CONTINUOUS or START_TX_CONTINUOUS mode.
          if ((!l1_config.TestMode)                                           ||
              (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS)      ||
              (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS))
        #endif
          {
            l1s.tpu_ctrl_reg |= CTRL_TX;
          }
        l1s.dsp_ctrl_reg |= CTRL_TX;
      }

    #if TESTMODE
      // Continuous mode: if end of control of START_RX/TX: go to CONTINUOUS state
      if (l1_config.TestMode && (l1_config.tmode.rf_params.tmode_continuous != TM_NO_CONTINUOUS))
        l1_config.tmode.rf_params.tmode_continuous = TM_CONTINUOUS;
    #endif

#if 0	/* FreeCalypso TCS211 reconstruction */
  }
#endif
}

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_hopping_algo()                                    */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* dedicated mode tasks: DDL, DUL, ADL, AUL, TCHTH/F and */
/* TCHA. This function performs the Hopping Sequence     */
/* generation. It computes the ARFCN to use on the next  */
/* frame. When the channel does not hop, it returns      */
/* the fixe ARFCN provided in the channel description.   */
/*                                                       */
/* If the channel is hopping and the ARFCN result is the */
/* BEACON frequency, an indication flag is set to warn   */
/* the DSP ("b_bcch_freq_ind").                          */
/*                                                       */
/* (see GSM05.02 $6.2.3)                                 */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.dedic_set.aset"                          */
/*   Active set of Dedicated channel parameters.         */
/*                                                       */
/* "l1s.l1s.next_time"                                   */
/*   frame number and derived numbers for next frame.    */
/*                                                       */
/* Returned parameter in globals:                        */
/* ------------------------------                        */
/*                                                       */
/* "l1a_l1s_com.dedic_set.radio_freq"                    */
/*   ARFCN to be used on the next frame.                 */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_hopping_algo(UWORD8 task, UWORD8 param2)
{
  UWORD8               mai;
  T_CHN_SEL           *chan_sel;
  T_MOBILE_ALLOCATION *alist_ptr;

  UWORD16             *ma;
  UWORD8               n;
  UWORD8               hsn;
  UWORD8               maio;
  UWORD16             *radio_freq_ptr;
  UWORD16             *beacon_channel_ptr=&l1a_l1s_com.Scell_info.radio_freq; // beacon channel of the serving cell
  T_TIME_INFO         *time_ptr;
  T_TIME_INFO         next_neighbor_time;


  switch(task)
  {

#if L1_GPRS
    case PTCCH:
    {
      chan_sel       = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel);
      alist_ptr      = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list);
      radio_freq_ptr = &l1pa_l1ps_com.transfer.ptcch.radio_freq;
      time_ptr       = &l1s.next_time;
    }
    break;

    case PDTCH:
    case SINGLE:
    // For PDTCH, set pointers to the PACKET parameter structures.
    {
      chan_sel       = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel);
      alist_ptr      = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list);
      radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq;
      time_ptr       = &l1s.next_time;
    }
    break;

    case PALLC:
    case PNP:
    case PEP:
    {
      chan_sel       = &l1pa_l1ps_com.pccch.packet_chn_desc.chan_sel;
      alist_ptr      = &l1pa_l1ps_com.pccch.frequency_list;
      radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq;
      time_ptr       = &l1s.next_time;
    }
    break;

    case POLL:
    {
      // Load adequat freq. list according to the current mode:
      // SINGLE (i.e. 2 phase access) else Packet Access or Packet Idle
      if(l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED)
      {
        chan_sel       = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel);
        alist_ptr      = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list);
        radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq;
      }
      else
      {
        chan_sel       = &l1pa_l1ps_com.pccch.packet_chn_desc.chan_sel;
        alist_ptr      = &l1pa_l1ps_com.pccch.frequency_list;
        radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq;
      }
      time_ptr       = &l1s.next_time;
    }
    break;

    case PBCCHS:
    {
      chan_sel       = &l1pa_l1ps_com.pbcchs.packet_chn_desc.chan_sel;
      alist_ptr      = &l1pa_l1ps_com.pbcchs.frequency_list;
      radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq;

      // If PBCCHS controlled one frame in advance --> correct Frame Number when PBCCH block is read
      if (l1pa_l1ps_com.pbcchs.control_offset)
        time_ptr       = &l1s.next_plus_time;
      else
      time_ptr       = &l1s.next_time;
    }
    break;

    case PBCCHN_IDLE:
    case PBCCHN_TRAN:
    {
      WORD32  next_neighbor_time_fn;

      chan_sel           = &l1pa_l1ps_com.pbcchn.packet_chn_desc.chan_sel;
      alist_ptr          = &l1pa_l1ps_com.pbcchn.frequency_list;
      radio_freq_ptr     = &l1pa_l1ps_com.p_idle_param.radio_freq;
      beacon_channel_ptr = &l1pa_l1ps_com.pbcchn.bcch_carrier;
      time_ptr           = &next_neighbor_time;

      // To review (is there any better solution?)...........
      next_neighbor_time_fn = l1s.next_time.fn + l1pa_l1ps_com.pbcchn.fn_offset;

      #if 0	/* correct code (corrected by TI for LoCosto) */
      if (next_neighbor_time_fn > ((WORD32)MAX_FN))//OMAPS00090550
      #else	/* wrong code to match TCS211 disassembly */
      if (next_neighbor_time_fn > MAX_FN)
      #endif
        next_neighbor_time.fn = (UWORD32) (next_neighbor_time_fn - MAX_FN);
      else if (next_neighbor_time_fn < 0)
        next_neighbor_time.fn = (UWORD32) (next_neighbor_time_fn + MAX_FN);
      else
        next_neighbor_time.fn = (UWORD32) (next_neighbor_time_fn);

      next_neighbor_time.t1 = next_neighbor_time.fn / (26L*51L);       // T1 = FN div 26*51
      next_neighbor_time.t2 = next_neighbor_time.fn % 26;              // T2 = FN % 26.
      next_neighbor_time.t3 = next_neighbor_time.fn % 51;              // T3 = FN % 51.
    }
    break;

    case ITMEAS:
    {
      // Packet transfer mode
      if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
      {
        // We use the active TBF frequency parameters
        chan_sel  = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel);
        alist_ptr = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list);
      }

      // Packet idle mode
      else
      {
        // We use the frequency parameters given in the MPHP_INT_MEAS_REQ message
        chan_sel     = &(l1pa_l1ps_com.itmeas.packet_intm_freq_param.chan_sel);
        alist_ptr    = &(l1pa_l1ps_com.itmeas.packet_intm_freq_param.freq_list);
      }

      radio_freq_ptr = &l1pa_l1ps_com.itmeas.radio_freq;
      time_ptr       = &l1s.next_plus_time;
    }
    break;

#endif

    case SMSCB:
    // For SMSCB, set pointers to the SMSCB parameter structures.
    {
      chan_sel       = &l1a_l1s_com.cbch_desc.chan_sel;
      alist_ptr      = &l1a_l1s_com.cbch_freq_list;
      radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq;

      // If SMSCB is controlled one frame in advance --> correct Frame Number when SMSCB block is read
      if (l1a_l1s_com.pre_scheduled_cbch)
        time_ptr       = &l1s.next_plus_time;
      else
      time_ptr       = &l1s.next_time;
    }
    break;

    default:
    // For SDCCH/TCH, set pointers to the active channel description.
    {
      chan_sel       = &(l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->chan_sel);
      alist_ptr      = l1a_l1s_com.dedic_set.aset->ma.alist_ptr;
      radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq;
      time_ptr       = &l1s.next_time;
    }
  } // End of switch(task)

  // Set local variables.
  ma   = &(alist_ptr->rf_chan_no.A[0]);
  n    =   alist_ptr->rf_chan_cnt;
  hsn  =   chan_sel->rf_channel.hopping_rf.hsn;
  maio =   chan_sel->rf_channel.hopping_rf.maio;

  if(chan_sel->h == FALSE)
  // Single RF channel, NOT HOPPING.
  {
    *radio_freq_ptr = chan_sel->rf_channel.single_rf.radio_freq;
  }

  else
  // Hopping channel...
  {
    /**************************************************/
    /* Perform the HOPPING algorithm.                 */
    /**************************************************/
    if(hsn == 0)
    // Cyclic hopping...
    {
      mai = (time_ptr->fn + maio) % n;
    }
    else
    {
      UWORD8  i = 0;
      UWORD8  m;
      UWORD8  mp;
      UWORD8  nbin;
      UWORD8  tp;
      UWORD8  s;
      UWORD8  t1r = (UWORD8)(time_ptr->t1 % 64);

      while(i<=6)
      {
        if((n >> i) > 0) nbin = i;
        i++;
      }
      nbin++;

      m  = time_ptr->t2 + RNTABLE[(hsn ^ t1r) + time_ptr->t3];
      mp = m % (1L << nbin);
      tp = time_ptr->t3 % (1L << nbin);

      if(mp < n) s = mp;
      else       s = (mp + tp) % n;

      mai = (s + maio) % n;
    }

    *radio_freq_ptr = ma[mai];
  }

  if(*radio_freq_ptr == *beacon_channel_ptr)
  // If ARFCN is the BEACON...
  {
    // Set "b_bcch_freq_ind" to TRUE.
    l1s_dsp_com.dsp_db_w_ptr->d_ctrl_system |= (1 << B_BCCH_FREQ_IND);

  }
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

//===============================================================================================//

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise

/*-------------------------------------------------------*/
/* l1s_read_dummy()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* task: ABORT. Since this task just aborts any ongoing  */
/* DSP task, there is no result returned by the DSP to   */
/* the MCU when this abort is completed, but the MCU/DSP */
/* com. read page must be switched properly. This the    */
/* only reason why we have created this function.        */
/*                                                       */
/* Modified parameter in globals:                        */
/* ------------------------------                        */
/*                                                       */
/* "l1s_dsp_com.dsp_r_page_used"                         */
/*   Flag used by the function which closes L1S          */
/*   execution ("l1s_end_manager()") to know if the      */
/*   MCU/DSP read page must be switched.                 */
/*   -> Set to 1.                                        */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_read_dummy(UWORD8 task, UWORD8 param2)
{
  l1_check_com_mismatch(task);

  #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
    trace_fct(CST_L1S_READ_DUMMY ,(UWORD32)(-1));//OMAPS00090550
  #endif

      // task is completed, make it INACTIVE (only in case of TCHD).
  if(task == TCHD)
   l1s.task_status[task].current_status = INACTIVE;

  #if FF_L1_IT_DSP_DTX
    // Fast DTX status update
    if(task == TCHD)
    {
      UWORD8 subchannel = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->subchannel;

      // Currently used for TCH-AHS only
      if (((subchannel == 0) && (l1s.actual_time.fn_mod13_mod4 == 0)) || // FN%13 = 4, 8 and 12 for TCH/H0 (no Read on FN%13=0)
          ((subchannel == 1) && (l1s.actual_time.fn_mod13_mod4 == 1)))   // FN%13 = 1, 5 and 9  for TCH/H1
      {
        // Latch TX activity status if DTX allowed
        if ((l1a_l1s_com.dedic_set.aset->dtx_allowed == FALSE) ||                // No DTX allowed
            (l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enc_data ) || // DTX allowed but not used
            (l1a_apihisr_com.dtx.fast_dtx_ready == FALSE))                       // Fast DTX status is invalid
          l1a_apihisr_com.dtx.tx_active = TRUE;
        else
          l1a_apihisr_com.dtx.tx_active = FALSE;
      }
    }
  #endif
  // Set flag used to change the read page at the end of "l1_synch".
  l1s_dsp_com.dsp_r_page_used = TRUE;
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif

/*-------------------------------------------------------*/
/* l1s_read_msagc()                                      */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: BCCHN,FBNEW,SB1,SB2,SBCONF. This function is   */
/* the reading result function used for reading a power  */
/* measurement result used then to refreshing the AGC    */
/* for those tasks. Here is a summary of the execution:  */
/*                                                       */
/*  - If SEMAPHORE(task) is low.                         */
/*    - Get the cell information structure.              */
/*    - Traces and debug.                                */
/*    - Read receive level result from MCU/DSP interface.*/
/*  - Flag the use of the MCU/DSP dual page read         */
/*    interface.                                         */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   BCCHN, BCCH Neighbor reading task.                  */
/*   FBNEW, Frequency Burst detection task in Idle mode. */
/*   SB1, Synchro Burst reading task in Idle mode.       */
/*   SB2, Synchro Burst detection task in Idle mode.     */
/*   SBCONF, Synchro Burst confirmation task in Idle     */
/*   mode.                                               */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.Ncell_info.bcch"                         */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/* "l1a_l1s_com.Ncell_info.acquis"                       */
/* "l1a_l1s_com.Ncell_info.conf"                         */
/*   cell information structure used for BCCHN,FBNEW,    */
/*   SB1/SB2,SBCONF respectively.                        */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s_dsp_com.dsp_r_page_used"                         */
/*   Flag used by the function which closes L1S          */
/*   execution ("l1s_end_manager()") to know if the      */
/*   MCU/DSP read page must be switched.                 */
/*   -> Set to 1.                                        */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_read_msagc(UWORD8 task, UWORD8 param2)
{
  BOOL      en_task;
  BOOL      task_param;
  UWORD8    pm_level[2];
#if (L1_FF_MULTIBAND == 1)
  UWORD16  operative_radio_freq;
#endif


  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

  if((en_task) && !(task_param))
  // Check the task semaphore and the task enable bit. The reading
  // task body is executed only when the task semaphore is 0 and the
  // task is still enabled.
  // The semaphore can be set to 1 whenever L1A makes some changes
  // to the task parameters. The task can be disabled by L1A.
  {
    T_NCELL_SINGLE  *cell_info_ptr = NULL;
    #if (L1_GPRS)
      T_NCELL_SINGLE pbcchn_cell_info;
    #endif
#if ((REL99 == 1) && (FF_BHO == 1))
    T_NCELL_SINGLE bho_cell_info;
#endif

    // Get the cell information structure.
    // ************************************

    switch(task)
    {
      case BCCHN_TOP:  cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top  ]; break;
      case BCCHN:      cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm ]; break;
      case FBNEW:  cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id];     break;
      case SB2:    cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id];     break;
      case SBCONF: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id]; break;
#if ((REL99 == 1) && (FF_BHO == 1))
      case FBSB:
      {
        cell_info_ptr = &bho_cell_info;
        bho_cell_info.radio_freq = l1a_l1s_com.nsync_fbsb.radio_freq;
        bho_cell_info.fn_offset  = l1a_l1s_com.nsync_fbsb.fn_offset;
      }
      break;
#endif
      #if (L1_GPRS)
        case PBCCHN_IDLE:
        {
          cell_info_ptr = &pbcchn_cell_info;
          pbcchn_cell_info.radio_freq = l1pa_l1ps_com.pbcchn.bcch_carrier;
          pbcchn_cell_info.fn_offset  = l1pa_l1ps_com.pbcchn.fn_offset;
        }
        break;
      #endif

      default: return;
    }

    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0)
      trace_fct(CST_L1S_READ_MSAGC , cell_info_ptr->radio_freq);
    #endif

    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
        buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq,
                      cell_info_ptr->fn_offset, pm);
      #endif
    #endif

    l1_check_com_mismatch(MS_AGC_ID);

    // Read receive level result from MCU/DSP interface.
    // **************************************************
    // Read 2 received levels...
    #if L1_GPRS
      switch (l1a_l1s_com.dsp_scheduler_mode)
      {
        case GPRS_SCHEDULER:
        {
          // Call the reading driver using GPRS scheduler
          l1pddsp_meas_read(2, pm_level);
        } break;

        case GSM_SCHEDULER:
        {
          // Call the reading driver using GSM scheduler
          l1ddsp_meas_read(2, pm_level);
        } break;
      }
    #else
      l1ddsp_meas_read(2, pm_level);
    #endif

    // Power Measurement performed during last l1s_ctrl_msagc with HIGH_AGC
    // returned in pm_level[0]
    // Power measurement performed during last l1s_ctrl_msagc with LOW_AGC
    // returned in pm_level[1]

    l1_check_pm_error(pm_level[0], MS_AGC_ID);
    l1_check_pm_error(pm_level[1], MS_AGC_ID);

    l1ctl_pgc2(pm_level[0], pm_level[1], cell_info_ptr->radio_freq);

    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_LNA)
      
       #if (L1_FF_MULTIBAND == 0)
            buffer_trace (4, 22, cell_info_ptr->radio_freq,
                      l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level,
                      l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off);

       #else // L1_FF_MULTIBAND = 1 below

            operative_radio_freq = 
              l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq);
            buffer_trace (4, 22, cell_info_ptr->radio_freq,
                     l1a_l1s_com.last_input_level[cell_info_ptr->agc_index].input_level,
                     l1a_l1s_com.last_input_level[cell_info_ptr->agc_index].lna_off); 

       #endif // #if (L1_FF_MULTIBAND == 0) else

      #endif
    #endif
  }

  // Flag the use of the MCU/DSP dual page read interface.
  // ******************************************************

  // Set flag used to change the read page at the end of "l1_synch".
  l1s_dsp_com.dsp_r_page_used = TRUE;
}

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_read_mon_result()                                 */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: FBNEW,SB1,SB2,SBCONF,SB51,SBCNF51,SB26,SBCNF26.*/
/* This function is the reading result function used for */
/* reading the neighbor cell monitoring results. Here is */
/* a summary of the execution:                           */
/*                                                       */
/*  - Traces and debug.                                  */
/*  - Get task result from MCU/DSP read interface.       */
/*                                                       */
/*      - case: FBNEW/FB51.                              */
/*          - If SEMAPHORE(task) is low.                 */
/*              - Update AFC if required.                */
/*              - Read FB detection results.             */
/*              - Reports results to L1A.                */
/*          - Disactivate and Disable task.              */
/*          - Reset buffers and flags in NDB.            */
/*                                                       */
/*      - case: FB26.                                    */
/*          - Read FB detection results.                 */
/*          - Reports results to L1A.                    */
/*          - Disactivate task.                          */
/*                                                       */
/*      - case: SB26/SBCNF26.                            */
/*          - Read SB reading results.                   */
/*          - Reports results to L1A.                    */
/*          - Disactivate task.                          */
/*                                                       */
/*      - case: SB1/SB2/SB51/SBCONF/SBCNF51.             */
/*          - If SEMAPHORE(task) is low.                 */
/*              - Update AFC if required.                */
/*              - Read FB detection results.             */
/*              - Reports results to L1A.                */
/*          - Disactivate task when required.            */
/*                                                       */
/*  - Flag the use of the MCU/DSP dual page read         */
/*    interface.                                         */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   FBNEW, Frequency Burst detection task in Idle mode. */
/*   SB1, Synchro Burst reading task in Idle mode.       */
/*   SB2, Synchro Burst detection task in Idle mode.     */
/*   SBCONF, Synchro Burst confirmation task in Idle     */
/*   mode.                                               */
/*   SB51, Synchro Burst reading task in SDCCH Dedicated */
/*   mode.                                               */
/*   SBCNF51, Synchro Burst confirmation task in SDCCH   */
/*   Dedicated mode.                                     */
/*   SB26, Synchro Burst reading task in TCH Dedicated   */
/*   mode.                                               */
/*   SBCNF26, Synchro Burst confirmation task in TCH     */
/*   Dedicated mode.                                     */
/*                                                       */
/* "attempt_for_sb2"                                     */
/*   Since SB2 calls twice this function, this parameter */
/*   tells the function which call it it. Used mainly    */
/*   to know when to DISACTIVATE the task.               */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip the body  */
/*   of this function if L1A has changed or is changing  */
/*   some of the task parameters.                        */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register.                       */
/*   -> disable FBNEW,FB51 task.                         */
/*                                                       */
/* "l1s.task_status[task].current_status"                */
/*   current task status. It must be reset (INACTIVE)    */
/*   when the task is completed.                         */
/*   -> disactivate task.                                */
/*                                                       */
/* "l1s_dsp_com.dsp_r_page_used"                         */
/*   Flag used by the function which closes L1S          */
/*   execution ("l1s_end_manager()") to know if the      */
/*   MCU/DSP read page must be switched.                 */
/*   -> Set to 1.                                        */
/*                                                       */
/* Use of MCU/DSP interface:                             */
/* -------------------------                             */
/* "l1s_dsp_com.dsp_ndb_ptr"                             */
/*   pointer to the non double buffered part (NDB) of    */
/*   the MCU/DSP interface. This part is R/W for both    */
/*   DSP and MCU.                                        */
/*                                                       */
/* "l1s_dsp_com.dsp_db_r_ptr"                            */
/*   pointer to the double buffered part (DB) of the     */
/*   MCU/DSP interface. This pointer points to the READ  */
/*   page.                                               */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_read_mon_result(UWORD8 task, UWORD8 attempt)
{
  UWORD32   flag=0;
  UWORD32   toa;
  UWORD32   pm;
  UWORD32   angle;
  UWORD32   snr;

  #if TESTMODE
    UWORD32   pm_fullres;
  #endif

  API      *data;

  BOOL      en_task;
  BOOL      task_param;
  UWORD32   fb_abort_flag=0;

  /*-------------------------------------------------------------------------------*/
  /* READ MONITORING TASK RESULTS FROM MCU/DSP INTERFACE...                        */
  /*-------------------------------------------------------------------------------*/
  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

  // Traces and debug.
  // ******************
    #if (TRACE_TYPE!=0)&& (TRACE_TYPE !=5)
      trace_fct(CST_L1S_READ_MON_RESULT,(UWORD32)(-1));
    #endif

  if(!(en_task) || (task_param))
  {
    #if (TRACE_TYPE!=0)
      // Current task is no more alive, L1A changed the task parameters.
      // -> Trace "ABORT" on log file and screen.
      trace_fct(CST_TASK_KILLED, (UWORD32)(-1));
    #endif
  }
  else
  // Current task is still alive, check task identifier and debug number...
  {
    #if (TRACE_TYPE!=0)
      if((task != FB26) && (task != SB26) && (task != SBCNF26)) // DB cannot be used for FB26/SB26/SBCNF26 result.
        if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_md & 0xffff) !=
           (UWORD32)DSP_TASK_CODE[task])
          // Task id. different than the one expected...
          trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND,(UWORD32)(-1));
    #endif

    if((task != FB26) && (task != SB26)
       && (task != SBCNF26) && (attempt==12)
       #if ((REL99 == 1) && (FF_BHO == 1))
         && (task != FBSB)
       #endif
      ) // DB cannot be used for FB26/SB26/SBCNF26 result.
    {
        l1_check_com_mismatch(task);
    }
  }

  // Get task result from MCU/DSP read interface.
  // *********************************************

  switch(task)
  {
    case FBNEW :
    case FB51 :
    /*---------------------------------------------------*/
    /* Frequency burst detection result...               */
    /*---------------------------------------------------*/
    {
      if((en_task) && !(task_param))
      // Check the task semaphore and the task enable bit. The reading
      // task body is executed only when the task semaphore is 0 and the
      // task is still enabled.
      // The semaphore can be set to 1 whenever L1A makes some changes
      // to the task parameters. The task can be disabled by L1A.
      {
        flag  = l1s_dsp_com.dsp_ndb_ptr->d_fb_det              & 0xffff; //  1 means FOUND.
        toa   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA]   & 0xffff; //  Unit is BIT.
        pm    = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM]   & 0xffff) >> 5;
                                                                         //  WARNING... to be used!!!
        #if TESTMODE
          pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff;  // F26.6
        #endif
        angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff; //  WARNING... to be used!!!
        snr   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR]   & 0xffff; //  WARNING... to be used!!!


        // Check FB detection flag and attempt:
        // If no detection and attempt < 12 than continue FB search
        // Attempt=11: special case: wait for next (last) read, as
        // other task may already be programmed in MFTAB (do not flush !!!)
        if(((!flag) && (attempt < 11)) || (attempt==11))
          break;

        // If FB detection occurs before 11th attempt, abort FB search
        if((flag == TRUE) && (attempt < 11))
          fb_abort_flag=TRUE;


        if (fb_abort_flag == TRUE)
        {
          if ((l1s_dsp_com.dsp_db_r_ptr->d_debug & 0xffff) != ((l1s.debug_time + (12 - attempt)) % 65536))
            l1_check_com_mismatch(task);
        }

//       l1_check_pm_error(pm, task);

        #if TRACE_TYPE==3
          stats_samples_fb(flag,toa,pm,angle,snr);
        #endif

        #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
          uart_trace(FB51);
        #endif

        // Update AFC: Call AFC control function (KALMAN filter).
        #if AFC_ALGO
          #if TESTMODE
            if (l1_config.afc_enable)
          #endif
            {
              WORD16 old_afc=l1s.afc;

           if((flag == TRUE) && (l1a_l1s_com.mode == CS_MODE))
           {
            #if (VCXO_ALGO == 0)
              l1s.afc = l1ctl_afc(AFC_OPEN_LOOP,
                                  &l1s.afc_frame_count,
                                  (WORD16)angle,
                                  0,
                                  l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);
            #else
              l1s.afc = l1ctl_afc(AFC_OPEN_LOOP,
                                  &l1s.afc_frame_count,
                                  (WORD16)angle,
                                  0,
                                  l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq,l1a_l1s_com.mode);
            #endif
            #if L2_L3_SIMUL
              #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN)
                buffer_trace (4,(WORD16)angle,old_afc,l1s.afc,0);
              #endif
            #endif
              }
            }
        #endif

        // Call FB report function (send report msg to L1A).
        #if TESTMODE
          if (l1_config.TestMode)
            l1s_read_fb(task, flag, toa, attempt, pm_fullres, angle, snr);
          else
            l1s_read_fb(task, flag, toa, attempt, pm, angle, snr);
        #else
          l1s_read_fb(task, flag, toa, attempt, pm, angle, snr);
        #endif

        // The Frequency Burst detection task in Idle (FBNEW) and
        // Dedicated/SDCCH (FB51) are 1 shot tasks, they must be
        // disabled in L1S when they are completed. Disable it.
        l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED;

        // the status is not used in D51 and D26 modes
        if (task != FB51 )
        {
          l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].status = NSYNC_COMPLETED;
        }
      }

      if ((fb_abort_flag == TRUE) || (attempt==12))
      {
        // FB task is completed, make it INACTIVE.
        l1s.task_status[task].current_status = INACTIVE;

        // Reset buffers and flags in NDB ...
        l1s_dsp_com.dsp_ndb_ptr->d_fb_det            = FALSE;
        l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] = 0;

        // This task is not compatible with Neigh. Measurement.
        // Clear "forbid_meas" to indicate when the task is complete.
        l1s.forbid_meas = 0;
      }

      // FB search finished before 11th attempt:
      // -reset DSP R/W pages, DSP tasks and TPU
      // -flush MFTAB and reset frame count
      // -adjust debug time
      if(fb_abort_flag)
      {
        l1d_reset_hw(l1s.tpu_offset);
        l1s.tpu_ctrl_reg |= CTRL_FB_ABORT; // set CTRL bit -> tpu_end_scenario
        l1s_clear_mftab(l1s.mftab.frmlst);
        l1s.frame_count = 0;

#if 0	/* FreeCalypso TCS211 reconstruction */
        // This task is not compatible with Neigh. Measurement.
        // Clear "forbid_meas" to indicate when the task is complete.
        l1s.forbid_meas = 0;
#endif
      }
    }
    break;

    case FB26 :
    /*---------------------------------------------------*/
    /* Frequency burst detection result...               */
    /*---------------------------------------------------*/
    {
      UWORD8 neigh_id;

      // read cell identifier.
      neigh_id = l1a_l1s_com.nsync.active_fb_id;

      if((en_task) && !(task_param))
      // Check the task semaphore and the task enable bit. The reading
      // task body is executed only when the task semaphore is 0 and the
      // task is still enabled.
      // The semaphore can be set to 1 whenever L1A makes some changes
      // to the task parameters. The task can be disabled by L1A.
      {
        flag  = l1s_dsp_com.dsp_ndb_ptr->d_fb_det              & 0xffff; //  1 means FOUND.
        toa   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA]   & 0xffff; //  Unit is BIT.
        pm    = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM]   & 0xffff) >> 5;
                                                                         //  WARNING... to be used!!!
        #if TESTMODE
          pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff;  // F10.6
        #endif

        // CQ 19836: do not check PM on FB26
        //l1_check_pm_error(pm, task);

        angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff; //  WARNING... to be used!!!
        snr   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR]   & 0xffff; //  WARNING... to be used!!!

        // Call FB report function (send report msg to L1A).
        #if TESTMODE
          if (l1_config.TestMode)
            l1s_read_fb(task, flag, toa, NO_PAR, pm_fullres, angle, snr);
          else
            l1s_read_fb(task, flag, toa, NO_PAR, pm, angle, snr);
        #else
          l1s_read_fb(task, flag, toa, NO_PAR, pm, angle, snr);
        #endif
      }

      #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
        uart_trace(FB26);
      #endif


      // The Frequency Burst detection task in Dedicated/TCH
      // is composed with several attempts managed in L1A.
      //    -> task is completed: set INACTIVE.
      l1s.task_status[task].current_status = INACTIVE;

      // Reset buffers and flags in NDB ...
      l1s_dsp_com.dsp_ndb_ptr->d_fb_det            = FALSE;
      l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] = 0;
    }
    break;

    case SB26 :
    case SBCNF26 :
    /*---------------------------------------------------*/
    /* Synchro. burst detection result...                */
    /*---------------------------------------------------*/
    {
      if((en_task) && !(task_param))
      // Check the task semaphore and the task enable bit. The reading
      // task body is executed only when the task semaphore is 0 and the

      // task is still enabled.
      // The semaphore can be set to 1 whenever L1A makes some changes
      // to the task parameters. The task can be disabled by L1A.
      {
        flag  = !(((l1s_dsp_com.dsp_ndb_ptr->a_sch26[0] & 0xffff) & (1<<B_SCH_CRC)) >> B_SCH_CRC); //  1 means ERROR.
        toa   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA]   & 0xffff;  //  Unit is BIT.
        pm    = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM]   & 0xffff) >> 5;
                                                                          //  WARNING... to be used!!!
        #if TESTMODE
          pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff;  // F26.6
        #endif

        angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff;
        snr   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR]   & 0xffff;
        data  = &(l1s_dsp_com.dsp_ndb_ptr->a_sch26[3]);                   // Set data block pointer (skip header).

        l1_check_pm_error(pm, task);

        // Call SB report function (send report msg to L1A).
        #if TESTMODE
          if (l1_config.TestMode)
            l1s_read_sb(task, flag, data, toa, attempt, pm_fullres, angle, snr);
          else
            l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr);
        #else
          l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr);
        #endif
      }
      #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
        uart_trace(SB26);
      #endif


      // The Synchro Burst detection (SB26) and confirmation (SBCNF26)
      // tasks in Dedicated/TCH are enabling/disabling are fully
      // managed by L1A.
      //    -> task is completed: set INACTIVE.
      l1s.task_status[task].current_status = INACTIVE;

      // Reset buffers and flags in NDB ...
      l1s_dsp_com.dsp_ndb_ptr->a_sch26[0]    =  (1<<B_SCH_CRC);
    }
    break;

    case SB2 :
    case SBCONF :
    case SB51 :
    case SBCNF51 :
    /*---------------------------------------------------*/
    /* Synchro. burst detection result...                */
    /*---------------------------------------------------*/
    {
      if((en_task) && !(task_param))
      // Check the task semaphore and the task enable bit. The reading
      // task body is executed only when the task semaphore is 0 and the
      // task is still enabled.
      // The semaphore can be set to 1 whenever L1A makes some changes
      // to the task parameters. The task can be disabled by L1A.
      {
        UWORD8  neigh_id;

        if((task == SB2) || (task == SB51))
          neigh_id = l1a_l1s_com.nsync.active_sb_id;
        else
          neigh_id = l1a_l1s_com.nsync.active_sbconf_id;

        flag  = !(((l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff) & (1<<B_SCH_CRC)) >> B_SCH_CRC); //  1 means ERROR.
        toa   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;  //  Unit is BIT.
        pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff) >> 5;
                                                                           //  WARNING... to be used!!!
        #if TESTMODE
          pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff;  // F26.6
        #endif

        angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
        snr   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;
        data  = &(l1s_dsp_com.dsp_db_r_ptr->a_sch[3]);                     // Set data block pointer (skip header).

        #if (L1_DEBUG_IQ_DUMP == 1)
          l1ddsp_read_iq_dump(task);
        #endif

        l1_check_pm_error(pm, task);

        // CQ30474. In case SNR is too low, the SB shall be considered as failed.
        // This is valuable for code running on target with DSP 3606.

	/*
	 * FreeCalypso: despite the above comment,
	 * this code is NOT present in TCS211.
	 */
#if 0
#if (CODE_VERSION == NOT_SIMULATION)
       if ( snr < MIN_ACCEPTABLE_SNR_FOR_SB )
         flag = FALSE;
#endif
#endif

        #if L2_L3_SIMUL
          #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
            buffer_trace(4, l1s.actual_time.fn, toa,pm, l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff);
          #endif
        #endif

        #if TRACE_TYPE==3
          stats_samples_sb(flag,toa,pm,angle,snr);
        #endif
        #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
          if (task == SBCONF) uart_trace(SBCONF);
          else uart_trace(SB2);        // display result code...
        #endif

        // Update AFC: Call AFC control function (KALMAN filter).
        #if AFC_ALGO
          #if TESTMODE
            if (l1_config.afc_enable)
          #endif
            {
              WORD16 old_afc=l1s.afc;

           if((flag == TRUE) && (l1a_l1s_com.mode == CS_MODE))
           {
            #if (VCXO_ALGO == 0)
              l1s.afc = l1ctl_afc(AFC_OPEN_LOOP,
                                  &l1s.afc_frame_count,
                                  (WORD16)angle,
                                  0,
                                  l1a_l1s_com.nsync.list[neigh_id].radio_freq);
            #else
              l1s.afc = l1ctl_afc(AFC_OPEN_LOOP,
                                  &l1s.afc_frame_count,
                                  (WORD16)angle,
                                  0,
                                  l1a_l1s_com.nsync.list[neigh_id].radio_freq,l1a_l1s_com.mode);
            #endif

                #if L2_L3_SIMUL
                  #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN)
                    buffer_trace (4,(WORD16)angle,old_afc,l1s.afc,1);
                  #endif
                #endif
              }
            }
        #endif

        // Call SB report function (send report msg to L1A).
        #if TESTMODE
          if (l1_config.TestMode)
            l1s_read_sb(task, flag, data, toa, attempt, pm_fullres, angle, snr);
          else
            l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr);
        #else
          l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr);
        #endif

        // the status is not used in D51 and D26 modes
        if ((task != SBCNF51 ) && (task != SB51))
        {
          // SB2 activity completed for this neighbour cell.
          if((task != SB2) || ((task == SB2) && (attempt == 2)))
            l1a_l1s_com.nsync.list[neigh_id].status = NSYNC_COMPLETED;
        }
      }

      // All tasks are completed by this function except SB2 which
      // calls it twice. SB2 is then completed only when making the
      // second execution of this function.
      //    -> task is completed: set INACTIVE.
      if((task != SB2) || (task == SB2) && (attempt == 2))
      {
        l1s.task_status[task].current_status = INACTIVE;
        l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED;
      }
    }
    break;
#if ((REL99 == 1) && (FF_BHO == 1))
    case FBSB :

    /*---------------------------------------------------*/
    /* Frequency + Synchro burst detection result...     */
    /*---------------------------------------------------*/
    {
      BOOL abort_flag = FALSE;

      if (l1a_l1s_com.nsync_fbsb.fb_found_attempt == 0)
      // Looking for FB
      {
        flag  = l1s_dsp_com.dsp_ndb_ptr->d_fb_det & 0xffff; //  flag = TRUE means FOUND.
        toa   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA]   & 0xffff; //  Unit is BIT.
        pm    = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM]   & 0xffff) >> 5;
#if TESTMODE
        pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff;  // F26.6
#endif
        angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff;
        snr   = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR]   & 0xffff;

        if (flag) // FB detected
        {
          // Store toa and attempt for future use
          l1a_l1s_com.nsync_fbsb.fb_toa = toa;
          l1a_l1s_com.nsync_fbsb.fb_found_attempt = attempt;

#if (TRACE_TYPE == 3)
          stats_samples_fb(flag, toa, pm, angle, snr);
#endif

#if (TRACE_TYPE == 2 ) || (TRACE_TYPE == 3)
          // uart_trace(FBSB);
#endif
        }
        else
        {
          if (attempt < 12)
          {
            // FB not found, some attempts remaining
            break;
          }
          else
          {
            // FB not found, no attempt remaining
            // Call FBSB report function (send report msg to L1A).
#if TESTMODE
            if (l1_config.TestMode)
              l1s_read_fbsb(task, attempt, FALSE, FALSE, (API *)NULL, toa, pm, angle, snr);
            else
#endif
              l1s_read_fbsb(task, attempt, FALSE, FALSE, (API *)NULL, toa, pm, angle, snr);

            abort_flag = TRUE;
          }
        }
      }
      else // if (l1a_l1s_com.nsync_fbsb.fb_found_attempt == 0)
      // Looking for SB
      {
        flag  = !(((l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff) & (1<<B_SCH_CRC)) >> B_SCH_CRC); //  //  flag = TRUE means FOUND.
        toa   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;  //  Unit is BIT.
        pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff) >> 5;
#if TESTMODE
        pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff;  // F26.6
#endif
        angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
        snr   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;
        data  = &(l1s_dsp_com.dsp_db_r_ptr->a_sch[3]);  		   // Set data block pointer (skip header).

        if (flag) // SB detected
        {
          // SB found report SUCCESS

#if L2_L3_SIMUL
#if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
          buffer_trace(4, l1s.actual_time.fn, toa,pm, l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff);
#endif
#endif

#if (TRACE_TYPE == 3)
          stats_samples_sb(flag, toa, pm, angle, snr);
#endif

#if (TRACE_TYPE == 2 ) || (TRACE_TYPE == 3)
          // uart_trace(FBSB);        // display result code...
#endif

          // Call FBSB report function (send report msg to L1A).
#if TESTMODE
  	      if (l1_config.TestMode)
  	        l1s_read_fbsb(task, attempt, TRUE, TRUE, data, toa, pm, angle, snr);
  	      else
#endif
  	        l1s_read_fbsb(task, attempt, TRUE, TRUE, data, toa, pm, angle, snr);

  	      abort_flag = TRUE;
  	    }
  	    else // if (flag)
  	    {
  	      if (attempt < (l1a_l1s_com.nsync_fbsb.fb_found_attempt + 2))
  	      {
  	        // SB not found, one attempt remaining
  	        break;
  	      }
  	      else
  	      {
  	        // SB not found, no attempt remaining
  	        // Call FBSB report function (send report msg to L1A).
#if TESTMODE
 	        if (l1_config.TestMode)
 	          l1s_read_fbsb(task, attempt, TRUE, FALSE, (API *)NULL, toa, pm, angle, snr);
 	        else
#endif
  	          l1s_read_fbsb(task, attempt, TRUE, FALSE, (API *)NULL, toa, pm, angle, snr);

  	        abort_flag = TRUE;
  	      }
  	    }
      } // if(l1a_l1s_com.nsync_fbsb.fb_found_attempt == 0)


      if(abort_flag == TRUE)
      {
        //    -> task is completed: set INACTIVE.
        l1s.task_status[task].current_status = INACTIVE;
        l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED;

        if (attempt < 14)
        {
          // FBSB search finished before last attempt:
          // -reset DSP R/W pages, DSP tasks and TPU
          // -flush MFTAB and reset frame count
          // -adjust debug time
          l1d_reset_hw(l1s.tpu_offset);
          l1s.tpu_ctrl_reg |= CTRL_FBSB_ABORT; // set CTRL bit -> tpu_end_scenario
          l1s_clear_mftab(l1s.mftab.frmlst);
          l1s.frame_count = 0;
        }
      }
    }
#endif // #if ((REL99 == 1) && (FF_BHO == 1))
  }

  // Flag the use of the MCU/DSP dual page read interface.
  // ******************************************************

  // Set flag used to change the read page at the end of "l1_synch" only if not
  // in dedicated/TCH mode (FB26,SB26,SBCNF26). Those task are not following the
  // common principle. They use only the NDB part of the MCU/DSP interface, no
  // page swapping is then needed.
#if ((REL99 == 1) && (FF_BHO == 1))
  if(((task != FB26) && (task != SB26) && (task != SBCNF26) && (task != FBNEW) && (task != FB51) && (task != FBSB)) ||
#else
  if(((task != FB26) && (task != SB26) && (task != SBCNF26) && (task != FBNEW) && (task != FB51)) ||
#endif // #if ((REL99 == 1) && (FF_BHO == 1))
     ((!fb_abort_flag) && (attempt==12)))
    l1s_dsp_com.dsp_r_page_used = TRUE;
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise

/*-------------------------------------------------------*/
/* l1s_read_snb_dl()                                     */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: BCCHS,NP,EP,ALLC,SMSCB.                        */
/* This function is the reading result function used for */
/* reading a serving cell burst acquisition result in    */
/* any mode except dedicated mode. Here is a summary of  */
/* the execution:                                        */
/*                                                       */
/*  - If SEMAPHORE(task) is low and task still enabled.  */
/*      - Traces and debug.                              */
/*      - Read control results and feed control algo.    */
/*      - Read DL DATA block from MCU/DSP interface.     */
/*  - Disactivate task.                                  */
/*  - Flag the use of the MCU/DSP dual page read         */
/*    interface.                                         */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   NP, Normal paging reading task.                     */
/*   EP, Extended paging reading task.                   */
/*   BCCHS, BCCH Serving reading task.                   */
/*   ALLC, All serving cell CCCH reading task.           */
/*   SMSCB, Short Message Service Cell Broadcast task.   */
/*                                                       */
/* "burst_id"                                            */
/*   BURST_1, 1st burst of the task.                     */
/*   BURST_2, 2nd burst of the task.                     */
/*   BURST_3, 3rd burst of the task.                     */
/*   BURST_4, 4th burst of the task.                     */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip the body  */
/*   of this function if L1A has changed or is changing  */
/*   some of the task parameters.                        */
/*                                                       */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register.                       */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.task_status[task].current_status"                */
/*   current task status. It must be reset (INACTIVE)    */
/*   when the task is completed.                         */
/*   -> disactivate task.                                */
/*                                                       */
/* "l1s_dsp_com.dsp_r_page_used"                         */
/*   Flag used by the function which closes L1S          */
/*   execution ("l1s_end_manager()") to know if the      */
/*   MCU/DSP read page must be switched.                 */
/*   -> Set to 1.                                        */
/*                                                       */
/* Use of MCU/DSP interface:                             */
/* -------------------------                             */
/* "l1s_dsp_com.dsp_ndb_ptr"                             */
/*   pointer to the non double buffered part (NDB) of    */
/*   the MCU/DSP interface. This part is R/W for both    */
/*   DSP and MCU.                                        */
/*                                                       */
/* "l1s_dsp_com.dsp_db_r_ptr"                            */
/*   pointer to the double buffered part (DB) of the     */
/*   MCU/DSP interface. This pointer points to the READ  */
/*   page.                                               */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_read_snb_dl(UWORD8 task, UWORD8 burst_id)
{
  UWORD32   toa;
  UWORD32   pm;
  UWORD32   angle;
  UWORD32   snr;
  BOOL      en_task;
  BOOL      task_param;
  UWORD16   radio_freq=0;
  static UWORD16 pwr_level;
#if L1_FF_MULTIBAND == 1
  UWORD16  operative_radio_freq;
#endif
  
#if (FF_L1_FAST_DECODING == 1)
  UWORD8 skipped_bursts = 0;
  BOOL fast_decoding_authorized = l1s_check_fast_decoding_authorized(task);
  BOOL fast_decoded = (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_COMPLETE);
  if (fast_decoded)
  {
    skipped_bursts = BURST_4 - burst_id;
  }
#endif /* if (FF_L1_FAST_DECODING == 1) */

  /*--------------------------------------------------------*/
  /* READ SERVING CELL RECEIVE TASK RESULTS...              */
  /*--------------------------------------------------------*/
  /* Rem: only a partial result is present in the mcu<-dsp  */
  /* communication buffer. The DATA BLOCK content itself is */
  /* in the last comm. (BURST_4)                               */
  /*--------------------------------------------------------*/
  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

  if((en_task) && !(task_param))
  // Check the task semaphore and the task enable bit. The reading
  // task body is executed only when the task semaphore is 0 and the
  // task is still enabled.
  // The semaphore can be set to 1 whenever L1A makes some changes
  // to the task parameters. The task can be disabled by L1A.
  {
    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
      trace_fct(CST_L1S_READ_SNB_DL , (UWORD32)(-1));//OMAPS00090550
    #endif

    #if (TRACE_TYPE!=0)
      #if L1_GPRS
         if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER)
         {
            // Check task identifier...
            if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
              trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));//OMAPS00090550

            // Check burst identifier...
            if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_burst_d & 0xffff) != burst_id)
              trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND, (UWORD32)(-1));//OMAPS00090550
         }
         else // GPRS scheduler
         {
            // Check burst identifier...
            if(l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs != burst_id)
              trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND, (UWORD32)(-1));
         }
      #else
        // Check task identifier...
        if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
          trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));

        // Check burst identifier...
        if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_burst_d & 0xffff) != burst_id)
          trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND,(UWORD32)( -1));
      #endif
    #endif

    l1_check_com_mismatch(task);

    // Read control results and feed control algorithms.
    // **************************************************

    // Read control information.
    #if L1_GPRS
      if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER)
      {
        toa   =  l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;
        pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]    & 0xffff) >> 5;
        angle =  l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
        snr   =  l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;
      }
      else
      {
        toa   =  l1ps_dsp_com.pdsp_db_r_ptr->a_burst_toa_gprs[0]   & 0xffff;
        pm    = (l1ps_dsp_com.pdsp_db_r_ptr->a_burst_pm_gprs[0]    & 0xffff) >> 5;
        angle =  l1ps_dsp_com.pdsp_db_r_ptr->a_burst_angle_gprs[0] & 0xffff;
        snr   =  l1ps_dsp_com.pdsp_db_r_ptr->a_burst_snr_gprs[0]   & 0xffff;
      }
    #else
        toa   =  l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;
        pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]    & 0xffff) >> 5;
        angle =  l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
        snr   =  l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;
    #endif

    l1_check_pm_error(pm, task);

    // Update AGC: Call PAGC algorithm
    radio_freq = l1a_l1s_com.Scell_info.radio_freq;

#if (L1_FF_MULTIBAND == 0)

    l1a_l1s_com.Scell_IL_for_rxlev = l1ctl_pagc((UWORD8)pm, radio_freq,
                                                &l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset]);
#else // L1_FF_MULTIBAND = 1 below

  operative_radio_freq = 
    l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq);
  l1a_l1s_com.Scell_IL_for_rxlev = l1ctl_pagc((UWORD8)pm, radio_freq,
                                                &l1a_l1s_com.last_input_level[operative_radio_freq]);  

#endif // #if (L1_FF_MULTIBAND == 0) else


#if (FF_L1_FAST_DECODING == 1)
    if (skipped_bursts>0)
    {
      l1ctl_pagc_missing_bursts(skipped_bursts);
    }
#endif /* if (FF_L1_FAST_DECODING == 1) */

    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_LNA)
      
        #if (L1_FF_MULTIBAND == 0)
            buffer_trace (4, 33, radio_freq,
                      l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].input_level,
                      l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].lna_off);
        
        #else // L1_FF_MULTIBAND = 1 below
        
            buffer_trace (4, 33, radio_freq,
                      l1a_l1s_com.last_input_level[operative_radio_freq].input_level,
                      l1a_l1s_com.last_input_level[operative_radio_freq].lna_off);
        
        #endif // #if (L1_FF_MULTIBAND == 0) else 
        
      #endif
    #endif

    #if TRACE_TYPE==3
      stats_samples_nb(toa,pm,angle,snr,burst_id,task);
    #endif

    // Update AFC: Call AFC control function (KALMAN filter).
    #if AFC_ALGO
      #if TESTMODE
        if (l1_config.afc_enable)
      #endif
        {
		  #if L2_L3_SIMUL
          #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN)//omaps00090550
          WORD16 old_afc  = l1s.afc;
          WORD16 old_count= l1s.afc_frame_count;
          #endif
          #endif



          #if (VCXO_ALGO == 0)
            l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq);
          #else
            l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode);
          #endif

          #if L2_L3_SIMUL
            #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN)
              buffer_trace (4,(WORD16)angle,old_count,old_afc,l1s.afc);
            #endif
            #if (DEBUG_TRACE == BUFFER_TRACE_TOA)
             if (task == NP || task == EP)
               buffer_trace(5,
                           l1s.debug_time,
                           0xf1,
                           i,
                           l1s.afc,
                           angle );
            #endif
          #endif
        }
    #endif

    //Feed TOA histogram.
    #if (TOA_ALGO != 0)
    if (task != SMSCB)
   {
      #if (TOA_ALGO == 2)
        if(l1s.toa_var.toa_snr_mask == 0)
      #else
        if(l1s.toa_snr_mask == 0)
      #endif
      #if (RF_FAM == 2) // RF 2
        #if (TOA_ALGO == 2)
			if(l1a_l1s_com.Scell_IL_for_rxlev < IL_FOR_RXLEV_SNR)
			{
           l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa);
			}
			else
			{
				l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa);
			}
        #else
			if(l1a_l1s_com.Scell_IL_for_rxlev <IL_FOR_RXLEV_SNR)
            {
           l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count
#if (FF_L1_FAST_DECODING == 1)
               , skipped_bursts
#endif
               );
			}
			else
			{
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count
#if (FF_L1_FAST_DECODING == 1)
                    , skipped_bursts
#endif
                    );
			}
        #endif

        #if L2_L3_SIMUL
          #if (DEBUG_TRACE == BUFFER_TRACE_TOA )
           if (task == NP || task == EP)
             buffer_trace(5,
                     l1s.debug_time,
                     0xf0,
                     toa,
                     snr,
                     l1s.tpu_offset );
          #endif
        #endif
      #else // RF 2
        #if (TOA_ALGO == 2)
			if(l1a_l1s_com.Scell_IL_for_rxlev < IL_FOR_RXLEV_SNR)
			{
           l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa);
			}
			else
			{
				l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa);
			}
        #else
			if(l1a_l1s_com.Scell_IL_for_rxlev <IL_FOR_RXLEV_SNR)
            {
           l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count
#if (FF_L1_FAST_DECODING == 1)
               , skipped_bursts
#endif
               );
			}
			else
			{
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count
#if (FF_L1_FAST_DECODING ==1)
                    , skipped_bursts
#endif
                    );
			}
        #endif
      #endif // RF 2
   }
  #else  // TOA_ALGO
    #if L2_L3_SIMUL
      #if (DEBUG_TRACE == BUFFER_TRACE_TOA)
        if (task == NP || task == EP)
             buffer_trace(5,
                     l1s.debug_time,
                     0xf0,
                     toa,
                     snr,
                     l1s.tpu_offset );
      #endif
    #endif
  #endif // TOA_ALGO

    #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
      RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev)
    #endif
    #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM
      l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev);
    #endif
    #if (BURST_PARAM_LOG_ENABLE == 1)
      l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev);
    #endif

    // compute the Data bloc Power.
    // ******************************
    if(burst_id == BURST_1)
      pwr_level = 0;

    // add the burst power
    pwr_level += l1a_l1s_com.Scell_IL_for_rxlev;


    // Read downlink DATA block from MCU/DSP interface.

    if (task == NP)
    {
          toa_tab[burst_id] = toa;
  }

#if 0	/* FreeCalypso TCS211 reconstruction */
// added Enhanced RSSI
   if(l1s_dsp_com.dsp_ndb_ptr->a_cd[2] != 0xffff)
   {
        qual_acc_idle1[0]  += l1s_dsp_com.dsp_ndb_ptr->a_cd[2];
        //RX Qual value reporting- total number of decoded bits
         qual_acc_idle1[1] += 1;
   }
#endif

#if (FF_L1_FAST_DECODING == 1)
    /* Perform the reporting if
        - Burst is the 4th one (whether CRC is ok or not)
        - Fast decoding enabled and CRC already ok
    */
    if ( (burst_id == BURST_4) || fast_decoded )
#else /* #if (FF_L1_FAST_DECODING == 1) */
    if(burst_id == BURST_4)
#endif /* FF_L1_FAST_DECODING */
    {
      UWORD8 i;

      #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
        uart_trace(task);
      #endif

      // the data power bloc = pwr_level/4.
#if (FF_L1_FAST_DECODING == 1)
      /* Data power block = pwr_level / (nb of bursts)*/
      pwr_level = pwr_level / (burst_id + 1);
#else /* #if (FF_L1_FAST_DECODING == 1) */
      // the data power bloc = pwr_level/4.
      pwr_level = pwr_level >> 2;
#endif /* #if (FF_L1_FAST_DECODING == 1) #else*/

#if (FF_L1_FAST_DECODING == 1)
      if(!fast_decoding_authorized)
      {
        /* When fast decoding wasn't used, burst_id is undefined (for the trace) */
        l1a_l1s_com.last_fast_decoding = 0;
      }
      else
      {
        l1a_l1s_com.last_fast_decoding = burst_id + 1;
      }
#endif /* #if (FF_L1_FAST_DECODING == 1) */

      // Read L3 frame block and send msg to L1A.
      #if L1_GPRS
        if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER)
          l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task);
        else
          l1s_read_l3frm(pwr_level,&(l1ps_dsp_com.pdsp_ndb_ptr->a_dd_gprs[0][0]), task);
      #else
          l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task);
      #endif

      #if L1_GPRS
        if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER)
      #endif
      {
        // reset buffers and flags in NDB ...
        // reset nerr....
        // reset A_CD contents.......
        l1s_dsp_com.dsp_ndb_ptr->a_cd[2]     =  0xffff;
        for (i=0;i<12;i++)
          l1s_dsp_com.dsp_ndb_ptr->a_cd[3+i] =  0x0000;
      }

    } // End if...
  } // End if...

  // The NP/EP task was enabled and could cancel a PTCCH burst
  // This incomplete PTCCH decoding block cause DSP troubles and so COM/PM errors
  // and then a recovery  => in this case restart the PTCCH from the burst 0
#if L1_GPRS
  if((task == NP)||(task == EP))
    if(l1a_l1s_com.l1s_en_task[PTCCH] == TASK_ENABLED)
      if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // a PTCCH DL task is running
        if((l1s.actual_time.t2 >= 13) && (l1s.actual_time.t2 <= 17))  // only if the NP/EP remove a PTCCH activity
        {
          // Restart PTCCH DL task from the begining (i.e BURST 0).
          l1pa_l1ps_com.transfer.ptcch.activity ^= PTCCH_DL;  // disable PTCCH_DL activity running
          l1pa_l1ps_com.transfer.ptcch.request_dl = TRUE;     // restart PTCCH DL from the Burst0
        }
#endif

  // Deactivate task.
  // ******************

  // End of task -> task must become INACTIVE.
  // Rem: some TASKS (ALLC) can be pipelined and therefore must stay active if
  // they have already reentered the flow.
#if (FF_L1_FAST_DECODING == 1)
  if ( (burst_id == BURST_4) || fast_decoded )
#else /* #if (FF_L1_FAST_DECODING == 1) */
  if(burst_id == BURST_4)
#endif /* #if (FF_L1_FAST_DECODING == 1) #else*/

  {
#if (FF_L1_FAST_DECODING == 1)
    if((task == NP) || (task == NBCCHS))
    {
      if (l1a_apihisr_com.fast_decoding.contiguous_decoding == TRUE)
      {
        /* A new block has started, a new fast API IT is expected */
        l1a_apihisr_com.fast_decoding.contiguous_decoding = FALSE;
        l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_AWAITED;
      }
      else if(task == l1a_apihisr_com.fast_decoding.task)
      {
        /* Reset decoding status */
        l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE;
      }
    }  /* end if tsk == NP */
#endif /* #if (FF_L1_FAST_DECODING == 1) */    
    if(l1s.task_status[task].current_status == RE_ENTERED)
      l1s.task_status[task].current_status = ACTIVE;
    else
      l1s.task_status[task].current_status = INACTIVE;
#if (FF_L1_FAST_DECODING == 1)
    if (burst_id != BURST_4)
    {
      /* Successful decode before the 4th burst, no other control/read activities are needed */
      l1s_clean_mftab(task, burst_id + 3);
      if(l1s.frame_count == (4 -burst_id))
      {
          l1s.frame_count = 1;
      }
    }
#endif /* #if (FF_L1_FAST_DECODING == 1) */
  }

  #if (L1_DEBUG_IQ_DUMP == 1)
    l1ddsp_read_iq_dump(task);
  #endif

  // Flag the use of the MCU/DSP dual page read interface.
  // ******************************************************

  // Set flag used to change the read page at the end of "l1_synch".
  l1s_dsp_com.dsp_r_page_used = TRUE;
}


//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif

/*-------------------------------------------------------*/
/* l1s_read_nnb()                                        */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: BCCHN.                                         */
/* This function is the reading result function used for */
/* reading a neighbor cell block acquisition result in   */
/* idle mode. Here is a summary of the execution:        */
/*                                                       */
/*  - If SEMAPHORE(task) is low and task still enabled.  */
/*      - Traces and debug.                              */
/*      - Read DL DATA block from MCU/DSP interface.     */
/*  - Disactivate task.                                  */
/*  - Flag the use of the MCU/DSP dual page read         */
/*    interface.                                         */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   BCCHN, BCCH Neighbor reading task.                  */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip the body  */
/*   of this function if L1A has changed or is changing  */
/*   some of the task parameters.                        */
/*                                                       */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register.                       */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.task_status[task].current_status"                */
/*   current task status. It must be reset (INACTIVE)    */
/*   when the task is completed.                         */
/*   -> disactivate task.                                */
/*                                                       */
/* "l1s_dsp_com.dsp_r_page_used"                         */
/*   Flag used by the function which closes L1S          */
/*   execution ("l1s_end_manager()") to know if the      */
/*   MCU/DSP read page must be switched.                 */
/*   -> Set to 1.                                        */
/*                                                       */
/* Use of MCU/DSP interface:                             */
/* -------------------------                             */
/* "l1s_dsp_com.dsp_ndb_ptr"                             */
/*   pointer to the non double buffered part (NDB) of    */
/*   the MCU/DSP interface. This part is R/W for both    */
/*   DSP and MCU.                                        */
/*                                                       */
/* "l1s_dsp_com.dsp_db_r_ptr"                            */
/*   pointer to the double buffered part (DB) of the     */
/*   MCU/DSP interface. This pointer points to the READ  */
/*   page.                                               */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_read_nnb(UWORD8 task, UWORD8 param)
{
  BOOL     en_task;
  BOOL     task_param;
  UWORD16  neigh_radio_freq;
  UWORD16  pwr_level;
  UWORD8   active_neigh_id;
#if (L1_FF_MULTIBAND == 1)
 UWORD16 operative_radio_freq;
#endif


  /*--------------------------------------------------------*/
  /* READ NEIGBOR CELL RECEIVE TASK RESULTS...              */
  /*--------------------------------------------------------*/
  /* Rem: the full result is present in the mcu<-dsp        */
  /* communication buffer.                                  */
  /*--------------------------------------------------------*/
  // Get "enable" task flag and "synchro semaphore" for current task.
  en_task    = l1a_l1s_com.l1s_en_task[task];
  task_param = l1a_l1s_com.task_param[task];

  if((en_task) && !(task_param))
  // Check the task semaphore and the task enable bit. The reading
  // task body is executed only when the task semaphore is 0 and the
  // task is still enabled.
  // The semaphore can be set to 1 whenever L1A makes some changes
  // to the task parameters. The task can be disabled by L1A.
  {
    // Traces and debug.
    // ******************

    #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
      trace_fct(CST_L1S_READ_NNB ,(UWORD32)(-1));
    #endif


    #if (TRACE_TYPE!=0)
      // Check task identifier...
      #if L1_GPRS
        switch(l1a_l1s_com.dsp_scheduler_mode)
        {
          case GSM_SCHEDULER:
          {
            if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
              trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));
          } break;
          case GPRS_SCHEDULER:
          {
            if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_md & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
              trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));
          } break;
        }
      #else
        if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
          trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));
      #endif
    #endif

    l1_check_com_mismatch(task);

    #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
      uart_trace(task);
    #endif

    if(task == BCCHN)
      active_neigh_id = l1a_l1s_com.bcchn.active_neigh_id_norm;
    else // BCCHN_TRAN and BCCHN_TOP tasks
      active_neigh_id = l1a_l1s_com.bcchn.active_neigh_id_top;

    // the mean power level is impossible for the neighbor bloc, so the las input level is used.
    neigh_radio_freq = l1a_l1s_com.bcchn.list[active_neigh_id].radio_freq;
#if 1	/* FreeCalypso TCS211 reconstruction */
    pwr_level = l1a_l1s_com.last_input_level[neigh_radio_freq].input_level;
#elif (L1_FF_MULTIBAND == 0)
    pwr_level = l1a_l1s_com.last_input_level[neigh_radio_freq - l1_config.std.radio_freq_index_offset].input_level;
#else
    operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(neigh_radio_freq);
    pwr_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; 
#endif



    // Read downlink DATA block from MCU/DSP interface.
    // *************************************************

    // Read L3 frame block and send msg to L1A.
    #if L1_GPRS
      if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER)
        l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task);
      else
        l1s_read_l3frm(pwr_level,&(l1ps_dsp_com.pdsp_ndb_ptr->a_dd_gprs[0][0]), task);
    #else
        l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task);
    #endif
    // Disable the served TC from the TC bitmap.
    if(task == BCCHN)
      l1a_l1s_com.bcchn.list[active_neigh_id].bcch_blks_req ^=
        ((UWORD16)(1L << l1a_l1s_com.bcchn.active_neigh_tc_norm));
    else // BCCHN_TRAN and BCCHN_TOP tasks
      l1a_l1s_com.bcchn.list[active_neigh_id].bcch_blks_req ^=
        ((UWORD16)(1L << l1a_l1s_com.bcchn.active_neigh_tc_top));
  }

  // The BCCHN task was enabled and could cancel a PTCCH burst
  // This incomplete PTCCH decoding block cause DSP troubles and so COM/PM errors
  // and then a recovery (seen with ULYSS) => in this case restart the PTCCH from the burst 0
  #if L1_GPRS
    if (task == BCCHN_TRAN)
    if(l1a_l1s_com.l1s_en_task[PTCCH] == TASK_ENABLED)
    if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // a PTCCH DL task is running
    if ((l1s.actual_time.t2 >= 13) && (l1s.actual_time.t2 <= 18))  // only if the BCCHN remove a PTCCH activity
    {
      // Restart PTCCH DL task from the begining (i.e BURST 0).
      l1pa_l1ps_com.transfer.ptcch.activity ^= PTCCH_DL;  // disable PTCCH_DL activity running
      l1pa_l1ps_com.transfer.ptcch.request_dl = TRUE;     // restart PTCCH DL from the Burst0
     }
  #endif

  // Disactivate task.
  // ******************

  // End of task -> task must become INACTIVE.
  l1s.task_status[task].current_status = INACTIVE;

  #if (L1_DEBUG_IQ_DUMP == 1)
    l1ddsp_read_iq_dump(task);
  #endif

  // Flag the use of the MCU/DSP dual page read interface.
  // ******************************************************

  // Set flag used to change the read page at the end of "l1_synch".
  l1s_dsp_com.dsp_r_page_used = TRUE;
}

/*-------------------------------------------------------*/
/* l1s_read_dedic_dl()                                   */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is a "COMPLEX" function used by the L1S */
/* tasks: DDL,ADL,TCHTH,TCHTF,TCHA.                      */
/* This function is the reading result function used for */
/* dedicated mode. Here is a summary of the execution:   */
/*                                                       */
/*  - Traces and debug.                                  */
/*  - Read control results and feed control algo.        */
/*  - Read DL DATA block from MCU/DSP interface.         */
/*  - Flag the use of the MCU/DSP dual page read         */
/*    interface.                                         */
/*                                                       */
/* Input parameters:                                     */
/* -----------------                                     */
/* "task"                                                */
/*   DDL, SDCCH DOWNLINK reading task.                   */
/*   ADL, SACCH DOWNLINK (associated with SDCCH)reading  */
/*   task.                                               */
/*   TCHTH, TCH channel task when dedicated/TCH Half rate*/
/*   TCHTF, TCH channel task when dedicated/TCH Full rate*/
/*   TCHA, Associated channel task when dedicated/TCH.   */
/*                                                       */
/* "burst_id" (used only by DDL/ADL tasks).              */
/*   BURST_1, 1st burst of the task.                     */
/*   BURST_2, 2nd burst of the task.                     */
/*   BURST_3, 3rd burst of the task.                     */
/*   BURST_4, 4th burst of the task.                     */
/*                                                       */
/* Input parameters from globals:                        */
/* ------------------------------                        */
/* "l1a_l1s_com.task_param"                              */
/*   task semaphore bit register. Used to skip the body  */
/*   of this function if L1A has changed or is changing  */
/*   some of the task parameters.                        */
/*                                                       */
/* "l1a_l1s_com.l1s_en_task"                             */
/*   L1S task enable bit register.                       */
/*                                                       */
/* Modified parameters from globals:                     */
/* ---------------------------------                     */
/* "l1s.task_status[task].current_status"                */
/*   current task status. It must be reset (INACTIVE)    */
/*   when the task is completed.                         */
/*   -> disactivate task.                                */
/*                                                       */
/* "l1s_dsp_com.dsp_r_page_used"                         */
/*   Flag used by the function which closes L1S          */
/*   execution ("l1s_end_manager()") to know if the      */
/*   MCU/DSP read page must be switched.                 */
/*   -> Set to 1.                                        */
/*                                                       */
/* Use of MCU/DSP interface:                             */
/* -------------------------                             */
/* "l1s_dsp_com.dsp_ndb_ptr"                             */
/*   pointer to the non double buffered part (NDB) of    */
/*   the MCU/DSP interface. This part is R/W for both    */
/*   DSP and MCU.                                        */
/*                                                       */
/* "l1s_dsp_com.dsp_db_r_ptr"                            */
/*   pointer to the double buffered part (DB) of the     */
/*   MCU/DSP interface. This pointer points to the READ  */
/*   page.                                               */
/*                                                       */
/* RXQUAL :                                              */
/* 1) SDCCH : for RXQUAL_FULL and RXQUAL_SUB we accumu-  */
/*            -late number of estimated errors (a_cd[2]) */
/*            for ALL SACCH and SDCCH TDMA frames.       */
/* 2) TCH   : for RXQUAL_FULL in TCH_FS_MODE and         */
/*            TCH_24F_MODE, we accumulate number of      */
/*            estimated errors for ALL FACCH (a_fd[2])   */
/*            TDMA frames and ALL speech (a_dd_0[2])     */
/*            TDMA frames.                               */
/*            for RXQUAL_FULL in all data modes (except  */
/*            TCH_24F_MODE, see above) we accumulate     */
/*            number of errors for ALL FACCH (a_fd[2])   */
/*            TDMA frames and ALL data (a_dd_0[2])       */
/*            TDMA frames.                               */
/*            for RXQUAL_SUB in TCH_FS_MODE and          */
/*            TCH_24F_MODE, we only accumulate number of */
/*            estimated errors for FACCH (a_fd[2]) TDMA  */
/*            frames and speech (a_dd_0[2]) TDMA frames  */
/*            at SID block boundary position.            */
/*            for RXQUAL_SUB in all data modes (except   */
/*            TCH_24F_MODE, see above) we only accumulate*/
/*            number of estimated errors for FACCH       */
/*            (a_fd[2]) TDMA frames at SID block boundary*/
/*            position. The GSM specification 5.08 $8.4  */
/*            is not clear about data block at SID block */
/*            boundary position. Do we need to accumulate*/
/*            if L2/fill frame at this SID block boundary*/
/*            position.                                  */
/* Note: before accumulating FACCH TDMA frame we only    */
/*       check b_blud value, we don't mind about b_fire. */
/*-------------------------------------------------------*/
void l1s_read_dedic_dl(UWORD8 task, UWORD8 burst_id)
{
  UWORD32         toa;
  UWORD32         pm;
  UWORD32         angle;
  UWORD32         snr;
  BOOL            beacon;
  T_INPUT_LEVEL  *IL_info_ptr;
  UWORD16         radio_freq=0;

  #if TESTMODE
    UWORD32 pm_fullres =0;//omaps00090550
  #endif


  #if REL99
  #if FF_EMR
    T_EMR_PARAMS emr_params;    // strucutre to store pre-calculated parameter

    /*--------------------------------------------------------*/
    /* INITIALIZATION OF EMR params..                         */
    /*--------------------------------------------------------*/

    emr_params.task             = task;
    emr_params.burst_id         = burst_id;
    emr_params.facch_present    = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD;
    emr_params.facch_fire1      = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1;
    emr_params.a_dd_0_blud      = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
    emr_params.a_dd_0_bfi       = ((l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0])&(1<<B_BFI)) >> B_BFI; // 3rd bit tells the BAD frame
    emr_params.a_dd_1_blud      = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD;
    emr_params.a_dd_1_bfi       = ((l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0])&(1<<B_BFI)) >> B_BFI; // 3rd bit tells the BAD frame
    emr_params.b_m1             = ((l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl[1]) &(1<<B_M1)) >> B_M1; // = 1 if second half frame for data 14.4
    emr_params.b_f48blk_dl      = ((l1s_dsp_com.dsp_ndb_ptr->d_ra_act) &(1<<B_F48BLK_DL)) >> B_F48BLK_DL; // = 1 if second half frame for data 4.8
    emr_params.b_ce             = (((l1s_dsp_com.dsp_ndb_ptr->d_ra_conf) & (1<<B_CE)) >> B_CE);
    emr_params.a_ntd            = (((l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl[1]) & (1<<B_FCS_OK)) >> B_FCS_OK);
    emr_params.a_cd_fire1       = (l1s_dsp_com.dsp_ndb_ptr->a_cd[0] & (1<<B_FIRE1)) >> B_FIRE1;
    emr_params.sid_present_sub0 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_SID1)) >> B_SID1; // find out whether sid1 is 0/1
    emr_params.sid_present_sub1 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_SID1)) >> B_SID1; // find out whether sid1 is 0/1
    #if (AMR == 1)
      emr_params.amr_facch_present= (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD;
      emr_params.amr_facch_fire1  = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1;
      emr_params.b_ratscch_blud   = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD;
      emr_params.ratscch_rxtype   = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;
      emr_params.amr_rx_type_sub0 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;
      emr_params.amr_rx_type_sub1 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;
    #endif //(AMR == 1)
  #endif //FF_EMR
  #endif //REL99



  /*--------------------------------------------------------*/
  /* READ DEDICATED CHANNEL DL RESULTS...                   */
  /*--------------------------------------------------------*/

  // Traces and debug.
  // ******************
  #if (TRACE_TYPE!=0) && (TRACE_TYPE !=5)
      trace_fct(CST_L1S_READ_DEDIC_DL, -1);
  #endif

  #if (TRACE_TYPE!=0)
    // Check task identifier...
    if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
      trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));
  #endif

    #if (TESTMODE)
      // WARNING!
      // Don't trace MCU-DSP mismatches during UL-only in TestMode. The DSP is not working
      // in that case so it is normal. However, if tracing happens the CPU overloads
      if (l1_config.TestMode && l1_config.tmode.rf_params.down_up & TMODE_DOWNLINK)
    #endif
      {
          l1_check_com_mismatch(task);
      }

  radio_freq = l1a_l1s_com.dedic_set.radio_freq_dd;

  if (radio_freq == l1a_l1s_com.Scell_info.radio_freq)
  {
    beacon=1;
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon;
  }
  else
  {
    beacon=0;
    IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas;
  }

  #if (AMR == 1)
  {
    // RATSCCH detection
    UWORD16 ratscch_dl_header=l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0];
    UWORD16 b_ratscch_dl_blud = (ratscch_dl_header & (1<<B_BLUD)) >> B_BLUD;

    if(b_ratscch_dl_blud==TRUE)
    {
      UWORD8 rx_type = (ratscch_dl_header & RX_TYPE_MASK) >> RX_TYPE_SHIFT;

      if(rx_type==C_RATSCCH_GOOD)
      {
        // RATSCCH block detected
        l1s_amr_update_from_ratscch(&l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0]);
      }
    }
  }
  #endif    // AMR

  switch(task)
  {
    case DDL :
    case ADL :
    /*---------------------------------------------------*/
    /* Dedicated mode: SDCCH receive task.               */
    /* Rem: only a partial result is present in the      */
    /* mcu<-dsp communication buffer. The BLOCK content  */
    /* itself is in the last comm. (BURST_4)             */
    /*---------------------------------------------------*/
    {
      UWORD8    i, IL_for_rxlev;

      #if (TRACE_TYPE!=0)
        // Check burst identifier...
        if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_burst_d & 0xffff) != burst_id)
          trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND, (UWORD32)(-1));
      #endif

      // Read control results and feed control algorithms.
      // **************************************************

      // Read control information.
      toa   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;
      pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff) >> 5;
      angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
      snr   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;

      l1_check_pm_error(pm, task);

      // Update AGC: Call DPAGC algorithm
      IL_for_rxlev = l1ctl_dpagc(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // dtx_on = 0

      // Dedicated mode serving cell measurement reading.
      #if REL99
      #if FF_EMR
        // only task,burst_id is valid in structure pointed by *emr_params
        l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params);
      #endif
      #else
        l1s_read_dedic_scell_meas(IL_for_rxlev, 1);
      #endif

      #if TRACE_TYPE==3
        stats_samples_nb(toa,pm,angle,snr,burst_id,task);
      #endif

      // Update AFC: Call AFC control function (KALMAN filter).
      #if AFC_ALGO
        #if TESTMODE
          if (l1_config.afc_enable)
        #endif
          {
            #if (VCXO_ALGO == 0)
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq);
            #else
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode);
            #endif
          }
      #endif

      //Feed TOA histogram.
      #if (TOA_ALGO != 0)
          #if (TOA_ALGO == 2)
            if(l1s.toa_var.toa_snr_mask == 0)
          #else
            if(l1s.toa_snr_mask == 0)
          #endif
          {
            #if 1	/* FreeCalypso TCS211 reconstruction */
              if (IL_for_rxlev < IL_FOR_RXLEV_SNR)
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count);
              else
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count);
            #else
              UWORD32 snr_temp;
              snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0;
              #if (TOA_ALGO == 2)
                l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa);
              #else
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count
                #if (FF_L1_FAST_DECODING ==1)
                    ,0
                #endif
                    );
              #endif
            #endif
          }
      #endif

       #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
         RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev)
       #endif
       #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM
         l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
       #endif
       #if (BURST_PARAM_LOG_ENABLE == 1)
         l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
       #endif
      // Read downlink DATA block from MCU/DSP interface.
      // *************************************************

      if(burst_id == BURST_4)
      {
        #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
          uart_trace(task);
        #endif

        if(task == DDL)
        {
          // Read DCCH DL data block from DSP, pass it to L2.
          l1s_read_dcch_dl(l1s_dsp_com.dsp_ndb_ptr->a_cd, task);
        }
        else
        {
          // Read L2 frame block and send msg to L1A.
          l1s_read_sacch_dl(l1s_dsp_com.dsp_ndb_ptr->a_cd, task);
        }

        // RXQUAL_FULL/RXQUAL_SUB : number of estimated errors, this value is contained
        // in a_cd[2] field, for every SACCH and SDDCH blocks
        l1a_l1s_com.Smeas_dedic.qual_acc_full      += l1s_dsp_com.dsp_ndb_ptr->a_cd[2]&0xffff;
        l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += A_D_BLEN;
        l1a_l1s_com.Smeas_dedic.qual_acc_sub       += l1s_dsp_com.dsp_ndb_ptr->a_cd[2]&0xffff;
        l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub  += A_D_BLEN;

        // TEMPORARY : reset buffers and flags in NDB ...
        //             reset nerr....
        //             reset A_CD contents.......
        l1s_dsp_com.dsp_ndb_ptr->a_cd[0]   =  (1<<B_FIRE1); // B_FIRE1=1,B_FIRE0=0,BLUD=0.
        l1s_dsp_com.dsp_ndb_ptr->a_cd[2]   =  0xffff;
        for (i=0; i<12  ;i++)
          l1s_dsp_com.dsp_ndb_ptr->a_cd[3+i] =  0x0000;

        // task is completed, make it INACTIVE.
        l1s.task_status[task].current_status = INACTIVE;
      }
    }
    break;

    case TCHTH:
    /*---------------------------------------------------*/
    /* Dedicated mode: TCHTH receive task.               */
    /*                 HALF RATE                         */
    /*---------------------------------------------------*/
    {
      UWORD32   b_blud;
      UWORD8    channel_mode;
      //OMAPS00090550 UWORD8    channel_type;
      UWORD8    subchannel;
      UWORD32   l1_mode;
      UWORD32   fn_mod_104;
      UWORD32   fn_mod_52;
      //OMAPS00090550 UWORD32   fn_report_mod13_mod4;
      UWORD32   normalised_fn_report_mod13_mod4;
      UWORD32   normalised_fn_report_mod26;
      UWORD8    IL_for_rxlev = 0; //omaps00090550
      #if (AMR == 1)
        UWORD8    rx_type;
        UWORD8    b_ratscch_blud,b_facch_blud;
        UWORD8    voco_type;
        BOOL      facch_present = FALSE;
        #if REL99
        #if FF_EMR
          emr_params.amr_facch_present = FALSE;
          emr_params.amr_facch_fire1   = FALSE;
        #endif
		#endif
      #endif

      // Read control results and feed control algorithms.
      // **************************************************

      // Read control information.
      toa   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;
      pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff) >> 5;
      angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
      snr   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;

      l1_check_pm_error(pm, task);

      #if TRACE_TYPE==3
        stats_samples_tch(toa,pm,angle,snr);
      #endif
      #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
        uart_trace(TCHTH);
      #endif

      // Update AFC: Call AFC control function (KALMAN filter).

      #if AFC_ALGO
        #if TESTMODE
          if (l1_config.afc_enable)
        #endif
          {
            #if (VCXO_ALGO == 0)
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq);
            #else
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode);
            #endif
          }
      #endif

      // Increment number of burst not sent due to DTX.
      if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) == TCH_DTX_UL)
      {
        l1a_l1s_com.Smeas_dedic.dtx_used++;
        l1s.dtx_ul_on = TRUE;
      }
      else
      {
        l1s.dtx_ul_on = FALSE;
      }

      // Check SID frame subset...
      channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode;
//OMAPS00090550      channel_type = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type;
      subchannel   = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->subchannel;
      fn_mod_104   = l1s.actual_time.fn % 104;
      fn_mod_52    = l1s.actual_time.fn % 52;

    #if REL99
    #if FF_EMR
      // Compute FN in reporting period % 13 % 4 = (((FN-subchannel)+ 13) %13) %4
      normalised_fn_report_mod13_mod4 = ((l1s.actual_time.fn - subchannel + 13)  % 13) % 4;

      // Compute FN in reporting period % 26 independently of the considered subchannel.
      normalised_fn_report_mod26 = (l1s.actual_time.fn - subchannel + 26)  % 26;

      emr_params.channel_mode                    = channel_mode;
      emr_params.subchannel                      = subchannel;
      emr_params.normalised_fn_mod13_mod4 = normalised_fn_report_mod13_mod4;
    #endif //FF_EMR
    #endif //REL99


    #if (AMR == 1)
      // Check if we're in AMR DTX mode
      if(channel_mode==TCH_AHS_MODE &&
         ( (((l1s.actual_time.fn_mod13 % 4)==3) && (subchannel==0)) ||    // AHS0: block is decoded on DSP side at fn%13%4=2
           (((l1s.actual_time.fn_mod13 % 4)==0) && (subchannel==1)) ))    // AHS1: block is decoded on DSP side at fn%13%4=3
      {
        if(subchannel==0)
        {
          b_blud  = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
          rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;
        }
        else
        {
          b_blud  = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD;
          rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;
        }
        b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD;
        b_facch_blud   = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD;

        // Check if AMR DTX mode is on
        if((((rx_type==SID_FIRST) || (rx_type==SID_UPDATE) || (rx_type==SID_BAD)) && b_blud==TRUE) ||
           (rx_type==AMR_NO_DATA && b_blud==FALSE))
		{
          l1s.dtx_amr_dl_on=TRUE;
		}
        else if(b_ratscch_blud==FALSE && b_facch_blud==FALSE)
		{
          l1s.dtx_amr_dl_on=FALSE;
		}
      }
    #endif

    #if (AMR == 1)
      if (channel_mode != TCH_AHS_MODE)
      {
      // This AGC and TOA update isn't applied to the adaptative half rate mode.
      if(((channel_mode == TCH_HS_MODE) && (subchannel == 0) &&
          (fn_mod_52 > 0)  && (fn_mod_52 <= 7))  ||
         ((channel_mode == TCH_HS_MODE) && (subchannel == 1) &&
          (fn_mod_52 > 14)  && (fn_mod_52 <= 21))  ||
         ((channel_mode != TCH_HS_MODE)  &&
         (subchannel == 0) && (fn_mod_104 > 56) && (fn_mod_104 <= 76)) ||
         ((channel_mode != TCH_HS_MODE)  &&
         (subchannel == 1) && (fn_mod_104 > 66) && (fn_mod_104 <= 86)))
    #else
      if(((channel_mode == TCH_HS_MODE) && (subchannel == 0) &&
          (fn_mod_52 > 0)  && (fn_mod_52 <= 7))  ||
         ((channel_mode == TCH_HS_MODE) && (subchannel == 1) &&
          (fn_mod_52 > 14)  && (fn_mod_52 <= 21))  ||
         ((channel_mode != TCH_HS_MODE) && (subchannel == 0) &&
          (fn_mod_104 > 56) && (fn_mod_104 <= 76)) ||
         ((channel_mode != TCH_HS_MODE) && (subchannel == 1) &&
          (fn_mod_104 > 66) && (fn_mod_104 <= 86)))
    #endif
      // Current results are from the TDMA frame subset always received (GSM05.08, $8.3).
      // -> pwr meas. must be used for SUB set result.
      // -> TOA filtering can be fed with SNR/TOA.
      // WARNING: TCH/H in signalling only is here processed like TCH/H data. GSM spec is
      // ======== unclear !!!!!!!!!!!!!!!1
      {
        // Update AGC: Call DPAGC algorithm
        IL_for_rxlev = l1ctl_dpagc(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);

        // Dedicated mode serving cell measurement reading, indicate "SUB".
        #if REL99
        #if FF_EMR
          l1s_read_dedic_scell_meas(IL_for_rxlev, 1,&emr_params);
        #endif
        #else
          l1s_read_dedic_scell_meas(IL_for_rxlev, 1);
        #endif

        //Feed TOA histogram.
        #if (TOA_ALGO != 0)
          // When in 1/2 rate data, we are working on 14 SID frames (instead
          // of 12 otherwise), so we need to increment length of the histogram
          // filling period from 36 to 42.
          if (channel_mode != TCH_HS_MODE)
            l1_mode=DEDIC_MODE_HALF_DATA;
          else
            l1_mode=l1a_l1s_com.mode;

          #if (TOA_ALGO == 2)
            if(l1s.toa_var.toa_snr_mask == 0)
          #else
            if(l1s.toa_snr_mask == 0)
          #endif
          {
            #if 1	/* FreeCalypso TCS211 reconstruction */
              if (IL_for_rxlev < IL_FOR_RXLEV_SNR)
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count);
              else
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count);
            #else
              UWORD32 snr_temp;
              snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0;
              #if (TOA_ALGO == 2)
                l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, snr_temp, toa);
              #else
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count
                #if (FF_L1_FAST_DECODING == 1)
                    ,0
                #endif
                    );
              #endif
            #endif
          }
        #endif
      } // if(((channel_mode == TCH_HS_MODE) && (subchannel == 0) &&
      else
      {
        // Update AGC: Call DPAGC algorithm
        IL_for_rxlev = l1ctl_dpagc(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr);

        // Dedicated mode serving cell measurement reading, full set only.
        #if REL99
        #if FF_EMR
          l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
        #endif
        #else
          l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
        #endif
      }

    #if (AMR == 1)
      } // if (channel_mode != TCH_AHS_MODE)
    #endif

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev)
      #endif
      #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM
        l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
      #endif
      #if (BURST_PARAM_LOG_ENABLE == 1)
        l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
      #endif

      // Read downlink DATA block from MCU/DSP interface.
      // *************************************************

      // Compute FN % 13 % 4
      //OMAPS00090550 fn_report_mod13_mod4 = (l1s.actual_time.fn_mod13) % 4;
      // Compute normalised FN % 13 %4 = (((FN-subchannel)+ 13) %13) %4
      normalised_fn_report_mod13_mod4 = ((l1s.actual_time.fn - subchannel + 13)  % 13) % 4;
      // Compute normalised FN %26 = ((FN - subchannel)+ 26) %26
      normalised_fn_report_mod26 = (l1s.actual_time.fn - subchannel + 26)  % 26;

      if((normalised_fn_report_mod26 == 16)||
         (normalised_fn_report_mod26 == 24)||
         (normalised_fn_report_mod26 == 7))
        // It is time to get FACCH/H data block.
      {
        // FACCH: Check A_FD information block.
        //-------------------------------------

      UWORD8  temp;
        b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD;
        #if ((REL99) && (AMR == 1))
        #if FF_EMR
          emr_params.amr_facch_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1;
        #endif
        #endif

        if(b_blud == TRUE)
        {
          // Read FACCH DL data block from DSP, pass it to L2.
      #if ( FF_REPEATED_DL_FACCH == 1 )
               #if (TRACE_TYPE == 1 || TRACE_TYPE == 4)
                trace_info.facch_dl_count_all++;
               #endif
                  // if the current block is a repetition reports NULL to L2 otherwise reports the current block
                  l1s_read_dcch_dl((API*)l1s_repeated_facch_check(l1s_dsp_com.dsp_ndb_ptr->a_fd), task);
       #else
                  l1s_read_dcch_dl(l1s_dsp_com.dsp_ndb_ptr->a_fd, task);
       #endif

        #if (AMR == 1)
          if (channel_mode != TCH_AHS_MODE)
          {
        #endif

          // RXQUAL_SUB : In case of data taffic channels, accumulate number of
          // estimated errors, this value is contained in a_fd[2] field, only
          // for SID TDMA frames received as FACCH frames. (GSM 5.08 $8.4)
          if (((fn_mod_104==59) &&  (channel_mode==TCH_HS_MODE)     && (subchannel==0))    ||
              ((fn_mod_104==73) &&  (channel_mode==TCH_HS_MODE)     && (subchannel==1))    ||
              ((fn_mod_104==76) && ((channel_mode==TCH_48H_MODE)||
                                    (channel_mode==TCH_24H_MODE))   && (subchannel==0))    ||
              ((fn_mod_104==86) && ((channel_mode==TCH_48H_MODE)||
                                    (channel_mode==TCH_24H_MODE))   && (subchannel==1)))
          // last SID TDMA frame received as FACCH frames.
          {
             l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff;
             l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN;
          }

        #if (AMR == 1)
          } // if (channel_mode != TCH_AHS_MODE)
          else
          {
            // Indicate to AMR specific processing that burst was a FACCH
            facch_present = TRUE;
            #if ((REL99) && (AMR == 1))
            #if FF_EMR
              emr_params.amr_facch_present = facch_present;
            #endif
            #endif


            // Update AGC: Call DPAGC algorithm
            IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);

            // Dedicated mode serving cell measurement reading, indicate "FULL".
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
            #endif
          }
        #endif

          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_fd[2] field, for each TCHT block.
          // The same for AMR
	#if (AMR == 1)
          // in AMR, l1s.dtx_amr_dl_on is FALSE if DTX mode is off
          // in non AMR TCH, l1s.dtx_amr_dl_on is always FALSE
          // In AMR DTX, DSP patch sometimes reports FACCH blocks which ARE NOT FACCH blocks
          // therefore they shouldn't be taken into account in the RXQUALL_FULL computation
          if(l1s.dtx_amr_dl_on==FALSE)
	#endif
		  {
          l1a_l1s_com.Smeas_dedic.qual_acc_full      += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff;
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN;
		  }

          // Reset A_FD header.
          // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0
          l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1);
          l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff;

          // Rem: when FACCH is received, we must reset A_DD_0 header also.
          // Reset A_DD_0 header in NDB.
#if (AMR == 1)
          if ((channel_mode==TCH_AHS_MODE) && (subchannel==0))
          {
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] &= (API)(RX_TYPE_MASK);
          }
          else
#endif
          {
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
          }
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;

          // Rem: when FACCH is received, we must reset A_DD_1 header also.
          // Reset A_DD_0 header in NDB.
#if (AMR == 1)
          if ((channel_mode==TCH_AHS_MODE) && (subchannel==1))
          {
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] &= (API)(RX_TYPE_MASK);
          }
          else
#endif
          {
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0;
          }
          l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff;

        } // if(b_blud == TRUE)

        else
        // No FACCH received at FACCH boundary frame. Nevertheless, need to read dummy
        // FACCH DL data block.
        {
          // Dummy: Read FACCH DL data block from DSP, pass it to L2.
          // Rem: this is an upper layer requirement to call this
          // function at every FACCH DL boundary.
          l1s_read_dcch_dl(NULL, task);
        }
      } // if((normalised_fn_report_mod26 == 16)|| ...

      // else we are not at FACCH boundary frame
      // We must check for the presence of a TCH/H block (even if it does fall on a FACCH boundary)
      // We use the b_blud bit to confirm presence of TCH/H (or FACCH)
      if((normalised_fn_report_mod13_mod4 == 3) && (channel_mode==TCH_HS_MODE))
      // It is time to get TCH/HS data block.
      {
        #if TRACE_TYPE==3
          if (l1_stats.type == PLAY_UL       &&
             (channel_mode  == TCH_HS_MODE))
            play_trace();
        #endif
        if (tch_dl_sniff_mode && channel_mode == TCH_HS_MODE)
        {
          if (subchannel == 0)
            tch_send_downlink_bits(l1s_dsp_com.dsp_ndb_ptr->a_dd_0, 11,
                                   channel_mode, fn_mod_104);
          else if (subchannel == 1)
            tch_send_downlink_bits(l1s_dsp_com.dsp_ndb_ptr->a_dd_1, 11,
                                   channel_mode, fn_mod_104);
        }

        // Check A_DD_0 information block only if no FACCH.
        if (subchannel==0)
           b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
        else
           b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD;

        if(b_blud == TRUE)
        {
          if (subchannel==0)
          {
            // RXQUAL_SUB : In case of speech traffic channels, accumulate number of
            // estimated errors, this value is contained in a_dd_0[2] field, only
            // for SID TDMA frames. (GSM 5.08 $8.4)
            if (fn_mod_104==59)
            {
               l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
               l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_HS_BLEN;
            }
            // RXQUAL_FULL : accumulate number of estimated errors, this value is
            // contained in a_dd_0[2] field, for each TCHT block.
            l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
            // Reset A_DD_0 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
          } // if (subchannel==0)
          else
          {
            // RXQUAL_SUB : In case of speech traffic channels, accumulate number of
            // estimated errors, this value is contained in a_dd_1[2] field, only
            // for SID TDMA frames. (GSM 5.08 $8.4)
            if (fn_mod_104==73)
            {
               l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;
               l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_HS_BLEN;
            }
            l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;
            // Reset A_DD_1 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0;
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff;
          }
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_HS_BLEN;
        } // if(b_blud == TRUE)
      } // if((normalised_fn_report_mod13_mod4 == 3) && (channel_mode==TCH_HS_MODE))

    #if (AMR == 1)
      if(((normalised_fn_report_mod26 == 20)  ||
          (normalised_fn_report_mod26 == 3)   ||
          (normalised_fn_report_mod26 == 11)) &&
         ((channel_mode == TCH_48H_MODE)      ||
          (channel_mode == TCH_24H_MODE)))
    #else
      if(((normalised_fn_report_mod26 == 20)  ||
          (normalised_fn_report_mod26 == 3)   ||
        (normalised_fn_report_mod26 == 11)) && (channel_mode!=TCH_HS_MODE))
    #endif
      // It is time to get TCH/H4.8 or TCH/H2.4 data block.
      {
        // Check A_DD_0 information block only if no FACCH.
        if (subchannel==0)
           b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
        else
           b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD;

        if(b_blud == TRUE)
        {
          if (subchannel==0)
          {
            // RXQUAL_SUB : In case of speech traffic channels, accumulate number of
            // estimated errors, this value is contained in a_dd_0[2] field, only
            // for SID TDMA frames. (GSM 5.08 $8.4)
            if (fn_mod_104==76)
            {
               l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
               l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN;
            }
            // RXQUAL_FULL : accumulate number of estimated errors, this value is
            // contained in a_dd_0[2] field, for each TCHT block.
            l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;

            // Reset A_DD_0 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
          }
          else
          {
            // RXQUAL_SUB : In case of speech traffic channels, accumulate number of
            // estimated errors, this value is contained in a_dd_1[2] field, only
            // for SID TDMA frames. (GSM 5.08 $8.4)
            if (fn_mod_104==86)
            {
               l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;
               l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN;
            }
            l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;
            // Reset A_DD_1 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0;
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff;
          }
          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_dd_1[2] field, for each TCHT block.
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN;

          // WARNING: sequence number is not implemented in DATA half rate
          // TO BE DEFINED......
        } // if(b_blud == TRUE)
      } // if(((normalised_fn_report_mod26 == 20)  || ...
    #if (AMR == 1)
      if ((channel_mode == TCH_AHS_MODE) && (facch_present == FALSE))
      {
        // the channel is a TCH/AHS and it's time to receive a new block
        if (subchannel == 0)
        {
          // Load the bit to check if the block is valid
          b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
        }
        else // subchannel 1
        {
          // Load the bit to check if the block is valid
          b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD;
        }

        b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD;

        // All frames except NO_DATA (b_blud = FALSE) and FACCH, i.e AMR speech/SID block or a RATSCCH block
        if(b_ratscch_blud==TRUE)
        {
          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_ratscch_dl[2] field, for each TCHT block.
          l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] & 0xffff;

          // Reset the A_RATSCCH_DL header in NDB.
          l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] = 0;
          l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] = 0xffff;

          // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on
          // the block received.
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += RATSCCH_BLEN;

          IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
            #endif
        }
        else if(b_blud==TRUE)
        {
          if (subchannel == 0)
          {
            // Load the type of the block received
            rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;

            // Load the type of vocoder currently used
            voco_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & VOCODER_TYPE_MASK) >> VOCODER_TYPE_SHIFT;

          #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
            Trace_dedic_tch_block_stat(rx_type, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], voco_type);
          #endif

            // RXQUAL_SUB : In case of adaptative traffic channel, accumulate number of estimated errors
            // is contained in the a_dd_0[2] value but the accumulation is made with SID_UPDATE frame only.
           if((rx_type==SID_UPDATE) || (rx_type==SID_BAD))

            {
              l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
              l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += SID_UPDATE_BLEN;
            }

            // RXQUAL_FULL : accumulate number of estimated errors, this value is
            // contained in a_dd_0[2] field, for each TCHT block.
              l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;









            // Reset A_DD_0 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] &= (API)(RX_TYPE_MASK);
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
          }
          else // subchannel ==1
          {
            // Load the type of the block received
            rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;

            // Load the type of vocoder currently used
            voco_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & VOCODER_TYPE_MASK) >> VOCODER_TYPE_SHIFT;

          #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
            Trace_dedic_tch_block_stat(rx_type, l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2], voco_type);
          #endif

            // RXQUAL_SUB : In case of adaptative traffic channel, accumulate number of estimated errors
            // is contained in the a_dd_1[2]  value but the accumulation is made with SID_UPDATE block only.
			if((rx_type==SID_UPDATE) || (rx_type==SID_BAD))

            {
              l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;
              l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += SID_UPDATE_BLEN;
            }

            // RXQUAL_FULL : accumulate number of estimated errors, this value is
            // contained in a_dd_1[2] field, for each TCHT block.
              l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;

            // Reset A_DD_1 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] &= (API)(RX_TYPE_MASK);
            l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff;
          } // subchannel == 1





          // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on
          // the block received.
if((rx_type==SPEECH_GOOD) || (rx_type==SPEECH_DEGRADED) || (rx_type==SPEECH_BAD))
          {
            // The block length depens on the vocoder type
            switch (voco_type)
            {
              case AMR_CHANNEL_7_95:
              {
                // TCH-AHS 7.95
                l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_7_95_BLEN;
              }
              break;
              case AMR_CHANNEL_7_4:
              {
                // TCH-AHS 7.4
                l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_7_4_BLEN;
              }
              break;
              case AMR_CHANNEL_6_7:
              {
                // TCH-AHS 6.7
                l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_6_7_BLEN;
              }
              break;
              case AMR_CHANNEL_5_9:
              {
                // TCH-AHS 5.9
                l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_5_9_BLEN;
              }
              break;
              case AMR_CHANNEL_5_15:
              {
                // TCH-AHS 5.15
                l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_5_15_BLEN;
              }
              break;
              case AMR_CHANNEL_4_75:
              {
                // TCH-AHS 4.75
               l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_4_75_BLEN;
              }
              break;
            } // switch
          } // if ( (rx_type == SPEECH_GOOD) || ...
          else
			if((rx_type == SID_UPDATE) || (rx_type == SID_BAD))

          {
            // the block is a SID UPDATE
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += SID_UPDATE_BLEN;
          }







          // AGC, TOA update for AMR... SUB FIFO only for SID_UPDATE frame
          if((rx_type == SID_UPDATE) || (rx_type == SID_BAD))

          {
            IL_for_rxlev = l1ctl_dpagc_amr(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 1);
            #endif

          #if (TOA_ALGO != 0)
            #if (TOA_ALGO == 2)
              if(l1s.toa_var.toa_snr_mask == 0)
            #else
              if(l1s.toa_snr_mask == 0)
            #endif
            {
              #if 1	/* FreeCalypso TCS211 reconstruction */
                if (IL_for_rxlev < IL_FOR_RXLEV_SNR)
                  l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count);
                else
                  l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count);
              #else
                UWORD32 snr_temp;
                snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0;
                #if (TOA_ALGO == 2)
                  l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa);
                #else
                  l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count
                  #if (FF_L1_FAST_DECODING == 1)
                      ,0
                  #endif
                      );
                #endif
              #endif
            }
          #endif
          }
          else
          {
            IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
            #endif
          }
        } // if (b_blud == TRUE)
        // simple burst or NO_DATA frame
        else
        {
          // NO_DATA is considered a bad frame
          if (normalised_fn_report_mod13_mod4 == 3)
          {
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_4_75_BLEN;
            if (subchannel == 0)
            {
              l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;

            #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
              Trace_dedic_tch_block_stat(AMR_NO_DATA, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], 0);
            #endif

              // Reset A_DD_0 header in NDB.
              l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] &= (API)(RX_TYPE_MASK);
              l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
            }
            else
            {
              l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff;

            #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
              Trace_dedic_tch_block_stat(AMR_NO_DATA, l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2], 0);
            #endif

              // Reset A_DD_0 header in NDB.
              l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] &= (API)(RX_TYPE_MASK);
              l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff;
            }
          }
          // Update AGC: Call DPAGC AMR algorithm in order to fill the G_all buffer
          IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr);

          // Dedicated mode serving cell measurement reading, full set only.
          #if REL99
          #if FF_EMR
            l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
          #endif
          #else
            l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
          #endif
        }
      } // if ((channel_mode == TCH_AHS_MODE) && (facch_present == FALSE))
    #endif

      // task is completed, make it INACTIVE.
      l1s.task_status[task].current_status = INACTIVE;
    }
    break;

    case TCHTF:
    /*---------------------------------------------------*/
    /* Dedicated mode: TCHTF receive task.               */
    /*                 FULL RATE                         */
    /*---------------------------------------------------*/
    {
      UWORD8   IL_for_rxlev = 0; //omaps00090550
      UWORD32  b_blud;

      UWORD8   channel_mode;
      //OMAPS00090550 UWORD8   channel_type;
      UWORD32  fn_mod_104;
      //OMAPS00090550 UWORD32  fn_mod_52;
      UWORD32  fn_report_mod13_mod4;
      #if (AMR == 1)
        UWORD8   rx_type;
        UWORD8   b_ratscch_blud,b_facch_blud;
        BOOL     facch_present = FALSE;
      #endif

      #if TESTMODE
        xSignalHeaderRec *msg;
      #endif

      // Read control results and feed control algorithms.
      // **************************************************

      // Read control information.
      toa   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;
      pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff) >> 5;
      angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
      snr   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;

      l1_check_pm_error(pm, task);

      #if TRACE_TYPE==3
        stats_samples_tch(toa,pm,angle,snr);
      #endif

      #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
        uart_trace(TCHTF);
      #endif

      // Update AFC: Call AFC control function (KALMAN filter).
      #if AFC_ALGO
        #if TESTMODE
          if (l1_config.afc_enable)
        #endif
          {
            #if (VCXO_ALGO == 0)
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq);
            #else
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode);
            #endif
          }
      #endif

      // Check SID frame subset...
      channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode;
      //OMAPS00090550 channel_type = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type;
      fn_mod_104   = l1s.actual_time.fn % 104;
      //OMAPS00090550 fn_mod_52    = l1s.actual_time.fn % 52;

	  #if (AMR == 1)
      // Check if we're in AMR DTX mode
      if(channel_mode==TCH_AFS_MODE && (l1s.actual_time.fn_mod13 % 4)==0)    // AFS: block is decoded on DSP side at fn%13%4=3
      {
        b_blud         = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
        rx_type        = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;
        b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD;
        b_facch_blud   = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD;

        // Check if AMR DTX mode is on
        if((((rx_type==SID_FIRST) || (rx_type==SID_UPDATE) || (rx_type==SID_BAD)) && b_blud==TRUE) ||
           (rx_type==AMR_NO_DATA && b_blud==FALSE))
		{
          l1s.dtx_amr_dl_on=TRUE;
		}
        else if(b_ratscch_blud==FALSE && b_facch_blud==FALSE)
		{
          l1s.dtx_amr_dl_on=FALSE;
		}
      }
	 #endif

      #if REL99
      #if FF_EMR
        emr_params.channel_mode = channel_mode;
//        emr_params.fn_mod13_mod4 = l1s.actual_time.fn_mod13_mod4;
        #if (AMR == 1)
          emr_params.amr_facch_present = FALSE;
          emr_params.amr_facch_fire1 = FALSE;
        #endif
       #endif
      #endif

      // Increment number of burst not sent due to DTX.
      if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) == TCH_DTX_UL)
      {
        l1a_l1s_com.Smeas_dedic.dtx_used++;
        l1s.dtx_ul_on = TRUE;
      }
      else
      {
        // Some bursts are always sent in DTX mode. d_task_u does not give DTX_UL
        // so we must keep previous value of dtx_on
        if (! ((fn_mod_104 > 52) && (fn_mod_104 <= 60)) )
          l1s.dtx_ul_on = FALSE;
      }

    #if FF_L1_IT_DSP_DTX
      // Currently used for TCH-AFS only
      if (l1s.actual_time.fn_mod13_mod4 == 0) // FN%13 = 4, 8 and 12 (no TCH/F Read on FN%13=0)
      {
        // Latch TX activity status if DTX allowed
        if ((l1a_l1s_com.dedic_set.aset->dtx_allowed == FALSE) ||                // No DTX allowed
            (l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enc_data) ||                    // DTX allowed but not used
            (l1a_apihisr_com.dtx.fast_dtx_ready == FALSE))                       // Fast DTX status is invalid
          l1a_apihisr_com.dtx.tx_active = TRUE;
        else
          l1a_apihisr_com.dtx.tx_active = FALSE;
      }
    #endif

    #if (AMR == 1)
      if (channel_mode != TCH_AFS_MODE)
      {
      // This AGC and TOA update isn't applied to the adaptative full rate mode
    #endif

      if((fn_mod_104 > 52) && (fn_mod_104 <= 60))
      // Current results are from the TDMA frame subset always received (GSM05.08, $8.3).
      // -> pwr meas. must be used for SUB set result.
      // -> TOA filtering can be fed with SNR/TOA.
      // This DTX is only applied to the mode EFR, FR and data.
      {
        // Update AGC: Call DPAGC algorithm
        IL_for_rxlev = l1ctl_dpagc(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);

        // Dedicated mode serving cell measurement reading, indicate "SUB".
        #if REL99
        #if FF_EMR
          l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params);
        #endif
        #else
          l1s_read_dedic_scell_meas(IL_for_rxlev, 1);
        #endif

        //Feed TOA histogram.
        #if (TOA_ALGO != 0)
          #if (TOA_ALGO == 2)
            if(l1s.toa_var.toa_snr_mask == 0)
          #else
            if(l1s.toa_snr_mask == 0)
          #endif
          {
            #if 1	/* FreeCalypso TCS211 reconstruction */
              if (IL_for_rxlev < IL_FOR_RXLEV_SNR)
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count);
              else
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count);
            #else
              UWORD32 snr_temp;
              snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0;
              #if (TOA_ALGO == 2)
                l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa);
              #else
                l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count
                #if (FF_L1_FAST_DECODING == 1)
                    ,0
                #endif
                    );
              #endif
            #endif
          }
        #endif
      }
      else
      {
        // Update AGC: Call DPAGC algorithm
        IL_for_rxlev = l1ctl_dpagc(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr);

        // Dedicated mode serving cell measurement reading, full set only.
        #if REL99
        #if FF_EMR
          l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
        #endif
        #else
          l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
        #endif
      }
    #if (AMR == 1)
      } // if (channel_mode != TCH_AFS_MODE)
    #endif

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev)
      #endif
      #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM
        l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
      #endif
      #if (BURST_PARAM_LOG_ENABLE == 1)
        l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
      #endif

      // Read downlink DATA block from MCU/DSP interface.
      // *************************************************

      // Compute FN in reporting period % 13 % 4.
      fn_report_mod13_mod4 = (l1s.actual_time.fn_mod13) % 4;

      if(fn_report_mod13_mod4 == 0)
      // It is time to get FACCH/F or TCH/F2.4 or TCH/(E)FS data block.
      {
        UWORD8 temp;
        #if TRACE_TYPE==3
          if (l1_stats.type == PLAY_UL &&
             (channel_mode == TCH_FS_MODE || channel_mode == TCH_24F_MODE
              || channel_mode == TCH_EFR_MODE))
            play_trace();
        #endif
        if (tch_dl_sniff_mode &&
            (channel_mode == TCH_FS_MODE || channel_mode == TCH_EFR_MODE))
        {
            tch_send_downlink_bits(l1s_dsp_com.dsp_ndb_ptr->a_dd_0, 20,
                                   channel_mode, fn_mod_104);
        }

        // FACCH: Check A_FD information block.
        //-------------------------------------

        b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD;
        #if ((REL99) && (AMR == 1))
        #if FF_EMR
          emr_params.amr_facch_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1;
        #endif
		#endif

        if(b_blud == TRUE)
        {
          // Read FACCH DL data block from DSP, pass it to L2.
        #if ( FF_REPEATED_DL_FACCH == 1 )
        #if (TRACE_TYPE == 1 || TRACE_TYPE == 4)
             trace_info.facch_dl_count_all++;
         #endif
          /* if the current block is a repetition reports NULL to L2 otherwise reports the current block */
       l1s_read_dcch_dl((API*)l1s_repeated_facch_check(l1s_dsp_com.dsp_ndb_ptr->a_fd), task);
       #else
       /* UWORD8 error_flag =*/ l1s_read_dcch_dl(l1s_dsp_com.dsp_ndb_ptr->a_fd, task);
      #endif /* ( FF_REPEATED_DL_FACCH == 1 ) */

        #if (AMR == 1)
          // Non AMR FACCH handling
          if (channel_mode != TCH_AFS_MODE)
          {
        #endif

          // RXQUAL_SUB : In case of data taffic channels, accumulate number of
          // estimated errors, this value is contained in a_fd[2] field, only
          // for SID TDMA frames received as FACCH frames. (GSM 5.08 $8.4)
          if (fn_mod_104==60)
          {
            l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff;
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN;
          }

        #if (AMR == 1)
          }
          else
          {
            // AGC, RXLEV_FULL

            // Indicate to AMR specific processing that burst was a FACCH
            facch_present = TRUE;
            #if ((REL99) && (AMR == 1))
            #if FF_EMR
              emr_params.amr_facch_present = facch_present;
            #endif
            #endif

            // Update AGC: Call DPAGC algorithm
            IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);

            // Dedicated mode serving cell measurement reading, indicate "FULL".
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
            #endif
          }
        #endif

          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_fd[2] field, for each TCHT block.
	#if (AMR == 1)
          // in AMR, l1s.dtx_amr_dl_on is FALSE if DTX mode is off
          // in non AMR TCH, l1s.dtx_amr_dl_on is always FALSE
          // In AMR DTX, DSP patch sometimes reports FACCH blocks which ARE NOT FACCH blocks
          // therefore they shouldn't be taken into account in the RXQUALL_FULL computation
          if(l1s.dtx_amr_dl_on==FALSE)
	#endif
          {
          l1a_l1s_com.Smeas_dedic.qual_acc_full      += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff;
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN;
		  }









          // Reset A_FD header.
          // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0
          l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1);
          l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff;

          // Rem: when FACCH is received, we must reset A_DD_0 header also.
          // Reset A_DD_0 header in NDB.
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;

          // Rem: when FACCH is received, we must reset A_DD_1 header also.
          // Reset A_DD_0 header in NDB.
          l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0;
          l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff;

          #if TESTMODE
            if (l1_config.TestMode)
            {
              pm_fullres = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff); // F26.6

              // Allocate result message.
              msg = os_alloc_sig(sizeof(T_TMODE_TCH_INFO));
              DEBUGMSG(status,NU_ALLOC_ERR)
              msg->SignalCode = TMODE_TCH_INFO;

              ((T_TMODE_TCH_INFO *)(msg->SigP))->pm_fullres         = pm_fullres; // F26.6
              ((T_TMODE_TCH_INFO *)(msg->SigP))->snr                = snr;
              ((T_TMODE_TCH_INFO *)(msg->SigP))->toa                = toa;
              ((T_TMODE_TCH_INFO *)(msg->SigP))->angle              = (WORD16) angle; // signed
              ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_full          = l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
              ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_nbr_meas_full = TCH_FS_BLEN;

              // send TMODE_TCH_INFO message...
              os_send_sig(msg, L1C1_QUEUE);
              DEBUGMSG(status,NU_SEND_QUEUE_ERR)
            }
          #endif
        } // if (b_blud == TRUE)

        else // (if (b_blud == TRUE) FACCH
        {
          // No FACCH received.

          // Dummy: Read FACCH DL data block from DSP, pass it to L2.
          // Rem: this is an upper layer requirement to call this
          // function at every FACCH DL boundary.
          l1s_read_dcch_dl(NULL, task);

        #if (AMR == 1)
          if (channel_mode != TCH_AFS_MODE)
          {
        #endif

          // Check A_DD_0 information block for TCH/F2.4 or TCH/FS.
          // TCH/F2.4 or TCH/FS: Check A_DD_0 information block.
          //----------------------------------------------------

          b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
          if(b_blud == TRUE)
          {
            // RXQUAL_SUB : In case of speech traffic channels, accumulate number of
            // estimated errors, this value is contained in a_dd_0[2] field, only
            // for SID TDMA frames. (GSM 5.08 $8.4)
            if (fn_mod_104==60)
            {
               l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
               l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_FS_BLEN;
            }

            // RXQUAL_FULL : accumulate number of estimated errors, this value is
            // contained in a_dd_0[2] field, for each TCHT block.
            l1a_l1s_com.Smeas_dedic.qual_acc_full      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_FS_BLEN;

            #if TESTMODE
              if (l1_config.TestMode)
              {
                pm_fullres = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff); // F26.6

                // Allocate result message.
                msg = os_alloc_sig(sizeof(T_TMODE_TCH_INFO));
                DEBUGMSG(status,NU_ALLOC_ERR)
                msg->SignalCode = TMODE_TCH_INFO;

                ((T_TMODE_TCH_INFO *)(msg->SigP))->pm_fullres         = pm_fullres; // F26.6
                ((T_TMODE_TCH_INFO *)(msg->SigP))->snr                = snr;
                ((T_TMODE_TCH_INFO *)(msg->SigP))->toa                = toa;
                ((T_TMODE_TCH_INFO *)(msg->SigP))->angle              = (WORD16) angle; // signed
                ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_full          = l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
                ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_nbr_meas_full = TCH_FS_BLEN;

                // send TMODE_TCH_INFO message...
                os_send_sig(msg, L1C1_QUEUE);
                DEBUGMSG(status,NU_SEND_QUEUE_ERR)
              }
            #endif

            if(channel_mode == TCH_24F_MODE)
            {
              #if IDS
              // Integrated Data Services implementation
              {
                dll_data_dl(l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl,
                            &l1s_dsp_com.dsp_ndb_ptr->d_ra_act,
                             &l1s_dsp_com.dsp_ndb_ptr->d_ra_statd);
              }
              #else
              {
                // DATA traffic.
                // Pass data block to DATA ADAPTOR.
                // REM: Data packet is always given to the DATA ADAPTOR.
                // There is no RX quality check !!
                {
                  rx_tch_data(&l1s_dsp_com.dsp_ndb_ptr->a_dd_0[3], channel_mode, 0);
                }
              }
              #endif
            }

            // Reset A_DD_0 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
          } // if(b_blud == TRUE)
        #if (AMR == 1)
          } // if (channel_mode != TCH_AFS_MODE)
        #endif
        } // if (b_blud == TRUE) FACCH (else)
     #if (FF_REPEATED_DL_FACCH == 1)
#if 1
      temp=l1s.repeated_facch.counter_candidate;
      l1s.repeated_facch.counter_candidate=l1s.repeated_facch.counter;
      l1s.repeated_facch.counter=temp;
#else
if (l1s.repeated_facch.counter_candidate == 1)
	l1s.repeated_facch.counter_candidate = 0 ;
else if (l1s.repeated_facch.counter_candidate == 0 )
	l1s.repeated_facch.counter_candidate = 0 ;

   l1s.repeated_facch.counter++ ;
if (l1s.repeated_facch.counter == 4)
{
l1s.repeated_facch.counter = 0;
l1s.repeated_facch.pipeline[0].buffer_empty=l1s.repeated_facch.pipeline[1].buffer_empty=TRUE;
}
#endif
    #endif/*(FF_REPEATED_DL_FACCH == 1)*/
/* FACCH Full rate */
      } // if(fn_report_mod13_mod4 == 0)

      else // if(fn_report_mod13_mod4 == 0)
    #if (AMR == 1)
      if ((fn_report_mod13_mod4 == 2) && (channel_mode != TCH_AFS_MODE))
    #else
      if(fn_report_mod13_mod4 == 2)
    #endif
      // It is time to get TCH/F4.8 or TCH/F9.6 data block.
      {
        #if TRACE_TYPE==3
          if (l1_stats.type == PLAY_UL &&
             (channel_mode == TCH_48F_MODE || channel_mode == TCH_96_MODE || channel_mode == TCH_144_MODE))
            play_trace();
        #endif

        // Check A_DD_0 information block only if no FACCH.
        b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;
        if(b_blud == TRUE)
        {
          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_dd_0[2] field, for each TCHT block.
          l1a_l1s_com.Smeas_dedic.qual_acc_full      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN;

          if((channel_mode == TCH_48F_MODE) || (channel_mode == TCH_96_MODE) || (channel_mode == TCH_144_MODE))
          {
            #if IDS
            // Integrated Data Services implementation
            {
              dll_data_dl(l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl,
                          &l1s_dsp_com.dsp_ndb_ptr->d_ra_act,
                           &l1s_dsp_com.dsp_ndb_ptr->d_ra_statd);
            }
            #else
            {
              // DATA traffic.
              // Pass data block to DATA ADAPTOR.
              // REM: Data packet is always given to the DATA ADAPTOR.
              // There is no RX quality check !!
              {
                UWORD8 sequence_number;
                UWORD8 fn_report_mod26 = l1s.actual_time.fn_in_report % 26;

                // Catch sequence number. This is used in TCH/F4.8 to distinguish
                // data blocks (see GSM 5.02) received on B0,B2,B4 (sequence number 0)
                // and data blocks received on B1,B2,B3 (sequence number 1).
                if((fn_report_mod26 == 23) || (fn_report_mod26 == 6) || (fn_report_mod26 == 15))
                  sequence_number = 0;
                else
                  sequence_number = 1;
                rx_tch_data(&l1s_dsp_com.dsp_ndb_ptr->a_dd_0[3], channel_mode, sequence_number);
              }
            }
          #endif
          }
          // Reset A_DD_0 header in NDB.
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
        } // if(b_blud == TRUE)
      } // if(fn_report_mod13_mod4 == 2)

    #if (AMR == 1)
      if ((channel_mode == TCH_AFS_MODE) && (facch_present == FALSE))
      {
        // Load the bit to check if the block is valid
        b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD;

        // Load the bit to check if the block is a RATSCCH in case of rx_type = NO_DATA
        b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD;

        // All detected AMR frames except NO_DATA (b_blud = 0) and FACCH are handled here, i.e. speech/SID/RATSCCH
        if(b_ratscch_blud==TRUE)
        {
          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_ratscch_dl[2] field, for each TCHT block.
          l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] & 0xffff;

          // Reset the A_RATSCCH_DL header in NDB.
          l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] = 0;
          l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] = 0xffff;

          // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on
          // the block received.
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += RATSCCH_BLEN;

          IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
            #endif
        }
        else if(b_blud==TRUE)
        {
          // Load the type of the block received
          rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT;

        #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
          Trace_dedic_tch_block_stat(rx_type, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], 0);
        #endif

          // RXQUAL_SUB : In case of adaptative traffic channel, accumulate number of estimated errors
          // is contained in the a_dd_0[2] value but the accumulation is made with SID_UPDATE frame only.
          // Note: SID_UPDATE frame corresponds to rx_type SID_UPDATE (b_ratscch_blud = FALSE) or SID_BAD (See Memo)
          if((rx_type==SID_UPDATE) || (rx_type==SID_BAD))

          {
            l1a_l1s_com.Smeas_dedic.qual_acc_sub      += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += SID_UPDATE_BLEN;
          }

          // RXQUAL_FULL : accumulate number of estimated errors, this value is
          // contained in a_dd_0[2] field, for each TCHT block.




          // Frames, which have no class1 bit (so no quality meas is possible), have d_nerr = 0
          // so we can add them
            l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;

          // Reset A_DD_0 header in NDB.
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
          l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;





          // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on
          // the block received.
          if((rx_type==SPEECH_GOOD) || (rx_type==SPEECH_DEGRADED) || (rx_type==SPEECH_BAD))
          {
            // It's a speech block
            // Note: in AFS, the d_nerr value doesn't depend on the vocoder currently use
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AFS_BLEN;
          }
          else if((rx_type==SID_UPDATE) || (rx_type==SID_BAD))


          {
            // the block is a SID UPDATE frame
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += SID_UPDATE_BLEN;
          }







          // AGC, TOA, RXLEV for AMR. SUB queues only for SID_UPDATE frames
          if((rx_type==SID_UPDATE) || (rx_type==SID_BAD))

          {
            IL_for_rxlev = l1ctl_dpagc_amr(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 1);
            #endif

          #if (TOA_ALGO != 0)
            #if (TOA_ALGO == 2)
              if(l1s.toa_var.toa_snr_mask == 0)
            #else
              if(l1s.toa_snr_mask == 0)
            #endif
            {
              #if 1	/* FreeCalypso TCS211 reconstruction */
                if (IL_for_rxlev < IL_FOR_RXLEV_SNR)
                  l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count);
                else
                  l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count);
              #else
                UWORD32 snr_temp;
                snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0;
                #if (TOA_ALGO == 2)
                  l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa);
                #else
                  l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count
                  #if (FF_L1_FAST_DECODING == 1)
                      ,0
                  #endif
                      );
                #endif
              #endif
            }
          #endif
          }
          else
          {
            IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr);
            #if REL99
            #if FF_EMR
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
            #endif
            #else
              l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
            #endif
          }
        } // if(b_blud==TRUE)
        // NO_DATA block detected or simple burst
        else
        {
          if (fn_report_mod13_mod4 == 0)
          {
            l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff;
            l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AFS_BLEN;

          #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
            Trace_dedic_tch_block_stat(AMR_NO_DATA, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], 0);
          #endif

            // Reset A_DD_0 header in NDB.
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0;
            l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff;
          }

          // Update AGC: Call DPAGC AMR algorithm in order to fill the G_all buffer
          IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr);

          // Dedicated mode serving cell measurement reading, full set only.
          #if REL99
          #if FF_EMR
            l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params);
          #endif
          #else
            l1s_read_dedic_scell_meas(IL_for_rxlev, 0);
          #endif
        }
      } // if ((channel_mode == TCH_AFS_MODE) && (facch_present == FALSE))
    #endif

      // task is completed, make it INACTIVE.
      l1s.task_status[task].current_status = INACTIVE;
    }
    break;

    case TCHA:
    /*---------------------------------------------------*/
    /* Dedicated mode: SACCH receive task.               */
    /*---------------------------------------------------*/
    {
      UWORD8   IL_for_rxlev;
      UWORD32  b_blud;

      // Read control results and feed control algorithms.
      // **************************************************

      // Read control information.
      toa   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA]   & 0xffff;
      pm    = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM]   & 0xffff) >> 5;
      angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff;
      snr   = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR]   & 0xffff;

      #if TESTMODE
        if (l1_config.TestMode && l1_config.tmode.rf_params.down_up == TMODE_UPLINK)
        {
          // For UL-only tasks, TCHA is scheduled in every frame. TCH_INFO message is only
          // used to count loops; no stats are collected.

          xSignalHeaderRec *msg;
          // Allocate result message.
          msg = os_alloc_sig(sizeof(T_TMODE_TCH_INFO));
          DEBUGMSG(status,NU_ALLOC_ERR)
          msg->SignalCode = TMODE_TCH_INFO;
          // send TMODE_TCH_INFO message...
          os_send_sig(msg, L1C1_QUEUE);
          DEBUGMSG(status,NU_SEND_QUEUE_ERR)
        }
        // WARNING!
        // Don't trace PM=0 during UL-only in TestMode. The DSP is not working
        // in that case so it is normal. However, if tracing happens the CPU overloads
        if (l1_config.TestMode && l1_config.tmode.rf_params.down_up & TMODE_DOWNLINK)
      #endif
        {
            l1_check_pm_error(pm, task);
        }

      #if TRACE_TYPE==3
        stats_samples_tch_sacch(toa,pm,angle,snr);
      #endif

      #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
        uart_trace(task);
      #endif

      // Update AGC: Call DPAGC algorithm
      IL_for_rxlev = l1ctl_dpagc(1,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // dtx_on = 1

      // Dedicated mode serving cell measurement reading, indicate "SUB".
      #if REL99
      #if FF_EMR
        l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params);
      #endif
      #else
        l1s_read_dedic_scell_meas(IL_for_rxlev, 1);
      #endif

      // Update AFC: Call AFC control function (KALMAN filter).
      #if AFC_ALGO
        #if TESTMODE
          if (l1_config.afc_enable)
        #endif
          {
            #if (VCXO_ALGO == 0)
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq);
            #else
              l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode);
            #endif
          }
      #endif

      //Feed TOA histogram.
      #if (TOA_ALGO != 0)
        #if (TOA_ALGO == 2)
          if(l1s.toa_var.toa_snr_mask == 0)
        #else
          if(l1s.toa_snr_mask == 0)
        #endif
        {
          #if 1	/* FreeCalypso TCS211 reconstruction */
            if (IL_for_rxlev < IL_FOR_RXLEV_SNR)
              l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count);
            else
              l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count);
          #else
            UWORD32 snr_temp;
            snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0;
            #if (TOA_ALGO == 2)
              l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa);
            #else
              l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count
              #if (FF_L1_FAST_DECODING == 1)
                  ,0
              #endif
                  );
            #endif
          #endif
        }
      #endif

       #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
         RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev)
       #endif
       #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM
         l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
       #endif
       #if (BURST_PARAM_LOG_ENABLE == 1)
         l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev);
       #endif

      // Read downlink DATA block from MCU/DSP interface.
      // *************************************************

      if(l1s.actual_time.fn_in_report == 91)
      // It's time to read a SACCH DL result from DSP.
      {
        // Check A_CD information block.
        b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_cd[0] & (1<<B_BLUD)) >> B_BLUD;
        if(b_blud == TRUE)
        {
          #if W_A_DSP1
      // Temporary correction to fix a known DSP problem.  SACCH deinterleaver not
          // initialized on HO.
      //
            if (old_sacch_DSP_bug == TRUE)
            {
            // Invalidate the current sacch block - indicate it cannot be decoded
              l1s_dsp_com.dsp_ndb_ptr->a_cd[0]   =  (1<<B_FIRE1); // B_FIRE1=1,B_FIRE0=0,BLUD=0.
              old_sacch_DSP_bug = FALSE;
            }
          #endif

          // Read data block and send msg to L1A.
          l1s_read_sacch_dl(l1s_dsp_com.dsp_ndb_ptr->a_cd, task);

          // RXQUAL_FULL/RXQUAL_SUB : Accumulate number of estimated errors, this value
          // is contained in a_cd[2] field, for every SACCH block.
          l1a_l1s_com.Smeas_dedic.qual_acc_full      += l1s_dsp_com.dsp_ndb_ptr->a_cd[2] & 0xffff;
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += A_D_BLEN;
          l1a_l1s_com.Smeas_dedic.qual_acc_sub       += l1s_dsp_com.dsp_ndb_ptr->a_cd[2] & 0xffff;
          l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub  += A_D_BLEN;

          // TEMPORARY : reset buffers and flags in NDB ...
          //             reset nerr....
          //             reset A_CD contents.......
          l1s_dsp_com.dsp_ndb_ptr->a_cd[0]   =  (1<<B_FIRE1); // B_FIRE1=1,B_FIRE0=0,BLUD=0.
          l1s_dsp_com.dsp_ndb_ptr->a_cd[2]   =  0xffff;
        }
      }
      #if W_A_DSP1
        else if (l1s.actual_time.fn_in_report == 13)  // TF 5/8/98 - DSP fix
        {
          // As this is the first SACCH burst the known DSP bug cannot occur on a new channel.
          old_sacch_DSP_bug = FALSE;
        }
      #endif

      // task is completed, make it INACTIVE.
      l1s.task_status[task].current_status = INACTIVE;
    }
    break;
  } // End switch...

  #if (L1_DEBUG_IQ_DUMP == 1)
    l1ddsp_read_iq_dump(task);
  #endif

  // Flag the use of the MCU/DSP dual page read interface.
  // ******************************************************

  // Set flag used to change the read page at the end of "l1_synch".
  l1s_dsp_com.dsp_r_page_used = TRUE;
}

/*-------------------------------------------------------*/
/* l1s_read_tx_result()                                  */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1s_read_tx_result(UWORD8 task, UWORD8 burst_id)
{
  /*--------------------------------------------------------*/
  /* READ TRANSMIT TASK RESULTS...                          */
  /*--------------------------------------------------------*/

  #if (TRACE_TYPE!=0)
    if(task==RAACC)
    {
      if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_ra & 0xffff) != (UWORD32)DSP_TASK_CODE[task])
        trace_fct(CST_UL_TASKS_DO_NOT_CORRESPOND, -1);
    }
    else
    {
      if(((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) &&
         ((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) != TCH_DTX_UL))
        trace_fct(CST_UL_TASKS_DO_NOT_CORRESPOND, -1);
    }
  #endif

  l1_check_com_mismatch(task);

  switch(task)
  {
    case RAACC:
    /*---------------------------------------------------*/
    /* Serving Cell: Random Access TX task.              */
    /*---------------------------------------------------*/
    // Rem: confirmation message is sent at "CTRL" to be able to give FN%42432.
    {
      // Send confirmation msg to L1A.
      // ******************************

      // For ACCESS phase, a confirmation msg is sent to L1A.
      xSignalHeaderRec *msg;

      // send L1C_RA_DONE to L1A...
      msg = os_alloc_sig(sizeof(T_MPHC_RA_CON));
      DEBUGMSG(status,NU_ALLOC_ERR)

      if (l1s.actual_time.fn == 0)
        ((T_MPHC_RA_CON *)(msg->SigP))->fn = MAX_FN - 1;
      else
        ((T_MPHC_RA_CON *)(msg->SigP))->fn = l1s.actual_time.fn - 1;

      ((T_MPHC_RA_CON *)(msg->SigP))->channel_request = l1a_l1s_com.ra_info.channel_request;
      msg->SignalCode = L1C_RA_DONE;

      os_send_sig(msg, L1C1_QUEUE);
      DEBUGMSG(status,NU_SEND_QUEUE_ERR)

      // Desactivate the RAACC task.
      l1s.task_status[task].current_status = INACTIVE;

      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_RA, l1a_l1s_com.Scell_info.radio_freq);
      #endif
    }
    break;

    case DUL:
    /*---------------------------------------------------*/
    /* Serving Cell: SDCCH up link.                      */
    /*---------------------------------------------------*/
    {
      // Desactivate UL task.
      if(burst_id == BURST_4)
      {
        l1s.task_status[task].current_status = INACTIVE;

        #if (TRACE_TYPE == 5) // in simulation only the 4th burst is traced
          trace_fct(CST_L1S_READ_TX_NB__DUL, l1a_l1s_com.Scell_info.radio_freq);
        #endif
      }

      #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
        trace_fct(CST_L1S_READ_TX_NB__DUL, l1a_l1s_com.Scell_info.radio_freq);
      #endif
    }
    break;

    case AUL:
    /*---------------------------------------------------*/
    /* Serving Cell: SACCH up link.                      */
    /*---------------------------------------------------*/
    {
      // Desactivate UL task.
      if(burst_id == BURST_4)
      {
        l1s.task_status[task].current_status = INACTIVE;

        #if (TRACE_TYPE == 5) // in simulation only the 4th burst is traced
          trace_fct(CST_L1S_READ_TX_NB__AUL, l1a_l1s_com.Scell_info.radio_freq);
        #endif
      }

      #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
        trace_fct(CST_L1S_READ_TX_NB__AUL, l1a_l1s_com.Scell_info.radio_freq);
      #endif

    }
    break;

    case TCHA:
    case TCHTF:
    /*---------------------------------------------------*/
    /* Serving Cell: TCH link.                           */
    /*---------------------------------------------------*/
    {
      #if (TRACE_TYPE==5)
        if(burst_id == BURST_4) // in simulation only the 4th burst is traced
          trace_fct(CST_L1S_READ_TX_NB__TCHF, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
          trace_fct(CST_L1S_READ_TX_NB__TCHF, l1a_l1s_com.Scell_info.radio_freq);
      #endif
    }
    break;

    case TCHTH:
    /*---------------------------------------------------*/
    /* Serving Cell: TCH link.                           */
    /*---------------------------------------------------*/
    {
      #if (TRACE_TYPE==5)
        if(burst_id == BURST_2) // in simulation only lates burst is traced
          trace_fct(CST_L1S_READ_TX_NB__TCHH, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
          trace_fct(CST_L1S_READ_TX_NB__TCHH, l1a_l1s_com.Scell_info.radio_freq);
      #endif
    }
    break;
  }

  // Set flag used to change the read page at the end of "l1_synch".
  l1s_dsp_com.dsp_r_page_used = TRUE;
}

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

#if REL99
#if FF_EMR
void l1s_read_dedic_scell_meas(UWORD8 input_level, UWORD8 sub_flag, T_EMR_PARAMS *emr_params)
{
  UWORD8  task;
  UWORD8  burst_id;
  UWORD8  b_blud;
  UWORD8  counter;
  UWORD8  bfi;                  // band frame indicator
  UWORD8  channel_mode;         // current channel type
  //OMAPS00090550 UWORD8  fn_report_mod_26;
  UWORD8  subchannel;           // half rate sub channel
  UWORD8  sid_present;          // indication for sid block
  UWORD16 rx_type;
  UWORD32 normalised_fn_mod13_mod4;

  UWORD16 mean_bep_lsb = 0;     //l1s_dsp_com.dsp_ndb_ptr->d_mean_bep_block_lsb;
  UWORD16 mean_bep_msb = 0;     //l1s_dsp_com.dsp_ndb_ptr->d_mean_bep_block_msb;
  UWORD32 mean_bep = 0;         //((mean_bep_msb<<WORD_SHIFT)|(mean_bep_lsb)) >> MEAN_BEP_FORMAT;
  UWORD16 cv_bep = 0;           //(l1s_dsp_com.dsp_ndb_ptr->d_cv_bep_block) >> CV_BEP_FORMAT;

  static WORD16 last_corr_decoded_burst[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  static UWORD16 cv_bep_tch4_8f_144[2]   = {0, 0};
  static UWORD32 mean_bep_tch4_8f_144[2] = {0, 0};

  WORD16 rxlev = l1s_encode_rxlev(input_level);

  if (l1s_dsp_com.dsp_r_page == 1)
  {
      cv_bep       = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_0[D_CV_BEP];
      mean_bep_msb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_0[D_MEAN_BEP_MSW];
      mean_bep_lsb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_0[D_MEAN_BEP_LSW];
  }
  else
  {
      cv_bep       = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_1[D_CV_BEP];
      mean_bep_msb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_1[D_MEAN_BEP_MSW];
      mean_bep_lsb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_1[D_MEAN_BEP_LSW];
  }

  mean_bep = ((mean_bep_msb<<WORD_SHIFT)|(mean_bep_lsb)) >> MEAN_BEP_FORMAT;
  cv_bep   = cv_bep >> CV_BEP_FORMAT;

  // EMR : Copy of Legacy code begins
  // Measurement must be rejected if channel is hopping, hopped on
  // the beacon frequency and PWRC is TRUE (see GSM05.08, $8.1.3).
  if(!((l1a_l1s_com.dedic_set.pwrc == TRUE) &&
       (l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->chan_sel.h == TRUE) &&
       (l1a_l1s_com.dedic_set.radio_freq_dd == l1a_l1s_com.Scell_info.radio_freq)))
  {
    // Add to FULL set meas.
    l1a_l1s_com.Scell_info.meas.nbr_meas++;
    l1a_l1s_com.Scell_info.meas.acc += rxlev;

    if(sub_flag == TRUE)
    {
      // Add to SUB set meas.
      l1a_l1s_com.Smeas_dedic.nbr_meas_sub++;
      l1a_l1s_com.Smeas_dedic.acc_sub += rxlev;
    } // if(sub_flag == TRUE)
    // EMR : Copy of Legacy code ends
  } // if(!((l1a_l1s_com.dedic_set.pwrc == TRUE) && ....

  // new rxlev is received. remove the oldest rxlev.
  for(counter=0;counter<=6;counter++)
    last_corr_decoded_burst[counter] = last_corr_decoded_burst[counter+1];

  // store new rxlev.
  last_corr_decoded_burst[7] = rxlev;

  task                            = emr_params->task;
  burst_id                        = emr_params->burst_id;
  channel_mode                    = emr_params->channel_mode;
  normalised_fn_mod13_mod4 = emr_params->normalised_fn_mod13_mod4;

  // TCH FS and TCH EFR
  if((task == TCHTF) &&
     (l1s.actual_time.fn_mod13_mod4 == 0) &&
     ((channel_mode == TCH_FS_MODE) ||
      (channel_mode == TCH_EFR_MODE) ||
      (channel_mode == SIG_ONLY_MODE)))
  {
    if(emr_params->facch_present == TRUE)
    {
      // FACCH
      if(emr_params->facch_fire1 == FALSE)
      {
        // FACCH correctly decoded
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated

        // Accumulate BEP
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

        //accumulation of the correctly decoded block
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];

        if(channel_mode == SIG_ONLY_MODE)
        // accumulation of correctly decoded blocks excluding SACCH  and SID frames FACCH only for sig only mode
          l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;

      } // if(facch_fire1 == FALSE)
    } // if(facch_present == TRUE )
    else
    {
      // NOT FACCH,
      if (emr_params->a_dd_0_blud == TRUE)
      {
        if (emr_params->a_dd_0_bfi == FALSE)
        {
          // speech correctly decoded
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];

          if (emr_params->sid_present_sub0 == FALSE)
          {
            // accumulation of correctly decoded blocks excluding SACCH FACCH and SID frames
            l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
          } // if(sid_present == FALSE)
        } // if(bfi == FALSE)
      } // if(b_blud == TRUE)
    } // else part of if(facch_present == TRUE )
  } // TCH FS and TCH EFR

  // TCH 2.4F
  if((task == TCHTF) &&
     (l1s.actual_time.fn_mod13_mod4 == 0) &&
     (channel_mode == TCH_24F_MODE))
  {
    if(emr_params->facch_present == TRUE)
    {
      if(emr_params->facch_fire1 == FALSE)
      {
        // FACCH correctly decoded
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

        // Accumulate BEP
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

        //accumulation of the correctly decoded block
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                     last_corr_decoded_burst[5] +
                                                     last_corr_decoded_burst[6] +
                                                     last_corr_decoded_burst[7];
      }
    } // if(facch_present == TRUE)
    else
    {
      // NOT FACCH check whether the data buffer is updated!!
      if(emr_params->a_dd_0_blud == TRUE)
      {
        // Check if transparent data or not
        if(emr_params->b_ce == TRUE)// Non Transparent
        {
          //check if correctly decoded or not
          if(emr_params->a_ntd == FALSE)//good frame detected
          {
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

            // Accumulate BEP
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

            //accumulation of the correctly decoded block
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                         last_corr_decoded_burst[5] +
                                                         last_corr_decoded_burst[6] +
                                                         last_corr_decoded_burst[7];
            // accumulation of correctly decoded blocks excluding SACCH FACCH frames
            l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
          } // if(a_ntd == FALSE)
        } // if(b_ce == TRUE)
        else
        {
          // 2.4F transperent data (always considered as correctly decoded)
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

          //accumulation of the block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];

          // accumulation of decoded blocks excluding SACCH FACCH and SID frames
          l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
        } // if(b_ce == TRUE)
      } // if(b_blud == TRUE)
    } // else part of if(facch_present == TRUE)
  } // TCH 2.4F

  // TCH 9.6F
  if((task == TCHTF) &&
     (l1s.actual_time.fn_mod13_mod4 == 0) &&
     (channel_mode == TCH_96_MODE))
  {
    if(emr_params->facch_present == TRUE)
    {
      if(emr_params->facch_fire1 == FALSE)
      {
        // FACCH correctly decoded
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

        // Accumulate BEP
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

        //accumulation of the correctly decoded block
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                     last_corr_decoded_burst[5] +
                                                     last_corr_decoded_burst[6] +
                                                     last_corr_decoded_burst[7];
      } //if(fire1 == FALSE)
    } //if(facch_present == TRUE)
  } // if(fn_mod13_mod4 == 0)

  if((task == TCHTF) &&
     (l1s.actual_time.fn_mod13_mod4 == 2) &&
     (channel_mode == TCH_96_MODE))
  {
    if(emr_params->a_dd_0_blud == TRUE)
    {
      // Check if transparent data or not
      if(emr_params->b_ce == TRUE)// Non Transparent
      {
        //check if correctly decoded or not
        if(emr_params->a_ntd == FALSE)//good frame detected
        {
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];

          // accumulation of correctly decoded blocks excluding SACCH FACCH frames
          l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
        } // if(a_ntd == FALSE)
      } // if(b_ce == TRUE)
      else
      {
        // transparent data (always correctly decoded)
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

        // Accumulate BEP
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

        //accumulation of decoded block
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                     last_corr_decoded_burst[5] +
                                                     last_corr_decoded_burst[6] +
                                                     last_corr_decoded_burst[7];

        // accumulation of decoded blocks excluding SACCH FACCH frames
        l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
      } // transparent data
    } // if(b_blud == TRUE)
  } // TCH F9.6

  // TCH 4.8F/14.4F
  if((task == TCHTF) &&
     (l1s.actual_time.fn_mod13_mod4 == 0) &&
     ((channel_mode == TCH_48F_MODE) || (channel_mode == TCH_144_MODE)) )
  {
    if(emr_params->facch_present == TRUE)
    {
      if(emr_params->facch_fire1 == FALSE)
      {
        // FACCH correctly decoded
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;// 4 bursts are accumulated

        // Accumulate BEP
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

        //accumulation of the correctly decoded block
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                     last_corr_decoded_burst[5] +
                                                     last_corr_decoded_burst[6] +
                                                     last_corr_decoded_burst[7];
      } //if(fire1 == FALSE)
    } //if(facch_present == TRUE)
  } // if(fn_mod13_mod4 == 0)

  if((task == TCHTF) &&
     (l1s.actual_time.fn_mod13_mod4 == 2) &&
     ((channel_mode == TCH_48F_MODE) || (channel_mode == TCH_144_MODE)) )
  {
    // block end add new value of mean_bep and cv_bep value to mean_bep_tch4_8f_144 and
    // cv_bep_tch4_8f_144. remove the oldest value.
    mean_bep_tch4_8f_144[0] = mean_bep_tch4_8f_144[1];
    cv_bep_tch4_8f_144[0]   = cv_bep_tch4_8f_144[1];
    mean_bep_tch4_8f_144[1] = mean_bep;
    cv_bep_tch4_8f_144[1]   = cv_bep;

    if ( ((emr_params->a_dd_0_blud == TRUE) && (emr_params->b_m1) && (channel_mode == TCH_144_MODE)) ||
         ((emr_params->a_dd_0_blud == TRUE) && (emr_params->b_f48blk_dl) && (channel_mode == TCH_48F_MODE)) )
    {
      // Check if transparent data or not
      if(emr_params->b_ce == TRUE) // Non transparent
      {
        //check if correctly decoded or not. Accumulate last 8 slots
        if(emr_params->a_ntd == FALSE) //good frame detected
        {
          // two blocks are accumulated at a time, increment by 2.
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas+=8;   // 8 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep_tch4_8f_144[0] + mean_bep_tch4_8f_144[1];
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep_tch4_8f_144[0] + cv_bep_tch4_8f_144[1];

          // two blocks are accumulated at a time, increment by 2.
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num += 2;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num+=2;

          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[0] +
                                                       last_corr_decoded_burst[1] +
                                                       last_corr_decoded_burst[2] +
                                                       last_corr_decoded_burst[3] +
                                                       last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];

          // accumulation of correctly decoded blocks excluding SACCH FACCH frames
          l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks +=2;
        } // if(a_ntd == FALSE)
      } // if(b_ce == TRUE)
      else
      {
        // transparent data
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=8;   // 8 bursts are accumulated

        // Accumulate BEP
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep_tch4_8f_144[0] + mean_bep_tch4_8f_144[1];
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep_tch4_8f_144[0] + cv_bep_tch4_8f_144[1];

        // two blocks are accumulated at a time, increment by 2.
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num+=2;
        l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num += 2;

        //accumulation of the correctly decoded block
        l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[0] +
                                                     last_corr_decoded_burst[1] +
                                                     last_corr_decoded_burst[2] +
                                                     last_corr_decoded_burst[3] +
                                                     last_corr_decoded_burst[4] +
                                                     last_corr_decoded_burst[5] +
                                                     last_corr_decoded_burst[6] +
                                                     last_corr_decoded_burst[7];

        // accumulation of correctly decoded blocks excluding SACCH FACCH frames
        l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks +=2;
      } // Transparent data
    } // if(b_blud == TRUE)
  } // TCH 4.8F/14.4


  // TCH HS
  if((task == TCHTH) &&
     ((channel_mode == TCH_HS_MODE)||(channel_mode == SIG_ONLY_MODE))&&
     (normalised_fn_mod13_mod4 == 3) )
  {
    UWORD8 norm_fn_mod26;

    subchannel = emr_params->subchannel;
    norm_fn_mod26 = ((l1s.actual_time.fn - subchannel + 26)  % 26);

    if(subchannel == 0)
    {
      b_blud      = emr_params->a_dd_0_blud;
      bfi         = emr_params->a_dd_0_bfi;       // 3rd bit tells the BAD frame.
      sid_present = emr_params->sid_present_sub0; // find out whether sid1 is 0/1, 1 mean
    }
    else
    {
      b_blud      = emr_params->a_dd_1_blud;
      bfi         = emr_params->a_dd_1_bfi;       // 3rd bit tells the BAD frame.
      sid_present = emr_params->sid_present_sub1; // find out whether sid1 is 0/1, 1 mean
    }

    if(norm_fn_mod26 == 7 || norm_fn_mod26 == 16|| norm_fn_mod26 == 24 )
    {
      // FACCH: Check A_FD information block.
      if(emr_params->facch_present == TRUE)
      {
        // FACCH correctly decoded
        if(emr_params->facch_fire1 == FALSE)
        {
          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;
          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];

          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          if((channel_mode == SIG_ONLY_MODE))
            // accumulation of correctly decoded blocks excluding SACCH
            // and SID frames FACCH only for sig only mode
            l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
        }  //if(fire1 == FALSE)
      }  //if(facch_present ==....)
      else
      {
        // No Facch at this positions 7,16,24
        if (b_blud == TRUE)
        {
          if(bfi == FALSE)
          {
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

            // Accumulate BEP
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;
            //accumulation of the correctly decoded block
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[7] +
                                                         last_corr_decoded_burst[6] +
                                                         last_corr_decoded_burst[5] +
                                                         last_corr_decoded_burst[4] ;

            //as per standard 05.08 section 8.3
            //sid_present can become true only at (fn modulo 26) == 6
            //sid_present will be false at all other points

            if(sid_present == FALSE)
              // accumulation of correctly decoded blocks excluding SACCH
              // FACCH and SID frames
              l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
          } // if(bfi == FALSE)
        } // if (b_blud == TRUE)
      }  // else facch_present
    } //if(norm_fn_report_mod26 == 7 || norm_fn_report_mod26 == 16|| norm_fn_report_mod26 == 24 )
    else
    {
      //norm_fn_report_mod26 == 3 || norm_fn_report_mod26 == 11|| norm_fn_report_mod26 == 20
      if (b_blud == TRUE)
      {
        if(bfi == FALSE)
        {
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;
          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[7] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[4] ;

           //as per standard 05.08 section 8.3
           //sid_present can become true only at (fn modulo 26) == 6
           //sid_present will be false at all other points

           if(sid_present == FALSE)
             // accumulation of correctly decoded blocks excluding SACCH
             // FACCH and SID frames
             l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
        }  //if(bfi == FALSE)
      } // if (b_blud == TRUE)
    }  //else
  }//task == TCHTH.....

  // SACCH of TCH
  if((task == TCHA))
  {
    //unconditionnal accumulation of rxlev_val
    l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas++;
    l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += rxlev;
    if(l1s.actual_time.fn_in_report == 91)
    {
      // Set detection flag.
      if(emr_params->a_cd_fire1 == FALSE)
      {
        // rec 05.08 8.2.3: BEP value need to be accumulated on correctly received blocks
        // rec 05.08 8.4.8.2 : for SACCH of TCH, no accumulation for CV_BEP and nbr_rcvd_blocks
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
        l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;
      } // if(fire1 == FALSE)
    } // if(l1s.actual_time.fn_in_report == 91)
  } // // SACCH of TCH

  // SDCCH and SACCH of SDCCH
  if (((task == DDL) || (task == ADL)) && (burst_id == BURST_4))
  {
    //unconditional accumulation of Rxlev_val
    l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated
    l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                 last_corr_decoded_burst[5] +
                                                 last_corr_decoded_burst[6] +
                                                 last_corr_decoded_burst[7];

    // rec 05.08 8.2.3: in SDCCH, BEP value need to be accumulated on correctly received blocks
    if(emr_params->a_cd_fire1 == FALSE)
    {
      l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
      l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
      l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
      l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
      l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;
    }
  } // SDCCH

  //AMR FS
  #if (AMR == 1)
    if((task == TCHTF) &&
       (channel_mode == TCH_AFS_MODE) &&
       (l1s.actual_time.fn_mod13_mod4 == 0))
    {
      if(emr_params->amr_facch_present == TRUE)
      {
        // FACCH present
        // FACCH correctly decoded ?
        if(emr_params->amr_facch_fire1 == FALSE)
        {
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];
        } // if(fire1 == FALSE)
      } // if(facch_present == TRUE)
      else
      {
        // NOT FACCH
        if ((emr_params->b_ratscch_blud == TRUE) && (emr_params->ratscch_rxtype == RATSCCH_GOOD))
        {
          //RATSCCH correctly decoded
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated
          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                       last_corr_decoded_burst[5] +
                                                       last_corr_decoded_burst[6] +
                                                       last_corr_decoded_burst[7];
        } // if(b_ratscch_blud == TRUE)
        else if(emr_params->a_dd_0_blud == TRUE)
        {
          // Good speech frame.
          if((emr_params->amr_rx_type_sub0 == SPEECH_GOOD) ||
             (emr_params->amr_rx_type_sub0 == SPEECH_DEGRADED) ||
             (emr_params->amr_rx_type_sub0 == SID_UPDATE))
          {
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

            // Accumulate BEP
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   += cv_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

            //accumulation of the correctly decoded block
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                         last_corr_decoded_burst[5] +
                                                         last_corr_decoded_burst[6] +
                                                         last_corr_decoded_burst[7];

            if ((emr_params->amr_rx_type_sub0 == SPEECH_GOOD) || (emr_params->amr_rx_type_sub0 == SPEECH_DEGRADED))
              //Number of correctly decoded blocks excluding SACCH FACCH RATSCCH and SID frames.
              l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
          } // if((rx_type == SPEECH_GOOD) || (rx_type == SID_UPDATE))
        } // else if(b_blud == TRUE)
      } // else of if(facch_present == TRUE)
    } //AMR FS

    //AMR HS
    //TCH AHS
    if((task == TCHTH) &&
       (channel_mode == TCH_AHS_MODE)&&
       (normalised_fn_mod13_mod4 == 3))
    {
      UWORD8 norm_fn_mod26;
      subchannel = emr_params->subchannel;

      if (subchannel == 0)
      {
        // Load the bit to check if the block is valid
        b_blud =  emr_params->a_dd_0_blud;
        rx_type = emr_params->amr_rx_type_sub0;
      }
      else // subchannel 1
      {
        // Load the bit to check if the block is valid
        b_blud =  emr_params->a_dd_1_blud;
        rx_type = emr_params->amr_rx_type_sub1;
      }

      norm_fn_mod26 = (l1s.actual_time.fn - subchannel +26)  % 26;

      if(norm_fn_mod26 == 7 ||
         norm_fn_mod26 == 16||
         norm_fn_mod26 == 24 )
      {
        // FACCH: Check A_FD information block.
        if(emr_params->amr_facch_present == TRUE)
        {
          // FACCH present
          // FACCH correctly decoded ?
          if(emr_params->amr_facch_fire1 == FALSE)
          {
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

            // Accumulate BEP
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc +=mean_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   +=cv_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

            //accumulation of the correctly decoded block
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] +
                                                         last_corr_decoded_burst[5] +
                                                         last_corr_decoded_burst[6] +
                                                         last_corr_decoded_burst[7];
          } // if(fire1 == FALSE)
        } // if(facch_present == TRUE)
        else
        {
          // NOT FACCH
          // Load the bit to check if the block is a RATSCCH in caseof rx_type = NO_DATA
          //In half rate, there are 2 consecutive frames called RATSCCH_MARKER and
          //RATSCCH_DATA, MARKER doesn't contain any CRC. So we cannot make a decision
          //whether RATSCCH_MARKER is correctly decoded. Hence ratscch_rxtype_prev
          //is not valid. Hence the inner check has to be based only on ratscch_rxtype.
          //ratscch_rxtype is updated based on the CRC of RATSCCH_DATA.
          //The following are the decisions on the outer check "if (b_ratscch_blud == TRUE)....
          //b_ratscch_blud is updated based on RATSCCH_DATA. Hence it is a valid check
          //b_ratscch_blud_prev would have been accumulated based on RATSCCH_MARKER.
          //The assumption here is that when RATSCCH_MARKER is detected, the b_blud bit of
          //a_ratscch_dl will be updated.

          if ( ((emr_params->b_ratscch_blud == TRUE) && (emr_params->ratscch_rxtype == RATSCCH_GOOD)) ||
               ((b_blud==TRUE) && (rx_type == SID_UPDATE)) ||
               ((b_blud == TRUE)&&(rx_type == SPEECH_DEGRADED)) ||
               ((b_blud == TRUE)&&(rx_type == SPEECH_GOOD)) )
          {
            //RATSCCH or SID Update or Speech block correctly decoded, increment the counter
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

            // Accumulate BEP
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc +=mean_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   +=cv_bep;
            l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
            l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

            //accumulation of the correctly decoded block
            l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc +=last_corr_decoded_burst[4] +
                                                        last_corr_decoded_burst[5] +
                                                        last_corr_decoded_burst[6] +
                                                        last_corr_decoded_burst[7];
            if (((rx_type == SPEECH_GOOD) || (rx_type == SPEECH_DEGRADED)) && (emr_params->ratscch_rxtype != RATSCCH_GOOD))
              l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
          }
        } // else part of if(facch_present == TRUE)
      }//fnmod26 == 7||16 || 24
      else
      {
        //if (norm_fn_mod26 ==3 || norm_fn_mod26 == 11 ||
        //norm_fn_mod26 == 20)

        if ( ((emr_params->b_ratscch_blud == TRUE) && (emr_params->ratscch_rxtype == RATSCCH_GOOD)) ||
             ((b_blud==TRUE) && (rx_type == SID_UPDATE)) ||
             ((b_blud == TRUE)&&(rx_type == SPEECH_DEGRADED)) ||
             ((b_blud == TRUE)&&(rx_type == SPEECH_GOOD)) )
        {
          //RATSCCH or SID Update or Speech block correctly decoded, increment the counter
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;   // 4 bursts are accumulated

          // Accumulate BEP
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc +=mean_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc   +=cv_bep;
          l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++;
          l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++;

          //accumulation of the correctly decoded block
          l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc +=last_corr_decoded_burst[4] +
                                                      last_corr_decoded_burst[5] +
                                                      last_corr_decoded_burst[6] +
                                                      last_corr_decoded_burst[7];
          if (((rx_type == SPEECH_GOOD) || (rx_type == SPEECH_DEGRADED)) && (emr_params->ratscch_rxtype != RATSCCH_GOOD))
            l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++;
        }
      } //else fn = 3,11,20
    }//task == TCHTH.....
  #endif //(AMR == 1)
}
#endif //FF_EMR
#else //REL99

void l1s_read_dedic_scell_meas(UWORD8 input_level, UWORD8 sub_flag)
{
  WORD16 rxlev = l1s_encode_rxlev(input_level);

  // Measurement must be rejected if channel is hopping, hopped on
  // the beacon frequency and PWRC is TRUE (see GSM05.08, $8.1.3).
  if(!((l1a_l1s_com.dedic_set.pwrc == TRUE) &&
       (l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->chan_sel.h == TRUE) &&
       (l1a_l1s_com.dedic_set.radio_freq_dd == l1a_l1s_com.Scell_info.radio_freq)))
  {
    // Add to FULL set meas.
    l1a_l1s_com.Scell_info.meas.nbr_meas++;
    l1a_l1s_com.Scell_info.meas.acc += rxlev;

    if(sub_flag == TRUE)
    {
      // Add to SUB set meas.
      l1a_l1s_com.Smeas_dedic.nbr_meas_sub++;
      l1a_l1s_com.Smeas_dedic.acc_sub += rxlev;
    }
  }
}
#endif //REL99
/*-------------------------------------------------------*/
/* l1s_dedic_reporting()                                 */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                        */
/*-------------------------------------------------------*/
void l1s_dedic_reporting()
{
  xSignalHeaderRec  *msg;
  UWORD8             i;
  UWORD32            nbr_carrier = l1a_l1s_com.ba_list.nbr_carrier;

  // Allocate L1C_MEAS_DONE message...
  msg = os_alloc_sig(sizeof(T_MPHC_MEAS_REPORT));
  DEBUGMSG(status,NU_ALLOC_ERR)
  msg->SignalCode = L1C_MEAS_DONE;

  // Fill miscelaneous parameters
  //=============================
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ba_id = l1a_l1s_com.ba_list.ba_id;

  //timing_advance...
  //txpwr...
  //meas_valid...

  // Fill msg for Neighbor Cells
  //============================

  for(i=0;i<nbr_carrier;i++)
  {
    T_MEAS_INFO  *ba_ptr = &l1a_l1s_com.ba_list.A[i];

    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ncell_meas.A[i].bcch_freq      = ba_ptr->radio_freq;
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ncell_meas.A[i].rxlev_acc      = ba_ptr->acc;
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ncell_meas.A[i].rxlev_nbr_meas = ba_ptr->nbr_meas;

    // Reset BA.
    ba_ptr->acc      = 0;
    ba_ptr->nbr_meas = 0;
  }
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->no_of_ncell_meas = nbr_carrier;

  // Fill msg for Serving Cell
  //==========================

  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_full_acc         = l1a_l1s_com.Scell_info.meas.acc;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_full_nbr_meas    = l1a_l1s_com.Scell_info.meas.nbr_meas;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_sub_acc          = l1a_l1s_com.Smeas_dedic.acc_sub;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_sub_nbr_meas     = l1a_l1s_com.Smeas_dedic.nbr_meas_sub;

  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_full_acc_errors = l1a_l1s_com.Smeas_dedic.qual_acc_full;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_full_nbr_bits   = l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_sub_acc_errors  = l1a_l1s_com.Smeas_dedic.qual_acc_sub;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_sub_nbr_bits    = l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub;

  #if REL99
  #if FF_EMR
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_val_acc         = l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_val_nbr_meas    = l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->nbr_rcvd_blocks       = l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->mean_bep_block_acc    = l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->cv_bep_block_acc      = l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->mean_bep_block_num    = l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->cv_bep_block_num      = l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num;
  #endif
  #endif

  if(l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE)
  // Set "dtx_used" flag according to DSP transmit report result only if
  // DTX is allowed.
  {
    if(l1a_l1s_com.Smeas_dedic.dtx_used > 0)
      ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = TRUE;
    // Set the dtx_used flag in the case of TCHF/ no signaling
    else if ((l1a_l1s_com.dedic_set.aset->chan1.mode == SIG_ONLY_MODE)
            &&(l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type==TCH_F))
      ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = TRUE;
    else
      ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = FALSE;
  }
  else
  {
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = FALSE;
  }

  // Reset Serving Cell measurement variables.
  l1s_reset_dedic_serving_meas();


  // Give miscellaneous info to L3 (just for indication/debug).
  //===========================================================

  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->timing_advance = l1a_l1s_com.dedic_set.aset->timing_advance;
  ((T_MPHC_MEAS_REPORT*)(msg->SigP))->txpwr_used     = l1s.reported_txpwr;

  #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_dl_count = trace_info.facch_dl_count;
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_ul_count = trace_info.facch_ul_count;
  #if (FF_REPEATED_DL_FACCH == 1)
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_dl_combined_good_count = trace_info.facch_dl_combined_good_count; /* No of good blocks after combining */
    ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_dl_repetition_block_count = trace_info.facch_dl_repetition_block_count;
  #endif/* (FF_REPEATED_DL_FACCH == 1) */
    trace_info.facch_dl_fail_count_trace = trace_info.facch_dl_fail_count;
    trace_info.facch_dl_count = 0;
    trace_info.facch_ul_count = 0;
    trace_info.facch_dl_fail_count = 0;
   #if ( FF_REPEATED_DL_FACCH == 1 ) /* Reseting the values */
    trace_info.facch_dl_combined_good_count = 0;
    trace_info.facch_dl_repetition_block_count = 0;
   #endif/* (FF_REPEATED_DL_FACCH == 1) */
  #endif

  // send L1C_MEAS_DONE message...
  os_send_sig(msg, L1C1_QUEUE);
  DEBUGMSG(status,NU_SEND_QUEUE_ERR)
}

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_read_fb()                                         */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : this function sends L1C_FB_INFO to L1A*/
/*-------------------------------------------------------*/
void l1s_read_fb(UWORD8 task, UWORD32 fb_flag, UWORD32 toa, UWORD32 attempt,
                 UWORD32 pm, UWORD32 angle, UWORD32 snr)
{
  xSignalHeaderRec  *msg;
  WORD32             modif_toa = 0;
  WORD32             ntdma;
  UWORD32            fn_offset;

  // For detail of the here below equation cf. BUG1558
  #define MAX_TOA_FOR_SB (D_NSUBB_DEDIC*48)+DL_ABB_DELAY/4-(SB_BURST_DURATION+DL_ABB_DELAY+SB_MARGIN)/4-2

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dspres(dltsk_trace[task].name);
  #endif

  #if (TRACE_TYPE!=0)
    switch(task)
    {
      case FBNEW: trace_fct(CST_L1S_READ_FB, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);break;
      case FB51:  trace_fct(CST_L1S_READ_FB51, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);break;
      case FB26:  trace_fct(CST_L1S_READ_FB26, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);break;
      default:    trace_fct(CST_UNKNOWN_FB, l1a_l1s_com.nsync.list[0].radio_freq);break;
    }
  #endif

  if(fb_flag == TRUE)
  {
    switch (task)
    {
      case FBNEW:
      case FB51:
      // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window.
      {
        modif_toa = toa - (SB_MARGIN/4);     // Rem: unit is "BIT".
      }
      break;

      case FB26:
      // Compute TOA taking into account the 23 bit guard for next SB receive window
      // and the time diff. between a the fb search and a normal serving RX slot..
      // Rem: TOA cannot be less than "SB_MARGIN/4".
      {
        // Saturate TOA to MAX_TOA_FOR_SB since it is the last position compatible with the
        // SB26 tpu programming. MAX_TOA_FOR_SB + 1 would reject the TCHT/frame0 one frame later due
        // to an overlap of TPU scenarios.
        if(toa >= MAX_TOA_FOR_SB) toa = MAX_TOA_FOR_SB;

        modif_toa = toa + ((l1_config.params.fb26_anchoring_time + PROVISION_TIME - START_RX_FB)/4) - (SB_MARGIN/4); // Rem: unit is "BIT".
      }
      break;
    } // End of switch.

    if(modif_toa < 0)
    {
      modif_toa = (modif_toa + (TPU_CLOCK_RANGE/4)) * 4; // Unit is changed from bit to qbit.
      ntdma     = - 1;
    }
    else
    {
      ntdma     = modif_toa / (TPU_CLOCK_RANGE/4);
      modif_toa = (modif_toa - ntdma * (TPU_CLOCK_RANGE/4)) * 4;  // Unit is changed from bit to qbit.
    }

    switch (task)
    {
      case FBNEW:
      // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window.
      {
        // "fn_offset" loaded with serving frame number corresponding to FB.
        // Keep a %51 format to prepare SB scheduling.
        fn_offset = (l1s.actual_time.fn - attempt + ntdma + MAX_FN) % 51;
      }
      break;

      case FB51:
      // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window.
      {
        // "fn_offset" loaded with serving frame number corresponding to FB.
        // Keep a full frame number to allow scheduling of SB, 2 MF51 later.
        fn_offset = (l1s.actual_time.fn - attempt + ntdma + MAX_FN) % MAX_FN;
      }
      break;

      case FB26:
      {
        // "fn_offset" loaded with serving frame number corresponding to CTL(SB26).
        fn_offset = (l1s.actual_time.fn + 52 - 3) % MAX_FN;

        if(ntdma == 1) // 2nd frame...
          l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].sb26_offset = 1;
        else
          l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].sb26_offset = 0;
      }
      break;
    } // End of switch.

  } // End if.

  // Store TOA and FN offset in neighbor cell structure.
  l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].time_alignmt = modif_toa;
  l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].fn_offset    = fn_offset;

  // Create message T_L1C_FB_INFO.
  msg = os_alloc_sig(sizeof(T_L1C_FB_INFO));
  DEBUGMSG(status,NU_ALLOC_ERR)
  msg->SignalCode = L1C_FB_INFO;

  // Fill msg fields.
  ((T_L1C_FB_INFO *) (msg->SigP))->fb_flag    = fb_flag;
  ((T_L1C_FB_INFO *) (msg->SigP))->ntdma      = ntdma;
  ((T_L1C_FB_INFO *) (msg->SigP))->neigh_id   = l1a_l1s_com.nsync.active_fb_id;
  // Debug info or testmode
  ((T_L1C_FB_INFO *) (msg->SigP))->pm       = pm;
  ((T_L1C_FB_INFO*)(msg->SigP))->toa        = toa;
  ((T_L1C_FB_INFO*)(msg->SigP))->angle      = angle;
  ((T_L1C_FB_INFO*)(msg->SigP))->snr        = snr;
  ((T_L1C_FB_INFO *) (msg->SigP))->radio_freq = l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq;

  os_send_sig(msg, L1C1_QUEUE);
  DEBUGMSG(status,NU_SEND_QUEUE_ERR)
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_read_sb()                                         */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : this function sends L1C_SB_INFO to L1A*/
/*-------------------------------------------------------*/
void l1s_read_sb(UWORD8 task, UWORD32 flag, API *data, UWORD32 toa, UWORD8 attempt,
                 UWORD32 pm, UWORD32 angle, UWORD32 snr)
{
  xSignalHeaderRec  *msg;
  UWORD8             bsic=0;
  UWORD32            sb;
  WORD32             modif_toa = 0;
  UWORD32            fn_offset    = 0;
  WORD32             time_alignmt = 0;
  T_NCELL_SINGLE    *cell_ptr = NULL; //omaps00090550 NULL;
  UWORD32            SignalCode=0;
  UWORD8             fn_delay     = 2; // SB result read with 2 frames delay.
  UWORD8             neigh_id=0;
  UWORD32            fn;

  switch(task)
  {
    case SB2 :
    case SB51 :
    case SB26 :
      // Get Neighbour cell ptr.
      cell_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id];
      neigh_id = l1a_l1s_com.nsync.active_sb_id;

      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_SB, cell_ptr->radio_freq);
      #endif

      SignalCode = L1C_SB_INFO;
      if(task == SB26) fn_delay = 3 - l1a_l1s_com.nsync.list[neigh_id].sb26_offset;
    break;

    case SBCONF :
    case SBCNF51 :
    case SBCNF26 :
      // Get Neighbour cell ptr.
      cell_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id];
      neigh_id = l1a_l1s_com.nsync.active_sbconf_id;

      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_SBCONF, cell_ptr->radio_freq);
      #endif

      SignalCode = L1C_SBCONF_INFO;
      if(task == SBCNF26) fn_delay = 3 - l1a_l1s_com.nsync.list[neigh_id].sb26_offset;
    break;
  }

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dspres(dltsk_trace[task].name);
  #endif

  // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window.
  modif_toa = (toa - (SB_MARGIN/4)) * 4;       // Rem: unit is "QBIT".

  // Read SB content,.
  sb = data[0] & 0xffff | ((data[1] & 0xffff) << 16);

  if (flag == TRUE)
  // SB has been found...
  // We synchronized with a NEIGHBOUR cell.
  {
    UWORD32    t1, t2, t3, t3p;

    // extract BSIC, T1, T2, T3. Compute FN.
    // bsic contains NCC & BCC (GSM05.02, p9)
    bsic   = (UWORD8) ((sb & 0x000000fc) >> 2);

    t1  = ((sb & 0x00800000) >> 23 |   // t1 low
           (sb & 0x0000ff00) >> 7  |   // t1 midle
           (sb & 0x00000003) << 9);    // t1 high
    t2  =  (sb & 0x007c0000) >> 18;
    t3p = ((sb & 0x01000000) >> 24 |   // t3p low
           (sb & 0x00030000) >> 15);   // t3p high
    t3  =  (10*(t3p) +1);
    fn  =  (51 * ((t3 - t2 + 26) % 26) + t3 + (26 * 51 * t1));

    // Due to pipeline effect (CTRL.WORK.WORK.READ), sb content is taken into account
    // "fn_delay" TDMA later: that's why we use "fn + fn_delay..." in the offset computation.
    //
    // NEIGHBOUR DOMAIN:
    // -----------------
    // |                    |<----- 1 TDMA ----->| SB                 |                    |
    // |                    |                    |XXXX                |                    |
    // |                    |                    |                    |                    |
    // |                    |                    |  FN_neighbour(SB)  | FN_neighbour(SB)+1 | FN_neighbour(SB)+2
    // |                    |                    |                    |                    |
    //                                                                            offset   |
    //                                                                              +      |
    //                                                                             BOB     |
    //                                                                       |<----------->|
    // MS DOMAIN:                                                            |
    // ----------                  |                    |                    |                    |
    //        |        CTRL        |        WORK        |        WORK        |         READ       |
    //        |                    |                    |                    |                    |
    //
    // offset = FN_neighbour(SB)+ fn_delay - FN_serving(READ).
    // Bob: fine timing difference between the Neighbour timing and the MS internal timing.
    //
    fn_offset = (fn + fn_delay + MAX_FN - l1s.actual_time.fn) % MAX_FN;

    // "time_alignmt" must be corrected (use "modif_toa" from the SB read).
    // Check that "time_alignmt" do not become bigger than "TPU_CLOCK_RANGE".
    // If so, "fn_offset" must be decremented.
    time_alignmt   = cell_ptr->time_alignmt + modif_toa;
    if(time_alignmt >= TPU_CLOCK_RANGE)
    {
      time_alignmt -= TPU_CLOCK_RANGE;  // qbp for sim. Normal value is 1250;
      fn_offset    -= 1;                // WARNING....to be checked!!!!!!
    }
    else
    if(time_alignmt < 0)
    {
      time_alignmt += TPU_CLOCK_RANGE;  // qbp for sim. Normal value is 1250;
      fn_offset    += 1;                // WARNING....to be checked!!!!!!
    }
  }

  #if L1_RECOVERY
    if(flag)
    {
      // recovery flag is reseted because the system works fine
      // this check is performed in all modes.
      l1a_l1s_com.recovery_flag = FALSE;

      // Reset error flags and counter
      l1s.recovery.frame_count  = 0;
    }
  #endif

  // In all mode send result message to L1 Async.
  msg = os_alloc_sig(sizeof(T_MPHC_NCELL_SYNC_IND));
  DEBUGMSG(status,NU_ALLOC_ERR)
  msg->SignalCode   = SignalCode;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->sb_flag      = flag;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->radio_freq   = cell_ptr->radio_freq;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->bsic         = bsic;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->fn_offset    = fn_offset;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->time_alignmt = time_alignmt;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->neigh_id     = neigh_id;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->attempt      = attempt;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->pm           = pm;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->toa          = toa;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->angle        = angle;
  ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->snr          = snr;


  #if (L1_EOTD == 1)
  // In EOTD mode read additional results
  if (l1a_l1s_com.nsync.eotd_meas_session == TRUE)
  {
    UWORD8  i;
    WORD16  d_eotd_first;
    WORD16  d_eotd_max;
    UWORD32 d_eotd_nrj;
    API     *data = &(l1s_dsp_com.dsp_ndb_ptr->a_eotd_crosscor[0]);
    UWORD32 fn_sb_neigh;

    d_eotd_first   = l1s_dsp_com.dsp_ndb_ptr->d_eotd_first & 0xffff;

    d_eotd_max     = l1s_dsp_com.dsp_ndb_ptr->d_eotd_max & 0xffff;

    fn_sb_neigh = (l1s.actual_time.fn - fn_delay + MAX_FN) % MAX_FN;
    ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->fn_sb_neigh  = fn_sb_neigh;

    d_eotd_nrj   = (l1s_dsp_com.dsp_ndb_ptr->d_eotd_nrj_low & 0xffff) |
                   ((l1s_dsp_com.dsp_ndb_ptr->d_eotd_nrj_high & 0x00ff) << 16);

    // L1 SW :
    //         CPS Cursor expects the accumulated signal level of the cross
    //         correlation (d_eotd_nrj) to be 16bit format. The DSP reports
    //         it as 24bit format (lsb aligned in a 32bit word).
    //         We scale the DSP result by right shifting by 8, hence preserving
    //         the MSBs

    d_eotd_nrj >>= 8;

    ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->eotd_data_valid = TRUE;
    ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->d_eotd_first    = d_eotd_first;
    ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->d_eotd_max      = d_eotd_max;
    ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->d_eotd_nrj      = d_eotd_nrj;
    ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->fn_in_SB        = fn;
    for (i=0; i<18; i++)
      ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->a_eotd_crosscor[i] = data[i] & 0xffff;;

    if(task == SBCNF26)
    {
      ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->toa_correction =
        l1a_l1s_com.nsync.eotd_cache_toa_tracking;
    }
    else
    {
      ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->toa_correction = 0;
    }

  }
  else
   ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->eotd_data_valid = FALSE;
#endif



  os_send_sig(msg, L1C1_QUEUE);
  DEBUGMSG(status,NU_SEND_QUEUE_ERR)
}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

#if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

/*-------------------------------------------------------*/
/* l1s_read_fbsb()                                       */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : sends L1C_FBSB_INFO to L1A            */
/*-------------------------------------------------------*/
#if ((REL99 == 1) && (FF_BHO == 1))
void l1s_read_fbsb(UWORD8 task, UWORD8 attempt, BOOL fb_flag,  BOOL sb_flag, API *data, UWORD32 toa, UWORD32 pm, UWORD32 angle, UWORD32 snr)
{
  xSignalHeaderRec  *msg;
  UWORD8             bsic = 0;
  UWORD32            fn_offset = 0;
  UWORD32            time_alignmt = 0;

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dspres(dltsk_trace[task].name);
  #endif

  #if (TRACE_TYPE!=0)
    // trace_fct(CST_L1S_READ_FBSB, l1a_l1s_com.nsync_fbsb.radio_freq);
  #endif

  if ((fb_flag == TRUE) && (sb_flag == TRUE))
  {
    UWORD32    toa_qbit, sb, fn, fn2, t1, t2, t3, t3p;
    UWORD8     ntdma;

    // Read SB content,.
    sb = data[0] & 0xffff | ((data[1] & 0xffff) << 16);

    // extract BSIC, T1, T2, T3. Compute FN.
    // bsic contains NCC & BCC (GSM05.02, p9)
    bsic   = (UWORD8) ((sb & 0x000000fc) >> 2);

    t1  = ((sb & 0x00800000) >> 23 |   // t1 low
           (sb & 0x0000ff00) >> 7  |   // t1 midle
           (sb & 0x00000003) << 9);    // t1 high
    t2  =  (sb & 0x007c0000) >> 18;
    t3p = ((sb & 0x01000000) >> 24 |   // t3p low
           (sb & 0x00030000) >> 15);   // t3p high
    t3  =  (10*(t3p) +1);
    fn  =  (51 * ((t3 - t2 + 26) % 26) + t3 + (26 * 51 * t1));

    // _|-----------------------------------|___  : TPU WINDOW
    //                    |FB|          |SB|
    // _|---------------->|--------->|->|
    //        toa_fb       1 frame  toa_sb
    //
    //  we also need to take into account the 23 bit guard for SB receive window.

    toa_qbit = (l1a_l1s_com.nsync_fbsb.fb_toa + toa) * 4 + TPU_CLOCK_RANGE - SB_MARGIN;

    ntdma = toa_qbit / TPU_CLOCK_RANGE;

    fn_offset = (fn - l1s.actual_time.fn + attempt - ntdma + (2 * MAX_FN))% MAX_FN;

    time_alignmt = toa_qbit - (ntdma * TPU_CLOCK_RANGE);
  }

  // Create message T_L1C_FBSB_INFO.
  msg = os_alloc_sig(sizeof(T_L1C_FB_INFO));
  DEBUGMSG(status,NU_ALLOC_ERR)
  msg->SignalCode = L1C_FBSB_INFO;

  // Fill msg fields.
  ((T_L1C_FBSB_INFO *) (msg->SigP))->fb_flag      = fb_flag;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->sb_flag      = sb_flag;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->bsic         = bsic;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->fn_offset    = fn_offset;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->time_alignmt = time_alignmt;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->pm           = pm;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->toa          = toa;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->angle        = angle;
  ((T_L1C_FBSB_INFO *) (msg->SigP))->snr          = snr;


  os_send_sig(msg, L1C1_QUEUE);
  DEBUGMSG(status,NU_SEND_QUEUE_ERR)
}
#endif // #if ((REL99 == 1) && (FF_BHO == 1))
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise

/*-------------------------------------------------------*/
/* l1s_read_l3frm()                                      */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : reads NB data                         */
/*                 and formate MPHC_DATA_IND message     */
/*-------------------------------------------------------*/
void l1s_read_l3frm(UWORD8 pwr_level, API *info_address, UWORD32 task_rx)
{
  xSignalHeaderRec *msg;
  UWORD32           i,j;
  UWORD32           word32;
  UWORD32           rx_fail_flag;
  //OMAPS00090550 UWORD32           b_fire0;
  UWORD32           b_fire1;
  UWORD8            tc = l1s.actual_time.tc; // Default: tc loaded with current serving TC.
  UWORD16           radio_freq = l1a_l1s_com.Scell_info.radio_freq; // Default: radio_freq load with serving cell

  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dspres(dltsk_trace[task_rx].name);
  #endif

  // Allocate result message.

  #if (GSM_IDLE_RAM == 1)         // GPF not modified for GSM_IDLE_RAM -> enable Traffic Controller in L1S
    if (!READ_TRAFFIC_CONT_STATE)
    CSMI_TrafficControllerOn();
  #endif

  msg = os_alloc_sig(sizeof(T_MPHC_DATA_IND));
  DEBUGMSG(status,NU_ALLOC_ERR)

  switch(task_rx)
  {
    case NP:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_L3FRM__NP, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code and L2 channel.
      msg->SignalCode = L1C_NP_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_PCH;
    break;

    case EP:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_L3FRM__EP, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code and L2 channel.
      msg->SignalCode = L1C_EP_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_EPCH;
    break;

    case NBCCHS:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_L3FRM__NBCCHS, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code and L2 channel.
      msg->SignalCode = L1C_BCCHS_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_NBCCH;
    break;

    case EBCCHS:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_L3FRM__EBCCHS, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code and L2 channel.
      msg->SignalCode = L1C_BCCHS_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_EBCCH;
    break;

    case BCCHN:
    #if L1_GPRS
    case BCCHN_TRAN:
    #endif
    case BCCHN_TOP:
      #if (TRACE_TYPE!=0)
        if (task_rx == BCCHN)
          trace_fct(CST_L1S_READ_L3FRM__BCCHN, l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm].radio_freq);
        else // BCCHN_TRAN and BCCHN_TOP tasks
          trace_fct(CST_L1S_READ_L3FRM__BCCHN, l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top].radio_freq);
      #endif

      // Fill msg signal code, L2 channel and get neighbour TC.
      msg->SignalCode = L1C_BCCHN_INFO;

      // Save neighbour ID.
      // With TC and Neighbour ID, L1A can manage the remaining BCCH requests.
      if (task_rx == BCCHN)
      {
        ((T_MPHC_DATA_IND *)(msg->SigP))->neigh_id = l1a_l1s_com.bcchn.active_neigh_id_norm;
        tc = l1a_l1s_com.bcchn.active_neigh_tc_norm;
        radio_freq = l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm].radio_freq;
      }
      else // BCCHN_TRAN and BCCHN_TOP tasks
      {
        ((T_MPHC_DATA_IND *)(msg->SigP))->neigh_id = l1a_l1s_com.bcchn.active_neigh_id_top;
        tc = l1a_l1s_com.bcchn.active_neigh_tc_top;
        radio_freq = l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top].radio_freq;
      }

      if(tc >= 8)
      {
        // Reading Extended BCCH.
        tc -= 8;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_EBCCH;
      }
      else
      {
        // Reading Normal BCCH.
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_NBCCH;
      }

    break;

    case ALLC:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_L3FRM__ALLC, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code, L2 channel and get neighbour TC.
      msg->SignalCode = L1C_ALLC_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_CCCH;
    break;

    case SMSCB:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1S_READ_L3FRM__CB, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code, L2 channel and get neighbour TC.
      msg->SignalCode = L1C_CB_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_CBCH;
    break;

    #if L1_GPRS

      case PNP:
        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1PS_READ_L3FRM__PNP, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        // Fill msg signal code and L2 channel.
        msg->SignalCode = L1P_PNP_INFO;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PPCH;
        tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report;
      break;

      case PEP:
        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1PS_READ_L3FRM__PEP, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        // Fill msg signal code and L2 channel.
        msg->SignalCode = L1P_PEP_INFO;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PEPCH;
        tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report;
      break;

      case PALLC:
        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1PS_READ_L3FRM__PALLC, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        // Fill msg signal code and L2 channel.
        msg->SignalCode = L1P_PALLC_INFO;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PCCCH;
        tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report;
      break;

      case PBCCHS:
        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1PS_READ_L3FRM__PBCCHS, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        // Fill msg signal code and L2 channel.
        msg->SignalCode = L1P_PBCCHS_INFO;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PBCCH;
        tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report;
      break;

      case PBCCHN_IDLE:
      case PBCCHN_TRAN:
        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1PS_READ_L3FRM__PBCCHN, l1pa_l1ps_com.pbcchn.bcch_carrier);
        #endif

        // Fill msg signal code and L2 channel.
        msg->SignalCode = L1P_PBCCHN_INFO;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PBCCH;
        tc = l1pa_l1ps_com.pbcchn.relative_position;
        radio_freq = l1pa_l1ps_com.pbcchn.bcch_carrier;
      break;

      case SINGLE:
        #if (TRACE_TYPE!=0)
          trace_fct(CST_L1PS_READ_L3FRM__SINGLE, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        // Fill L2 channel.
        msg->SignalCode = L1P_PACCH_INFO;
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PACCH;
        tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report;
      break;

    #endif

    // WARNING !!! to be removed (for CBCH debugging).
    default:
      #if (TRACE_TYPE!=0)
        trace_fct(CST_L1PS_READ_L3FRM__UNKNOWN, l1a_l1s_com.Scell_info.radio_freq);
      #endif

      // Fill msg signal code, L2 channel and get neighbour TC.
      msg->SignalCode = L1C_CB_INFO;
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_CCCH;
  }

  #if L1_GPRS
  if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER)
  #endif
  {
    // Compute detection flag.
 //OMAPS00090550   b_fire0 = ((info_address[0] & 0xffff) & (1<<B_FIRE0)) >> B_FIRE0;
    b_fire1 = ((info_address[0] & 0xffff) & (1<<B_FIRE1)) >> B_FIRE1;
    if(b_fire1 != 1)
      rx_fail_flag = FALSE;  // information block received successfully.
    else
      rx_fail_flag = TRUE;   // information block reception failled.

    // Get 23 bytes info. from DSP.
    for (j=0, i=0; i<11; i++)
    {
      word32 = info_address[3 + i]; // Get info word, rem: skip info. header.
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x000000ff);
      ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x0000ff00) >> 8;
    }
    ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[22] = (info_address[14] & 0x000000ff);

    // reset buffers and flags in NDB ...
    // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0
    info_address[0] = (1<<B_FIRE1);
  }
  #if L1_GPRS
    else // GPRS scheduler
    {
      // Compute detection flag.
      rx_fail_flag = ((*info_address & 0x0100) >> 8);

      // Get 24 bytes info. from DSP: CS1 meaningful block is of size 12 UWORD16 data.
      // !!! WARNING: word32 type is for compatibility with chipset == 0.
      // Can be word16 if only chipset == 2 is used.
      for (j=0, i=0; i<12; i++)
      {
        // Data downloaded from a_dd_gprs[0][]...
        word32 = info_address[4 + i]; // Get info word, rem: skip info. header.
        #if 0	/* FreeCalypso TCS211 reconstruction */
        if(j<23)
        #endif
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x000000ff);
        #if 0	/* FreeCalypso TCS211 reconstruction */
        if(j<23)
        #endif
        ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x0000ff00) >> 8;
      }

      // reset buffers and flags in NDB ...
      // reset CS_TYPE
      info_address[0] = CS_NONE_TYPE;
    }
  #endif

  // Report detection flag.
  if((l1s_dsp_com.dsp_db_r_ptr->d_debug & 0xffff ) != (l1s.debug_time & 0xffff )) // in case of COM error the block is false
    ((T_MPHC_DATA_IND *)(msg->SigP))->error_flag = TRUE;
  else
    ((T_MPHC_DATA_IND *)(msg->SigP))->error_flag = rx_fail_flag;

  // be careful: radio_freq is setted at the beging of the code and may be modified inside the "case"
  ((T_MPHC_DATA_IND *)(msg->SigP))->radio_freq = radio_freq;

   // be careful: tc is setted at the beging of the code and may be modified inside the "case"
  ((T_MPHC_DATA_IND *)(msg->SigP))->tc = tc;

  // convert in ETSI format and send it back to L3
  ((T_MPHC_DATA_IND *)(msg->SigP))->ccch_lev = l1s_encode_rxlev(pwr_level);

#if (FF_L1_FAST_DECODING == 1)
  // Update the fn according to the number of the last decoded burst (2, 3 or 4) in case of fast paging: alignment with a block boudary
  if(l1a_l1s_com.last_fast_decoding == 0)
    // fast decoding was not not used
  ((T_MPHC_DATA_IND *)(msg->SigP))->fn       = l1s.actual_time.fn;
  else
    // fast decoding done, fn is incremented up to 2 frames (if fast decoding with 2 bursts), 0 if fast decoding with 4 bursts (normal decoding)
    ((T_MPHC_DATA_IND *)(msg->SigP))->fn       = l1s.actual_time.fn + BURST_4 + 1 - l1a_l1s_com.last_fast_decoding;
#else
    ((T_MPHC_DATA_IND *)(msg->SigP))->fn       = l1s.actual_time.fn;
#endif
  // send message...

  os_send_sig(msg, L1C1_QUEUE);
  DEBUGMSG(status,NU_SEND_QUEUE_ERR)
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif
/*-------------------------------------------------------*/
/* l1s_read_sacch_dl()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : reads NB data                         */
/*-------------------------------------------------------*/
void l1s_read_sacch_dl(API *info_address, UWORD32 task_rx)
{
  xSignalHeaderRec *msg;
  UWORD32           i,j;
  UWORD32           word32;
  UWORD32           rx_fail_flag;
 //OMAPS00090550 UWORD32           b_fire0;
  UWORD32           b_fire1;
  #if  (FF_REPEATED_SACCH == 1)
      BOOL           b_joint= 0; /* The flag to read the DSP response on combining */
      static BOOL prevfail = 0;
  #endif /* (FF_REPEATED_SACCH == 1) */

  // Traces.
  #if (TRACE_TYPE==5) && FLOWCHART
    trace_flowchart_dspres(dltsk_trace[task_rx].name);
  #endif

  #if (TRACE_TYPE!=0)
    if(task_rx == ADL)  trace_fct(CST_L1S_READ_SACCH_DL__ADL, l1a_l1s_com.dedic_set.radio_freq_dd);
    if(task_rx == TCHA) trace_fct(CST_L1S_READ_SACCH_DL__TCHA, l1a_l1s_com.dedic_set.radio_freq_dd);
  #endif

 #if (((TRACE_TYPE==1) || (TRACE_TYPE==4)) && ((FF_REPEATED_SACCH == 1)))
    trace_info.repeat_sacch.dl_count ++;        /* It is a SACCH downlink block */

 #endif
  // Compute detection flag.
 //OMAPS00090550 b_fire0 = ((info_address[0] & 0xffff) & (1<<B_FIRE0)) >> B_FIRE0;
  b_fire1 = ((info_address[0] & 0xffff) & (1<<B_FIRE1)) >> B_FIRE1;
  if(b_fire1 != 1)
    rx_fail_flag = FALSE;  // information block received successfully.
  else
    rx_fail_flag = TRUE;   // information block reception failled.

#if  (FF_REPEATED_SACCH == 1)
     b_joint = (BOOL)(((info_address[0] & 0xffff) & (1<<B_JOINT)) >> B_JOINT);

#endif  /* (FF_REPEATED_SACCH == 1) */
  // Clear 1st word of header.
  info_address[0] = 0;

    #if ((TESTMODE) && ((FF_REPEATED_SACCH == 1)) )
	     if(l1_config.repeat_sacch_enable != REPEATED_SACCH_ENABLE)
	     {
	         l1s.repeated_sacch.srr = 0;
	         #if (TRACE_TYPE == 1 || TRACE_TYPE == 4)
	         trace_info.repeat_sacch.dl_buffer_empty = TRUE;
	         #endif /* TRACE_TYPE*/
	      }
	     else
	     {
	#endif /* ((TESTMODE) && ((FF_REPEATED_SACCH == 1))) */


	#if  (FF_REPEATED_SACCH == 1)

	      if( (b_joint==TRUE) || (rx_fail_flag==TRUE ))
	      {
	          /* chase combining  occurred or the current block was unsuccessfully decoded.*/
	          l1s.repeated_sacch.srr = 1;

	      }
	      else
	      {
	          l1s.repeated_sacch.srr = 0; // debug

	      }


	#endif /* (FF_REPEATED_SACCH == 1) */
    #if ((TESTMODE) && ((FF_REPEATED_SACCH == 1)) )
		    } /* end else l1_config.repeat_sacch_enable */
	#endif /* ((TESTMODE) && ((FF_REPEATED_SACCH == 1))) */

	#if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH))
	      trace_info.repeat_sacch.srr = l1s.repeated_sacch.srr;
	      if(b_joint == TRUE && b_fire1!=1)
	      {
	           trace_info.repeat_sacch.dl_combined_good_count ++;
	           if (prevfail == 1)
	          trace_info.repeat_sacch.dl_error_count--;
	      }
	#endif /* ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) */

#if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH))
	      trace_info.repeat_sacch.srr = l1s.repeated_sacch.srr;
	      if( rx_fail_flag == TRUE) /* Information reception failed */
	      {
	           trace_info.repeat_sacch.dl_error_count ++;
	      }

#endif /* ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) */

  #if TESTMODE
    // Continunous mode: the SAACH data aren't valid. Therefore don't send to L1A.
    if ((!l1_config.TestMode) || ((l1_config.TestMode) &&
        (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS)))
  #endif
    {
      // Allocate result message.
      msg = os_alloc_sig(sizeof(T_PH_DATA_IND));
      DEBUGMSG(status,NU_ALLOC_ERR)
      msg->SignalCode = L1C_SACCH_INFO;
      ((T_PH_DATA_IND *)(msg->SigP))->l2_channel_type = L2_CHANNEL_SACCH;

      // Catch L1 Header if SACCH/DL data block successfully received.
      if(rx_fail_flag == FALSE)
      {
        UWORD8  supplied_txpwr = info_address[3] & 0x0000001f;
        UWORD8  supplied_ta    = (info_address[3] & 0x00007f00) >> 8;

        #if (FF_REPEATED_SACCH == 1)
		    //Set SRO parameter to transmit to the UL
		    l1s.repeated_sacch.sro = (info_address[3] & 0x00000040) >> 6;
             		 /*
			 		       7   | 6  |  5      | 4   3   2   1    0
			 		    Spare  | SRO| FPC EPC | Ordered MS power level
			 		    	   |    Ordered timing advance

		             */
		#endif /* (FF_REPEATED_SACCH == 1) */
        // Check max transmit power (min txpwr) according to powerclass.
        supplied_txpwr =  l1a_clip_txpwr(supplied_txpwr,l1a_l1s_com.dedic_set.radio_freq);

        #if TESTMODE
          // Update txpwr and ta only during Normal Mode
          if (!l1_config.TestMode)
        #endif
          {
            l1a_l1s_com.dedic_set.aset->new_target_txpwr = supplied_txpwr;

            // Check if supplied TA is valid, if not keep previous value.
            if(supplied_ta < 64)
              l1a_l1s_com.dedic_set.aset->new_timing_advance = supplied_ta;
          }
           #if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH))
		          l1s_check_sacch_dl_block(info_address);
		          trace_info.repeat_sacch.sro = l1s.repeated_sacch.sro;
		    #endif /* ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) */
		  } /* end if rx_fail_flag */
		  else
		  {
			  #if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH))
		       trace_info.repeat_sacch.dl_buffer_empty = TRUE;
		      #endif
       }

      // Get 23 bytes info. from DSP.
      for (j=0, i=0; i<11; i++)
      {
        word32 = info_address[3 + i]; // Get info word, rem: skip info. header.
        ((T_PH_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x000000ff);
        ((T_PH_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x0000ff00) >> 8;
      }
      ((T_PH_DATA_IND *)(msg->SigP))->l2_frame.A[22] = (info_address[14] & 0x000000ff);

      // Fill msg header...
      ((T_PH_DATA_IND *)(msg->SigP))->rf_chan_num = l1a_l1s_com.Scell_info.radio_freq;
      ((T_PH_DATA_IND *)(msg->SigP))->error_cause = rx_fail_flag;
      ((T_PH_DATA_IND *)(msg->SigP))->bsic        = l1a_l1s_com.Scell_info.bsic;
      ((T_PH_DATA_IND *)(msg->SigP))->tc          = l1s.actual_time.tc;

      // send message...

      os_send_sig(msg, L1C1_QUEUE);
      DEBUGMSG(status,NU_SEND_QUEUE_ERR)

    #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
      trace_info.sacch_d_nerr = info_address[2] & 0x00ff;
    #endif
    #if  (FF_REPEATED_SACCH == 1)
       prevfail= rx_fail_flag ;
    #endif /* (FF_REPEATED_SACCH == 1) */
    }
}

/*-------------------------------------------------------*/
/* l1s_read_dcch_dl()                                    */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : reads FACCH DL data block.            */
/*-------------------------------------------------------*/
void l1s_read_dcch_dl(API *info_address, UWORD32 task_rx)
{
  UWORD8  rx_valid_flag = FALSE;
  UWORD8 timing_advance = 255;
  BOOL  b_joint ;  /* DSP indicator to Chase Combining */
  #if (L1_SAGEM_INTERFACE == 1)
  UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type;
  #endif

  #if (FF_REPEATED_DL_FACCH == 1)
      b_joint = (BOOL) (((info_address[0] & 0xffff) & (1<<B_JOINT)) >> B_JOINT);

    #if TESTMODE
          if(l1_config.repeat_facch_dl_enable != REPEATED_FACCHDL_ENABLE)  /*  repeated FACCH mode is disabled  */
            b_joint = FALSE;
    #endif /* TESTMODE */

  #endif /* (FF_REPEATED_DL_FACCH == 1) */


  if(info_address != NULL)
  // A data block must be passed to L2.
  {
    UWORD32 b_fire1;

    #if (TRACE_TYPE!=0)
      if(task_rx == DDL)   trace_fct(CST_L1S_READ_DCCH_DL__DDL,   l1a_l1s_com.dedic_set.radio_freq_dd);
      if(task_rx == TCHTF) trace_fct(CST_L1S_READ_DCCH_DL__TCHTF, l1a_l1s_com.dedic_set.radio_freq_dd);
      if(task_rx == TCHTH) trace_fct(CST_L1S_READ_DCCH_DL__TCHTH, l1a_l1s_com.dedic_set.radio_freq_dd);
    #endif

    // Set detection flag.
    b_fire1 = ((info_address[0] & 0xffff) & (1<<B_FIRE1)) >> B_FIRE1;
    if(b_fire1 != 1)
      rx_valid_flag = TRUE;  // information block received successfully.
    else
      rx_valid_flag = FALSE; // information block reception failled.

    if((rx_valid_flag == TRUE) && (l1a_l1s_com.dedic_set.aset->t3124 != 0))
    // T3124 running...
    // Check for PHYSICAL INFORMATION message from FACCH.
    {
      UWORD32  message_type = info_address[5] & 0x00ff;

      if(message_type == 0x2D)
      // FACCH message is a PHYSICAL INFORMATION message.
      {
        // Catch TIMING ADVANCE information.
        timing_advance = (UWORD8)((info_address[5] & 0xff00) >> 8);
        l1a_l1s_com.dedic_set.aset->new_timing_advance = timing_advance;
        l1a_l1s_com.dedic_set.aset->timing_advance     = timing_advance;

        // Reset T3124.
        l1a_l1s_com.dedic_set.aset->t3124 = 0;

        // Stop sending Handover Access burst.
        l1a_l1s_com.dedic_set.aset->ho_acc_to_send = 0;

        // Handover access procedure is completed.
        // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A.
        l1s_send_ho_finished(HO_COMPLETE);
      }
    }

    // Clear 1st word of header.
    info_address[0] = 0;

    // Shift data block pointer to skip DSP header.
    info_address = &(info_address[3]);

    if (rx_valid_flag == TRUE)
    {
      #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
        trace_info.facch_dl_count ++;
      #endif
      #if (FF_REPEATED_DL_FACCH == 1)  /*Fire code is correct and information recieved successfully */
       l1s_store_facch_buffer(l1s.repeated_facch, info_address);
      #endif

	/* trace for FER calculation (Repeated FACCH mode):                          */
        /*  nb of DL FACCH blocks correctly decoded which is not a repetition  */

      #if ((TRACE_TYPE==1|| TRACE_TYPE==4) && (FF_REPEATED_DL_FACCH))
        trace_info.facch_dl_good_block_reported++;
        if(b_joint == TRUE) /*  The combined block is successfully decoded */
            trace_info.facch_dl_combined_good_count++;
      #endif /* ((TRACE_TYPE==1|| TRACE_TYPE==4) && (FF_REPEATED_DL_FACCH)) */
      #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
        Trace_dedic_tch_block_stat(FACCH_GOOD, l1s_dsp_com.dsp_ndb_ptr->a_fd[2], 0);
      #endif
    }
    else
    {
      #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
        trace_info.facch_dl_fail_count ++;
      #endif
      #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1)
        Trace_dedic_tch_block_stat(FACCH_BAD, l1s_dsp_com.dsp_ndb_ptr->a_fd[2], 0);
      #endif
    }
  }
     #if (FF_REPEATED_DL_FACCH == 1)
     if(rx_valid_flag == FALSE)
     {
      l1s.repeated_facch.pipeline[l1s.repeated_facch.counter_candidate].buffer_empty=TRUE;
     }
     #endif  /* (FF_REPEATED_DL_FACCH == 1) */

  #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
    RTTL1_FILL_DL_DCCH(rx_valid_flag, timing_advance)
  #endif

  // Pass data block to L2.
#if (SEND_FN_TO_L2_IN_DCCH==1)
#if (L1_SAGEM_INTERFACE == 1)
    dll_dcch_downlink(info_address, rx_valid_flag, l1s.actual_time.fn, channel_type);
#else
  dll_dcch_downlink(info_address, rx_valid_flag, l1s.actual_time.fn);
#endif
#else
#if (L1_SAGEM_INTERFACE == 1)
    dll_dcch_downlink(info_address, rx_valid_flag, channel_type);
#else
  dll_dcch_downlink(info_address, rx_valid_flag);
#endif
#endif

}

#if (CHIPSET==15)
/*-------------------------------------------------------*/
/* l1s_reset_tx_ptr()                                    */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality : Reset the TX data pointer for DRP     */
/*                 after ABORT                           */
/*-------------------------------------------------------*/

#define L1_DRP_TX_PTR_RESET_SET    (0x00000020)
#define L1_DRP_TX_PTR_RESET_RESET  (~(L1_DRP_TX_PTR_RESET_SET))

void l1s_reset_tx_ptr(UWORD8 param1, UWORD8 param2)
{
    volatile UWORD32 *ptr_drp_init32;
    ptr_drp_init32 = (UWORD32 *) (DRP_API_BASE_ADDRESS + DRP_REG_SRM_CW_ADDR); //0xFFFF1E00;

    // Set the TX_PTR_RESET bit to 1 to reset TX RD and WR pointers
    (*ptr_drp_init32) = (*ptr_drp_init32)|(L1_DRP_TX_PTR_RESET_SET);

    // Reset the bit to zero as aslong as the bit is 1, pointers are in reset state
    (*ptr_drp_init32) = (*ptr_drp_init32)&(L1_DRP_TX_PTR_RESET_RESET);
}
#endif