view src/cs/layer1/cfile/l1_sync.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 4e78acac3d88
children
line wrap: on
line source

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

//#pragma DUPLICATE_FOR_INTERNAL_RAM_START
  #include "l1_macro.h"
  #include "l1_confg.h"
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END

#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
  #define  L1_SYNC_C
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif

//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

#if (CODE_VERSION == SIMULATION)
  #include "nucleus.h"
  #include <string.h>
  #if (AUDIO_TASK == 1)
      #include "l1audio_const.h"
      #include "l1audio_cust.h"
      #include "l1audio_defty.h"
    #if (L1_VOCODER_IF_CHANGE == 1)
      #include "l1audio_signa.h"
    #endif // L1_VOCODER_IF_CHANGE == 1
  #endif // AUDIO_TASK
  #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 // TESTMODE



  #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

  #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 "ulpd.h"

  #if L2_L3_SIMUL
    #include "hw_debug.h"
  #endif // L2_L3 SIMUL

  #if L1_GPRS
    #include "l1p_cons.h"
    #include "l1p_msgt.h"
    #include "l1p_deft.h"
    #include "l1p_vare.h"
    #include "l1p_mfta.h"
    #include "l1p_tabs.h"
    #include "l1p_macr.h"
    #include "l1p_sign.h"
  #endif // L1_GPRS

  #include <stdio.h>
  #include "sim_cfg.h"
  #include "sim_cons.h"
  #include "sim_def.h"
  #include "sim_var.h"
  extern NU_TASK  L1S_task;
  #if (FF_L1_IT_DSP_USF == 1) || (FF_L1_IT_DSP_DTX == 1)
    extern NU_TASK  API_MODEM_task;
  #endif

#else // NO SIMULATION

  #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"
  #endif // TESTMODE

  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_defty.h"

  #if (L1_VOCODER_IF_CHANGE == 1)
    #include "l1audio_signa.h"
  #endif // L1_VOCODER_IF_CHANGE == 1

  #endif // AUDIO_TASK

  #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

  #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 "tpudrv.h"
  #include "l1_trace.h"

  #if L2_L3_SIMUL
    #include "hw_debug.h"
  #endif // L2_L3 SIMUL

  #include "ulpd.h"
  #include "mem.h"
  #include "inth.h"
  #include "iq.h"

  #if L1_GPRS
    #include "l1p_cons.h"
    #include "l1p_msgt.h"
    #include "l1p_deft.h"
    #include "l1p_vare.h"
    #include "l1p_mfta.h"
    #include "l1p_tabs.h"
    #include "l1p_macr.h"
    #include "l1p_sign.h"
  #endif // L1_GPRS
#endif // NO SIMULATION

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

#define	W_A_DSP_PR20037	1	/* FreeCalypso */

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

#if (CHIPSET >= 12)
  #include "sys_conf.h"
#endif

#if (OP_L1_STANDALONE != 1) && (WCP_PROF == 1)
  #include "prf/prf_api.h"
#endif

#if 0	/* FreeCalypso TCS211 reconstruction */
//Enhanced RSSI    -OMAPS00075410
#define TOTAL_NO_OF_BITS_IDLE_MEAS    625
extern UWORD32 qual_acc_idle1[2];
#endif

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

#if W_A_DSP1
  UWORD8 old_sacch_DSP_bug = FALSE;
#endif

#if (TRACE_TYPE == 6)
  #define TIMER_RESET_VALUE (0xFFFF)
  #define TICKS_PER_TDMA    (2144)
#endif

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

#if (TRACE_TYPE == 4)
  #define TIMER_RESET_VALUE (0xFFFF)
#endif

#if (L1_GTT == 1)
  /**************************************/
  /* External GTT prototypes            */
  /**************************************/
  extern void l1s_gtt_manager   (void);
#endif

#if(L1_DYN_DSP_DWNLD == 1)
  extern void l1s_dyn_dwnld_manager(void);
#endif

#if (AUDIO_TASK == 1)
  /**************************************/
  /* External audio prototypes          */
  /**************************************/
  extern void l1s_audio_manager   (void);
#endif
/*-------------------------------------------------------*/
/* Prototypes of external functions used in this file.   */
/*-------------------------------------------------------*/
void l1ddsp_meas_read      (UWORD8 nbmeas, UWORD8 *pm);

#if L1_GPRS
  void l1ps_transfer_mode_manager  (void);
  void l1ps_reset_db_mcu_to_dsp    (T_DB_MCU_TO_DSP_GPRS *page_ptr);
  void l1pddsp_meas_ctrl           (UWORD8 nbmeas, UWORD8 pm_pos);
  void l1pddsp_meas_read           (UWORD8 nbmeas, UWORD8 *pm_read);
  void l1ps_meas_manager           (void);
  void l1ps_transfer_meas_manager  (void);
  void l1ps_macs_rlc_downlink_call (void);
#endif

#if (TRACE_TYPE==7) // CPU_LOAD
  extern void l1_cpu_load_start(void);
  extern void l1_cpu_load_stop(void);
  extern void l1_cpu_load_interm(void);
#endif

//#pragma DUPLICATE_FOR_INTERNAL_RAM_END

#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 (CODE_VERSION==SIMULATION)
  // for verification of the suspend procedure
  STATUS status;

  /*-------------------------------------------------------*/
  /* frit_task()                                           */
  /*-------------------------------------------------------*/
  /*                                                       */
  /* Description:                                          */
  /* ------------                                          */
  /* This function simulates the TPU scheduling task, the  */
  /* BTS behavior and shedules the l1 IT (for the L1S).This*/
  /* task as the same priority (10) as the L2, L3, L1a     */
  /* tasks. This function calls the main function of the   */
  /* simulator "sim_main()"                                */
  /*-------------------------------------------------------*/
  void frit_task(UWORD32 argc, void *argv)
  {
    while(1)
    {
      sim_main();
      os_NU_Relinquish(); // give back hand to OS...
    }
  }

  /*-------------------------------------------------------*/
  /* l1s_task()                                           */
  /*-------------------------------------------------------*/
  /*                                                       */
  /* Description:                                          */
  /* ------------                                          */
  /* This function simulates the L1S task. This task is    */
  /* called by the main task (frit task). The L1S task has */
  /* the highest priority (5) under nucleus and calls the  */
  /* "sim_l1_int()" function. This task can suspend itsef  */
  /* in case of deep/big sleep simulation                  */
  /*-------------------------------------------------------*/

  void l1s_task(UWORD32 argc, void *argv)
  {
     while(1)
     {
       sim_l1_int();
       status = NU_Suspend_Task(&L1S_task);
       // check status value...
       if (status)
       {
       #if (TRACE_TYPE==5)
         printf("Error somewhere in the L1S suspend task \n");
       #endif
        EXIT;
        }
     }
  }

#if (FF_L1_IT_DSP_USF == 1) || (FF_L1_IT_DSP_DTX == 1)
  /*-------------------------------------------------------*/
  /* api_modem_task()                                      */
  /*-------------------------------------------------------*/
  /*                                                       */
  /* Description:                                          */
  /* ------------                                          */
  /* This function simulates the USF/DTX IT. This task is  */
  /* called by the main task (frit task). It task has      */
  /* the same priority as L1S under nucleus and calls the  */
  /* "sim_api_modem_int()" function.                       */
  /*-------------------------------------------------------*/

  void api_modem_task(UWORD32 argc, void *argv)
  {
     while(1)
     {
       extern void sim_api_modem_int(void);
       sim_api_modem_int();
       status = NU_Suspend_Task(&API_MODEM_task);
       // check status value...
       if (status)
       {
       #if (TRACE_TYPE==5)
         printf("Error somewhere in the API MODEM suspend task \n");
       #endif
        EXIT;
        }
     }
  }
#endif

#else // SIMULATION


  /*-------------------------------------------------------*/
  /* hisr()          High Interrupt service routine        */
  /*-------------------------------------------------------*/
  /*                                                       */
  /* Description:                                          */
  /* ------------                                          */
  /* This function is the ISR corresponding to the frame   */
  /* interrupt coming from the TPU every TDMA frame. It    */
  /* activates the Layer 1 synchronous part "l1s_synch()". */
  /*                                                       */
  /*-------------------------------------------------------*/

  extern unsigned short       layer_1_sync_end_time;
  void hisr(void)
  {
    /*
     * FreeCalypso TCS211 reconstruction: the LoCosto version
     * of this function had a whole bunch of junk here
     * which we have removed in order to match the TCS211
     * binary object.
     */

    // stop the gauging.This function must be called at the
    // begining of the HISR in order to have the IT_GAUGING
    // executed before the Deep sleep decision.
    // GOAL: reduce the wake up time by 1 frame
    l1s_gauging_task_end();

    // check if an IT DSP stills pending => it means a CPU load error in the MCU
    #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
      if (TPU_check_IT_DSP()==TRUE)
      {
        #if (GSM_IDLE_RAM == 0)
         l1_trace_IT_DSP_error();
        #else
         l1_trace_IT_DSP_error_intram();
        #endif
      }
    #endif


    /******************************************************/
    // Synchronous Cpu load measurement                   */
    //    Log LISR -> hisr() entry cpu time               */
    //    Start HW timer for hisr() measurement           */
    /******************************************************/
    #if (TRACE_TYPE==7) // CPU_LOAD
       l1_cpu_load_interm();
       l1_cpu_load_start();
    #endif

     if ((l1_config.pwr_mngt == PWR_MNGT) && (l1s.pw_mgr.frame_adjust))
     {
        /******************************************************/
        // 1 Frame Adjust. after unscheduled wake-up          */
        /******************************************************/
        l1s_wakeup_adjust();
     }
     else
     {
        // increment time counter used for debug and by L3 scenario...
        l1s.debug_time ++;

        /***************************************************/
        /* Frame counters management.                      */
        /***************************************************/
        // Time...
        // "Actual time" loaded with previous "next time".
        #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 (GSM_IDLE_RAM != 0)
            // Decrement counters
            l1s.gsm_idle_ram_ctl.os_load--;
            l1s.gsm_idle_ram_ctl.hw_timer--;
        #endif

        // Multiframe table...
        // Increment active frame % mftab size.
        IncMod(l1s.afrm, 1, MFTAB_SIZE);

        // Control function counters...
        // Increment frame count from last AFC update.
        l1s.afc_frame_count++;

        // Decrement time to next L1S task.
        if(l1a_l1s_com.time_to_next_l1s_task > 0 &&
           l1a_l1s_com.time_to_next_l1s_task < MAX_FN)

           l1a_l1s_com.time_to_next_l1s_task--;
    }

    /******************************************************/
    /* Call layer 1 synchronous part.                     */
    /******************************************************/

    l1s_synch();

    /*
     * The following double invokation of l1s_synch()
     * is NOT present in the TCS211 version.
     */
    #if 0
    if(l1s.pw_mgr.sleep_performed == CLOCK_STOP &&
	(l1s.pw_mgr.wakeup_type == WAKEUP_FOR_L1_TASK ||
	 l1s.pw_mgr.wakeup_type == WAKEUP_ASYNCHRONOUS_ULPD_0 ||
	 l1s.pw_mgr.wakeup_type == WAKEUP_FOR_OS_TASK ||
	 l1s.pw_mgr.wakeup_type == WAKEUP_FOR_HW_TIMER_TASK ||
	 l1s.pw_mgr.wakeup_type == WAKEUP_FOR_GAUGING_TASK))
    {
	l1s_synch();
    }
    #endif

    // Be careful:in case of asynchronous wake-up after sleep
    // an IT_TDMA may be unmasked and executed just after l1s_sleep_manager();
    // In order to avoid issues with the execution of hisr() inside hisr()
    // do not add code here after !!!

    #if (TRACE_TYPE == 6)
    {
      UWORD16 layer_1_sync_end_time;
      UWORD8  cpu_load;

      layer_1_sync_end_time = TIMER_RESET_VALUE - TM_ReadTimer(2);
      cpu_load = (100 * layer_1_sync_end_time) / TICKS_PER_TDMA;

      l1_trace_cpu_load(cpu_load);
    }
    #endif


    /* used to be #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) in LoCosto */
    #if (TRACE_TYPE == 1)	/* TSM30 code has it this way */
      // CPU load for TRACE_TYPE == 1 and 4 only
      if((trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_L1S_CPU_LOAD) &&
          (trace_info.sleep_performed == FALSE))
      {
        Trace_L1S_CPU_load();

    #if (WCP_PROF == 1)
#define TICKS_PER_TDMA (1875)
      prf_LogCPULoadL1S((unsigned char)((100 * layer_1_sync_end_time) / TICKS_PER_TDMA));
    #endif
      }
      trace_info.sleep_performed = FALSE;
    #endif

    /******************************************************/
    // Synchronous Cpu load measurement                   */
    //    Stop HW timer; compute results; output on uart  */
    //      if FN%13 = 11                                 */
    /******************************************************/

    #if (TRACE_TYPE==7) // CPU_LOAD
      l1_cpu_load_stop();
    #endif

  }

#endif // NO SIMULATION
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#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_synch()
// Description:
// This function is the core of L1S. Here is a summary
// of the execution:
//  - Frame counters management.
//  - Get current communication page pointers.
//  - RESET internal variables.
//  - RESET MCU->DSP DB communication page.
//  - TOA update management.
//  - L1 task manager,
//      - Dedicated_mode_manager.
//      - Task_scheduler.
//      - Execute_frame.
//      - Neighbor cells measurement manager.
//      - End manager.

void l1s_synch()
{
   #if (CODE_VERSION==SIMULATION)
      // increment time counter used for debug and by L3 scenario...
      l1s.debug_time ++;

      /***************************************************/
      /* Frame counters management.                      */
      /***************************************************/
      // Time...
      #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

      // Multiframe table...
      // Increment active frame % mftab size.
      IncMod(l1s.afrm, 1, MFTAB_SIZE);          // Increment active frame % mftab size.

      // Control function counters...
      // Increment frame count from last AFC update.
      l1s.afc_frame_count++;

      // this function is called in the HISR and must be call here in Simulation
      l1s_gauging_task_end();

      // Decrement time to next L1S task.
      if(l1a_l1s_com.time_to_next_l1s_task > 0 &&
         l1a_l1s_com.time_to_next_l1s_task < MAX_FN)
        l1a_l1s_com.time_to_next_l1s_task--;
   #endif
        /* l1s.tcr_prog_done=0; */
#if (FF_L1_FAST_DECODING == 1)
      /* If a fast decoding IT is expected AND a deferred control is scheduled */
      /* then it means that a fast decoding IT is still awaited from previous  */
      /* TDMA.                                                                 */
      if (
              (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_AWAITED)
           && (l1a_apihisr_com.fast_decoding.deferred_control_req == TRUE)
         )
      {
        l1_trace_IT_DSP_error(IT_DSP_ERROR_FAST_DECODING);
      }
#endif /* #if (FF_L1_FAST_DECODING == 1) */

  #if L1_GPRS
      /* l1s.tcr_prog_done=0; */
    // Increment TOA period counter used in packet tranfer mode
    if (l1a_l1s_com.mode == PACKET_TRANSFER_MODE)
    {
      // TOA update period in packet transfer mode = 4*78 frames
      // At least one block needs to be transmitted by the BTS every 78 frames
      // Taking into account fading probability at least one good block (4 TOA values)
      // is input to the TOA algorithm within the TOA update period

      #if (TOA_ALGO == 2)
      #else
        l1s.toa_period_count++;
      if (l1s.toa_period_count >= 4*78)
      {
        l1s.toa_update = TRUE;  // set TOA update flag => TOA shift will be updated upon next call to l1ctl_toa
      }
      #endif

    }
  #endif


  #if (TOA_ALGO == 2)
    {
      #if L1_GPRS
        if((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CON_EST_MODE1) || (l1a_l1s_com.mode == CON_EST_MODE2) ||
           (l1a_l1s_com.mode == DEDIC_MODE) || (l1a_l1s_com.mode == PACKET_TRANSFER_MODE))
      #else
        if((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CON_EST_MODE1) || (l1a_l1s_com.mode == CON_EST_MODE2) ||
           (l1a_l1s_com.mode == DEDIC_MODE))
      #endif
      {
        if( (l1s.actual_time.fn >= l1s.toa_var.toa_update_fn) &&
            ((l1s.actual_time.fn - l1s.toa_var.toa_update_fn) < L1_TOA_UPDATE_TIME)  )
        {
          // TOA needs to be updated every 'L1_TOA_UPDATE_TIME' frames
          l1s.toa_var.toa_update_fn = l1s.actual_time.fn + L1_TOA_UPDATE_TIME;
          if(l1s.toa_var.toa_update_fn >= MAX_FN)
          {
            l1s.toa_var.toa_update_fn-= MAX_FN;
          }

          // Set TOA idle update = TRUE;
          l1s.toa_var.toa_update_flag = TRUE;
        }
      }
      else
      {
        // TOA needs to be updated every 'L1_TOA_UPDATE_TIME' frames
        l1s.toa_var.toa_update_fn = l1s.actual_time.fn + L1_TOA_UPDATE_TIME;
        if(l1s.toa_var.toa_update_fn >= MAX_FN)
        {
          l1s.toa_var.toa_update_fn-=MAX_FN;
        }
      }
    }
  #endif

  #if (L1_DYN_DSP_DWNLD ==1)
      #if L1_GPRS
      if((l1a_l1s_com.l1a_activity_flag == TRUE)  ||
         (l1a_l1s_com.time_to_next_l1s_task == 0) ||
         (l1s.frame_count != 0) ||
         (l1s.pw_mgr.gauging_task == ACTIVE) ||
         (l1s_get_next_gauging_in_Packet_Idle()==0) ||
         (l1s.dyn_dwnld_state != 0))
    #else
        if((l1a_l1s_com.l1a_activity_flag == TRUE)  ||
         (l1a_l1s_com.time_to_next_l1s_task == 0) ||
         (l1s.frame_count != 0) ||
         (l1s.pw_mgr.gauging_task == ACTIVE) ||
         (l1s.dyn_dwnld_state != 0))
  #endif // L1_GPRS
  #else
  #if L1_GPRS
    if((l1a_l1s_com.l1a_activity_flag == TRUE)  ||
       (l1a_l1s_com.time_to_next_l1s_task == 0) ||
       (l1s.frame_count != 0) ||
       (l1s.pw_mgr.gauging_task == ACTIVE) ||
       (l1s_get_next_gauging_in_Packet_Idle()==0) )
  #else
      if((l1a_l1s_com.l1a_activity_flag == TRUE)  ||
       (l1a_l1s_com.time_to_next_l1s_task == 0) ||
       (l1s.frame_count != 0) ||
       (l1s.pw_mgr.gauging_task == ACTIVE))
  #endif // L1_GPRS
  #endif // L1_DYN_DSP_DWNLD
  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  // L1A has been executed, or
  // It's time to execute next task, or
  // A task is still in the MFTAB, or
  // a gauging will be performed in Packet Idle mode
  // ==> execute L1 core.
  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  {
    BOOL l1s_task_allowed = TRUE;

    /*
     * FreeCalypso TCS211 reconstruction: the following code
     * fails to compile because the wakeup_time structure member
     * is not present in TCS211 headers.  Let's try omitting it
     * so we can get a successful compile and start diffing the
     * compilation results.
     */
#if 0

    /* This is not required in Locosto after merge of deep-sleep
     * initialization and control frame */
 #if (CHIPSET != 15)
    // SETUP_AFC_AND_RF+1 frames shall pass since last wakeup
    // from deep sleep before scheduling any tasks due to RF wakeup.
    if ((l1_config.pwr_mngt == PWR_MNGT)  // PWR management enabled
      && ((l1s.pw_mgr.mode_authorized == DEEP_SLEEP) || (l1s.pw_mgr.mode_authorized == ALL_SLEEP)) // deep sleep is still authorized
      && (l1s.pw_mgr.sleep_performed == CLOCK_STOP) // previous sleep was deep sleep
      && (((l1s.actual_time.fn_mod42432 - l1s.pw_mgr.wakeup_time + 42432) % 42432) <= l1_config.params.setup_afc_and_rf)

    #if L1_GPRS
      && (l1a_l1s_com.mode != DEDIC_MODE) && (l1a_l1s_com.mode != PACKET_TRANSFER_MODE)) //check that board is not in dedicated or transfer
    #else
      && (l1a_l1s_com.mode != DEDIC_MODE) ) //check that board is not in dedicated
    #endif
    {
      l1s_task_allowed = FALSE;
    }
    else
    {
       l1s.pw_mgr.sleep_performed = DO_NOT_SLEEP; // In case l1s is executed, initialize sleep performed in order to avoid reentry in part above 42432 frames later
       l1s_task_allowed = TRUE;
    }
#else
    l1s.pw_mgr.sleep_performed = DO_NOT_SLEEP; // In case l1s is executed, initialize sleep performed in order to avoid reentry in part above 42432 frames later
    l1s_task_allowed = TRUE;
#endif
#endif

    if (l1s_task_allowed == TRUE)
    {
    // Reset L1A activity flag.
    l1a_l1s_com.l1a_activity_flag = FALSE;

    // Set default value in frame count to next task.
    l1a_l1s_com.time_to_next_l1s_task = MAX_FN;

    /*************************************************************/
    /* Get current communication page pointers.                  */
    /*************************************************************/
    // init pointer in DB according to "dsp read page" number

    #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
      if (l1s_dsp_com.dsp_r_page == 0)
      {
        if (l1s_dsp_com.dsp_w_page == 0) trace_fct(CST_NEW_FRAME_PAGE_R0_W0, (UWORD32)(-1));
        else                             trace_fct(CST_NEW_FRAME_PAGE_R0_W1, (UWORD32)(-1));
      }
      else
      {
        if (l1s_dsp_com.dsp_w_page == 0) trace_fct(CST_NEW_FRAME_PAGE_R1_W0, (UWORD32)(-1));
        else                             trace_fct(CST_NEW_FRAME_PAGE_R1_W1, (UWORD32)(-1));
      }
    #endif

    #if (CODE_VERSION == SIMULATION)
      l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) &(buf.mcu_rd[l1s_dsp_com.dsp_r_page]);
      l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) &(buf.mcu_wr[l1s_dsp_com.dsp_w_page]);
      #if (DSP == 38) || (DSP == 39)
      l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP *) &(buf.mcu_wr_common[l1s_dsp_com.dsp_w_page]);
      #endif

    #else
      if (l1s_dsp_com.dsp_r_page == 0)  l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) DB_R_PAGE_0;
      else                              l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) DB_R_PAGE_1;
      if (l1s_dsp_com.dsp_w_page == 0)  l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) DB_W_PAGE_0;
      else                              l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) DB_W_PAGE_1;
      #if (DSP == 38) || (DSP == 39)
        if (l1s_dsp_com.dsp_w_page == 0)  l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP*) DB_COMMON_W_PAGE_0;
        else  l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP *) DB_COMMON_W_PAGE_1;

      #endif
    #endif

    #if (L1_GPRS)
      #if (CODE_VERSION == SIMULATION)
        l1ps_dsp_com.pdsp_db_r_ptr = &(buf.mcu_rd_gprs[l1s_dsp_com.dsp_r_page]);
        l1ps_dsp_com.pdsp_db_w_ptr = &(buf.mcu_wr_gprs[l1s_dsp_com.dsp_w_page]);
      #else
        if (l1s_dsp_com.dsp_r_page == 0)  l1ps_dsp_com.pdsp_db_r_ptr = (T_DB_DSP_TO_MCU_GPRS *) DB_R_PAGE_0_GPRS;
        else                              l1ps_dsp_com.pdsp_db_r_ptr = (T_DB_DSP_TO_MCU_GPRS *) DB_R_PAGE_1_GPRS;
        if (l1s_dsp_com.dsp_w_page == 0)  l1ps_dsp_com.pdsp_db_w_ptr = (T_DB_MCU_TO_DSP_GPRS *) DB_W_PAGE_0_GPRS;
        else                              l1ps_dsp_com.pdsp_db_w_ptr = (T_DB_MCU_TO_DSP_GPRS *) DB_W_PAGE_1_GPRS;
      #endif
    #endif

    #if (DSP_DEBUG_TRACE_ENABLE == 1)
      if (l1s_dsp_com.dsp_r_page == 0)
      {
        l1s_dsp_com.dsp_db2_current_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_0;
        l1s_dsp_com.dsp_db2_other_r_ptr   = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_1;
      }
      else
      {
        l1s_dsp_com.dsp_db2_current_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_1;
        l1s_dsp_com.dsp_db2_other_r_ptr   = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_0;
      }
    #endif

    #if (D_ERROR_STATUS_TRACE_ENABLE == 1)
      if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_L1S_DEBUG)
      // check d_error_status variable
      #if (GSM_IDLE_RAM == 0)
         Trace_d_error_status();
      #else
         Trace_d_error_status_intram();
      #endif
    #endif

    /*************************************************************/
    /* RESET internal variables...                               */
    /* Must be performed after having set the current com. pages */
    /*************************************************************/
    l1s.tpu_win                 = 0;         // Reset resources for driver and sub tasks...
    l1s_dsp_com.dsp_r_page_used = FALSE;     // Init. flag for MCU<-DSP comm.
    l1s.tpu_ctrl_reg            = NO_CTRL;   // Reset MCU->TPU comm. task register (tx, rx, pw tasks).
    l1s.dsp_ctrl_reg            = NO_CTRL;   // Reset MCU->DSP comm. task register (tx, rx, pw tasks).

    /*************************************************************/
    /* RESET MCU->DSP DB communication page.                     */
    /*************************************************************/
    l1s_reset_db_mcu_to_dsp(l1s_dsp_com.dsp_db_w_ptr);
    #if (DSP == 38) || (DSP == 39)
      l1s_reset_db_common_mcu_to_dsp(l1s_dsp_com.dsp_db_common_w_ptr);
    #endif
    #if (L1_GPRS)
      l1ps_reset_db_mcu_to_dsp(l1ps_dsp_com.pdsp_db_w_ptr);
    #endif

   /********************************************************************/
    /* Reset DSP IT ENABLE bit Satu/Hyp/Dione TO BE REMOVED in HERCULES */
    /********************************************************************/
    #if (W_A_ITFORCE)
       (*(volatile UWORD16 *) TPU_INT_CTRL) &= ~TPU_INT_ITD_F;
    #endif

    /*************************************************************/
    /* TOA UPDATE MANAGEMENT.                                    */
    /*************************************************************/
    #if (TOA_ALGO != 0)
      if(l1a_l1s_com.toa_reset == TRUE)
      // TOA algo must be initialized
      {
        #if (TOA_ALGO == 2)
          l1s.toa_var.toa_shift  = l1ctl_toa(TOA_INIT, 0, 0, 0);
        #else
        l1s.toa_shift         = l1ctl_toa(TOA_INIT, 0, 0, 0, &l1s.toa_update, &l1s.toa_period_count
        #if (FF_L1_FAST_DECODING == 1)
            ,0
        #endif /* FF_L1_FAST_DECODING */
            );
        #endif
        l1a_l1s_com.toa_reset = FALSE;
      }

      // Decrement mask counter for TOA.
      // Rem: this counter is used to mask the SNR/TOA results for 2
      //      frames immediatly following an update of TOA.
      #if (TOA_ALGO == 2)
       if(l1s.toa_var.toa_snr_mask > 0) l1s.toa_var.toa_snr_mask--;
      #else
      if(l1s.toa_snr_mask > 0) l1s.toa_snr_mask--;
      #endif


    #endif

    /*************************************************************/
    /* L1 TASK MANAGER.                                          */
    /*************************************************************/

    #if (TRACE_TYPE == 1) || (TRACE_TYPE==4)
      #if (defined RVM_RTT_SWE || (OP_L1_STANDALONE == 1))
      trace_info.l1s_rtt_func.rtt_refresh_status(trace_info.l1s_trace_user_id);
      #endif

      RTTL1_FILL_FN(l1s.actual_time.fn)
    #endif

    #if (GSM_IDLE_RAM != 0)
      if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1) || (l1a_l1s_com.dedic_set.SignalCode != NULL))
        {
          if (!READ_TRAFFIC_CONT_STATE)
          {
            CSMI_TrafficControllerOn();
            #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
              l1s_trace_mftab();
            #endif
          }
          // Call routine: DEDICATED_MODE_MANAGER.
          l1s_dedicated_mode_manager();
        }
    #else // GSM_IDLE_RAM
      l1s_dedicated_mode_manager();
    #endif

    #if L1_GPRS
    #if (GSM_IDLE_RAM != 0)
          if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1))
            {
              l1ps_transfer_mode_manager();
            }
          else
            {
              if(!l1pa_l1ps_com.transfer.semaphore)
              {
                if ((l1pa_l1ps_com.transfer.fset[0]->SignalCode != NULL) || (l1pa_l1ps_com.transfer.fset[1]->SignalCode != NULL))
                {
                   if (!READ_TRAFFIC_CONT_STATE)
                     {
                       CSMI_TrafficControllerOn();
                     #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
                       l1s_trace_mftab();
                     #endif
                     }
                   // Call routine: TRANSFER_MODE_MANAGER.
                   l1ps_transfer_mode_manager();
                }
              }
            }
    #else // GSM_IDLE_RAM
      // Call routine: TRANSFER_MODE_MANAGER.
      l1ps_transfer_mode_manager();
    #endif // GSM_IDLE_RAM
    #endif // L1_GPRS

    l1s_task_scheduler_process();

    // Call routine: EXECUTE_FRAME.
    l1s_execute_frame();
    #if L1_GPRS
      // Call routine: PACKET_MEAS_MANAGER.
      l1ps_meas_manager();

      #if (GSM_IDLE_RAM != 0)
        if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1))
          {
            if (l1a_l1s_com.l1s_en_task[PDTCH] != TASK_DISABLED)            // <- Added in line with comment on l1s_meas_manager() :
            // Call routine: PACKET_TRANSFER_MODE_MANAGER                   //    "Measurement manager not usefull in packet transfer mode
            l1ps_transfer_meas_manager();                                   //    This permit to save CPU in packet transfer mode    // Call routine: TASK_SCHEDULER."
          }
      #else
        l1ps_transfer_meas_manager();                                   //    This permit to save CPU in packet transfer mode    // Call routine: TASK_SCHEDULER."
      #endif //GSM_IDLE_RAM
    #endif  //L1_GPRS

    #if L1_GPRS
      // Measurement manager not usefull in packet transfer mode
      // This permit to save CPU in packet transfer mode
      if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_DISABLED)
    #endif
        // Call routine: MEAS_MANAGER.
        l1s_meas_manager();
    #if (L1_GTT == 1)

      #if (GSM_IDLE_RAM != 0)
        if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1))
      #endif //GSM_IDLE_RAM
          {
             // Call routine: GTT MANAGER.
             l1s_gtt_manager();
          }

    #endif

    #if (AUDIO_TASK == 1)
      // Call routine: AUDIO MANAGER.
      #if (GSM_IDLE_RAM != 0)
        if ( l1s.gsm_idle_ram_ctl.l1s_full_exec == TRUE)
          {
            l1s_audio_manager();
          }
      #else
            l1s_audio_manager();
      #endif
    #else
      #if (GSM_IDLE_RAM != 0)
        l1s.gsm_idle_ram_ctl.l1s_full_exec = FALSE;
      #endif
    #endif

// Triton Audio ON/OFF Changes
#if (L1_AUDIO_MCU_ONOFF == 1)
    l1s_audio_onoff_manager();
#endif // L1_AUDIO_MCU_ONOFF

    #if(L1_DYN_DSP_DWNLD ==1)
      // Call routine: DSP DYNAMIC DOWNLOAD MANAGER
      l1s_dyn_dwnld_manager();
    #endif



    // Call routine: END_MANAGER.
    l1s_end_manager();
  }
  }

  #if ((TRACE_TYPE==1) || (TRACE_TYPE == 4))
    Trace_PM_Equal_0_balance();
  #endif

  #if (DSP_DEBUG_TRACE_ENABLE == 1)
    if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_DSP_DEBUG)
      #if (GSM_IDLE_RAM != 0)
        if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1))
      #endif
        {
#if 0	/* LoCosto code */
  #if(MELODY_E2 || L1_MP3 || L1_AAC || L1_DYN_DSP_DWNLD)
          // DSP Trace is output ONLY if melody e2, mp3 or dynamic download are not currently running
          if(trace_info.dsptrace_handler_globals.trace_flag_blocked == FALSE)
  #endif
#else	/* FreeCalypso support for L1_DYN_DSP_DWNLD=1 with MELODY_E2=0 */
  #if (L1_DYN_DSP_DWNLD)
          if (l1a.dyn_dwnld.trace_flag_blocked == FALSE)
  #endif
#endif
          Trace_dsp_debug();
        }
    #if (AMR == 1)
      if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_DSP_AMR_DEBUG)
      #if (GSM_IDLE_RAM != 0)
        if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1))
      #endif
      	{
#if 0	/* LoCosto code */
  #if(MELODY_E2 || L1_MP3 || L1_AAC || L1_DYN_DSP_DWNLD )
          // DSP Trace is output ONLY if melody e2, mp3 or dynamic download are not currently running
          if(trace_info.dsptrace_handler_globals.trace_flag_blocked == FALSE)
  #endif
#else	/* FreeCalypso support for L1_DYN_DSP_DWNLD=1 with MELODY_E2=0 */
  #if (L1_DYN_DSP_DWNLD)
          if (l1a.dyn_dwnld.trace_flag_blocked == FALSE)
  #endif
#endif
          Trace_dsp_amr_debug();
      	}
    #endif
  #endif

  // Vmemo/Reco sign-to-talk trace
  #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3)
    uart_trace_multiframe();
  #endif

  #if (TRACE_TYPE == 1) || (TRACE_TYPE==4)
    if (l1s.actual_time.fn_mod13 == 12)
    {
      RTTL1_EVENT(RTTL1_EVENT_FNMOD13_EQUAL_12, RTTL1_EVENT_SIZE_FNMOD13_EQUAL_12)
    }
  #endif

  /******************************************************/
  /* if layer 1 ready to sleep, evaluate System loading.*/
  /*                                                    */
  /* Conditions are :                                   */
  /* - no RF/GSM task in progress                       */
  /* - next RF/GSM task at min in 4 frames              */
  /* - Layer1 in Idle mode                              */
  /******************************************************/

  #if (GSM_IDLE_RAM != 0)
    if (((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CS_MODE0)) && (l1_config.TestMode == 0))
    {
      // Normally os_load and hw_timer shall be meaningful since last sleep phase without checking os - otherwise traffic controller is already on
      if ((l1s.gsm_idle_ram_ctl.os_load == 0) || (l1s.gsm_idle_ram_ctl.hw_timer == 0))
      {
        if (!READ_TRAFFIC_CONT_STATE)
        {
          CSMI_TrafficControllerOn();
          #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
            l1s_trace_mftab();
          #endif
        }
      }
    }

    #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
      if (READ_TRAFFIC_CONT_STATE)
      {
            l1_intram_send_trace();
      }
    #endif
  #endif

  if (l1_config.pwr_mngt == PWR_MNGT)
  {
    if ( (l1s.frame_count == 0)                               &&
         (l1a_l1s_com.time_to_next_l1s_task > MIN_SLEEP_TIME) &&
         (l1s.pw_mgr.gauging_task  == INACTIVE)               &&
         ((l1a_l1s_com.mode == I_MODE)||(l1a_l1s_com.mode == CS_MODE0)) )
    {
      // sleep mode is authorized by primitive ....
      if ( l1s.pw_mgr.mode_authorized >= BIG_SLEEP )
        {
          l1s_sleep_manager();
        }
    }
    #if 0	/* FreeCalypso TCS211 reconstruction */
    else{
      l1_trace_fail_sleep(FAIL_SLEEP_L1SYNCH,0,0);
    }
    #endif
  }

#if (GSM_IDLE_RAM_DEBUG == 1)
      (*( volatile unsigned short* )(0xFFFE4802)) &= ~ (1 << 2);    // GPIO-2=0
#endif
// Be careful: The Deep sleep can be performed just above
// Do not add something here !!!!

}

//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

#if ((GSM_IDLE_RAM != 0))  //omaps00090550
//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START

void l1s_keep_mftab_hist(void)
{
    UWORD8 task_id, bit;
    WORD8 nb_bitmap;
    T_L1S_GSM_IDLE_INTRAM * gsm_idle_ram_ctl;

    gsm_idle_ram_ctl = &(l1s.gsm_idle_ram_ctl);

    bit=0;

    for(nb_bitmap=0; nb_bitmap<SIZE_TAB_L1S_MONITOR; nb_bitmap++)
    {
      gsm_idle_ram_ctl->mem_task_bitmap_idle_ram[nb_bitmap] = gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap];
      gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap]=0;
    }

    nb_bitmap=0;

    for(task_id=0; task_id<NBR_DL_L1S_TASKS; task_id++)
    {
      gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap] |= ((!(l1s.task_status[task_id].current_status == INACTIVE)) << bit);
      bit++;

      if ((bit == 32) || (task_id == (NBR_DL_L1S_TASKS -1)))
      {
        bit = 0;
        nb_bitmap++;
      }
    }
}

BOOL l1s_mftab_has_changed(void)
{
  WORD8 nb_bitmap;
  UWORD32 diff_detected;
  T_L1S_GSM_IDLE_INTRAM * gsm_idle_ram_ctl;

  gsm_idle_ram_ctl = &(l1s.gsm_idle_ram_ctl);

  diff_detected=0;
  for(nb_bitmap=0; nb_bitmap<SIZE_TAB_L1S_MONITOR; nb_bitmap++)
  {
    diff_detected |= ((gsm_idle_ram_ctl->mem_task_bitmap_idle_ram[nb_bitmap] ^ gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap]));
  }
  return (diff_detected != 0);
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#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_task_scheduler_process()                          */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is the task scheduler of L1S. It        */
/* schedules any enabled task. When a task must start,   */
/* it becomes PENDING. Since several tasks can become    */
/* pending at the same time, the highest priority one    */
/* is elected. The elected task compete then with the    */
/* current running task. If they conflict, the highest   */
/* priority one wins. If the winning is the new comer    */
/* then the multiframe table is reset and the new coming */
/* task is installed.                                    */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_task_scheduler_process()
{
  WORD32 pending_task;

  // Call routine: SCHEDULE_TASKS.
  l1s_schedule_tasks(&pending_task);

  // Call routine: MERGE_MANAGER (contains LOAD_MFTAB).
  l1s_merge_manager(pending_task);

#if (GSM_IDLE_RAM != 0)
  l1s_keep_mftab_hist();
  if (((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CS_MODE0)) && (l1_config.TestMode == 0))
  {
    l1s_adapt_traffic_controller();
  }
#endif

}

//#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_schedule_tasks()                                  */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function schedules all L1S tasks except measure- */
/* -ment tasks which are handled separately.             */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_schedule_tasks(WORD32 *best_pending_task)
{
  UWORD8 task_id;

  T_TASK_STATUS *task_ptr = &(l1s.task_status[0]);

  #if ((TRACE_TYPE == 1)||(TRACE_TYPE == 4))
    UWORD8 nb_bitmap = 0;
    UWORD8 bit = 0;
  #endif

  // Reset "new_status" for all L1S tasks: make them NOT_PENDING.
  for(task_id=0; task_id<NBR_DL_L1S_TASKS; task_id++)
  {
    task_ptr->new_status = NOT_PENDING;
    task_ptr->time_to_exec = MAX_FN;
    task_ptr++;

    #if ((TRACE_TYPE == 1)||(TRACE_TYPE == 4))
      // L1S Task enabling trace
      trace_info.task_bitmap[nb_bitmap] |= l1a_l1s_com.l1s_en_task[task_id] << bit;
      bit++;
      if (bit == 32)
      {
        bit = 0;
        nb_bitmap++;
      }
    #endif
  }

  #if ((TRACE_TYPE == 1)||(TRACE_TYPE == 4))
    if(SELECTED_BITMAP(RTTL1_ENABLE_L1S_TASK_ENABLE))
    {
      // For the moment up to 64 tasks supported !!!
      if ((trace_info.task_bitmap[0] != trace_info.mem_task_bitmap[0]) ||
          (trace_info.task_bitmap[1] != trace_info.mem_task_bitmap[1]))
      {
        RTTL1_FILL_L1S_TASK_ENABLE(trace_info.task_bitmap[0], trace_info.task_bitmap[1])
      }

      trace_info.mem_task_bitmap[0] = trace_info.task_bitmap[0];
      trace_info.mem_task_bitmap[1] = trace_info.task_bitmap[1];
      trace_info.task_bitmap[0]     = 0;
      trace_info.task_bitmap[1]     = 0;
    }
  #endif

#if ((REL99 == 1) && (FF_BHO == 1))
  if ((l1a_l1s_com.l1s_en_task[FBSB] == TASK_ENABLED) && (l1s.task_status[FBSB].current_status == INACTIVE))
  //----------------------------------
  // FBSB task is ENABLED.
  //----------------------------------
  {
    l1s.task_status[FBSB].time_to_exec = 0;

  }
#endif // #if ((REL99 == 1) && (FF_BHO == 1))

  if(l1a_l1s_com.l1s_en_task[SYNCHRO] == TASK_ENABLED)
  //--------------------------------------------
  // Synchro (jump on new Cell) task is ENABLED.
  //--------------------------------------------
  {
    // SYNCHRO task is not schedule if we are in the specific case:
    // L1A is touching SYNCHRO parameters (tn_difference, dl_tn and dsp_scheduler_mode)
    // and leave L1A to go in HISR (L1S) in middle of the update (cf. BUG1339)
    if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
    {
      // Save scheduling result.
      l1s.task_status[SYNCHRO].time_to_exec = 0;
    }
  }

  if (l1a_l1s_com.mode == CS_MODE0)
  if((l1a_l1s_com.l1s_en_task[ADC_CSMODE0] == TASK_ENABLED) &&
     (l1s.task_status[ADC_CSMODE0].current_status == INACTIVE))
  if ((l1a_l1s_com.l1s_en_meas & FSMS_MEAS) == 0) // avoid conflict with the Measurement campaign
  //--------------------------------
  // ADC task is ENABLED in CS_MODE0.
  //--------------------------------
  {
    UWORD32  time_to_adc;

    if (l1a_l1s_com.adc_mode & ADC_NEXT_CS_MODE0)
    {
      time_to_adc = 0; // ADC performed in the current frame
    }
    else
    if (l1a_l1s_com.adc_mode & ADC_EACH_CS_MODE0) // perform ADC on each "idle_period" * 102
    {
      time_to_adc = (102 * l1a_l1s_com.adc_idle_period-1) - (l1s.actual_time.fn % (102 * l1a_l1s_com.adc_idle_period));
    }

    // Save scheduling result.
    l1s.task_status[ADC_CSMODE0].time_to_exec = time_to_adc;
  }



  if((l1a_l1s_com.l1s_en_task[NP] == TASK_ENABLED) &&
     (l1s.task_status[NP].current_status == INACTIVE))
  //-------------------------------
  // Normal Paging task is ENABLED.
  //-------------------------------
  {
    UWORD8   mf51_for_ms_paging;
    UWORD32  np_position;
    UWORD32  paging_period;
    UWORD32  time_to_np;
    UWORD32  fn;


    fn = l1s.actual_time.fn;

    #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.
    //But the SYNCHRO task is not used anymore as opposite to CS mode for CCCH readings
    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))
    {
      // if CCCH timeslot is lower than current timeslot, it means that the scheduling
      //    must be anticipated by 1 frame

      if((l1a_l1s_com.ccch_group * 2) < l1a_l1s_com.dl_tn)
      {
        fn = l1s.next_time.fn;
        l1s.ctrl_synch_before = TRUE;
      }
      else
        l1s.ctrl_synch_before = FALSE;
    }
    #endif

    // compute MF51 number (0 to 8) in a Paging Period which carries the Paging.
    mf51_for_ms_paging  = l1a_l1s_com.page_group / l1a_l1s_com.nb_pch_per_mf51;

    np_position   = (l1a_l1s_com.idle_task_info.pg_position - 1) + (mf51_for_ms_paging * 51);
    paging_period = l1a_l1s_com.bs_pa_mfrms * 51;
    time_to_np    = (np_position + paging_period - (fn % paging_period)) % paging_period;

    // Save scheduling result.
    l1s.task_status[NP].time_to_exec = time_to_np;

    // Inform Gauging scheduler that NP task is pending....
    if (time_to_np == 0)
      l1s.pw_mgr.paging_scheduled = TRUE;

    // Clear param. synchro. semaphore.
    l1a_l1s_com.task_param[NP] = SEMAPHORE_RESET;
  }

  if((l1a_l1s_com.l1s_en_task[EP] == TASK_ENABLED) &&
     (l1s.task_status[EP].current_status == INACTIVE))
  //---------------------------------
  // Extended Paging task is ENABLED.
  //---------------------------------
  {
    UWORD8   mf51_for_ms_paging;
    UWORD32  ep_position;
    UWORD32  paging_period;
    UWORD32  time_to_ep;
    UWORD32  fn;

    fn = l1s.actual_time.fn;

    #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.
    //But the SYNCHRO task is not used anymore as opposite to CS mode for CCCH readings
    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))
    {
      // if CCCH timeslot is lower than current timeslot, it means that the scheduling
      //    must be anticipated by 1 frame
      if((l1a_l1s_com.ccch_group * 2) < l1a_l1s_com.dl_tn)
      {
        fn = l1s.next_time.fn;
        l1s.ctrl_synch_before = TRUE;
      }
      else
        l1s.ctrl_synch_before = FALSE;
    }
    #endif


    // compute MF51 number (0 to 8) in a Paging Period which carries the Paging.
    mf51_for_ms_paging  = ((l1a_l1s_com.page_group + 2) / l1a_l1s_com.nb_pch_per_mf51) % l1a_l1s_com.bs_pa_mfrms;

    ep_position   = (l1a_l1s_com.idle_task_info.extpg_position - 1) + (mf51_for_ms_paging * 51);
    paging_period = l1a_l1s_com.bs_pa_mfrms * 51;
    time_to_ep    = (ep_position + paging_period - (fn % paging_period)) % paging_period;

    // Save scheduling result.
    l1s.task_status[EP].time_to_exec = time_to_ep;

    // Clear param. synchro. semaphore.
    l1a_l1s_com.task_param[EP] = SEMAPHORE_RESET;
  }

  if((l1a_l1s_com.l1s_en_task[NBCCHS] == TASK_ENABLED) &&
     (l1s.task_status[NBCCHS].current_status == INACTIVE))
  //-------------------------------------
  // Normal BCCH Serving task is ENABLED.
  //-------------------------------------
  {
    UWORD32  min_time_to_nbcchs = MAX_FN;
    WORD32   time_to_nbcchs;
    WORD16   time_in_mf51;
    WORD32   fn_div_51 = l1s.actual_time.fn / 51;
    UWORD8   i;
    UWORD16  modulus;
    WORD16   relative_position;
    WORD32   modulus_times_51;
    WORD16   current_mf51_position;

    // NBCCHS task starts in frame position "1" in the MF51.
    time_in_mf51 = 1 - l1s.actual_time.t3;

    #if (L1_GPRS)
      if(l1a_l1s_com.mode == PACKET_TRANSFER_MODE)
      {
        // In transfer mode, if l1a_l1s_com.dl_tn != 0, a change synchro is performed
        // So the CTRL must be compute the frame before
        if(l1a_l1s_com.dl_tn != 0)
          time_in_mf51 -- ;
      }
    #endif

    for(i=0;i<l1a_l1s_com.nbcchs.schedule_array_size;i++)
    {
      modulus               = l1a_l1s_com.nbcchs.schedule_array[i].modulus;
      relative_position     = l1a_l1s_com.nbcchs.schedule_array[i].relative_position;
      modulus_times_51      = modulus * 51;
      current_mf51_position = fn_div_51 % modulus;

      time_to_nbcchs = time_in_mf51 + (relative_position - current_mf51_position)*51;

      if(time_to_nbcchs < 0)
        time_to_nbcchs += modulus_times_51;
      else
        if(time_to_nbcchs >= modulus_times_51)
          time_to_nbcchs -= modulus_times_51;

      if(time_to_nbcchs < min_time_to_nbcchs)
        min_time_to_nbcchs = time_to_nbcchs;
    }

    // Save scheduling result.
    l1s.task_status[NBCCHS].time_to_exec = min_time_to_nbcchs;

    // Clear param. synchro. semaphore.
    l1a_l1s_com.task_param[NBCCHS] = SEMAPHORE_RESET;

  } // End of "if / NBCCHS"

  if((l1a_l1s_com.l1s_en_task[EBCCHS] == TASK_ENABLED) &&
     (l1s.task_status[EBCCHS].current_status == INACTIVE))
  //---------------------------------------
  // Extended BCCH Serving task is ENABLED.
  //---------------------------------------
  {
    UWORD32  min_time_to_ebcchs = MAX_FN;
    WORD32   time_to_ebcchs;
    WORD16   time_in_mf51;
    WORD32   fn_div_51 = l1s.actual_time.fn / 51;
    UWORD8   i;
    UWORD16  modulus;
    WORD16   relative_position;
    WORD32   modulus_times_51;
    WORD16   current_mf51_position;

    // EBCCHS task starts in frame position "5" in the MF51.
    time_in_mf51 = 5 - l1s.actual_time.t3;

    #if (L1_GPRS)
      if(l1a_l1s_com.mode == PACKET_TRANSFER_MODE)
      {
        // 3 cases are considered:
        //  => the l1a_l1s_com.dl_tn = {7,6,5,4,3,2,1}
        //       the BCCHS burst is in the previous frame than the PDTCH, so the CTRL must be done
        //       on the previous frame
        //  => the l1a_l1s_com.dl_tn = {0}
        //       the BCCHS burst is in the same frame than the PDTCH, so the CTRL must be done
        //       on the same frame
        if(l1a_l1s_com.dl_tn != 0)
          time_in_mf51 -- ; // CTRL done on the previous frame
      }
    #endif

    for(i=0;i<l1a_l1s_com.ebcchs.schedule_array_size;i++)
    {
      modulus               = l1a_l1s_com.ebcchs.schedule_array[i].modulus;
      relative_position     = l1a_l1s_com.ebcchs.schedule_array[i].relative_position;
      modulus_times_51      = modulus * 51;
      current_mf51_position = fn_div_51 % modulus;

      time_to_ebcchs = time_in_mf51 + (relative_position - current_mf51_position)*51;

      if(time_to_ebcchs < 0)
        time_to_ebcchs += modulus_times_51;
      else
        if(time_to_ebcchs >= (WORD32)modulus_times_51)
          time_to_ebcchs -= modulus_times_51;

      if(time_to_ebcchs < (WORD32)min_time_to_ebcchs)
        min_time_to_ebcchs = time_to_ebcchs;
    }

    // Save scheduling result.
    l1s.task_status[EBCCHS].time_to_exec = min_time_to_ebcchs;

    // Clear param. synchro. semaphore.
    l1a_l1s_com.task_param[EBCCHS] = SEMAPHORE_RESET;

  } // End of "if / EBCCHS"

  if(l1a_l1s_com.l1s_en_task[ALLC] == TASK_ENABLED)
  //---------------------------------
  // ALL CCCH reading is ENABLED.
  //---------------------------------
  {
    if(l1a_l1s_com.task_param[ALLC] == SEMAPHORE_RESET)
    {
    #define CCCH0_START_TIME   6 - 1   // CCCH block 0.
    #define CCCH1_START_TIME  12 - 1   // CCCH block 1.
    #define CCCH2_START_TIME  16 - 1   // CCCH block 2.
    #define CCCH3_START_TIME  22 - 1   // CCCH block 3.
    #define CCCH4_START_TIME  26 - 1   // CCCH block 4.
    #define CCCH5_START_TIME  32 - 1   // CCCH block 5.
    #define CCCH6_START_TIME  36 - 1   // CCCH block 6.
    #define CCCH7_START_TIME  42 - 1   // CCCH block 7.
    #define CCCH8_START_TIME  46 - 1   // CCCH block 8.

    UWORD32  min_time_to_allc = MAX_FN;

    if(l1s.actual_time.t3 <= CCCH0_START_TIME)
      min_time_to_allc = CCCH0_START_TIME - l1s.actual_time.t3;
    else
    if(l1s.actual_time.t3 <= CCCH1_START_TIME)
      min_time_to_allc = CCCH1_START_TIME - l1s.actual_time.t3;
    else
    if(l1s.actual_time.t3 <= CCCH2_START_TIME)
      min_time_to_allc = CCCH2_START_TIME - l1s.actual_time.t3;

    // CCCH3 to CCCH8 are considered only when MF51 is not combined.
    else
    if(l1a_l1s_com.bcch_combined == FALSE)
    {
      if(l1s.actual_time.t3 <= CCCH3_START_TIME)
        min_time_to_allc = CCCH3_START_TIME - l1s.actual_time.t3;
      else
      if(l1s.actual_time.t3 <= CCCH4_START_TIME)
        min_time_to_allc = CCCH4_START_TIME - l1s.actual_time.t3;
      else
      if(l1s.actual_time.t3 <= CCCH5_START_TIME)
        min_time_to_allc = CCCH5_START_TIME - l1s.actual_time.t3;
      else
      if(l1s.actual_time.t3 <= CCCH6_START_TIME)
        min_time_to_allc = CCCH6_START_TIME - l1s.actual_time.t3;
      else
      if(l1s.actual_time.t3 <= CCCH7_START_TIME)
        min_time_to_allc = CCCH7_START_TIME - l1s.actual_time.t3;
      else
      if(l1s.actual_time.t3 <= CCCH8_START_TIME)
        min_time_to_allc = CCCH8_START_TIME - l1s.actual_time.t3;
      // Attempt to read CCCH0.
      else
        min_time_to_allc = 51 + CCCH0_START_TIME - l1s.actual_time.t3;
    }

    // Attempt to read CCCH0.
    else
      min_time_to_allc = 51 + CCCH0_START_TIME - l1s.actual_time.t3;

    // Save scheduling result.
    l1s.task_status[ALLC].time_to_exec = min_time_to_allc;
    }

    else
    // Semaphore is Set, reset it when ALLC inactive.
    {
    if(l1s.task_status[ALLC].current_status == INACTIVE)
      l1a_l1s_com.task_param[ALLC] = SEMAPHORE_RESET;
  }
  }

  if(l1a_l1s_com.l1s_en_task[SMSCB] == TASK_ENABLED)
  //------------------------------------------------------
  // Short Message Service Cell Broadcast task is ENABLED.
  //------------------------------------------------------
  {
    if(l1s.task_status[SMSCB].current_status == INACTIVE)
    {
      WORD32   time_to_norm_smscb = MAX_FN;
      WORD32   time_to_ext_smscb  = MAX_FN;
      WORD32   time_to_smscb_info = MAX_FN;
      UWORD32  min_time_to_smscb;

      if(l1a_l1s_com.cbch_info_req.next < l1a_l1s_com.cbch_info_req.cbch_num)
      {
        // Still some CBCH blocks to read from TB1/2/3/5/6/7, get next one.
        time_to_smscb_info = l1a_l1s_com.cbch_info_req.start_fn[l1a_l1s_com.cbch_info_req.next] +
                             MAX_FN -
                             l1s.actual_time.fn;

        if(time_to_smscb_info >= MAX_FN) time_to_smscb_info -= MAX_FN;

        // Check if passing 1 schedule position.
        if(time_to_smscb_info == 0)
          l1a_l1s_com.cbch_info_req.next++;
      }

      else
      {
        //%%%%%%%%%%%%%%%%
        // Normal CBCH...
        //%%%%%%%%%%%%%%%%
        // Check for scheduling info.

        if(l1a_l1s_com.norm_cbch_schedule.cbch_state == CBCH_SCHEDULED)
        {
          // CBCH header (TB0) reading is scheduled.

          if(l1a_l1s_com.norm_cbch_schedule.next < l1a_l1s_com.norm_cbch_schedule.cbch_num)
          {
            // Still some scheduled CBCH to read, get next one.
            time_to_norm_smscb = l1a_l1s_com.norm_cbch_schedule.first_block[l1a_l1s_com.norm_cbch_schedule.next] +
                                 MAX_FN -
                                 l1s.actual_time.fn;

            if(time_to_norm_smscb >= MAX_FN) time_to_norm_smscb -= MAX_FN;

            // Check if passing 1 schedule position.
            if(time_to_norm_smscb == 0)
              l1a_l1s_com.norm_cbch_schedule.next++;
          }

          else
          {
            // No more scheduled CBCH/TB0.
            l1a_l1s_com.norm_cbch_schedule.cbch_state = CBCH_CONTINUOUS_READING;
          }
        }

        if(l1a_l1s_com.norm_cbch_schedule.cbch_state == CBCH_CONTINUOUS_READING)
        {
          // CBCH header (TB0) reading is continuous.

          if(l1a_l1s_com.norm_cbch_schedule.start_continuous_fn != -1)
          {
            time_to_norm_smscb = l1a_l1s_com.norm_cbch_schedule.start_continuous_fn +
                                 MAX_FN -
                                 l1s.actual_time.fn;

            if(time_to_norm_smscb >= MAX_FN) time_to_norm_smscb -= MAX_FN;

            // Check for "CBCH continuous reading" starting frame number.
            if(time_to_norm_smscb == 0)
              l1a_l1s_com.norm_cbch_schedule.start_continuous_fn = -1;
          }

          else
          {
            // Continuous CBCH/TB0 reading is ongoing.

            WORD32 time_in_mf51;

            // No more scheduled CBCH to read, we must read all TB0.

            time_in_mf51 = l1a_l1s_com.cbch_start_in_mf51 - l1s.actual_time.t3;

            // Time to next TB0 CBCH block.
            time_to_norm_smscb = time_in_mf51 + (8-l1s.actual_time.tc)*51;
            if(time_to_norm_smscb <  0)    time_to_norm_smscb += 8*51;
            if(time_to_norm_smscb >= 8*51) time_to_norm_smscb -= 8*51;
          }
        }

        //%%%%%%%%%%%%%%%%%
        // Extended CBCH...
        //%%%%%%%%%%%%%%%%%
        // Check for scheduling info.

        if(l1a_l1s_com.ext_cbch_schedule.cbch_state == CBCH_SCHEDULED)
        {
          // CBCH header (TB4) reading is scheduled.

          if(l1a_l1s_com.ext_cbch_schedule.next < l1a_l1s_com.ext_cbch_schedule.cbch_num)
          {
            // Still some scheduled CBCH to read, get next one.
            time_to_ext_smscb = l1a_l1s_com.ext_cbch_schedule.first_block[l1a_l1s_com.ext_cbch_schedule.next] +
                                 MAX_FN -
                                 l1s.actual_time.fn;

            if(time_to_ext_smscb >= MAX_FN) time_to_ext_smscb -= MAX_FN;

            // Check if passing 1 schedule position.
            if(time_to_ext_smscb == 0)
              l1a_l1s_com.ext_cbch_schedule.next++;  // passing 1 schedule position.
          }

          else
          {
            // No more scheduled CBCH/TB4.
            l1a_l1s_com.ext_cbch_schedule.cbch_state = CBCH_CONTINUOUS_READING;
          }
        }

        if(l1a_l1s_com.ext_cbch_schedule.cbch_state == CBCH_CONTINUOUS_READING)
        {
          // Check for "CBCH continuous reading " starting frame number.

          if(l1a_l1s_com.ext_cbch_schedule.start_continuous_fn != -1)
          {
            time_to_ext_smscb = l1a_l1s_com.ext_cbch_schedule.start_continuous_fn +
                                 MAX_FN -
                                 l1s.actual_time.fn;

            if(time_to_ext_smscb >= MAX_FN) time_to_ext_smscb -= MAX_FN;

            // Check for "CBCH continuous reading" starting frame number.
            if(time_to_ext_smscb == 0)
              l1a_l1s_com.ext_cbch_schedule.start_continuous_fn = -1;
          }

          else
          {
            // Continuous CBCH/TB4 reading is ongoing.

            WORD32 time_in_mf51;

            // No more scheduled CBCH to read, we must read all TB4.

            time_in_mf51 = l1a_l1s_com.cbch_start_in_mf51 - l1s.actual_time.t3;

            // Time to next TB4 CBCH block.
            time_to_ext_smscb = time_in_mf51 + (4-l1s.actual_time.tc)*51;
            if(time_to_ext_smscb <  0)    time_to_ext_smscb += 8*51;
            if(time_to_ext_smscb >= 8*51) time_to_ext_smscb -= 8*51;
          }
        }
      }

      // Choose closest one...
      if(time_to_norm_smscb < time_to_ext_smscb)
        min_time_to_smscb = time_to_norm_smscb;
      else
        min_time_to_smscb = time_to_ext_smscb;

      if(time_to_smscb_info < min_time_to_smscb)
        min_time_to_smscb = time_to_smscb_info;

      // Save scheduling result.
      l1s.task_status[SMSCB].time_to_exec = min_time_to_smscb;

      // Clear param. synchro. semaphore.
      l1a_l1s_com.task_param[SMSCB] = SEMAPHORE_RESET;
    }
  }

  //---------------------------------------------
  // Random Access management for ACCESS phase.
  //---------------------------------------------
  if(l1a_l1s_com.l1s_en_task[RAACC] == TASK_ENABLED)
  // Random Access (ACCESS mode) task is ENABLED.
  {
    // RAACC task requires to run L1S scheduler every frame.
    l1a_l1s_com.time_to_next_l1s_task = 0;

    if((l1a_l1s_com.bcch_combined == FALSE) ||
       (COMBINED_RA_DISTRIB[l1s.actual_time.t3] == TRUE))
    // Current frame is at a "slot" boundary -> decrement time to next RA.
    {
      if(l1a_l1s_com.ra_info.rand == 0)
      // It is time to controle a RACH transmit.
      {
        l1s.task_status[RAACC].new_status = PENDING;
      }

      // Decrement "rand" value after test to avoid a negative rand when L3
      // specifies a rand = 0
      l1a_l1s_com.ra_info.rand --;
    }
  }

  #if (L1_GPRS)
    // BCCHN task ENABLED and NBCCH task is INACTIVE
    if(((l1a_l1s_com.l1s_en_task[BCCHN     ] == TASK_ENABLED) && (l1s.task_status[BCCHN     ].current_status == INACTIVE)) ||
       ((l1a_l1s_com.l1s_en_task[BCCHN_TOP ] == TASK_ENABLED) && (l1s.task_status[BCCHN_TOP ].current_status == INACTIVE)) ||
       ((l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED) && (l1s.task_status[BCCHN_TRAN].current_status == INACTIVE)))
  #else
    // BCCHN task is ENABLED.
    if(((l1a_l1s_com.l1s_en_task[BCCHN    ] == TASK_ENABLED) && (l1s.task_status[BCCHN    ].current_status == INACTIVE)) ||
       ((l1a_l1s_com.l1s_en_task[BCCHN_TOP] == TASK_ENABLED) && (l1s.task_status[BCCHN_TOP].current_status == INACTIVE)))
  #endif
  {
    {
      UWORD32  neigh_fn;
      UWORD8   neigh_tc;
      UWORD8   neigh_fn_mod51;
      WORD32   time_to_bcchn;
      WORD16   time_in_mf51;
      UWORD16  si_bitmap;
      UWORD8   first_possible_neigh_tc;
      UWORD8   i;
      UWORD8   tc_count;
      UWORD8   ext_bcch_start_time;
      UWORD8   bcchn_priority;

      //array in order to memorize for each priority the closest NBCCH
      // 3 priorities: TOP_PRIORITY, HIGH_PRIORITY, NORMAL_PRIORITY
      UWORD32  min_time_to_bcchn[3] = {MAX_FN,MAX_FN,MAX_FN};
      UWORD8   best_neigh_id[3]     = {0,0,0};
      UWORD8   best_neigh_tc[3]     = {0,0,0};

      // Up to 6 pending Ncell BCCH reading.
      for(i=0;i<6;i++)
      {
        // Consider only the "in use" locations from the "6 neigh. list".
        if(l1a_l1s_com.bcchn.list[i].status != NSYNC_FREE)
        {
          // Get neighbor cell FN.
          neigh_fn = (l1s.actual_time.fn + l1a_l1s_com.bcchn.list[i].fn_offset) % MAX_FN;

          // Get neighbor cell TC.
          neigh_tc = (neigh_fn / 51) % 8;

          // Get neighbor cell TC.
          neigh_fn_mod51 = (neigh_fn % 51);

          //-----------------
          // Normal BCCH...
          //-----------------

          // Still some Normal BCCH to read.
          if(l1a_l1s_com.bcchn.list[i].bcch_blks_req & 0x00FF)
          {
            #if (L1_GPRS)
              // in case of packet transfer mode there is no measurement window
              if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED)
              {
                // Since Normal BCCH reading must start in FN_mod_51=50+2=1, current TC cannot
                // be read. First possible TC is therefore the next one.
                time_in_mf51 = 1 - neigh_fn_mod51;

                if(neigh_fn_mod51 > 1)
                  first_possible_neigh_tc = neigh_tc + 1;
                else
                  first_possible_neigh_tc = neigh_tc;
              }
              else
              {
                // Since Normal BCCH reading must start in FN_mod_51=50, current TC cannot
                // be read. First possible TC is therefore the next one.
                time_in_mf51            = 50 - neigh_fn_mod51;
                first_possible_neigh_tc = neigh_tc + 1;
              }
            #else
              // Since Normal BCCH reading must start in FN_mod_51=50, current TC cannot
              // be read. First possible TC is therefore the next one.
              time_in_mf51            = 50 - neigh_fn_mod51;
              first_possible_neigh_tc = neigh_tc + 1;
            #endif

            if(first_possible_neigh_tc >= 8)
              first_possible_neigh_tc -=8;

            // Get the duplicate version of the Normal BCCH si_bitmap.
            si_bitmap = l1a_l1s_com.bcchn.list[i].bcch_blks_req;

            // Look for 1st bit activated from current TC.
            tc_count = 0;
            while((!(si_bitmap & (1L << first_possible_neigh_tc))) && (tc_count < 8))
            {
              tc_count++;
              first_possible_neigh_tc++;
              if(first_possible_neigh_tc >= 8) first_possible_neigh_tc -=8;
            }

            // Compute time to wait until NBCCH activation.
            #if (L1_GPRS)
              if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED)
                time_to_bcchn  = time_in_mf51 + (first_possible_neigh_tc - neigh_tc    )*51;
              else
                time_to_bcchn  = time_in_mf51 + (first_possible_neigh_tc - neigh_tc - 1)*51;
            #else
                time_to_bcchn  = time_in_mf51 + (first_possible_neigh_tc - neigh_tc - 1)*51;
            #endif

            // Prevent negative result.
            if(time_to_bcchn < 0)
              time_to_bcchn += 8*51;
            else
              if(time_to_bcchn >= 8*51)
                time_to_bcchn -= 8*51;

            // memorize the next BCCHN according to its priority
            // (TOP_PRIORITY or HIGH_PRIORITY or NORMAL_PRIORITY )
            bcchn_priority = l1a_l1s_com.bcchn.list[i].gprs_priority ;
            if(time_to_bcchn < min_time_to_bcchn[bcchn_priority])
            {
              min_time_to_bcchn[bcchn_priority] = time_to_bcchn;

              // Save Neighbour number
              best_neigh_id[bcchn_priority] = i;
              best_neigh_tc[bcchn_priority] = first_possible_neigh_tc;
            }
          }

          //-----------------
          // Extended BCCH...
          //-----------------

          // Still some Extended BCCH to read.
          if(l1a_l1s_com.bcchn.list[i].bcch_blks_req & 0xFF00)
          {
            #if (L1_GPRS)
              // in case of packet transfer mode there are no measurement windows
              if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED)
                 ext_bcch_start_time=3+2;
              else
                 ext_bcch_start_time=3;
            #else
                 ext_bcch_start_time=3;
            #endif

            // Extended BCCH reading must start in FN_mod_51=ext_bcch_start_time.
            // Check if current TC could be read immediately.
            time_in_mf51 = ext_bcch_start_time - neigh_fn_mod51;

            if(neigh_fn_mod51 > ext_bcch_start_time)
              first_possible_neigh_tc = neigh_tc + 1;
            else
              first_possible_neigh_tc = neigh_tc;

            if(first_possible_neigh_tc >= 8)
              first_possible_neigh_tc -=8;

            // Offset TC by 8 to be within the EBCCH bitmap.
            first_possible_neigh_tc += 8;

            // Get the duplicate version of the Extended BCCH si_bitmap.
            si_bitmap = l1a_l1s_com.bcchn.list[i].bcch_blks_req;

            // Look for 1st bit activated from current TC.
            tc_count = 0;
            while((!(si_bitmap & (1L << first_possible_neigh_tc))) && (tc_count < 8))
            {
              tc_count++;
              first_possible_neigh_tc++;
              if(first_possible_neigh_tc >= 16) first_possible_neigh_tc -=8;
            }

            // Compute time to wait until NBCCH activation.
            time_to_bcchn  = time_in_mf51 + (first_possible_neigh_tc - neigh_tc - 8)*51;

            // Prevent negative result.
            if(time_to_bcchn < 0)
              time_to_bcchn += 8*51;
            else
              if(time_to_bcchn >= 8*51)
                time_to_bcchn -= 8*51;

            // memorize the next BCCHN according to its priority
            // (TOP_PRIORITY or HIGH_PRIORITY or NORMAL_PRIORITY )
            bcchn_priority = l1a_l1s_com.bcchn.list[i].gprs_priority;
            if(time_to_bcchn < min_time_to_bcchn[bcchn_priority])
            {
              min_time_to_bcchn[bcchn_priority] = time_to_bcchn;

              // Save Neighbour number
              best_neigh_id[bcchn_priority] = i;
              best_neigh_tc[bcchn_priority] = first_possible_neigh_tc;
            }
          }
        }
      }

      // Save scheduling result.
      #if L1_GPRS
      if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED)
      {
        // in packet transfer only task one task is allowed: BCCHN_TRAN with a TOP priority
        l1s.task_status[BCCHN_TRAN].time_to_exec = min_time_to_bcchn[TOP_PRIORITY];
        l1a_l1s_com.bcchn.active_neigh_id_top    = best_neigh_id[TOP_PRIORITY];
        l1a_l1s_com.bcchn.active_neigh_tc_top    = best_neigh_tc[TOP_PRIORITY];
        l1a_l1s_com.task_param[BCCHN_TRAN]       = SEMAPHORE_RESET;
      }
      else
      #endif
      {
        // in IDLE 2 tasks are allowed: BCCHN_TOP with a TOP priority or BCCHN with normal and high priorities
        // these 2 tasks may be enabled together.
        if((l1a_l1s_com.l1s_en_task[BCCHN_TOP] == TASK_ENABLED)&&(l1s.task_status[BCCHN_TOP].current_status == INACTIVE))
        {
          // update only if the task is not being running.
          l1s.task_status[BCCHN_TOP].time_to_exec = min_time_to_bcchn[TOP_PRIORITY];
          l1a_l1s_com.bcchn.active_neigh_id_top   = best_neigh_id[TOP_PRIORITY];
          l1a_l1s_com.bcchn.active_neigh_tc_top   = best_neigh_tc[TOP_PRIORITY];
          l1a_l1s_com.task_param[BCCHN_TOP]       = SEMAPHORE_RESET;
        }

        if((l1a_l1s_com.l1s_en_task[BCCHN] == TASK_ENABLED) && (l1s.task_status[BCCHN].current_status == INACTIVE))
        {
          // update only if the task is not being running.
          l1a_l1s_com.task_param[BCCHN] = SEMAPHORE_RESET;

          if(min_time_to_bcchn[HIGH_PRIORITY] < min_time_to_bcchn[NORMAL_PRIORITY] + BLOC_BCCHN_SIZE-1)
          {
            l1s.task_status[BCCHN].time_to_exec    = min_time_to_bcchn[HIGH_PRIORITY];
            l1a_l1s_com.bcchn.active_neigh_id_norm = best_neigh_id[HIGH_PRIORITY];
            l1a_l1s_com.bcchn.active_neigh_tc_norm = best_neigh_tc[HIGH_PRIORITY];
          }
          else
          {
            l1s.task_status[BCCHN].time_to_exec    = min_time_to_bcchn[NORMAL_PRIORITY];
            l1a_l1s_com.bcchn.active_neigh_id_norm = best_neigh_id[NORMAL_PRIORITY];
            l1a_l1s_com.bcchn.active_neigh_tc_norm = best_neigh_tc[NORMAL_PRIORITY];
          }
        }
      }

    } // End of "if / current_status"
  } // End of "if / BCCHN"

#if (L1_GPRS)
  if((l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED) ||
     ((l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) &&
     (l1s.task_status[PEP].current_status == INACTIVE)))
  //-------------------------------------
  // Packet Normal Paging task is ENABLED.
  //-------------------------------------
  {
    #define  BS_PAG_BLKS    l1pa_l1ps_com.pccch.bs_pag_blks_res
    #define  BS_PBCCH_BLKS  l1pa_l1ps_com.pccch.bs_pbcch_blks

    UWORD16  fn_mod;
    UWORD16  paging_group;
    UWORD8   mf52_index;
    UWORD32  m_index_dvd;
    UWORD32  m_index_rest;
    UWORD16  block_index_in_mf64x52;
    UWORD16  m_index_dvd_intermediate;
    UWORD8   mf52_for_ms_pg;
    UWORD8   mf52_for_ms_epg;
    UWORD8   pg_block_index;
    WORD16   time_to_pnp;
    WORD16   time_to_pep, time_to_pep_2;
    UWORD8   pnp_blk_position;
    UWORD8   pep_blk_position;

    UWORD16  m_index;
    WORD16   m_for_pep;
    UWORD16  pnp_position, pep_position_2 =0;//omaps00090550

    static UWORD16  pep_position;

    UWORD8   i = 0;

    // Actual Frame Number modulo Paging Period
    fn_mod = l1s.actual_time.fn % (64*52);

    //----------------------------------------
    // Step1:
    //----------------------------------------
    // Find next potential PCCCH block index
    // according to current FN.
    //----------------------------------------

    // Translate actual time Frame Number in an element of the "paging Block
    // available" set.
    mf52_index = fn_mod / 52;

    // Look for next PCCCH block "potentially" containing PNP.
    // Result in "i".
    while(((l1s.actual_time.fn_mod52 - PACKET_PG_POSITION[(i + (BS_PAG_BLKS+BS_PBCCH_BLKS)*11)]) >= 0) &&
          (i < l1pa_l1ps_com.pccch.nb_ppch_per_mf52))
    {
      i++;
    }

    // Compute "potential" PNP block index in the MF64x52.
    // block_index_mf64x52 has the same dimension as PAGING_GROUP!!!
    block_index_in_mf64x52 = mf52_index * l1pa_l1ps_com.pccch.nb_ppch_per_mf52 + i;

    //----------------------------------------
    // Step2:
    //----------------------------------------
    // Reverse ETSI equation to compute "m"
    // index corresponding to the next coming
    // PNP block.
    //----------------------------------------

    // Compute intermediate value to avoid % usage.
    m_index_dvd_intermediate = block_index_in_mf64x52 -
                               l1pa_l1ps_com.pccch.first_pg_grp +
                               l1pa_l1ps_com.pccch.pg_blks_avail;

    if(m_index_dvd_intermediate >= l1pa_l1ps_com.pccch.pg_blks_avail)
      m_index_dvd_intermediate -= l1pa_l1ps_com.pccch.pg_blks_avail;

    // Compute the reverse of ETSI equation
    //  m_index = ((block_index_in_mf64x52 - ALPHA - BETA)*SPLIT)DIV M
    // with:
    // ALPHA = (IMSImod10000)div(KC*N)
    // BETA  = IMSImod1000
    m_index_dvd  = (UWORD32)m_index_dvd_intermediate * (UWORD32)l1pa_l1ps_com.pccch.split_pg_value;

    m_index      = (UWORD16)(m_index_dvd / (UWORD32)(l1pa_l1ps_com.pccch.pg_blks_avail));
    m_index_rest = m_index_dvd - (UWORD32)(m_index)*(UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail;

    // Cope with rounding effect...
    // Choose next PAGING_GROUP index.
    // Note: if rest of the division "m_index_dvd/pg_blks_avail !=0"
    // then PAGING GROUP index must be incremented.
    if(m_index_rest != 0)
    {
      m_for_pep = m_index;
      m_index += 1;
    }
    else
    {
      m_for_pep = m_index - 1;;

      if(m_for_pep < 0)
        m_for_pep += l1pa_l1ps_com.pccch.split_pg_value;
    }

    //----------------------------------------
    // Step3:
    //----------------------------------------
    // Find PAGING GROUP associated with the
    // "m" index found in step 2.
    // Then compute MF52 containing this block
    // and associated block index in the MF52.
    //----------------------------------------

    // PAGING GROUP computation:
    paging_group    = (l1pa_l1ps_com.pccch.pg_offset + (((UWORD32)m_index * (UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail)
                        / (UWORD32)l1pa_l1ps_com.pccch.split_pg_value)) % l1pa_l1ps_com.pccch.pg_blks_avail ;

    // Computation of the MF52 for MS Packet Paging
    mf52_for_ms_pg = paging_group / l1pa_l1ps_com.pccch.nb_ppch_per_mf52;

    // Paging Block Index computation
    pg_block_index = paging_group % l1pa_l1ps_com.pccch.nb_ppch_per_mf52;

    // Normal and Extended paging position
    pnp_blk_position =
            PACKET_PG_POSITION[(pg_block_index + (l1pa_l1ps_com.pccch.bs_pag_blks_res +
                                l1pa_l1ps_com.pccch.bs_pbcch_blks)*MAX_NBR_PG_BLKS)];

    // Computation of the PPCH block position in the MF52
    pnp_position = (pnp_blk_position - 1) + mf52_for_ms_pg * 52;

    // Time between actual fn and next PPCH block
    // Apply modulo 64*52.
    time_to_pnp = pnp_position - fn_mod + (64*52);

    if(time_to_pnp >= (64*52))
      time_to_pnp -= (64*52);

    // Save Time to next PPCH block position in a global structure.
    // "time_to_pnp" is used in Cell reselection measurement scheduling.
    l1pa_l1ps_com.pccch.time_to_pnp = time_to_pnp;

    // Semaphore is Set, reset it when PNP inactive.
    if(l1a_l1s_com.task_param[PNP] == SEMAPHORE_SET)
    {
      if(l1s.task_status[PNP].current_status == INACTIVE)
        l1a_l1s_com.task_param[PNP] = SEMAPHORE_RESET;
    }

    if(l1a_l1s_com.task_param[PNP] == SEMAPHORE_RESET)
    {
      // Save scheduling result.
      l1s.task_status[PNP].time_to_exec = time_to_pnp;

      if(time_to_pnp == 0)
      {
        // Force PEP scheduling computation
        l1pa_l1ps_com.pccch.epg_computation = PPCH_POS_NOT_COMP;
      }
    }

    if(l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED)
      {
        if(l1pa_l1ps_com.pccch.epg_computation == PPCH_POS_NOT_COMP)
        {
          // PAGING GROUP computation:
          paging_group    = (l1pa_l1ps_com.pccch.pg_offset + (((UWORD32)(m_index) * (UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail)
                              / (UWORD32)l1pa_l1ps_com.pccch.split_pg_value)) % l1pa_l1ps_com.pccch.pg_blks_avail;

          // Computation of the MF52 for MS Packet Extented Paging
          mf52_for_ms_epg = ((paging_group + 3) / l1pa_l1ps_com.pccch.nb_ppch_per_mf52) % 64;

          // Paging Block Index computation
          pg_block_index = paging_group % l1pa_l1ps_com.pccch.nb_ppch_per_mf52;

          // Normal and Extended paging position
          pep_blk_position =
          PACKET_PG_POSITION[(((pg_block_index + 3) % l1pa_l1ps_com.pccch.nb_ppch_per_mf52) +
                              (l1pa_l1ps_com.pccch.bs_pag_blks_res +
                               l1pa_l1ps_com.pccch.bs_pbcch_blks)*11)];

          // Computation of the PEPCH block position in the MF52
          pep_position = (pep_blk_position - 1) + mf52_for_ms_epg * 52;

          // PEP is scheduled for the 1st time. If first PPCH block is a PEP and not PNP
          // then PEP scheduling has to be computed with "m_for_pep = m_index - 1"
          if(l1a_l1s_com.task_param[PEP] == SEMAPHORE_SET)
          {
            // PAGING GROUP computation:

            paging_group = (l1pa_l1ps_com.pccch.pg_offset + (((UWORD32)(m_for_pep) * (UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail)
                                / (UWORD32)l1pa_l1ps_com.pccch.split_pg_value)) % l1pa_l1ps_com.pccch.pg_blks_avail;

            // Computation of the MF52 for MS Packet Extented Paging
            mf52_for_ms_epg = ((paging_group + 3) / l1pa_l1ps_com.pccch.nb_ppch_per_mf52) % 64;

            // Paging Block Index computation
            pg_block_index = paging_group % l1pa_l1ps_com.pccch.nb_ppch_per_mf52;

            // Normal and Extended paging position
            pep_blk_position =
            PACKET_PG_POSITION[(((pg_block_index + 3) % l1pa_l1ps_com.pccch.nb_ppch_per_mf52) +
                                (l1pa_l1ps_com.pccch.bs_pag_blks_res +
                                 l1pa_l1ps_com.pccch.bs_pbcch_blks)*11)];

            // Computation of the PEPCH block position in the MF52
            pep_position_2 = (pep_blk_position - 1) + mf52_for_ms_epg * 52;
          }

          //Step in PPCH reading block state machine
          l1pa_l1ps_com.pccch.epg_computation = PPCH_POS_COMP;
        }

        // Time between actual fn and next PEPCH block
        time_to_pep = (pep_position - fn_mod + (64*52)) % (64*52);

        if(l1a_l1s_com.task_param[PEP] == SEMAPHORE_SET)
        {
          // Time between actual fn and next PEPCH block
          time_to_pep_2 = (pep_position_2 - fn_mod + (64*52)) % (64*52);

          // Compute Position of First PEP block and update pep_position
          if(time_to_pep_2 < time_to_pep)
          {
            time_to_pep = time_to_pep_2;
            pep_position = pep_position_2;
          }

          // Semaphore is Set, reset it when PEP inactive.
          if(l1s.task_status[PEP].current_status == INACTIVE)
            l1a_l1s_com.task_param[PEP] = SEMAPHORE_RESET;
        }

        if(l1a_l1s_com.task_param[PEP] == SEMAPHORE_RESET)
        {
          // Save scheduling result.
          l1s.task_status[PEP].time_to_exec = time_to_pep;
        }

      }// End of if(l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED)

  } // End of if PNP_TASK || PEP_TASK

  if(l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED)
  //---------------------------------
  // ALL PCCCH reading is ENABLED.
  //---------------------------------
  {
    // Semaphore is Set, reset it when PALLC inactive.
    if(l1a_l1s_com.task_param[PALLC] == SEMAPHORE_SET)
    {
      if(l1s.task_status[PALLC].current_status == INACTIVE)
        l1a_l1s_com.task_param[PALLC] = SEMAPHORE_RESET;
    }

    if(l1a_l1s_com.task_param[PALLC] == SEMAPHORE_RESET)
    {
      #define PCCCH0_START_TIME  13 - 1  // PCCCH block 0.
      #define PCCCH1_START_TIME   4 - 1  // PCCCH block 1.
      #define PCCCH2_START_TIME   8 - 1  // PCCCH block 2.

      UWORD32  min_time_to_pallc;

      if(l1s.actual_time.fn_mod13 <= PCCCH1_START_TIME)
        min_time_to_pallc = PCCCH1_START_TIME - l1s.actual_time.fn_mod13;
      else
      if(l1s.actual_time.fn_mod13 <= PCCCH2_START_TIME)
        min_time_to_pallc = PCCCH2_START_TIME - l1s.actual_time.fn_mod13;
      else
        min_time_to_pallc = PCCCH0_START_TIME - l1s.actual_time.fn_mod13;

      // Save scheduling result.
      l1s.task_status[PALLC].time_to_exec = min_time_to_pallc;
    }
  } // End of if(l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED)

  if(l1a_l1s_com.l1s_en_task[PBCCHS] == TASK_ENABLED)
  //--------------------------------------------
  // Serving Cell PCCCH reading task is ENABLED.
  //--------------------------------------------
  {
    if(l1s.task_status[PBCCHS].current_status == INACTIVE)
    {
      #define  PbcchS  l1pa_l1ps_com.pbcchs

      UWORD32  fn;
      UWORD32  min_time_to_pbcchs = MAX_FN;
      UWORD8   psi_index = 0;
      UWORD8   fn_sub_period = 0;

      if(PbcchS.control_offset)
      // 1) PBCCHS timeslot is lower than current PCCCH timeslot, this means that the scheduling
      //    must be anticipated by 1 frame
      // 2) PBCCHS task must contain a synchro change (sync on "current TS" + 4)
      //    and a synchro back to current TS.
      //    => "offset" array contains the frame to which "next_time.fn" must comply.
      {
        fn = l1s.next_time.fn;
      }
      else
      {
        fn = l1s.actual_time.fn;
      }

      // Scheduling...
      {
        UWORD16  psi_period         = PbcchS.pbcch_period;
        UWORD16  fn_mod_ps1_period  = fn % PbcchS.pbcch_period;
        UWORD8   i;

        if(PbcchS.read_all_psi)
        {
          psi_period        = 52;
          fn_sub_period     = fn_mod_ps1_period / psi_period;
          fn_mod_ps1_period = fn % psi_period;
        }

        // Look for the closest PBCCH block (loop on 20 max)
        for(i=0;i<PbcchS.nbr_psi;i++)
        {
          WORD16 time_to_pbcchs;

          // Get time diff between current frame and this PBCCHS block.
          time_to_pbcchs = PbcchS.offset_array[i] - fn_mod_ps1_period;
          if(time_to_pbcchs < 0)
            time_to_pbcchs += psi_period;

          // Save Min time to next PBCCHS block.
          if(time_to_pbcchs < min_time_to_pbcchs)
          {
            min_time_to_pbcchs = time_to_pbcchs;
            psi_index          = i;
          }
        }
      }

      // Save scheduling result.
      l1s.task_status[PBCCHS].time_to_exec = min_time_to_pbcchs;

      // Clear param. synchro. semaphore.
      l1a_l1s_com.task_param[PBCCHS] = SEMAPHORE_RESET;

      // If block to decode is B0 (decoding is made in next MF52) then increment fn_sub_period
      // This is only applicable to the specific case: All PSI to read
      if(PbcchS.read_all_psi)
      {
        if(psi_index == 0)
        {
          fn_sub_period +=1;

          if(fn_sub_period >= PbcchS.psi1_repeat_period)
            fn_sub_period -= PbcchS.psi1_repeat_period;
        }
      }

      // Save Relative Position of the PBCCH block read to L3
      l1pa_l1ps_com.pbcchs.rel_pos_to_report = PbcchS.relative_position_array[psi_index]
                                               + (fn_sub_period * (PbcchS.bs_pbcch_blks + 1));
    }
  }

  if((l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] == TASK_ENABLED) ||
     (l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] == TASK_ENABLED))
  //--------------------------------------------
  // Neighbor Cell PCCCH reading task is ENABLED.
  //--------------------------------------------
  {
    #define  PbcchN  l1pa_l1ps_com.pbcchn

    WORD32   min_time_to_pbcchn;
    UWORD32  neighbor_fn;
    UWORD16  neighbor_fn_mod_ps1_period;
    WORD16   task;

    // in case of packet transfer mode there are no measurement windows
    if (l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] == TASK_ENABLED)
      task=PBCCHN_IDLE;
    else
      task=PBCCHN_TRAN;

    // ================================
    // compute the current neighbor FN
    // ================================

    neighbor_fn = l1s.actual_time.fn + PbcchN.fn_offset ;
    neighbor_fn_mod_ps1_period  = neighbor_fn % PbcchN.pbcch_period;

    // Get time diff between current neighbor frame and this PBCCHN block.
    min_time_to_pbcchn = PbcchN.offset- neighbor_fn_mod_ps1_period;
    if (min_time_to_pbcchn < 0)
      min_time_to_pbcchn += PbcchN.pbcch_period;

    if(l1s.task_status[task].current_status == INACTIVE)
    {
      // Clear param. synchro. semaphore.
      l1a_l1s_com.task_param[task] = SEMAPHORE_RESET;
    }

    // Save scheduling result.
    l1s.task_status[task].time_to_exec = min_time_to_pbcchn;
  }

#endif // if L1_GPRS

  if ((l1a_l1s_com.l1s_en_task[NSYNC] == TASK_ENABLED)
    && (l1a_l1s_com.l1s_en_task[ALLC] == TASK_DISABLED))
  // Do not allow NSYNC task to enter MFTAB in reorg paging mode

  //------------------------------------
  // Neigbour Cell Synchro task enabled
  //------------------------------------
  {
    if((l1s.task_status[FBNEW].current_status  == INACTIVE) &&
       (l1s.task_status[SB2].current_status    == INACTIVE) &&
       (l1s.task_status[SBCONF].current_status == INACTIVE))
    {
      //Remarks:
      //--------
      // We do not allow entrance of a neigh FB or SB task if there
      // is already some neigh task (FB/SB or BCCH) running. This is
      // to avoid to cope with many abort cases (we cannot list them
      // easily).
#if (L1_12NEIGH == 1)
      // This machine does not work for DEDICATED MODE.
       #if (L1_GPRS)
       if ((l1a_l1s_com.mode != DEDIC_MODE) && (l1a_l1s_com.mode != PACKET_TRANSFER_MODE))
       // Due to transition modes sometimes mode is PACKET_TRANSFER and
       // PDTCH is DISABLED. So we must test also PACKET_TRANSFER mode.
       #else
       if (l1a_l1s_com.mode != DEDIC_MODE)
       #endif
       {
#endif

      UWORD8  i;
      UWORD8  j;
      UWORD8  first_in_list=l1a_l1s_com.nsync.first_in_list ;

      WORD32  best_time_to_fb     = MAX_FN;
      WORD32  best_time_to_sbconf = MAX_FN;
      WORD32  best_time_to_sb2    = MAX_FN;
      UWORD8  best_neigh_fb       = 255;
      UWORD8  best_neigh_sbconf   = 255;
      UWORD8  best_neigh_sb2      = 255;

#if (L1_12NEIGH ==1)
  #if (L1_EOTD == 1)
      // Up to NBR_NEIGHBOURS + 1 (Serving Cell pending)
      for(j=first_in_list;j<(NBR_NEIGHBOURS+1+first_in_list);j++)
      {
         if (j>=NBR_NEIGHBOURS+1)
            i=j-NBR_NEIGHBOURS-1;
         else
            i=j;
  #else
      // Up to NBR_NEIGHBOURS
      for(j=first_in_list;j<(NBR_NEIGHBOURS+first_in_list);j++)
      {
         if (j>=NBR_NEIGHBOURS)
            i=j-NBR_NEIGHBOURS;
         else
            i=j;
  #endif // L1_EOTD

#else // L1_12NEIGH

      for(j=first_in_list;j<(6+first_in_list);j++)
      {
         if (j>=6)
            i=j-6;
         else
            i=j;

#endif // L1_12NEIGH

        // Consider only the "in use" locations from the "N neigh. list".
        if(l1a_l1s_com.nsync.list[i].status == NSYNC_PENDING)
        {
          UWORD32  neigh_fn_mod51;

          switch(l1a_l1s_com.nsync.list[i].timing_validity)
          {
            case 0: // No valid info is supplied: search FB with no a priori info.
            {
              // Consider the Neighbour in respecting their order in the list.
              if(best_time_to_fb != 0)
              {
                best_time_to_fb = 0;
                best_neigh_fb   = i;
              }
            }
            break;

            case 1:  // Approximate timing is supplied: search FB with a priori info..
            {
                UWORD32  min_time_to_fb = MAX_FN;

                // Get neighbour cell FN % 51.
                neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51;

                // Attempt to read 2nd FB.
                // Frame 7 is the position to read 2nd FB within MF51 (due to C/W/R and AGC)
                if(neigh_fn_mod51 <= 7)
                {
                  min_time_to_fb = 7 - neigh_fn_mod51;
                }

                // Attempt to read 3rd FB.
                // Frame 17 is the position to read 3rd FB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 17)
                {
                  min_time_to_fb = 17 - neigh_fn_mod51;
                }

                // Attempt to read 4th FB.
                // Frame 27 is the position to read 4th FB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 27)
                {
                  min_time_to_fb = 27 - neigh_fn_mod51;
                }

                // Attempt to read 5th FB.
                // Frame 37 is the position to read 5th FB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 37)
                {
                  min_time_to_fb = 37 - neigh_fn_mod51;
                }

                // Attempt to read 1st FB.
                // Frame 48 is the position to read 1st FB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 48)
                {
                  min_time_to_fb = 48 - neigh_fn_mod51;
                }
                // Attempt to read 2nd FB
                // Special case: frame 49 and frame 50
                else
                {
                  min_time_to_fb = 50 - neigh_fn_mod51 + 8;
                }

              if(min_time_to_fb <(UWORD32 ) best_time_to_fb)
                {
                best_time_to_fb = min_time_to_fb;
                best_neigh_fb   = i;
              }
            }
            break;

            case 2:  // Accurate timing is supplied: confirm SB.
              {
                UWORD32  min_time_to_sb = MAX_FN;

                // Get neighbour cell FN % 51.
                neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51;

                // Attempt to read 2nd SB.
                // Frame 8 is the position to read 2nd SB within MF51 (due to C/W/R and AGC)
                if(neigh_fn_mod51 <= 8)
                {
                  min_time_to_sb = 8 - neigh_fn_mod51;
                }

                // Attempt to read 3rd SB.
                // Frame 18 is the position to read 3rd SB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 18)
                {
                  min_time_to_sb = 18 - neigh_fn_mod51;
                }

                // Attempt to read 4th SB.
                // Frame 28 is the position to read 4th SB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 28)
                {
                  min_time_to_sb = 28 - neigh_fn_mod51;
                }

                // Attempt to read 5th SB.
                // Frame 38 is the position to read 5th SB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 38)
                {
                  min_time_to_sb = 38 - neigh_fn_mod51;
                }

                // Attempt to read 1st SB.
                // Frame 49 is the position to read 1st SB within MF51 (due to C/W/R and AGC)
                else
                if(neigh_fn_mod51 <= 49)
                {
                  min_time_to_sb = 49 - neigh_fn_mod51;
                }
                // Attempt to read 2nd SB
                // Special case: Frame=50 (idle frame)
                else
                {
                  min_time_to_sb = 9;
                }

              if(min_time_to_sb <(UWORD32 ) best_time_to_sbconf)
                {
                best_time_to_sbconf = min_time_to_sb;
                best_neigh_sbconf   = i;
                }

            }
            break;

         #if ((REL99 == 1) && ((FF_BHO == 1) || (FF_RTD == 1)))
            case SB_ACQUISITION_PHASE: // SB search following a FB search.
          #else
            case 3:  // SB search following a FB search.
          #endif
            {
                UWORD8   spent_fn;
                UWORD32  min_time_to_sb = MAX_FN;

                // "fn_offset" contains the FN%51 corresponding to the FB detected

                spent_fn = (l1s.actual_time.t3 - l1a_l1s_com.nsync.list[i].fn_offset + 51) % 51;

                // Attempt to read 1st SB.
                // Frame 8 is the position to read 1st SB within MF51 (due to C/W/R and AGC)
                if(spent_fn <= 8)
                {
                  min_time_to_sb = 8 - spent_fn;
                }

                // Attempt to read 2nd SB.
                // Frame 18 is the position to read 2nd SB within MF51 (due to C/W/R and AGC)
                else
                if(spent_fn <= 18)
                {
                  min_time_to_sb = 18 - spent_fn;
                }

                // Attempt to read 3rd SB.
                // Frame 28 is the position to read 3rd SB within MF51 (due to C/W/R and AGC)
                else
                if(spent_fn <= 28)
                {
                  min_time_to_sb = 28 - spent_fn;
                }

                // Attempt to read 4th SB.
                // Frame 38 is the position to read 4th SB within MF51 (due to C/W/R and AGC)
                else
                if(spent_fn <= 38)
                {
                  min_time_to_sb = 38 - spent_fn;
                }

                // Attempt to read 5tht SB.
                // Frame 49 is the position to read 5tht SB within MF51 (due to C/W/R and AGC)
                else
                if(spent_fn <= 49)
                {
                  min_time_to_sb = 49 - spent_fn;
                }
                // Attempt to read 2nd SB
                // Special case: Frame=50 (idle frame)
                else
                {
                  min_time_to_sb = 9;
                }

              if(min_time_to_sb <= ( UWORD32 )best_time_to_sb2)
                {
                best_time_to_sb2 = min_time_to_sb;
                best_neigh_sb2   = i;
                }

            }
            break;

          } // End of "switch"
        } // End of "if"
      } // End of "for"

      if(best_neigh_fb != 255)
      {
        // Save active neighbour id.
        l1a_l1s_com.nsync.active_fb_id = best_neigh_fb;

          // Save scheduling result.
        l1s.task_status[FBNEW].time_to_exec = best_time_to_fb;

          // Enable FBNEW task
          l1a_l1s_com.l1s_en_task[FBNEW] = TASK_ENABLED;

          // Clear param. synchro. semaphore.
          l1a_l1s_com.task_param[FBNEW] = SEMAPHORE_RESET;
        }

      if(best_neigh_sbconf != 255)
        {
        // Save active neighbour id.
        l1a_l1s_com.nsync.active_sbconf_id = best_neigh_sbconf;

          // Save scheduling result.
        l1s.task_status[SBCONF].time_to_exec = best_time_to_sbconf;

          l1a_l1s_com.l1s_en_task[SBCONF] = TASK_ENABLED;

          // Clear param. synchro. semaphore.
          l1a_l1s_com.task_param[SBCONF] = SEMAPHORE_RESET;
        }

      if(best_neigh_sb2 != 255)
        {
        // Save active neighbour id.
        l1a_l1s_com.nsync.active_sb_id = best_neigh_sb2;

          // Save scheduling result.
        l1s.task_status[SB2].time_to_exec = best_time_to_sb2;

          // Enable SB2 task
          l1a_l1s_com.l1s_en_task[SB2] = TASK_ENABLED;

          // Clear param. synchro. semaphore.
          l1a_l1s_com.task_param[SB2] = SEMAPHORE_RESET;
        }
#if (L1_12NEIGH == 1)
    } // End of "if / DEDIC = IDLE-MODE
#endif
    } // End of "if / current_status"
  } // End of "if / NSYNC"

  if(l1a_l1s_com.l1s_en_task[HWTEST] == TASK_ENABLED)
  //-------------------------
  // HW_TEST task is ENABLED.
  //-------------------------
  {
    if(l1s.task_status[HWTEST].current_status == INACTIVE)
    // HW_TEST task is INACTIVE.
    // Rem: HW_TEST task has no occurence time. Therefore whenever HW_TEST
    //      is ENABLED and INACTIVE it must be executed.
    {
      // Save scheduling result.
      l1s.task_status[HWTEST].time_to_exec = 0;
    }
  }

  //================================================================
  //==                   DEDICATED MODE TASKS                     ==
  //==                   --------------------                     ==
  //================================================================
#if (L1_12NEIGH == 0)
  if(l1a_l1s_com.l1s_en_task[FB26] == TASK_ENABLED)
  //-------------------------
  // FB26 task is ENABLED.
  //-------------------------
  {
    UWORD32  time_to_fb26 = MAX_FN;

    if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
    //---------------------------------------------
    // Dedicated mode tasks are enabled.
    //---------------------------------------------
    {
      T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

      // Rem: this task is used in dedicated/TCH_H/F

      if(desc_ptr->channel_type == TCH_H)
      {
        UWORD8 normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26;

        if(normalised_fn_mod26 <= 22)
          time_to_fb26 = 22 - normalised_fn_mod26;
        else
          time_to_fb26 = 26+ 22 - normalised_fn_mod26;
      }
      else
      if(desc_ptr->channel_type == TCH_F)
      {
        UWORD8 normalised_fn_mod26 = l1s.actual_time.fn_in_report % 26;

        if(normalised_fn_mod26 <= 23)
          time_to_fb26 = 23 - normalised_fn_mod26;
        else
          time_to_fb26 = 26 + 23 - normalised_fn_mod26;
      }
    }

    #if L1_GPRS
    else
    if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
    //---------------------------------------------
    // Packet Transfer mode task is enabled.
    //---------------------------------------------
    {
      if(l1s.actual_time.t2 <= 23)
        time_to_fb26 = 23 - l1s.actual_time.t2;
      else
        time_to_fb26 = 26 + 23 - l1s.actual_time.t2;
    }
    #endif

    // No scheduling result for FB26 task to avoid selection of this task.
    // -> l1s.task_status[FB26].time_to_exec stays equal to MAX_FN

    // Set FB26 as PENDING to trigger the l1s_merge_manager() to install it
    // in MFTAB.
    if(time_to_fb26 == 0)
      l1s.task_status[FB26].new_status = PENDING;

    // Set active neighbor identifier.
    l1a_l1s_com.nsync.active_fb_id = 0;

    // Clear param. synchro. semaphore.
    l1a_l1s_com.task_param[FB26] = SEMAPHORE_RESET;

  } // End if(...[FB26] == TASK_ENABLED)

  if(l1a_l1s_com.l1s_en_task[SB26] == TASK_ENABLED)
  //-------------------------
  // SB26 task is ENABLED.
  //-------------------------
  {
    WORD32  time_to_sb26 = MAX_FN;

    if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
    //---------------------------------------------
    // Dedicated mode tasks are enabled.
    //---------------------------------------------
    {
      T_CHANNEL_DESCRIPTION *desc_ptr   = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

      // Rem: this task is used in dedicated/TCH_H/F

      if((desc_ptr->channel_type == TCH_F) || (desc_ptr->channel_type == TCH_H))
      {
        // Monitoring area starting frame is reached...
        if(l1s.actual_time.fn <= l1a_l1s_com.nsync.list[0].fn_offset)
          time_to_sb26 = l1a_l1s_com.nsync.list[0].fn_offset - l1s.actual_time.fn;
        else
          time_to_sb26 = MAX_FN + l1a_l1s_com.nsync.list[0].fn_offset - l1s.actual_time.fn;
      }
    }

    #if L1_GPRS
    else
    if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
    //---------------------------------------------
    // Packet Transfer mode task is enabled.
    //---------------------------------------------
    {

      UWORD8 SB26_attempt = l1a_l1s_com.nsync.list[0].sb26_attempt;
      // schedule SB26 at all possible positions
      // attempt=0 => first SB after FB found is at FB position + 52
      // attempt=1 => next SB is at position: FN_offset + 9*26
      // attempt=2 => or next SB is at position: FN_offset + 9*26 + 52 (due to Idle frame)
      // REM: an higher priority task could have canceled the SB scheduled, that's why
      // we must plan the  following SB with its 2 possible positions.

      // Monitoring area starting frame is reached...
        time_to_sb26 = l1a_l1s_com.nsync.list[0].fn_offset - l1s.actual_time.fn;

      if(time_to_sb26 < 0) // in this case a SB was missed by a higher priority task
      {
         if (SB26_attempt == 1) // next SB is 9*26 frame later
            time_to_sb26 += 26*9;
         else if (SB26_attempt == 2) // or next FB is 9*26 + 52 frames later
            time_to_sb26 += 26*9 + 52;
              else // should never happen
                time_to_sb26 += MAX_FN;
      }

      if(time_to_sb26 == 0)
      {
        l1a_l1s_com.nsync.list[0].sb26_attempt++;

        if (SB26_attempt>2)
          l1a_l1s_com.nsync.list[0].sb26_attempt=1;
      }

    }
    #endif

    // No scheduling result for SB26 task to avoid selection of this task.
    // -> l1s.task_status[SB26].time_to_exec stays equal to MAX_FN

    // Set SB26 as PENDING to trigger the l1s_merge_manager() to install it
    // in MFTAB.
    if(time_to_sb26 == 0)
      l1s.task_status[SB26].new_status = PENDING;

    // Set active neighbor identifier.
    l1a_l1s_com.nsync.active_sb_id = 0;

    // Clear param. synchro. semaphore.
    l1a_l1s_com.task_param[SB26] = SEMAPHORE_RESET;

  } // End if(...[SB26] == TASK_ENABLED)

  if(l1a_l1s_com.l1s_en_task[SBCNF26] == TASK_ENABLED)
  //-------------------------
  // SBCNF26 task is ENABLED.
  //-------------------------
  {
    BOOL check_sbcnf26 = 0;

    if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
    //---------------------------------------------
    // Dedicated mode tasks are enabled.
    //---------------------------------------------
    {
      T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;
      UWORD8                 normalised_fn_mod26;

      normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26;

      if(((normalised_fn_mod26 == 22) && (desc_ptr->channel_type == TCH_H)) ||
        (((l1s.actual_time.fn_in_report % 26) == 23) && (desc_ptr->channel_type == TCH_F)))
      // Monitoring area control frame is reached...
      {
        check_sbcnf26 = 1;
      }
    }

    #if L1_GPRS
    else
    if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
    //---------------------------------------------
    // Packet Transfer mode task is enabled.
    //---------------------------------------------
    {
      if(l1s.actual_time.t2 == 23)
      // Monitoring area control frame is reached...
      {
        check_sbcnf26 = 1;
      }
    }
    #endif

    if(check_sbcnf26)
    // SBCNF26 must be checked.
    {
      UWORD32 next_neigh_fn_mod51;

      // Get neighbor domain frame number %51 for frame 24.
      next_neigh_fn_mod51 = (l1s.next_time.fn + l1a_l1s_com.nsync.list[0].fn_offset) % 51;

      // No scheduling result for SBCNF26 task to avoid selection of this task.
      // -> l1s.task_status[SBCNF26].time_to_exec stays equal to MAX_FN

      if((next_neigh_fn_mod51 % 10) == 1)
      // SB26 rx window starts in the frame 24...
      {
        if(l1a_l1s_com.nsync.list[0].time_alignmt >= l1_config.params.fb26_anchoring_time)
        // SB feet in the search slot...
        // Set SBCNF26 as PENDING to trigger the l1s_merge_manager() to install it
        // in MFTAB.
        {
          l1s.task_status[SBCNF26].new_status = PENDING;

          l1a_l1s_com.nsync.list[0].sb26_offset   = 0;

          // Set active neighbor identifier.
          l1a_l1s_com.nsync.active_sbconf_id  = 0;

          // Clear param. synchro. semaphore.
          l1a_l1s_com.task_param[SBCNF26] = SEMAPHORE_RESET;
        }
      }
      else
      if((next_neigh_fn_mod51 == 0)  ||
         (next_neigh_fn_mod51 == 10) ||
         (next_neigh_fn_mod51 == 20) ||
         (next_neigh_fn_mod51 == 30) ||
         (next_neigh_fn_mod51 == 40))
      // SB26 rx window starts in the frame 25...
      {
        if(l1a_l1s_com.nsync.list[0].time_alignmt < ((l1_config.params.fb26_anchoring_time
                                                      +FB26_ACQUIS_DURATION
                                                      -SB_ACQUIS_DURATION
                                                      +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE))
        // SB feet in the search slot...
        // Set SBCNF26 as PENDING to trigger the l1s_merge_manager() to install it
        // in MFTAB.
        {
          l1s.task_status[SBCNF26].new_status = PENDING;

          l1a_l1s_com.nsync.list[0].sb26_offset   = 1;

          // Set active neighbor identifier.
          l1a_l1s_com.nsync.active_sbconf_id  = 0;

          // Clear param. synchro. semaphore.
          l1a_l1s_com.task_param[SBCNF26] = SEMAPHORE_RESET;
        }
      }
    }
  }


  if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
  //---------------------------------------------
  // Dedicated mode tasks are enabled.
  //---------------------------------------------
  {
    T_CHANNEL_DESCRIPTION *desc_ptr   = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;
    T_SDCCH_DESC          *sdcch_desc = NULL;//OMAPS00090550

    // No scheduling result for DEDIC task to avoid selection of this task.
    // -> l1s.task_status[DEDIC].time_to_exec stays equal to MAX_FN

    // DEDIC task requires to run L1S scheduler every frame.
    l1a_l1s_com.time_to_next_l1s_task = 0;

    //=================================
    // MF51 tasks...
    //=================================

    if((desc_ptr->channel_type == SDCCH_4) || (desc_ptr->channel_type == SDCCH_8))
    // SDCCH channel -> MF51 structure.
    {
      UWORD8  start_time =0; //omaps00090550
      UWORD8  fn_in_report_mod51 = l1s.next_time.fn_in_report % 51;

      // Save position of the monitoring area for SDCCH.
      if(desc_ptr->channel_type == SDCCH_8)
      {
        start_time =  SDCCH_DESC_NCOMB[desc_ptr->subchannel].mon_area_position;
        sdcch_desc = &(SDCCH_DESC_NCOMB[desc_ptr->subchannel]);
      }
      else
      {
        start_time =  SDCCH_DESC_COMB[desc_ptr->subchannel].mon_area_position;
        sdcch_desc = &(SDCCH_DESC_COMB[desc_ptr->subchannel]);
      }

      if(l1a_l1s_com.l1s_en_task[FB51] == TASK_ENABLED)
      //-------------------------
      // FB51 task is ENABLED.
      //-------------------------
      {
        UWORD32  time_to_fb51;

        if(l1s.actual_time.fn_in_report <= start_time)
          time_to_fb51 = start_time - l1s.actual_time.fn_in_report;
        else
          time_to_fb51 = MAX_FN + start_time - l1s.actual_time.fn_in_report;

        // Save scheduling result.
        l1s.task_status[FB51].time_to_exec = time_to_fb51;

        // Set active neighbor identifier.
        l1a_l1s_com.nsync.active_fb_id = 0;

        // Clear param. synchro. semaphore.
        l1a_l1s_com.task_param[FB51] = SEMAPHORE_RESET;
      }

      if(l1a_l1s_com.l1s_en_task[SB51] == TASK_ENABLED)
      //-------------------------
      // SB51 task is ENABLED.
      //-------------------------
      {
        // Rem: this task is used in dedicated/SDCCH.
        //      SB reading task is 102 frames after the FB.

        UWORD32  time_to_sb51;
        UWORD32  fn_sb51 = (l1a_l1s_com.nsync.list[0].fn_offset + 102)%MAX_FN;

        fn_sb51 = l1a_l1s_com.nsync.list[0].fn_offset + 102;
        if(fn_sb51 >= MAX_FN) fn_sb51 -= MAX_FN;

        if(l1s.actual_time.fn <= fn_sb51)
          time_to_sb51 = fn_sb51 - l1s.actual_time.fn;
        else
          time_to_sb51 = MAX_FN + fn_sb51 - l1s.actual_time.fn;

        // Save scheduling result.
        l1s.task_status[SB51].time_to_exec = time_to_sb51;

        // Set active neighbor identifier.
        l1a_l1s_com.nsync.active_sb_id = 0;

        // Clear param. synchro. semaphore.
        l1a_l1s_com.task_param[SB51] = SEMAPHORE_RESET;
      }

      if(l1a_l1s_com.l1s_en_task[SBCNF51] == TASK_ENABLED)
      //-------------------------
      // SBCNF51 task is ENABLED.
      //-------------------------
      {
        // Rem: this task is used in dedicated/SDCCH.

        if((l1s.actual_time.fn_in_report >= start_time) &&
           (l1s.actual_time.fn_in_report <  start_time + 11))
        {
          UWORD32  neigh_fn_mod51;

          // Get neighbour cell FN % 51 and then % 10.
          neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[0].fn_offset) % 51;

          // SBCNF51 task is a special case: it is not using a predictive scheduling.
          // Thi scheduling would be too complex.

          if((neigh_fn_mod51 == 0)  ||
             (neigh_fn_mod51 == 10) ||
             (neigh_fn_mod51 == 20) ||
             (neigh_fn_mod51 == 30) ||
             (neigh_fn_mod51 == 40))
          // It is time to start SBCNF51 task.
          {
            // SBCNF51 must be started immediately.
            l1s.task_status[SBCNF51].time_to_exec = 0;

            // Set active neighbor identifier.
            l1a_l1s_com.nsync.active_sbconf_id = 0;

            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[SBCNF51] = SEMAPHORE_RESET;
          }
          else
          {
            // SBCNF51 is not started.
            l1s.task_status[SBCNF51].time_to_exec = MAX_FN;
          }
        }
      }

      if((l1a_l1s_com.l1s_en_task[DDL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550
      //-------------------------
      // SDCCH DL task is ENABLED.
      //-------------------------
      {
        UWORD32 time_to_ddl;

        if(fn_in_report_mod51 <= sdcch_desc->dl_sdcch_position)
          time_to_ddl = sdcch_desc->dl_sdcch_position - fn_in_report_mod51;
        else
          time_to_ddl = 51 + sdcch_desc->dl_sdcch_position - fn_in_report_mod51;

        // Save scheduling result.
        l1s.task_status[DDL].time_to_exec = time_to_ddl;
      }

      if((l1a_l1s_com.l1s_en_task[DUL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550
      //-------------------------
      // SDCCH DUL task is ENABLED.
      //-------------------------
      {
        UWORD32 time_to_dul;

        if(fn_in_report_mod51 <= sdcch_desc->ul_sdcch_position)
          time_to_dul = sdcch_desc->ul_sdcch_position - fn_in_report_mod51;
        else
          time_to_dul = 51 + sdcch_desc->ul_sdcch_position - fn_in_report_mod51;

        // Save scheduling result.
        l1s.task_status[DUL].time_to_exec = time_to_dul;
      }

      if((l1a_l1s_com.l1s_en_task[ADL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550
      //----------------------------------
      // SACCH DL (SDCCH) task is ENABLED.
      //----------------------------------
      {
        UWORD32 time_to_adl;

        if(l1s.next_time.fn_in_report <= sdcch_desc->dl_sacch_position)
          time_to_adl = sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report;
        else
          time_to_adl = 102 + sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report;

        // Save scheduling result.
        l1s.task_status[ADL].time_to_exec = time_to_adl;
      }

      if((l1a_l1s_com.l1s_en_task[AUL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550
      //----------------------------------
      // SACCH UL (SDCCH) task is ENABLED.
      //----------------------------------
      {
        UWORD32 time_to_aul;

        if(l1s.next_time.fn_in_report <= sdcch_desc->ul_sacch_position)
          time_to_aul = sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report;
        else
          time_to_aul = MAX_FN + sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report;

        // Save scheduling result.
        l1s.task_status[AUL].time_to_exec = time_to_aul;
      }
    } // channel_type == SDCCH_4 or SDCCH_8
#endif

//================================================================
//==                   DEDICATED MODE TASKS                     ==
//==                   --------------------                     ==
//==    NEW NCELL MONITORING SCHEDULER for 12 Neighbors         ==
//================================================================
#if (L1_12NEIGH == 1)
  #if (L1_GPRS)
  // This machine works only for DEDICATED MODE and PACKET TRANSFER MODE
  // (Remark: PACKET TRANSFER MODE activated == PDTCH task activated)
  if((l1a_l1s_com.mode == DEDIC_MODE) || (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED))
  #else
  // This machine works only for DEDICATED MODE.
  if (l1a_l1s_com.mode == DEDIC_MODE)
  #endif
  {
    #define MF51       1
    #define MF26       2

    UWORD8                channel = 255;
    UWORD8                start_time;
    UWORD8                fn_in_report_mod51 = l1s.next_time.fn_in_report % 51;
    T_CHANNEL_DESCRIPTION *desc_ptr;
    T_SDCCH_DESC          *sdcch_desc;

    if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
    //---------------------------------------------
    // Dedicated mode tasks are enabled.
    //---------------------------------------------
    {
      // init desc_ptr
      desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;

      // No scheduling result for DEDIC task to avoid selection of this task.
      // -> l1s.task_status[DEDIC].time_to_exec stays equal to MAX_FN

      // DEDIC task requires to run L1S scheduler every frame
      l1a_l1s_com.time_to_next_l1s_task = 0;

      // Rem: this task is used in dedicated/TCH_H/F

      // MF51 tasks...
      //==============
      if((desc_ptr->channel_type == SDCCH_4) || (desc_ptr->channel_type == SDCCH_8))
      // SDCCH channel -> MF51 structure.
      {
        // init channel to MF51
        channel = MF51;

        // Save position of the monitoring area for SDCCH.
        if(desc_ptr->channel_type == SDCCH_8)
        {
          start_time =  SDCCH_DESC_NCOMB[desc_ptr->subchannel].mon_area_position;
          sdcch_desc = &(SDCCH_DESC_NCOMB[desc_ptr->subchannel]);
        }
        else
        {
          start_time =  SDCCH_DESC_COMB[desc_ptr->subchannel].mon_area_position;
          sdcch_desc = &(SDCCH_DESC_COMB[desc_ptr->subchannel]);
        }
      }
      // MF26 tasks...
      //==============
      else
        channel = MF26;
    } // End of "if DEDIC task"

    #if (L1_GPRS)
    else
    if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
      channel = MF26;
    #endif

    //============================================================
    // DEDIC  MODE - MF51 - NEIGHBOUR MONITORING tasks SCHEDULING
    //============================================================
    if (channel == MF51)
    {
      if (l1a_l1s_com.l1s_en_task[NSYNC] == TASK_ENABLED)
      //--------------------------------------------
      // Neigbour Cell Synchro task enabled for MF51
      //--------------------------------------------
      {
        if((l1s.task_status[FB51].current_status    == INACTIVE) &&
           (l1s.task_status[SB51].current_status    == INACTIVE) &&
           (l1s.task_status[SBCNF51].current_status == INACTIVE))
        {
          //Remarks:
          //--------
          // We do not allow entrance of a neigh FB or SB task if there
          // is already some neigh task (FB/SB or BCCH) running. This is
          // to avoid to cope with many abort cases (we cannot list them
          // easily).

          UWORD8  i;
          UWORD8  j;
          UWORD8  first_in_list=l1a_l1s_com.nsync.first_in_list ;


          WORD32  best_time_to_fb     = MAX_FN;
          WORD32  best_time_to_sb     = MAX_FN;
          WORD32  best_time_to_sbconf = MAX_FN;
          UWORD8  best_neigh_fb       = 255;
          UWORD8  best_neigh_sbconf   = 255;
          UWORD8  best_neigh_sb       = 255;

#if (L1_EOTD == 1)
          // Up to NBR_NEIGHBOURS + 1 (Serving Cell pending)
          for(j=first_in_list;j<(NBR_NEIGHBOURS+1+first_in_list);j++)
          {
            if (j>=NBR_NEIGHBOURS+1)
              i=j-NBR_NEIGHBOURS-1;
            else
              i=j;
#else
          // Up to NBR_NEIGHBOURS
          for(j=first_in_list;j<(NBR_NEIGHBOURS+first_in_list);j++)
          {
            if (j>=NBR_NEIGHBOURS)
              i=j-NBR_NEIGHBOURS;
            else
              i=j;
#endif // L1_EOTD

            // Consider only the "in use" locations from the "12 neigh. list".
            if(l1a_l1s_com.nsync.list[i].status == NSYNC_PENDING)
            {

              switch(l1a_l1s_com.nsync.list[i].timing_validity)
              {
                case 0: // No valid info is supplied: search FB with no a priori info.
              #if ((REL99 == 1) && (FF_RTD == 1))
                case 3: // approximate timing based on RTD is supplied
              #endif
                {
                  UWORD32  min_time_to_fb = MAX_FN;

                  if(l1s.actual_time.fn_in_report <= start_time)
                    min_time_to_fb = start_time - l1s.actual_time.fn_in_report;
                  else
                    min_time_to_fb = MAX_FN + start_time - l1s.actual_time.fn_in_report;

                  if(min_time_to_fb < (UWORD32)best_time_to_fb)
                  {
                    best_time_to_fb = min_time_to_fb;
                    best_neigh_fb = i;
                  }
                }
                break;


                case 1:  // Approximate timing is supplied: search FB with a priori info..
                {
                  UWORD32  min_time_to_fb = MAX_FN;
                  UWORD32  neigh_fn_mod51;

                  if((l1s.actual_time.fn_in_report >= start_time) &&
                     (l1s.actual_time.fn_in_report <  start_time + 11))
                  {
                    UWORD32  neigh_fn_mod51;

                    // Get neighbour cell FN % 51 and then % 10.
                    neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51;

                    // Attempt to read 2nd FB.
                    // Frame 7 is the position to read 2nd FB within MF51 (due to C/W/R and AGC)
                    if(neigh_fn_mod51 <= 7)
                    {
                      min_time_to_fb = 7 - neigh_fn_mod51;
                    }

                    // Attempt to read 3rd FB.
                    // Frame 17 is the position to read 3rd FB within MF51 (due to C/W/R and AGC)
                    else
                    if(neigh_fn_mod51 <= 17)
                    {
                      min_time_to_fb = 17 - neigh_fn_mod51;
                    }

                    // Attempt to read 4th FB.
                    // Frame 27 is the position to read 4th FB within MF51 (due to C/W/R and AGC)
                    else
                    if(neigh_fn_mod51 <= 27)
                    {
                      min_time_to_fb = 27 - neigh_fn_mod51;
                    }

                    // Attempt to read 5th FB.
                    // Frame 37 is the position to read 5th FB within MF51 (due to C/W/R and AGC)
                    else
                    if(neigh_fn_mod51 <= 37)
                    {
                      min_time_to_fb = 37 - neigh_fn_mod51;
                    }

                    // Attempt to read 1st FB.
                    // Frame 48 is the position to read 1st FB within MF51 (due to C/W/R and AGC)
                    else
                    if(neigh_fn_mod51 <= 48)
                    {
                      min_time_to_fb = 48 - neigh_fn_mod51;
                    }
                    // Attempt to read 2nd FB
                    // Special case: frame 49 and frame 50
                    else
                    {
                      min_time_to_fb = 50 - neigh_fn_mod51 + 8;
                    }

                    if(min_time_to_fb <(UWORD32) best_time_to_fb)
                    {
                      best_time_to_fb = min_time_to_fb;
                      best_neigh_fb   = i;
                    }
                  }
                }
                break;

                case 2:  // Accurate timing is supplied SBCONF: confirm SB.
                {
                  UWORD32 min_time_to_sbconf = MAX_FN;

                  if((l1s.actual_time.fn_in_report >= start_time) &&
                     (l1s.actual_time.fn_in_report <  start_time + 11))
                  {
                    UWORD32  neigh_fn_mod51;

                    // Get neighbour cell FN % 51 and then % 10.
                    neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51;

                    // SBCNF51 task is a special case: it is not using a predictive scheduling.
                    // Thi scheduling would be too complex.
                    if((neigh_fn_mod51 == 0)  ||
                       (neigh_fn_mod51 == 10) ||
                       (neigh_fn_mod51 == 20) ||
                       (neigh_fn_mod51 == 30) ||
                       (neigh_fn_mod51 == 40))
                    // It is time to start SBCNF51 task.
                    {
                      min_time_to_sbconf = 0;
                    }
                  }

                  if(min_time_to_sbconf <(UWORD32) best_time_to_sbconf)
                  {
                    best_time_to_sbconf = min_time_to_sbconf;
                    best_neigh_sbconf = i;
                  }
                }
                break;

             #if ((REL99 == 1) && ((FF_BHO == 1) || (FF_RTD == 1)))
                case SB_ACQUISITION_PHASE: // SB search following a FB search.
              #else
                case 3:  // SB search following a FB search.
              #endif
                {
                  UWORD32  min_time_to_sb = MAX_FN;

                  UWORD32  fn_sb51 = (l1a_l1s_com.nsync.list[i].fn_offset + 102)%MAX_FN;

                  fn_sb51 = l1a_l1s_com.nsync.list[i].fn_offset + 102;
                  if(fn_sb51 >= MAX_FN) fn_sb51 -= MAX_FN;

                  if(l1s.actual_time.fn <= fn_sb51)
                    min_time_to_sb = fn_sb51 - l1s.actual_time.fn;
                  else
                    min_time_to_sb = MAX_FN + fn_sb51 - l1s.actual_time.fn;

                  if(min_time_to_sb <(UWORD32) best_time_to_sb)
                  {
                    best_time_to_sb = min_time_to_sb;
                    best_neigh_sb = i;
                  }
                }
                break;
              } // End of "switch"
            } // End of "if PENDING"
          } // End of "for"

          if(best_neigh_fb != 255)  // for FB ACQUISITION or CONFIRMATION
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_fb_id = best_neigh_fb;
            // Save scheduling result.
            l1s.task_status[FB51].time_to_exec = best_time_to_fb;
            // Enable FB51 task
            l1a_l1s_com.l1s_en_task[FB51] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[FB51] = SEMAPHORE_RESET;
          }

          if(best_neigh_sbconf != 255) // for SB CONFIRMATION
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_sbconf_id = best_neigh_sbconf;
            // Save scheduling result.
            l1s.task_status[SBCNF51].time_to_exec = 0;
            // Enable SBCNF51 task
            l1a_l1s_com.l1s_en_task[SBCNF51] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[SBCNF51] = SEMAPHORE_RESET;
          }

          if(best_neigh_sb != 255) // for SB ACQUISITION
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_sb_id = best_neigh_sb;
             // Save scheduling result.
            l1s.task_status[SB51].time_to_exec = best_time_to_sb;
            // Enable SB2 task
            l1a_l1s_com.l1s_en_task[SB51] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[SB51] = SEMAPHORE_RESET;
          }

        } // End of "if / current_status"
      } // End of "if / NSYNC"

      if (l1a_l1s_com.l1s_en_task[DDL] == TASK_ENABLED)
      //-------------------------
      // SDCCH DL task is ENABLED.
      //-------------------------
      {
        UWORD32 time_to_ddl;

        if(fn_in_report_mod51 <= ( UWORD8)sdcch_desc->dl_sdcch_position)
          time_to_ddl = sdcch_desc->dl_sdcch_position - fn_in_report_mod51;
        else
          time_to_ddl = 51 + sdcch_desc->dl_sdcch_position - fn_in_report_mod51;

        // Save scheduling result.
        l1s.task_status[DDL].time_to_exec = time_to_ddl;
      }

      if (l1a_l1s_com.l1s_en_task[DUL] == TASK_ENABLED)
      //-------------------------
      // SDCCH DUL task is ENABLED.
      //-------------------------
      {
        UWORD32 time_to_dul;

        if(fn_in_report_mod51 <= sdcch_desc->ul_sdcch_position)
          time_to_dul = sdcch_desc->ul_sdcch_position - fn_in_report_mod51;
        else
          time_to_dul = 51 + sdcch_desc->ul_sdcch_position - fn_in_report_mod51;

        // Save scheduling result.
        l1s.task_status[DUL].time_to_exec = time_to_dul;
      }

      if (l1a_l1s_com.l1s_en_task[ADL] == TASK_ENABLED)
      //----------------------------------
      // SACCH DL (SDCCH) task is ENABLED.
      //----------------------------------
      {
        UWORD32 time_to_adl;

        if(l1s.next_time.fn_in_report <= sdcch_desc->dl_sacch_position)
          time_to_adl = sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report;
        else
          time_to_adl = 102 + sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report;

        // Save scheduling result.
        l1s.task_status[ADL].time_to_exec = time_to_adl;
      }

      if (l1a_l1s_com.l1s_en_task[AUL] == TASK_ENABLED)
      //----------------------------------
      // SACCH UL (SDCCH) task is ENABLED.
      //----------------------------------
      {
        UWORD32 time_to_aul;

        if(l1s.next_time.fn_in_report <= sdcch_desc->ul_sacch_position)
          time_to_aul = sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report;
        else
          time_to_aul = MAX_FN + sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report;

        // Save scheduling result.
        l1s.task_status[AUL].time_to_exec = time_to_aul;
      }

    } // End of "if MF51"

    //==================================================================
    // DEDIC/PACKET MODE - MF26 - NEIGHBOUR MONITORING tasks SCHEDULING
    //==================================================================
    if (channel == MF26)
    {
      #if L1_EDA
        UWORD8 enter_nsync_task = TRUE;

        //Initialize FB/SB activity detection flag
        if((l1s.actual_time.t2 < 20) || (l1s.actual_time.t2 == 25))
        {
          l1ps_macs_com.fb_sb_task_enabled = FALSE;
        }
      #endif
      if (l1a_l1s_com.l1s_en_task[NSYNC] == TASK_ENABLED)
      //-----------------------------------------------------------
      // Neigbour Cell Synchro task enabled for DEDIC TCH or PACKET
      //-----------------------------------------------------------
      {
        T_CHANNEL_DESCRIPTION *desc_ptr;

        if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
        {
          desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;
        }

        if((l1s.task_status[FB26].current_status    == INACTIVE) &&
           (l1s.task_status[SB26].current_status    == INACTIVE) &&
           (l1s.task_status[SBCNF26].current_status == INACTIVE))
        {
          //Remarks:
          //--------
          // We do not allow entrance of a neigh FB or SB task if there
          // is already some neigh task (FB/SB or BCCH) running. This is
          // to avoid to cope with many abort cases (we cannot list them
          // easily).
          UWORD8  i;
          UWORD8  j;
          UWORD8  first_in_list=l1a_l1s_com.nsync.first_in_list ;


          WORD32  best_time_to_fb     = MAX_FN;
          WORD32  best_time_to_sbconf = MAX_FN;
          WORD32  best_time_to_fbconf = MAX_FN;
          WORD32  best_time_to_sb     = MAX_FN;
          UWORD8  best_neigh_fb       = 255;
          UWORD8  best_neigh_sbconf   = 255;
          UWORD8  best_neigh_fbconf   = 255;
          UWORD8  best_neigh_sb       = 255;
          #if ((REL99 == 1) && (FF_BHO == 1))
            UWORD8 fb26_position ;
          #endif

#if (L1_EOTD == 1)
          // Up to NBR_NEIGHBOURS + 1 (Serving Cell pending)
          for(j=first_in_list;j<(NBR_NEIGHBOURS+1+first_in_list);j++)
          {
            if (j>=NBR_NEIGHBOURS+1)
              i=j-NBR_NEIGHBOURS-1;
            else
              i=j;
#else
          // Up to NBR_NEIGHBOURS
          for(j=first_in_list;j<(NBR_NEIGHBOURS+first_in_list);j++)
          {
            if (j>=NBR_NEIGHBOURS)
              i=j-NBR_NEIGHBOURS;
            else
              i=j;
#endif // L1_EOTD

            // Consider only the "in use" locations from the "NBR_NEIGHBOURS neigh. list".
            if(l1a_l1s_com.nsync.list[i].status == NSYNC_PENDING)
            {

              switch(l1a_l1s_com.nsync.list[i].timing_validity)
              {
                case 0: // No valid info is supplied: search FB with no a priori info.
                {
                  UWORD32  min_time_to_fb = MAX_FN;

                  if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
                  //---------------------------------------------
                  // Dedicated mode tasks are enabled.
                  //---------------------------------------------
                  {
                    // Rem: this task is used in dedicated/TCH_H/F
                    // No Scheduling result for FB26 task to avoid selection of this task.
                    if(desc_ptr->channel_type == TCH_H)
                    {
                      UWORD8 normalised_fn_mod26 = ((l1s.actual_time.fn_in_report) - desc_ptr->subchannel ) % 26;

                      if(normalised_fn_mod26 <= 22)
                        min_time_to_fb = 22 - normalised_fn_mod26;
                      else
                        min_time_to_fb = 26+ 22 - normalised_fn_mod26;
                    }
                    else
                    if(desc_ptr->channel_type == TCH_F)
                    {
                      UWORD8 normalised_fn_mod26 = l1s.actual_time.fn_in_report % 26;

                      if(normalised_fn_mod26 <= 23)
                        min_time_to_fb = 23 - normalised_fn_mod26;
                      else
                        min_time_to_fb = 26 + 23 - normalised_fn_mod26;
                    }
                  } // end DEDIC task
                  #if L1_GPRS
                  else
                  if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
                  //---------------------------------------------
                  // Packet Transfer mode task is enabled.
                  //---------------------------------------------
                  {
                    if(l1s.actual_time.t2 <= 23)
                      min_time_to_fb = 23 - l1s.actual_time.t2;
                    else
                      min_time_to_fb = 26 + 23 - l1s.actual_time.t2;
                  }
                  #endif

                  if(min_time_to_fb < ( UWORD32)best_time_to_fb)
                  {
                    best_time_to_fb = min_time_to_fb;
                    best_neigh_fb = i;
                  }
                }
                break;

                case 1:  // Approximate timing is supplied: search FB with a priori info..
              #if ((REL99 == 1) && (FF_RTD == 1))
                case 3:  // approximate timing based on RTD is supplied
              #endif
                {
                  BOOL check_fbcnf26 = 0;
                  UWORD32 min_time_to_fbconf = MAX_FN;

                  if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
                  //---------------------------------------------
                  // Dedicated mode tasks are enabled.
                  //---------------------------------------------
                  {
                    UWORD8                 normalised_fn_mod26;


                    normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26;

                    if(((normalised_fn_mod26 == 22) && (desc_ptr->channel_type == TCH_H)) ||
                      (((l1s.actual_time.fn_in_report % 26) == 23) && (desc_ptr->channel_type == TCH_F)))
                    // Monitoring area control frame is reached...
                    {
                      check_fbcnf26 = 1;
                    }
                  }  // end DEDIC task
                  #if L1_GPRS
                  else
                  if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
                  //---------------------------------------------
                  // Packet Transfer mode task is enabled.
                  //---------------------------------------------
                  {
                    if(l1s.actual_time.t2 == 23)
                    // Monitoring area control frame is reached...
                    {
                      check_fbcnf26 = 1;
                    }
                  }
                  #endif

                  if(check_fbcnf26)
                  // FBCNF26 must be checked.
                  {
                    UWORD32 next_neigh_fn_mod51;
		  #if ((REL99 == 1) && (FF_RTD == 1))
		    UWORD32 next_neigh_time_alignmt;
		  #endif


                    // Get neighbor domain frame number %51 for frame 24.
                    next_neigh_fn_mod51 = (l1s.next_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51;

                    if( ((next_neigh_fn_mod51 % 10) == 0)&&(next_neigh_fn_mod51 != 50) )
                    // FB26 rx window starts in the frame 24...
                    { // time_alignt has been advanced from 23 bits
                      UWORD32  u32Temp;
                      // and FB algo. needs 24 bits ==> miss 1 bit = 4 qbits
                      u32Temp =  l1_config.params.fb26_anchoring_time ;
                      if(l1a_l1s_com.nsync.list[i].time_alignmt >= u32Temp +4 )
                      // FB feet in the search slot...
                      {
                        min_time_to_fbconf = 0;
                        l1a_l1s_com.nsync.list[i].sb26_offset   = 0;
                      }
                    }
                    else
                    if((next_neigh_fn_mod51 == 50)||
                       (next_neigh_fn_mod51 == 9) ||
                       (next_neigh_fn_mod51 == 19) ||
                       (next_neigh_fn_mod51 == 29) ||
                       (next_neigh_fn_mod51 == 39))
                    // FB26 rx window starts in the frame 25...
                    {
                      UWORD16 fb26, sb26;
                      UWORD32 time;
			 UWORD32  u32temp ;
                      time = ((l1_config.params.fb26_anchoring_time  +FB26_ACQUIS_DURATION
                               -SB_ACQUIS_DURATION  +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE);

                      fb26 = FB26_ACQUIS_DURATION;
                      sb26 = SB_ACQUIS_DURATION;

		       u32temp = ((l1_config.params.fb26_anchoring_time
                                                                    +FB26_ACQUIS_DURATION
                                                                    -SB_ACQUIS_DURATION
                                                                    +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE);


			  if(l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32) u32temp )

			   /*

                      if(l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32)((l1_config.params.fb26_anchoring_time
                                                                    +FB26_ACQUIS_DURATION
                                                                    -SB_ACQUIS_DURATION
                                                                    +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE)) */
                      // FB feet in the search slot...
                      // Set FBCNF26 as PENDING to trigger the l1s_merge_manager() to install it
                      // in MFTAB.
                      {
                        min_time_to_fbconf = 0;
                        l1a_l1s_com.nsync.list[i].sb26_offset   = 1;
                      }
                    }

                  #if ((REL99 == 1) && (FF_RTD == 1)) // RTD feature

                    if ((l1a_l1s_com.nsync.list[i].timing_validity == 3) && (min_time_to_fbconf == 0))
                    {
                    #if !L1_EGPRS
                      next_neigh_time_alignmt = l1a_l1s_com.nsync.list[i].time_alignmt;
                    #endif

                      if (((next_neigh_fn_mod51 % 10) == 0) && (next_neigh_fn_mod51 != 50))
                      {   // for frame 0, 10, 20, 30, 40
                        if (l1a_l1s_com.nsync.list[i].fb26_position == 255)  // is it the first attempt?
                        {
                          if ((next_neigh_time_alignmt - RTD_LEFT_MARGIN) < l1_config.params.fb26_anchoring_time + 4)

                            fb26_position = 0 ; // it means first try in the multiframe 51 at position = 0,10,20,30,40
                          else
                            fb26_position = 255 ;
                        }
                        else
                        {     // the previous one must be at the other side position
                          if (l1a_l1s_com.nsync.list[i].fb26_position == 1)
                          {
                            fb26_position = l1a_l1s_com.nsync.list[i].fb26_position ;
                          }
                          else
                          {
                            min_time_to_fbconf = MAX_FN;  // discard this position which has been already tried
                          }
                        }
                      }
                      else
                      {     // for frame 9, 19, 29, 39, 50
                        if (l1a_l1s_com.nsync.list[i].fb26_position == 255)  // is it the first attempt?
                        {
                          if ((next_neigh_time_alignmt + RTD_RIGHT_MARGIN) > ((l1_config.params.fb26_anchoring_time
                                                                             + FB26_ACQUIS_DURATION
                                                                             - SB_ACQUIS_DURATION
                                                                             + TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE))
                            fb26_position = 1 ; // it means first try in the multiframe 51 at position = 9,19,29,39,50
                          else
                            fb26_position = 255 ;
                        }
                        else
                        {      // the previous one must be at the other side position
                          if (l1a_l1s_com.nsync.list[i].fb26_position == 0)
                          {
                            fb26_position = l1a_l1s_com.nsync.list[i].fb26_position ;
                          }
                          else
                          {
                            min_time_to_fbconf = MAX_FN;  // discard this position which has been already tried
                          }
                        }
                      }
                    }
                  #endif // L1_R99 RTD feature
                    if(min_time_to_fbconf == 0)
                    {
                      // Fixed BUG2963
                      best_time_to_fbconf = 0;
                      best_neigh_fbconf   = i;
                    }
                  }
                }
                break;

                case 2:  // Accurate timing is supplied SBCONF: confirm SB.
                {
                  BOOL check_sbcnf26 = 0;
                  UWORD32 min_time_to_sbconf = MAX_FN;

                  if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
                  //---------------------------------------------
                  // Dedicated mode tasks are enabled.
                  //---------------------------------------------
                  {
                    UWORD8                 normalised_fn_mod26;

                    normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26;

                    if(((normalised_fn_mod26 == 22) && (desc_ptr->channel_type == TCH_H)) ||
                      (((l1s.actual_time.fn_in_report % 26) == 23) && (desc_ptr->channel_type == TCH_F)))
                    // Monitoring area control frame is reached...
                    {
                      check_sbcnf26 = 1;
                    }
                  }  // end DEDIC task
                  #if L1_GPRS
                  else
                  if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
                  //---------------------------------------------
                  // Packet Transfer mode task is enabled.
                  //---------------------------------------------
                  {
                    if(l1s.actual_time.t2 == 23)
                    // Monitoring area control frame is reached...
                    {
                      check_sbcnf26 = 1;
                    }
                  }
                  #endif

                  if(check_sbcnf26)
                  // SBCNF26 must be checked.
                  {
                    UWORD32 next_neigh_fn_mod51;
		      UWORD32 u32Temp;
		      UWORD32 u32Temp1;

                    // Get neighbor domain frame number %51 for frame 24.
                    next_neigh_fn_mod51 = (l1s.next_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51;

                    // Cq19539: the RF SB26 acquisition window shall be scheduled within the RF FB26 acquisition window range
                    // So the time alignment of the neighbour  (+ TPU_CLOCK_RANGE if needed) shall be within the range of
                    // [ fb26_anchoring_time , fb26_anchoring_time+FB26_ACQUIS_DURATION-SB_ACQUIS_DURATION+TPU_CLOCK_RANGE [
                    // (During an SB acquisition after a FB aquisition, it can't be outside of this range
                    // because of the clipping to MAX_TOA_FOR_SB into l1s_read_fb).
                    // If a SB26 burst acquisition window is started outside of this range, the RX of the NB
                    // in the next frame will be delayed by one frame due to the delay needed by the TPU
                    // to execute offset, leave TPU sleep mode, switch the TPU page, and restore the synchro.
                    // Such a delay is taken into account within the computation of fb26_anchoring_time.
                    // Therefore, a time alignement outside this range must be clipped to fb26_anchoring_time
                    // and SB will be scheduled at the end of the frame 24.

		     u32Temp1  = l1_config.params.fb26_anchoring_time ;
                   u32Temp= ((l1_config.params.fb26_anchoring_time
                                                                    +FB26_ACQUIS_DURATION
                                                                    -SB_ACQUIS_DURATION
                                                                    +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE );

		if (( l1a_l1s_com.nsync.list[i].time_alignmt >= u32Temp)
                       && ( l1a_l1s_com.nsync.list[i].time_alignmt <u32Temp1 ))


			/*
		     if (( l1a_l1s_com.nsync.list[i].time_alignmt >= (UWORD32)(l1_config.params.fb26_anchoring_time
                                                                    +FB26_ACQUIS_DURATION
                                                                    -SB_ACQUIS_DURATION
                                                                    +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE )
                       && ( l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32)l1_config.params.fb26_anchoring_time ))*/
                    {
                      // clip time alignment because it's outside of allowed range
                      l1a_l1s_com.nsync.list[i].time_alignmt = l1_config.params.fb26_anchoring_time;
                    }

                    if((next_neigh_fn_mod51 == 0)  ||
                       (next_neigh_fn_mod51 == 10) ||
                       (next_neigh_fn_mod51 == 20) ||
                       (next_neigh_fn_mod51 == 30) ||
                       (next_neigh_fn_mod51 == 40))
                    // check if SB26 rx window can be started in the frame 25...
                    {
                     u32Temp= ((l1_config.params.fb26_anchoring_time
                                                                    +FB26_ACQUIS_DURATION
                                                                    -SB_ACQUIS_DURATION
                                                                    +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE);
			 if (l1a_l1s_com.nsync.list[i].time_alignmt < u32Temp)

                     /* if(l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32)(l1_config.params.fb26_anchoring_time
                                                                    +FB26_ACQUIS_DURATION
                                                                    -SB_ACQUIS_DURATION
                                                                    +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE)*/
                      // SB feet in the search slot...
                      // Set sb26_offset to 1 to add a NOP in TPU scenario in order to reach frame 25
                      {
                        min_time_to_sbconf = 0;
                        l1a_l1s_com.nsync.list[i].sb26_offset   = 1;
                      }
                    }
                    else
                    if((next_neigh_fn_mod51 % 10) == 1)
                    // ... otherwise SB26 rx window starts at the end of the frame 24.
                    {
                    UWORD32 u32Temp;
		      u32Temp = 	l1_config.params.fb26_anchoring_time;
			if(l1a_l1s_com.nsync.list[i].time_alignmt >= u32Temp )
                      /*if(l1a_l1s_com.nsync.list[i].time_alignmt >= (UWORD32)l1_config.params.fb26_anchoring_time)*/
                      // SB feet in the search slot...
                      {
                        min_time_to_sbconf = 0;
                        l1a_l1s_com.nsync.list[i].sb26_offset   = 0;
                      }
                    }

                    if(min_time_to_sbconf == 0)
                    {
                      best_time_to_sbconf = 0;
                      best_neigh_sbconf = i;
                    }
                  }
                }
                break;

              #if ((REL99 == 1) && ((FF_BHO == 1) || (FF_RTD == 1)))
                case SB_ACQUISITION_PHASE:  // SB search following a FB search.
              #else
                case 3:  // SB search following a FB search.
              #endif
                {
                  UWORD32  min_time_to_sb = MAX_FN;
                  UWORD8 sb26_attempt = l1a_l1s_com.nsync.list[i].sb26_attempt;
				  UWORD32 u32Temp;
                  // Monitoring area starting frame is reached...
                  min_time_to_sb = l1a_l1s_com.nsync.list[i].fn_offset - l1s.actual_time.fn;

                  if ((WORD32)min_time_to_sb < 0)
                  //the SB following the FB was missed because of an higher priority task
                  //next SB is 26*9 frames later or it is 26*9+52 frames later
                  //Fix for BUG2864 and BUG2842
                  {
                     if (sb26_attempt == 1)
                        min_time_to_sb += 26*9;
                     else if (sb26_attempt == 2)
                        min_time_to_sb += 26*9+52;
                  else
                        min_time_to_sb += MAX_FN; //shall never happen
                  }

                  if (min_time_to_sb == 0)
                  {
                      l1a_l1s_com.nsync.list[i].sb26_attempt++;
                  }

		   u32Temp      =  best_time_to_sb;
                  if((min_time_to_sb < 26) && (min_time_to_sb < u32Temp ))
                  {
                    best_time_to_sb = min_time_to_sb;
                    best_neigh_sb = i;
                  }
                }
                break;

              } // End of "switch"
            } // End of "if PENDING"
          } // End of "for"

          #if L1_EDA
            if((l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) && (l1ps_macs_com.fb_sb_task_detect))
            {
              //Flag used to cope with worst case mixing FB/SB task and allocation for MS class 12
              if(l1s.actual_time.t2 == 20)
              {
                l1ps_macs_com.fb_sb_task_enabled = TRUE;
              }
              else if (l1s.actual_time.t2 > 20)
                enter_nsync_task = l1ps_macs_com.fb_sb_task_enabled;
            }

            if (!(l1ps_macs_com.fb_sb_task_detect) || enter_nsync_task)
            {
          #endif
          // Remarks:
          //--------
          // While FB26/SB26/SBCNF26 are set as PENDING to trigger the
          // l1s_merge_manager() to install it , we have to select the
          // highest priority task HERE.

          if(best_neigh_sb != 255)
          // SB26 is higher priority while it can not be delayed without
          // performing again an FB26 search !
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_sb_id = best_neigh_sb;
            // set SB26 as pending to trigger the l1s_merge_manager()
            // to install it in MFTAB
            if (best_time_to_sb == 0)
              l1s.task_status[SB26].new_status = PENDING;
            // Enable SB2 task
            l1a_l1s_com.l1s_en_task[SB26] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[SB26] = SEMAPHORE_RESET;
          }

          else
          if(best_neigh_fbconf != 255)
          // FB CONFIRMATION is medium priority due to its short duration
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_fb_id = best_neigh_fbconf;
            // set FB as pending to trigger the l1s_merge_manager()
            // to install it in MFTAB
            if (best_time_to_fbconf == 0)
              l1s.task_status[FB26].new_status = PENDING;
            // Enable FB task
            l1a_l1s_com.l1s_en_task[FB26] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[FB26] = SEMAPHORE_RESET;
                #if ((REL99 == 1) && (FF_RTD == 1)) // RTD feature
                  if (l1a_l1s_com.nsync.list[best_neigh_fbconf].timing_validity == 3)
                  {   // check if we are not at the border of the window so FB must be detected inside the current window
                    if (fb26_position == 255)
                      l1a_l1s_com.nsync.list[best_neigh_fbconf].nb_fb_attempt = 1;
                    else
                      l1a_l1s_com.nsync.list[best_neigh_fbconf].fb26_position = fb26_position;
                  }
                #endif // L1_R99
          }

          else
          if(best_neigh_sbconf != 255)
          // SBCNF26 is medium priority due to its short duration
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_sbconf_id = best_neigh_sbconf;
            // set SBCNF26 as pending to trigger the l1s_merge_manager()
            // to install it in MFTAB
            if (best_time_to_sbconf == 0)
              l1s.task_status[SBCNF26].new_status = PENDING;
            // Enable SBCNF26 task
            l1a_l1s_com.l1s_en_task[SBCNF26] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[SBCNF26] = SEMAPHORE_RESET;
          }

          else
          if(best_neigh_fb != 255)
          // FB26 is low priority due to its long duration
          {
            // Save active neighbour id.
            l1a_l1s_com.nsync.active_fb_id = best_neigh_fb;
            // set FB26 as pending to trigger the l1s_merge_manager()
            // to install it in MFTAB
            if (best_time_to_fb == 0)
              l1s.task_status[FB26].new_status = PENDING;
            // Enable FB26 task
            l1a_l1s_com.l1s_en_task[FB26] = TASK_ENABLED;
            // Clear param. synchro. semaphore.
            l1a_l1s_com.task_param[FB26] = SEMAPHORE_RESET;
          }
          #if L1_EDA
            }
          #endif

        } // End of "if / current_status"
      } // End of " if NSYNC"

    } // End of "if channel is MF26"

    if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED)
   {
#endif

    if(l1a_l1s_com.l1s_en_task[TCHA] == TASK_ENABLED)
    //----------------------------------
    // SACCH (TCH) task is ENABLED.
    //----------------------------------
    {
      UWORD32 time_to_tcha;

      if(l1s.next_time.fn_in_report <= 12)
        time_to_tcha = 12 - l1s.next_time.fn_in_report;
      else
      if(l1s.next_time.fn_in_report <= 38)
        time_to_tcha = 38 - l1s.next_time.fn_in_report;
      else
      if(l1s.next_time.fn_in_report <= 64)
        time_to_tcha = 64 - l1s.next_time.fn_in_report;
      else
      if(l1s.next_time.fn_in_report <= 90)
        time_to_tcha = 90 - l1s.next_time.fn_in_report;
      else
        time_to_tcha = 104 + 12 - l1s.next_time.fn_in_report;

      // Save scheduling result.
      l1s.task_status[TCHA].time_to_exec = time_to_tcha;
    }

    if(l1a_l1s_com.l1s_en_task[TCHTF] == TASK_ENABLED)
    //----------------------------------
    // TCHTF task is ENABLED.
    //----------------------------------
    {
      UWORD32 time_to_tchf;

      #if TESTMODE
        // if UL-only, ONLY schedule TCHA task, and schedule it every frame
        if (l1_config.TestMode && (l1_config.tmode.rf_params.down_up == TMODE_UPLINK))
        {
          // Save scheduling result: force TCHA task over TCHTF
          l1s.task_status[TCHA].time_to_exec = 0;
          l1s.task_status[TCHTF].time_to_exec = 0xff;
        }
        else
        {
          if(l1s.next_time.fn_mod13 == 12)
            time_to_tchf = 1;
          else
            time_to_tchf = 0;

          // Save scheduling result.
          l1s.task_status[TCHTF].time_to_exec = time_to_tchf;
        }
      #else
        if(l1s.next_time.fn_mod13 == 12)
          time_to_tchf = 1;
        else
          time_to_tchf = 0;

        // Save scheduling result.
        l1s.task_status[TCHTF].time_to_exec = time_to_tchf;
      #endif
    }

    if(l1a_l1s_com.l1s_en_task[TCHTH] == TASK_ENABLED)
    //----------------------------------
    // TCHTF task is ENABLED.
    //----------------------------------
    {
      UWORD32 time_to_tchh;
      UWORD32 time_to_tchd;
      WORD32  normalised_fn_mod13;
      UWORD8 subchannel;
      subchannel = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->subchannel;
      normalised_fn_mod13 = l1s.next_time.fn_mod13 -
                              subchannel;

      if(normalised_fn_mod13 < 0) normalised_fn_mod13 += 13;

      if((normalised_fn_mod13 == 0) || (normalised_fn_mod13 == 2)  ||
         (normalised_fn_mod13 == 4) || (normalised_fn_mod13 == 6)  ||
         (normalised_fn_mod13 == 8) || (normalised_fn_mod13 == 10))
      {
        time_to_tchh = 0;
        time_to_tchd = 1;
      }
      else
      {
        time_to_tchd = 0;
        /*if (l1s.next_time.fn_mod13 == 12)
        {
          if (subchannel == 0)
          {
            time_to_tchd = 2;
          }
          else
          {
            time_to_tchd = 1;
          }
        }*/
        if(normalised_fn_mod13 == 11)
          time_to_tchh = 2;
        else
          time_to_tchh = 1;
      }

      // Save scheduling result.
      l1s.task_status[TCHTH].time_to_exec = time_to_tchh;
      l1s.task_status[TCHD].time_to_exec  = time_to_tchd;
    }

#if (L1_12NEIGH == 1)
  }
#endif

  } // End of if(DEDIC is ENABLED)

#if L1_GPRS
  //==========================================================
  //==             PACKET ACCESS                            ==
  //==========================================================
  // Either fixed block allocation or USF method may be
  // used to determine possible PRACH slots. If fixed blocks
  // are allocated they take precedence over USF decoding
  // When PRACH slot is determined by fixed allocation this
  // is marked by fix_alloc_flag=TRUE, and USF method is not
  // executed afterwards.
  {
    if(l1a_l1s_com.l1s_en_task[PRACH] == TASK_ENABLED)
    // PRACH task enabled
    {
      BOOL fix_alloc_flag = FALSE;

      #if FF_L1_IT_DSP_USF
        // No USF uncertainty by default i.e. if fixed allocation mode is used
        // or dynamic on TDMA 1, 2 or 3 of a block.
        l1ps_macs_com.usf_status = USF_AVAILABLE;
      #endif // FF_L1_IT_DSP_USF

      if(l1pa_l1ps_com.pra_info.prach_alloc != DYN_PRACH_ALLOC)
      // FIXED BLOCK ALLOCATION
      {
        UWORD8 fn_mod_52;
        UWORD8 i, start_time =0;//omaps00090550

        fn_mod_52 = l1s.next_time.fn_mod52;  // start times for control phase

        for (i=0; i<l1pa_l1ps_com.pra_info.bs_prach_blks; i++)
        {
          // Block boundary for PRACH
          start_time = ORDERED_BLOCK_START_TIME[i];

          if ((fn_mod_52 == start_time)     ||
              (fn_mod_52 == start_time + 1) ||
              (fn_mod_52 == start_time + 2) ||
              (fn_mod_52 == start_time + 3))
          {
            fix_alloc_flag = TRUE;

            l1pa_l1ps_com.pra_info.rand --;

            if ( l1pa_l1ps_com.pra_info.rand == 0)
            {
              l1s.task_status[PRACH].new_status  = PENDING;
              l1pa_l1ps_com.pra_info.prach_alloc = FIX_PRACH_ALLOC;
            }
            break;
          }
        } // end for
      }

      // either FIXED blocks or USF method
      if(!fix_alloc_flag)
      // DYNAMIC MODE WITH USF DECODING
      {
        API d_usf_updated;
        static API static_usf_state;  // USF read on first frame of a block, valid for whole block
        UWORD8 actual_fn_mod13_mod4 = l1s.actual_time.fn_mod13_mod4;
        UWORD8 next_fn_mod13_mod4   = l1s.next_time.fn_mod13_mod4;

        // Flag used for correcting l1pa_l1ps_com.pra_info.rand in case it
        // has been decremented although USF was bad
        static BOOL static_usf_invalid_flag = FALSE;

        // Get USF from DSP => for PRACH only TS0 is needed
        // Read frame 3 of each block to anticipate USF state for first frame of next block
        // Do not read USF on frames that preceed idle frames
        if ((next_fn_mod13_mod4 == 0) && (l1s.next_time.fn_mod13 != 12))
        {
          d_usf_updated = ((l1ps_dsp_com.pdsp_ndb_ptr->d_usf_updated_gprs >> ((7-0)*2)) & 0x0003);

          if (d_usf_updated == USF_INVALID)
          // USF decoding on block boundary
          // if USF invalid => decision to send PRACH is left to DSP
          {
             static_usf_invalid_flag = TRUE;
             l1pa_l1ps_com.pra_info.rand --;

             if ( l1pa_l1ps_com.pra_info.rand == 0)
             {
               l1s.task_status[PRACH].new_status = PENDING;

               #if FF_L1_IT_DSP_USF
                 // Dynamic allocation in use, random number of opportunities
                 // elapsed and USF status is not available. Therefore we have
                 // to rely on DSP USF interrupt.
                 l1ps_macs_com.usf_status = USF_AWAITED;
               #endif // FF_L1_IT_DSP_USF
             }
          }
          static_usf_state = d_usf_updated;

        }
        // Update USF state on the first frame of each block
        else if (actual_fn_mod13_mod4 == 0)
        {
          static_usf_state = ((l1ps_dsp_com.pdsp_ndb_ptr->d_usf_updated_gprs >> ((7-0)*2)) & 0x0003);

          if ((static_usf_state != USF_GOOD) && (static_usf_invalid_flag == TRUE))
          // rand was decremented in previous frame but USF is bad => compensate
          {
            l1pa_l1ps_com.pra_info.rand ++;
            static_usf_invalid_flag = FALSE;
          }
        }

        if ((static_usf_state == USF_GOOD) && (l1s.next_time.fn_mod13 != 12))
        {
          static_usf_invalid_flag = FALSE;

          l1pa_l1ps_com.pra_info.rand --;

          if ( l1pa_l1ps_com.pra_info.rand == 0)
          {
            l1s.task_status[PRACH].new_status = PENDING;
          }
        }
      }
    }
  }

  //=====================================================
  //==             PACKET POLLING                      ==
  //=====================================================
  {
    if(l1a_l1s_com.l1s_en_task[POLL] == TASK_ENABLED)
    // POLL task enabled (packet queuing notification
    {
      if(l1s.task_status[POLL].current_status == INACTIVE)
      {

        UWORD32 time_to_poll;

        time_to_poll = ( (l1pa_l1ps_com.poll_info.fn) - (l1s.next_time.fn % 42432) + 2*42432) % 42432;

        if((time_to_poll >= 32024) && (time_to_poll <= 42431))
        {
          xSignalHeaderRec *msg;

          // Poll response occurence passed...

          // Task disabled to avoid a new transmission of L1P_POLL_DONE in following
          // TDMA if L1A isn't executed
          // This isn't a problem because the sending of two simultaneous POLL is forbidden
          l1a_l1s_com.l1s_en_task[POLL] = TASK_DISABLED;

          // send an error message to L1A
          msg = os_alloc_sig(sizeof(T_MPHP_POLLING_IND));
          DEBUGMSG(status,NU_ALLOC_ERR)

          ((T_MPHP_POLLING_IND *)(msg->SigP))->fn = 0xFFFFFFFF; // Invalid (TO BE CONFIRMED)
          msg->SignalCode = L1P_POLL_DONE;

          os_send_sig(msg, L1C1_QUEUE);
          DEBUGMSG(status,NU_SEND_QUEUE_ERR)
        }
        else if (time_to_poll == 0)
        {
          // Poll reponse occurs on next FN
          l1s.task_status[POLL].new_status = PENDING;
          l1s.task_status[POLL].time_to_exec = time_to_poll;
        }
        else
        {
          // Update scheduling result
          l1s.task_status[POLL].time_to_exec = time_to_poll;
        }
      }
    }
  }

  //================================================================
  //==                   PACKET TASKS                             ==
  //==                   ------------                             ==
  //================================================================
  {
    if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
    //-------------------------
    // PDTCH task is ENABLED.
    //-------------------------
    {
      UWORD8 time_to_pdtch;

      // PDTCH task begins on a block boundary (fn_mod13 = 0, 4, 8)
      if (l1s.next_time.fn_mod13 == 0)
        time_to_pdtch = 0;
      else
      if (l1s.next_time.fn_mod13 <= 4)
        time_to_pdtch = 4 - l1s.next_time.fn_mod13;
      else
      if (l1s.next_time.fn_mod13 <= 8)
        time_to_pdtch = 8 - l1s.next_time.fn_mod13;
      else
        time_to_pdtch = 13 - l1s.next_time.fn_mod13;

      // Save scheduling result.
      l1s.task_status[PDTCH].time_to_exec  = time_to_pdtch;
    }

    if(l1a_l1s_com.l1s_en_task[PTCCH] == TASK_ENABLED)
    //-------------------------
    // PTCCH task is ENABLED.
    //-------------------------
    {
      #define  TA_INDEX  l1pa_l1ps_com.transfer.aset->packet_ta.ta_index

      typedef struct
      {
        UWORD16  start_ptcch_dl_block;  // DL PTCCH block position (2 TDMA in advance).
        UWORD16  tai_to_fnmod416;       // UL PTCCH position (2 TDMA in advance).
      }
      T_PTCCH_SCHEDULE_INFO;

      const T_PTCCH_SCHEDULE_INFO  PTCCH_SCHEDULE[16] =
      {
        {116, 12},{116, 38},{116, 64},{116, 90},
        {220,116},{220,142},{220,168},{220,194},
        {324,220},{324,246},{324,272},{324,298},
        { 12,324},{ 12,350},{ 12,376},{ 12,402}
      };

      UWORD16  fn_mod416         = l1s.next_time.fn % 416;
      UWORD32  time_to_ptcch_dl  = MAX_FN;
      UWORD32  time_to_ptcch_ul  = MAX_FN;

      // PTCCH/DL scheduling...
      {
        if(l1pa_l1ps_com.transfer.ptcch.request_dl)
        // Request to start PTCCH/DL after PTCCH/UL execution.
        {
          if(fn_mod416 <= PTCCH_SCHEDULE[TA_INDEX].start_ptcch_dl_block)
            time_to_ptcch_dl = PTCCH_SCHEDULE[TA_INDEX].start_ptcch_dl_block - fn_mod416;
          else
            time_to_ptcch_dl = 416 + PTCCH_SCHEDULE[TA_INDEX].start_ptcch_dl_block - fn_mod416;

          if(time_to_ptcch_dl == 0)
          {
            // PTCCH must execute PTCCH/DL.
            l1pa_l1ps_com.transfer.ptcch.activity |= PTCCH_DL;

            // Reset DL request bit.
            l1pa_l1ps_com.transfer.ptcch.request_dl = FALSE;
          }
        }

        if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL)
        // PTCCH/DL alrady active, continue reception at correct boundaries.
        {
          if(l1s.next_time.t2 <= 12)
            time_to_ptcch_dl = 12 - l1s.next_time.t2;
          else
            time_to_ptcch_dl = 26 + 12 - l1s.next_time.t2;
        }
      }

      // PTCCH/UL scheduling...always enabled according to TAI.
      {
        // Schedule PTCCH/UL according to TAI.
        if(fn_mod416 <= PTCCH_SCHEDULE[TA_INDEX].tai_to_fnmod416)
          time_to_ptcch_ul = PTCCH_SCHEDULE[TA_INDEX].tai_to_fnmod416 - fn_mod416;
        else
          time_to_ptcch_ul = 416 + PTCCH_SCHEDULE[TA_INDEX].tai_to_fnmod416 - fn_mod416;

        if(time_to_ptcch_ul == 0)
        {
          // PTCCH must execute PTCCH/UL.
          l1pa_l1ps_com.transfer.ptcch.activity |= PTCCH_UL;
        }
      }

      // Save scheduling result.
      if(time_to_ptcch_dl < time_to_ptcch_ul)
        l1s.task_status[PTCCH].time_to_exec = time_to_ptcch_dl;
      else
        l1s.task_status[PTCCH].time_to_exec = time_to_ptcch_ul;

      // Clear param. synchro. semaphore.
      l1a_l1s_com.task_param[PTCCH] = SEMAPHORE_RESET;
    }

    if(l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED)
    //-------------------------
    // SINGLE task is ENABLED.
    //-------------------------
    {
      // SINGLE task can be re-entrant, we can't check for
      // current_status == INACTIVE.

      if((l1pa_l1ps_com.transfer.single_block.activity & SINGLE_DL) ||
         (l1pa_l1ps_com.transfer.single_block.activity & SINGLE_UL))
      // L1 is camped on SINGLE timeslot.
      // -> no need to make a temporary synchro change.
      // -> SINGLE task is scheduled 1 frame before the block position.
      {
        UWORD32  time_to_single;

        if (l1s.next_time.fn_mod13 == 0)
          time_to_single = 0;
        else
        if (l1s.next_time.fn_mod13 <= 4)
          time_to_single = 4 - l1s.next_time.fn_mod13;
        else
        if (l1s.next_time.fn_mod13 <= 8)
          time_to_single = 8 - l1s.next_time.fn_mod13;
        else
          time_to_single = 13 - l1s.next_time.fn_mod13;

        // SINGLE task requires to run L1S scheduler every frame.
        l1a_l1s_com.time_to_next_l1s_task = 0;

        // Save scheduling result.
        l1s.task_status[SINGLE].time_to_exec = time_to_single;
      }
    } // SINGLE task enabled

    if(l1a_l1s_com.l1s_en_task[ITMEAS] == TASK_ENABLED)
    //-------------------------
    // ITMEAS task is ENABLED.
    //-------------------------
    {
      UWORD8 time_to_itmeas;

      // time to ITMEAS processing
      // ITMEAS must be scheduled 2 frames in advance (C W W R scheme)
      // --> use of 'next_plus_time'
      switch(l1pa_l1ps_com.itmeas.position)
      {
        case ANY_IDLE_FRAME:
          // ITMEAS task must be scheduled on any idle frame --> fn_mod13 = 12
          time_to_itmeas = 12 - l1s.next_plus_time.fn_mod13;
        break;

        case PTCCH_FRAME:
        {
          // ITMEAS must be scheduled on a PTCCH frame --> fn_mod26 = 12
          if (l1s.next_plus_time.t2 <= 12)
            time_to_itmeas = 12 - l1s.next_plus_time.t2;
          else
            time_to_itmeas = 38 - l1s.next_plus_time.t2;
        }
        break;

        case SEARCH_FRAME:
        {
          // ITMEAS must be scheduled on a search frame --> fn_mod26 = 25
          time_to_itmeas = 25 - l1s.next_plus_time.t2;
        }
        break;
      } // End of "switch"

      // Save scheduling result.
      l1s.task_status[ITMEAS].time_to_exec = time_to_itmeas;

      if(l1s.task_status[ITMEAS].current_status == INACTIVE)
      {
      // Clear param. synchro. semaphore.
      l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_RESET;
      }
    } // ITMEAS task enabled
  } // end of packet tasks
#endif

  //--------------------------------------------
  // TASK SELECTION...
  //--------------------------------------------
  {
    WORD32 forward_task          = NO_NEW_TASK;
    WORD32 forward_task_complete = MAX_FN;
    WORD32 forward_task_size     = MAX_FN;

    WORD32 backward_task = NO_NEW_TASK;
    WORD8  task;

    // FORWARD procedure...
    // Look for best pending task...
    // Tasks are ordered: Low priority .. to high priority.
    for(task=0; task<NBR_DL_L1S_TASKS; task++)
    {
      if(l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED)
      {
        if(l1s.task_status[task].time_to_exec < forward_task_complete)
        {
          forward_task = task;
          forward_task_complete = l1s.task_status[task].time_to_exec + TASK_ROM_MFTAB[task].size - 2;
        }
      }
    }

    if(forward_task != NO_NEW_TASK)
    {
      task = forward_task;

      // BACKWARD procedure...
      while((--task>=0) && (backward_task == NO_NEW_TASK))
      {
        if(l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED)
        {
          if((l1s.task_status[task].time_to_exec + TASK_ROM_MFTAB[task].size - 2) <=
             (l1s.task_status[forward_task].time_to_exec))
          {
            backward_task = task;
          }
        }
      }

      if(backward_task != NO_NEW_TASK)
      {
        Select_min_time(l1s.task_status[backward_task].time_to_exec,
                        l1a_l1s_com.time_to_next_l1s_task);

        // Pass back the best task.
        if(l1s.task_status[backward_task].time_to_exec == 0)
          *best_pending_task = backward_task;
        else
          *best_pending_task = NO_NEW_TASK;
      }
      else
      {
        Select_min_time(l1s.task_status[forward_task].time_to_exec,
                        l1a_l1s_com.time_to_next_l1s_task);

        // Pass back the best task.
        if(l1s.task_status[forward_task].time_to_exec == 0)
          *best_pending_task = forward_task;
        else
          *best_pending_task = NO_NEW_TASK;
      }
    }
    else
    {
      // Pass back the best task.
      *best_pending_task = NO_NEW_TASK;
    }
  }
} // End of procedure.

//#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_merge_manager()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1s_merge_manager(WORD32 pending_task)
{
  if(pending_task != NO_NEW_TASK)
  // There is a new pending task...
  {
    if(pending_task == SYNCHRO)
    // SYNCHRO task must be executed in any case.
    // It is used also to reset the MFTAB content.
    {
      WORD32 i;

      #if L1_GPRS
        // PDTCH task can't be aborted... SYNCHRO is delayed to next block boundary
        // This is needed when a synchronization change is needed to switch to a new
        // while a TBF is currently running: the end of the current TBF mustn't
        // be aborted so the first block of the new TBF will be used to switch to the
        // new synchronization.
        // SYNCHRO task has also to be delayed if a task needing a pseudo-synchro (with a synchro back
        // performed on the burst4, i.e. PBCCHS, PBCCHN_IDLE, SMSCB, PBCCHN_TRAN and Normal or Extended BCCH
        // ,(Packet)normal and (Packet)extended paging in Packet Transfer) is interrupted. This delay is requested in order to
        // to finish the current TPU scenario and to not disturb current L1 Timeslot Number Reference.
        // Cf. correction of BUG1004.
        if((l1s.task_status[PBCCHS].current_status == INACTIVE)      &&
           (l1s.task_status[PBCCHN_IDLE].current_status == INACTIVE) &&
           (l1s.task_status[PBCCHN_TRAN].current_status == INACTIVE) &&
           (l1s.task_status[PDTCH].current_status == INACTIVE)       &&
           (l1s.task_status[SMSCB].current_status == INACTIVE)       &&
           (((l1a_l1s_com.mode != PACKET_TRANSFER_MODE) ||
               ((l1s.task_status[NBCCHS].current_status == INACTIVE) &&
               (l1s.task_status[EBCCHS].current_status == INACTIVE)
           #if 0	/* FreeCalypso TCS211 reconstruction */
	       && (l1s.task_status[PNP].current_status == INACTIVE)
               && (l1s.task_status[PEP].current_status == INACTIVE)
               && (l1s.task_status[NP].current_status == INACTIVE)
               && (l1s.task_status[EP].current_status == INACTIVE)
           #endif
           ))))

       #else
         if (l1s.task_status[SMSCB].current_status == INACTIVE)
       #endif
         {
           // Clear the current content of the DL MFTAB.
           l1s_clear_mftab(l1s.mftab.frmlst);

           #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4))
             trace_info.abort_task = pending_task;
           #endif

           // Load the ABORT function in the MFTAB.
           l1s_load_mftab( BLOC_ABORT,            // Rom block address.
                           BLOC_ABORT_SIZE,       // Rom block size.
                           l1s.afrm,              // Start with current frame.
                           l1s.mftab.frmlst);     // Proceed on MFTAB.

           // Load the new task in the MFTAB.
           l1s_load_mftab( TASK_ROM_MFTAB[pending_task].address,  // Rom block address.
                           TASK_ROM_MFTAB[pending_task].size,     // Rom block size.
                           l1s.afrm,                              // Start with current frame.
                           l1s.mftab.frmlst);                     // Proceed on MFTAB.

           // All task become INACTIVE except PENDING which becomes ACTIVE.
           for(i=0; i<NBR_DL_L1S_TASKS; i++)
             l1s.task_status[i].current_status = INACTIVE;

           l1s.task_status[pending_task].current_status = ACTIVE;

           // Load FRAME_COUNT with the new task Rom block size.
           l1s.frame_count = TASK_ROM_MFTAB[pending_task].size;

           // MFTAB is reset, no more task not compatible with Neigh. Measurement.
           // Clear "forbid_meas".
           l1s.forbid_meas = 0;

           // Check that ABORT task is not bigger than pending_task.
           if(BLOC_ABORT_SIZE > l1s.frame_count) l1s.frame_count = BLOC_ABORT_SIZE;

           return;
         }

    } //(pending_task == SYNCHRO)
    else
    if(l1s.frame_count <= 2)
    // The incoming pending task can be merged within the MFTAB.
    {

      BOOL specific_case = FALSE;
      if(pending_task == DUL)
      { // this DOOLEAN is mandatory because we can access to this channel description only in dedicated
        // otherwise we have memory access error during the execution.
        T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;
        if ((desc_ptr->channel_type == SDCCH_8) && ((desc_ptr->subchannel>=4 && (desc_ptr->subchannel<=7))) )
          if ((l1s.actual_time.fn % 102) > 51) // only in the second multiframe D51
            specific_case = TRUE;
      }

      if(specific_case == TRUE)
      {
        // DUL(subch6) and ADL(subch6) (same for subch 4,5,6,7).
        // Here the task DUL is already installed which means that
        // if we install the ADL task we will have the UL task
        // controled before the DL task. This is not compatible
        // with the tpu programming.
        // To correct the problem, we detect this case, flush the
        // MFTAB and install a mixed DL/UL task block containing
        // the full ADL task and the end of the DUL task.
        // (see mftab.h)
        // The MFTAB is cleared.
        // Load the SPECIAL ADL/DUL MIXED TASK in the MFTAB.

        l1s_load_mftab( BLOC_DUL_ADL_MIXED,       // Rom block address.
                        BLOC_DUL_ADL_MIXED_SIZED, // Rom block size.
                        l1s.afrm,                 // Start with current frame.
                        l1s.mftab.frmlst);        // Proceed on MFTAB.

        l1s.task_status[DUL].current_status = ACTIVE;
        l1s.task_status[ADL].current_status = ACTIVE;

        // Load FRAME_COUNT with the new task Rom block size.
        l1s.frame_count = BLOC_DUL_ADL_MIXED_SIZED;
      }
      else
      {
        l1s_load_mftab( TASK_ROM_MFTAB[pending_task].address,   // Rom block address.
                        TASK_ROM_MFTAB[pending_task].size,      // Rom block size.
                        l1s.afrm,                               // Start with current frame.
                        l1s.mftab.frmlst);                      // Proceed on MFTAB.

        // PENDING becomes ACTIVE except if it is already active,
        // in this case is is stated RE_ENTERED.
        if(l1s.task_status[pending_task].current_status == ACTIVE)
          l1s.task_status[pending_task].current_status = RE_ENTERED;
        else
          l1s.task_status[pending_task].current_status = ACTIVE;

        // Load FRAME_COUNT with the new task Rom block size.
        l1s.frame_count = TASK_ROM_MFTAB[pending_task].size;
      }
    }

    else
    // The incoming pending task CANNOT be merged within the MFTAB.
    {
      #if L1_GPRS
      // Interference measurements special merging case
      // Merge is not possible when FB26/SB26/SBCNF26 in packet transfer
      // are also pending.
      if((pending_task == ITMEAS) &&
         (l1s.task_status[FB26].new_status    == NOT_PENDING) &&
         (l1s.task_status[SB26].new_status    == NOT_PENDING) &&
         (l1s.task_status[SBCNF26].new_status == NOT_PENDING))
      {
        // If frame_count = 3:
        // - Serving task (aligned on MF52 or MF51): interference measurements can
        //   be done during the last work phase (merge with the last Control
        //   of the serving task)
        //
        //     Frame count    6 5 4 3 2 1
        //     Serving task   C W R
        //                      C W R
        //                        C W R
        //                          C W R
        //     ITMEAS               C W W R
        //
        // - Neighbor tasks: merge always forbidden by l1s.forbid_meas

        if((l1s.frame_count == 3) && (l1s.forbid_meas < 2))
        {
          l1s_load_mftab( TASK_ROM_MFTAB[ITMEAS].address,   // Rom block address.
                          TASK_ROM_MFTAB[ITMEAS].size,      // Rom block size.
                          l1s.afrm,                         // Start with current frame.
                          l1s.mftab.frmlst);                // Proceed on MFTAB.

          // PENDING becomes ACTIVE.
          l1s.task_status[pending_task].current_status = ACTIVE;

          // Load FRAME_COUNT with the new task Rom block size.
          l1s.frame_count = TASK_ROM_MFTAB[pending_task].size;
        }
      } // End if "pending task is ITMEAS"
      else
      #endif

      if((l1s.task_status[FBNEW].current_status != INACTIVE) && (pending_task != FBNEW))
      // FBNEW task is the only aborted task.
      // We check to avoid aborting FBNEW by itself.
      {
        WORD32 i;

        // Clear the current content of the DL MFTAB.
        l1s_clear_mftab(l1s.mftab.frmlst);

         #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4))
           trace_info.abort_task = pending_task;
         #endif

        // Load the ABORT function in the MFTAB.
        l1s_load_mftab( BLOC_ABORT,            // Rom block address.
                        BLOC_ABORT_SIZE,       // Rom block size.
                        l1s.afrm,              // Start with current frame.
                        l1s.mftab.frmlst);     // Proceed on MFTAB.

        // Load the new task in the MFTAB.
        l1s_load_mftab( TASK_ROM_MFTAB[pending_task].address,  // Rom block address.
                        TASK_ROM_MFTAB[pending_task].size,     // Rom block size.
                        l1s.afrm,                              // Start with current frame.
                        l1s.mftab.frmlst);                     // Proceed on MFTAB.

        // All task become INACTIVE except PENDING which becomes ACTIVE.
        for(i=0; i<NBR_DL_L1S_TASKS; i++) l1s.task_status[i].current_status = INACTIVE;
        l1s.task_status[pending_task].current_status = ACTIVE;

        // Load FRAME_COUNT with the new task Rom block size.
        l1s.frame_count = TASK_ROM_MFTAB[pending_task].size;

        // MFTAB is reset, no more task not compatible with Neigh. Measurement.
        // Clear "forbid_meas".
        l1s.forbid_meas = 0;

        // Check that ABORT task is not bigger than pending_task.
        if(BLOC_ABORT_SIZE > l1s.frame_count) l1s.frame_count = BLOC_ABORT_SIZE;
      }

      else
      // NO abort.
      {}
    }
  }

  //---------------------------------------------------------
  // Additional tasks................
  //---------------------------------------------------------
  // -> These tasks are generaly supperposed to
  //    another main task.
  //      RAACC with ALLC / NP / EP /  NBCCHS / EBCCHS
  //      FB26 / SB26 / SBCNF26 with TCHTF
  //      ...
  //---------------------------------------------------------

  if(l1s.task_status[RAACC].new_status == PENDING)
  // CHANNEL ACCESS task is pending and MUST be set in the MFTAB.
  // Merge is always possible since only the serving tasks can be running.
  //   ->install RAACC whitout any other change.
  {
    l1s_load_mftab( TASK_ROM_MFTAB[RAACC].address,   // Rom block address.
                    TASK_ROM_MFTAB[RAACC].size,      // Rom block size.
                    l1s.afrm,                        // Start with current frame.
                    l1s.mftab.frmlst);               // Proceed on MFTAB.

    l1s.task_status[RAACC].current_status = ACTIVE;

    // Load FRAME_COUNT with the RAAC Rom block size.
    if(l1s.frame_count < TASK_ROM_MFTAB[RAACC].size)
      l1s.frame_count = TASK_ROM_MFTAB[RAACC].size;
  }

  #if L1_GPRS
  if((l1s.task_status[TCHTF].current_status != INACTIVE) ||
     (l1s.task_status[TCHTH].current_status != INACTIVE) ||
     (l1s.task_status[PDTCH].current_status != INACTIVE))
  #endif
  {
    // Dedicated/Transfer mode monitoring tasks...
    if(l1s.task_status[FB26].new_status == PENDING)
    {
      UWORD8 time_to_task_complete = TASK_ROM_MFTAB[FB26].size - 2;

      #if L1_GPRS
      if((l1s.task_status[PBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[NBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[EBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[PBCCHN_TRAN].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[NP         ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[EP         ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[BCCHN_TRAN ].time_to_exec >= time_to_task_complete))
      #endif
      {
        l1s_load_mftab( TASK_ROM_MFTAB[FB26].address,   // Rom block address.
                        TASK_ROM_MFTAB[FB26].size,      // Rom block size.
                        l1s.afrm,                       // Start with current frame.
                        l1s.mftab.frmlst);              // Proceed on MFTAB.

        l1s.task_status[FB26].current_status = ACTIVE;
      }
    }
    else
    if(l1s.task_status[SB26].new_status == PENDING)
    {
      UWORD8 time_to_task_complete = TASK_ROM_MFTAB[SB26].size - 2;

      #if L1_GPRS
      if((l1s.task_status[PBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[NBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[EBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[PBCCHN_TRAN].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[NP         ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[EP         ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[BCCHN_TRAN ].time_to_exec >= time_to_task_complete))
      #endif
      {
        l1s_load_mftab( TASK_ROM_MFTAB[SB26].address,   // Rom block address.
                        TASK_ROM_MFTAB[SB26].size,      // Rom block size.
                        l1s.afrm,                       // Start with current frame.
                        l1s.mftab.frmlst);              // Proceed on MFTAB.

        l1s.task_status[SB26].current_status = ACTIVE;
      }
    }
    else
    if(l1s.task_status[SBCNF26].new_status == PENDING)
    {
      UWORD8 time_to_task_complete = TASK_ROM_MFTAB[SBCNF26].size - 2;

      #if L1_GPRS
      if((l1s.task_status[PBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[NBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[EBCCHS     ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[PBCCHN_TRAN].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[NP         ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[EP         ].time_to_exec >= time_to_task_complete) &&
         (l1s.task_status[BCCHN_TRAN ].time_to_exec >= time_to_task_complete))
      #endif
      {
        l1s_load_mftab( TASK_ROM_MFTAB[SBCNF26].address,   // Rom block address.
                        TASK_ROM_MFTAB[SBCNF26].size,      // Rom block size.
                        l1s.afrm,                          // Start with current frame.
                        l1s.mftab.frmlst);                 // Proceed on MFTAB.

        l1s.task_status[SBCNF26].current_status = ACTIVE;
      }
    }
  }

#if L1_GPRS
  if(l1s.task_status[PRACH].new_status == PENDING)
  // PACKET CHANNEL ACCESS task is pending and MUST be set in the MFTAB.
  // Merge is always possible since only the serving tasks can be running.
  //   ->install PRACH without any other change.
  {
    l1s_load_mftab( TASK_ROM_MFTAB[PRACH].address,   // Rom block address.
                    TASK_ROM_MFTAB[PRACH].size,      // Rom block size.
                    l1s.afrm,                        // Start with current frame.
                    l1s.mftab.frmlst);               // Proceed on MFTAB.

    l1s.task_status[PRACH].current_status = ACTIVE;

    // Load FRAME_COUNT with the RAAC Rom block size.
    if(l1s.frame_count < TASK_ROM_MFTAB[PRACH].size)
      l1s.frame_count = TASK_ROM_MFTAB[PRACH].size;
  }

  else
  if((l1s.task_status[POLL].new_status == PENDING) &&
     (l1s.task_status[POLL].current_status != ACTIVE))
  // POLL RESPONSE task is pending.
  // Merge is not always possible since POLL can conflict with a Neighbour process
  // (SB2, SBCONF, BCCHN, BCCHN_TOP, PBCCHN_IDLE) or PBCCHS and CCCH operation mode II/III tasks.
  // From the fact that POLL can be load in MFTAB here below (when there is no pending_task
  // except POLL), merging can be done only if current_status is != ACTIVE.
  {
    UWORD8 time_to_task_complete = BLOC_POLL_NO_HOPP_SIZE - 2;

    if((l1s.task_status[PBCCHS     ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[PBCCHN_IDLE].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[BCCHN      ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[BCCHN_TOP  ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[SMSCB      ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[NP         ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[EP         ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[SB2        ].time_to_exec >= time_to_task_complete) &&
       (l1s.task_status[SBCONF     ].time_to_exec >= time_to_task_complete))
    {
      if((l1s.task_status[PBCCHS     ].current_status != ACTIVE) &&
         (l1s.task_status[PBCCHN_IDLE].current_status != ACTIVE) &&
         (l1s.task_status[BCCHN      ].current_status != ACTIVE) &&
         (l1s.task_status[BCCHN_TOP  ].current_status != ACTIVE) &&
         (l1s.task_status[SMSCB      ].current_status != ACTIVE) &&
         (l1s.task_status[NP         ].current_status != ACTIVE) &&
         (l1s.task_status[EP         ].current_status != ACTIVE) &&
         (l1s.task_status[SB2        ].current_status != ACTIVE) &&
         (l1s.task_status[SBCONF     ].current_status != ACTIVE))
      {
        l1s_load_mftab( BLOC_POLL_NO_HOPP,              // Rom block address.
                        BLOC_POLL_NO_HOPP_SIZE,         // Rom block size.
                        l1s.afrm,                       // Start with current frame.
                        l1s.mftab.frmlst);              // Proceed on MFTAB.

        l1s.task_status[POLL].current_status = ACTIVE;

        // Load FRAME_COUNT with the POLL Rom block size.
        if(l1s.frame_count < BLOC_POLL_NO_HOPP_SIZE)
          l1s.frame_count = BLOC_POLL_NO_HOPP_SIZE;
      }
    }
  }
#endif

}

//#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_execute_frame()                                   */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1s_execute_frame()
{
  // Execute functions from MFTAB.
  l1s_exec_mftab();

  // Force time_to_next_l1s_task to 0.
  // This statement has been introduced to force L1S to
  // reschedule the next activity when the current activity
  // is completed.
  if(l1s.frame_count == 1) l1a_l1s_com.time_to_next_l1s_task = 0;

  // Decrement the actual FRAME_COUNT.
  if(l1s.frame_count > 0) l1s.frame_count--;

  // Decrement the actual meas_forbidden counter.
  if(l1s.forbid_meas > 0) l1s.forbid_meas--;
}

//#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_meas_manager()                                    */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is the measurement tasks manager.       */
/* The followings tasks are handled:                     */
/*                                                       */
/* FSMS_MEAS:                                            */
/* 1) Full list measurement in Cell Selection            */
/* The machine performs 1 valid measurement per carrier  */
/* from the full list of GSM carriers. To achieve 1      */
/* valid measurement, 2 attempt with 2 different AGC     */
/* are performed worst case. When all carriers are       */
/* a reporting message L1C_VALID_MEAS_INFO is built and */
/* sent to L1A.                                          */
/*                                                       */
/* 2) Full list measurement in Idle mode.                */
/* The machine performs 1 valid measurement per carrier  */
/* from the full list of GSM carriers. To achieve 1      */
/* valid measurement, 2 attempt with 2 different AGC     */
/* are performed worst case. When all carriers are       */
/* a reporting message L1C_VALID_MEAS_INFO is built and */
/* sent to L1A.                                          */
/*                                                       */
/* I_BAMS_MEAS: BA list measurement in Idle mode.        */
/* The machine performs 8 measurements per PCH reading   */
/* (4*2) looping on the BA list. When 8 measurements are */
/* completed (end of PCH) a reporting message            */
/* L1C_RXLEV_PERIODIC_DONE is built and sent to L1A.      */
/*                                                       */
/*-------------------------------------------------------*/
void l1s_meas_manager(void)
{
  /* static static_s_rxlev_cntr = 0; */
  UWORD32  i;
  UWORD8   IL_for_rxlev;
  UWORD8   adc_active = INACTIVE;

  static xSignalHeaderRec *pch_msg          = NULL;
  static UWORD8           static_read_index = 0;
  static UWORD8           static_ctrl_index = 0;

  #if((RF_FAM == 61) && (CODE_VERSION != SIMULATION))
    UWORD16 dco_algo_ctl_pw = 0;
    UWORD16 dco_algo_ctl_pw_temp = 0;
    UWORD8 if_ctl = 0;
	UWORD8 if_threshold = 180;
  #endif
  #if(CODE_VERSION == SIMULATION)// This is a temp fix- pl Verify the RF family for L1 simulator and change
    UWORD16 dco_algo_ctl_pw = 0;
    UWORD16 dco_algo_ctl_pw_temp = 0;
    UWORD8 if_ctl = 0;
	UWORD8 if_threshold = 180;
  #endif

  #if FF_L1_IT_DSP_USF
    // Bypass Circuit switched measurment during Packet Access phase:
    // 1) FSMS_MEAS not active because full list measurement not allowed in
    // this state (see S921 Annex C "Transisition rules").
    // 2) I_BAMS_MEAS inactive because PCCCH idle therefore P_CRMS_MEAS is
    // used for neighbour monitoring.
    // 3) D_BAMS_MEAS is inactive because dedicated mode not compatible with
    // this state.
    // Running it induces side effects with Fast USF during PA because it
    // clears l1pa_l1ps_com.cr_freq_list.pnp_ctrl...

    // PA state detection with fast USF interrupt in use...
    if ((l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED)
         && (l1ps_macs_com.usf_status == USF_AWAITED))
      return;
  #endif
#if (FF_L1_FAST_DECODING == 1)
    if (l1a_apihisr_com.fast_decoding.deferred_control_req == TRUE)
    {
      /* Do not execute l1s_meas_manager if a fast decoding IT is scheduled */
      return;
    }
#endif /*#if (FF_L1_FAST_DECODING == 1)*/

  //====================================================
  //  RESET MEASUREMENT MACHINES WHEN SYNCHRO EXECUTED.
  //====================================================

  if(l1s.tpu_ctrl_reg & CTRL_SYNC)
  // SYNCHRO task has been controled, anything else is forbidden!!!
  // -> Reset FULL SET and BA LIST measurement machines.
  // -> return.
  {
    // Rem:
    // SYNCHRO task affects Idle FSMS_MEAS task since 1 frame is skipped.
    // Idle FSMS_MEAS session is restarted from scratch.

    // Reset Idle mode FULL LIST measurement machine.
    {
      // Init power measurement multi_session process
      l1a_l1s_com.full_list.meas_1st_pass_ctrl   = 1;     // Set 1st pass flag for power measurement session in ctrl.
      l1a_l1s_com.full_list.meas_1st_pass_read   = 1;     // Set 1st pass flag for power measurement session in read.
      l1a_l1s_com.full_list.nbr_sat_carrier_ctrl = 0;     // Clear number of saturated carrier in ctrl.
      l1a_l1s_com.full_list.nbr_sat_carrier_read = 0;     // Clear number of saturated carrier in read.

      l1a_l1s_com.full_list.ms_ctrl              = 0; //nbr of meas.controled.
      l1a_l1s_com.full_list.ms_ctrl_d            = 0; // ... 1 frame delay.
      l1a_l1s_com.full_list.ms_ctrl_dd           = 0; // ... 2 frames delay.

      // Set global parameters for full list measurement.
      l1a_l1s_com.full_list.next_to_ctrl = 0;
      l1a_l1s_com.full_list.next_to_read = 0;
    }

    // Reset BA LIST measurement machine.
    {
      // Rewind "next_to_ctrl" counter to come back to the next carrier to
      // measure.
      l1a_l1s_com.ba_list.next_to_ctrl = l1a_l1s_com.ba_list.next_to_read;

      // Reset flags.
      l1a_l1s_com.ba_list.ms_ctrl      = 0;
      l1a_l1s_com.ba_list.ms_ctrl_d    = 0;
      l1a_l1s_com.ba_list.ms_ctrl_dd   = 0;

      // Reset serving cell dedicated mode measurement session.
      l1s_reset_dedic_serving_meas();
    }

    return;
  }

  if(l1s.dsp_ctrl_reg & CTRL_ABORT)
  // A task conflict has happened, ABORT has been controled reseting
  // the MCU/DSP communication. We must rewind any measurement activity.
  {
    // FULL LIST measurement machine.
    {
      // Init power measurement multi_session process
      l1a_l1s_com.full_list.meas_1st_pass_ctrl   = l1a_l1s_com.full_list.meas_1st_pass_read;
      l1a_l1s_com.full_list.nbr_sat_carrier_ctrl = l1a_l1s_com.full_list.nbr_sat_carrier_read;     // Clear number of saturated carrier in ctrl.

      l1a_l1s_com.full_list.ms_ctrl              = 0; //nbr of meas.controled.
      l1a_l1s_com.full_list.ms_ctrl_d            = 0; // ... 1 frame delay.
      l1a_l1s_com.full_list.ms_ctrl_dd           = 0; // ... 2 frames delay.

      // Set global parameters for full list measurement.
      l1a_l1s_com.full_list.next_to_ctrl = l1a_l1s_com.full_list.next_to_read;
    }

    return;
  }

  //====================================================
  //  FULL LIST...
  //  -> Cell Selection  or,
  //  -> Idle mode.
  //====================================================

  // Clear semaphore when all running meas. are completed...
  if(!l1a_l1s_com.full_list.ms_ctrl_d && !l1a_l1s_com.full_list.ms_ctrl_dd)
  {
    l1a_l1s_com.meas_param &= FSMS_MEAS_MASK;
  }

  // When a READ is performed we set dsp_r_page_used flag to switch the read page...
    //if(l1a_l1s_com.full_list.ms_ctrl_dd) l1s_dsp_com.dsp_r_page_used = TRUE;

  // Call Cell Selection measurement management function or Idle PLMN permitted function
  // if meas. task still enabled.
  if((l1a_l1s_com.l1s_en_meas & FSMS_MEAS) && !(l1a_l1s_com.meas_param & FSMS_MEAS))
  {
    #if L1_GPRS
      UWORD8   pm_read[NB_MEAS_MAX_GPRS];
    #else
      UWORD8   pm_read[NB_MEAS_MAX];
    #endif

    UWORD8    nbmeas, max_nbmeas;

    // When FULL LIST measurement task is enabled L1S is executed every frame.
    l1a_l1s_com.time_to_next_l1s_task = 0;

    // the first PW window
    if ((l1a_l1s_com.full_list.next_to_ctrl ==0 ) &&(l1a_l1s_com.full_list.next_to_read ==0))
    {
      // ADC measurement
      // ***************
      if ((l1a_l1s_com.mode == CS_MODE) || (l1a_l1s_com.mode == CS_MODE0)) // only in cell selection and inside the first window
      {
         // ADC performed only with the 1st PW window
         if (l1a_l1s_com.adc_mode & ADC_NEXT_MEAS_SESSION)  // perform ADC only one time
         {
            adc_active = ACTIVE;
            l1a_l1s_com.adc_mode &= ADC_MASK_RESET_IDLE; // reset in order to have only one ADC measurement in Idle
         }
         else
           if (l1a_l1s_com.adc_mode & ADC_EACH_MEAS_SESSION) // perform ADC on each bloc
             adc_active = ACTIVE;
       }
    }

    // **********************
    // READ task if needed!!!
    // **********************

    if(l1a_l1s_com.full_list.ms_ctrl_dd)
      l1_check_com_mismatch(FULL_LIST_MEAS_ID);

    //A measure was control two TDMA earlier. Read ms_ctrl_dd number of  measures.
    #if L1_GPRS
      // !!! WARNING: word32 type is for compatibility with chipset == 0.
      // Can be word16 if only chipset == 2 is used. Extraction of pm using
      // AND operator can be removed.
      // Read power measurement result from DSP.

      switch(l1a_l1s_com.dsp_scheduler_mode)
      {
        // MCU/DSP interface is GSM one
        case GSM_SCHEDULER:
          // Read power measurement result from DSP.
          l1ddsp_meas_read(l1a_l1s_com.full_list.ms_ctrl_dd,pm_read);
        break;

        // MCU/DSP interface is GPRS one
        case GPRS_SCHEDULER:
          // Read power measurement result from DSP.
          l1pddsp_meas_read(l1a_l1s_com.full_list.ms_ctrl_dd,pm_read);
        break;
      }
    #else
      // Read power measurement result from DSP.
      l1ddsp_meas_read(l1a_l1s_com.full_list.ms_ctrl_dd,pm_read);
    #endif

    // When a READ is performed we set dsp_r_page_used flag to switch the read page...
    if(l1a_l1s_com.full_list.ms_ctrl_dd) l1s_dsp_com.dsp_r_page_used = TRUE;


    for(i=0; i < l1a_l1s_com.full_list.ms_ctrl_dd; i++)
    // Background measurements....
    // A measurement controle was performed 2 tdma earlier, read result now!!
    {

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

      l1_check_pm_error(pm_read[i], FULL_LIST_MEAS_ID);

      #if (TRACE_TYPE==3)
        stats_samples_pm(pm_read[i]);
      #endif

      // If we are running 2nd pass (because of saturated carrier during 1st pass),
      // we read radio_freq until we found the next one which is flagged saturated.
      if((!l1a_l1s_com.full_list.meas_1st_pass_read) &&
         ( l1a_l1s_com.full_list.nbr_sat_carrier_read!=0))
      {
        while(l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read]==0)
          l1a_l1s_com.full_list.next_to_read++;  // increase carrier index until a saturated one
                                                 // is found.

        l1a_l1s_com.full_list.nbr_sat_carrier_read--;
      }

      // Test meas value and validate or not the measurement.
      // Fill accordingly input_level and sat_flag fields.

      // L1_FF_MULTIBAND TBD
      IL_for_rxlev = l1ctl_csgc((UWORD8)(pm_read[i]),l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].radio_freq);

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_FULL_LIST_MEAS(pm_read[i], IL_for_rxlev, FULL_LIST_MEAS_ID, l1a_l1s_com.full_list.next_to_read)
      #endif

      // Accumulate only valid results (no saturated carriers)
      if (l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read]==0)
      {
        // Fill result "message" (array passed by L3 is directly filled by L1S).
        #if TESTMODE
          if (l1_config.TestMode)
          {
            // L1_FF_MULTIBAND TBD
            l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].accum_power_result =
            IL_for_rxlev;
          }
          else
          {
           // L1_FF_MULTIBAND TBD
           l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].accum_power_result +=
            l1s_encode_rxlev(IL_for_rxlev);
          }
        #else
          // L1_FF_MULTIBAND TBD
          l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].accum_power_result +=
          l1s_encode_rxlev(IL_for_rxlev);
        #endif
      }

      #if L2_L3_SIMUL
        #if (DEBUG_TRACE == BUFFER_TRACE_POWER)
          buffer_trace( 4, l1a_l1s_com.full_list.next_to_read+l1_config.std.radio_freq_index_offset,
                           pm_read[i],
                           l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read], 0);
        #endif
      #endif


      // Increment "next_to_read" field for next measurement...
      if(++l1a_l1s_com.full_list.next_to_read >= l1a_l1s_com.full_list_ptr->power_array_size)
      {
        l1a_l1s_com.full_list.next_to_read       = 0;
        l1a_l1s_com.full_list.meas_1st_pass_read = 0;
      }
    }// end of for (READ)


    // **********************
    // CTRL task if needed!!!
    // **********************

    // We can make a measurement on any frame excepted the frame
    // used to execute tasks not compatible with full list measurement.
    // (FBNEW,SB2,...
    #if L1_GPRS
      if(((l1pa_l1ps_com.cr_freq_list.ms_ctrl_d == 0) &&
          (l1a_l1s_com.ba_list.np_ctrl == 0)) &&
          (l1s.forbid_meas < 2))
    #else
      if((l1a_l1s_com.ba_list.np_ctrl == 0) &&
         (l1s.forbid_meas < 2))
    #endif
    {
      if(!l1a_l1s_com.full_list.meas_1st_pass_ctrl) // 2nd pass
      {
        if(l1a_l1s_com.full_list.nbr_sat_carrier_ctrl!=0) // there are still saturated carriers
        {
          WORD16  tpu_win_rest;
          UWORD16 power_meas_split;

          // Compute how many BP_SPLIT remains for full list meas.
          // Rem: we take into account the SYNTH load for 1st RX in next frame.
          tpu_win_rest = FRAME_SPLIT - l1s.tpu_win;

          power_meas_split = (l1_config.params.rx_synth_load_split + PWR_LOAD);

          max_nbmeas = 0;

          while(tpu_win_rest >= power_meas_split)
          {
            max_nbmeas ++;
            tpu_win_rest -= power_meas_split;
          }

          if(l1a_l1s_com.full_list.nbr_sat_carrier_ctrl >= max_nbmeas ) nbmeas = max_nbmeas;
          else nbmeas = l1a_l1s_com.full_list.nbr_sat_carrier_ctrl;

          #if L1_GPRS
            switch(l1a_l1s_com.dsp_scheduler_mode)
            {
              // MCU/DSP interface is GSM one
              case GSM_SCHEDULER:
              {
                // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code
                if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX;

                // Program DSP to make nbmeas neighbor measurments.
                // DSP code 33 is the only one to support more than 4PM (up to 8PM)
                #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP != 39)
                  if(l1s.tpu_win) // check whether NB scheduled in same frame
                  {
                    if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM
                      nbmeas = NB_MEAS_MAX-1;   // TPU RAM needs to be checked, too !!!
                  }
                  l1ddsp_load_monit_task(nbmeas,0);
                #else
                  // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201)
                  l1ddsp_load_monit_task(nbmeas+0x200, 0);
                #endif
              }
              break;

              // MCU/DSP interface is GPRS one
              case GPRS_SCHEDULER:
              {
                // GPRS scheduler can perform 8 meas. per TDMA max.
                if (nbmeas > NB_MEAS_MAX_GPRS) nbmeas = NB_MEAS_MAX_GPRS;

                // Program DSP to make nbmeas neighbor measurments.
                // Note: At this level, l1s.tpu_win is considered to be
                // equal to 1 or 2.
                if(l1s.tpu_win)
                  l1pddsp_meas_ctrl(nbmeas, 1);
                else
                  l1pddsp_meas_ctrl(nbmeas, 0);
              }
              break;
            }
          #else
            // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code
            if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX;

            // Program DSP to make nbmeas neighbor measurments.
            // DSP code 33 is the only one to support more than 4PM (up to 8PM)
            #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP != 39)
              if(l1s.tpu_win) // check whether NB scheduled in same frame
              {
                if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM
                  nbmeas = NB_MEAS_MAX-1;   // TPU RAM needs to be checked, too !!!
              }
              l1ddsp_load_monit_task(nbmeas,0);
            #else
              // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201)
              l1ddsp_load_monit_task(nbmeas+0x200, 0);
            #endif
          #endif

          // for each meas. do TPU control.
          for ( i = 0; i<nbmeas; i++)
          {
            while(l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_ctrl]==0)
              l1a_l1s_com.full_list.next_to_ctrl++; // increase carrier index until a saturated one
                                                    // is found.

            // Decrement the number of sat carriers.
            l1a_l1s_com.full_list.nbr_sat_carrier_ctrl--;

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

#if(RF_FAM == 61)   // Locosto DCO
           #if (PWMEAS_IF_MODE_FORCE == 0)
              cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID ,
                  0,
                  ( l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq),if_threshold);
            #else
              if_ctl = IF_120KHZ_DSP;
              dco_algo_ctl_pw_temp = DCO_IF_0KHZ;
            #endif


            dco_algo_ctl_pw |= ((dco_algo_ctl_pw_temp & 0x03)<< (i*2));

#endif

            // tpu pgm: 1 measurement only.
            // L1_FF_MULTIBAND TBD
            l1dtpu_meas(l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq,
                        l1_config.params.low_agc,
                        0,
                        l1s.tpu_win,
                        l1s.tpu_offset,
                        adc_active
#if(RF_FAM == 61)
                ,L1_AFC_SCRIPT_MODE
                ,if_ctl
#endif
			);

            // only one ADC: with the first window
            adc_active = INACTIVE;


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

            // increment carrier counter for next measurement...
            if(++l1a_l1s_com.full_list.next_to_ctrl >= l1a_l1s_com.full_list_ptr->power_array_size)
              l1a_l1s_com.full_list.next_to_ctrl = 0;
          }
  #if(RF_FAM == 61)
          l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
  #endif
          l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;


          // Flag measurement control.
          // **************************

          // Set nbr of meas. programmed  "ms_ctrl" to nbmeas.
          // It will be used as 2 tdma delayed to
          // trigger the reading.
          l1a_l1s_com.full_list.ms_ctrl = nbmeas;

          // 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;

        }
      }
      else // 1st pass
      {
        WORD16  tpu_win_rest;
        UWORD16 power_meas_split;

        // Compute how many BP_SPLIT remains for full list meas.
        // Rem: we take into account the SYNTH load for 1st RX in next frame.
        tpu_win_rest = FRAME_SPLIT - l1s.tpu_win;

        power_meas_split = (l1_config.params.rx_synth_load_split + PWR_LOAD);

        max_nbmeas = 0;

        while(tpu_win_rest >= power_meas_split)
        {
          max_nbmeas ++;
          tpu_win_rest -= power_meas_split;
        }

        i = l1a_l1s_com.full_list_ptr->power_array_size - l1a_l1s_com.full_list.next_to_ctrl;

        if( i >= max_nbmeas ) nbmeas = max_nbmeas;
        else                  nbmeas = i;

          #if L1_GPRS
            switch(l1a_l1s_com.dsp_scheduler_mode)
            {
              // MCU/DSP interface is GSM one
              case GSM_SCHEDULER:
              {
                // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code
                if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX;

                // Program DSP to make nbmeas neighbor measurments.
                // DSP code 33 is the only one to support more than 4PM (up to 8PM)
                #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP != 39)
                  if(l1s.tpu_win) // check whether NB scheduled in same frame
                  {
                    if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM
                      nbmeas = NB_MEAS_MAX-1;   // TPU RAM needs to be checked, too !!!
                  }
                  l1ddsp_load_monit_task(nbmeas,0);
                #else
                  // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201)
                  l1ddsp_load_monit_task(nbmeas+0x200, 0);
                #endif
              }
              break;

              // MCU/DSP interface is GPRS one
              case GPRS_SCHEDULER:
              {
                // GPRS scheduler can perform 8 meas. per TDMA max.
                if (nbmeas > NB_MEAS_MAX_GPRS) nbmeas = NB_MEAS_MAX_GPRS;

                // Program DSP to make nbmeas neighbor measurments.
                // Note: At this level, l1s.tpu_win is considered to be
                // equal to 1 or 2.
                if(l1s.tpu_win)
                  l1pddsp_meas_ctrl(nbmeas, 1);
                else
                  l1pddsp_meas_ctrl(nbmeas, 0);
              }
              break;
            }
          #else
            // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code
            if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX;

            // Program DSP to make nbmeas neighbor measurments.
            // DSP code 33 is the only one to support more than 4PM (up to 8PM)
            #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP !=39)
              if(l1s.tpu_win) // check whether NB scheduled in same frame
              {
                if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM
                  nbmeas = NB_MEAS_MAX-1;   // TPU RAM needs to be checked, too !!!
              }
              l1ddsp_load_monit_task(nbmeas,0);
            #else
              // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201)
              l1ddsp_load_monit_task(nbmeas+0x200, 0);
            #endif
          #endif

        // for each meas. do TPU control.
        for (i=0; i<nbmeas; i++)
        {
#if(RF_FAM == 61)   // Locosto DCO
        #if (PWMEAS_IF_MODE_FORCE == 0)
            cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID ,
                0,
                l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq,if_threshold);
          #else
            if_ctl = IF_120KHZ_DSP;
            dco_algo_ctl_pw_temp = DCO_IF_0KHZ;
          #endif

            dco_algo_ctl_pw |= ((dco_algo_ctl_pw_temp & 0x03)<< (i*2)) ;
#endif

          // tpu pgm: 1 measurement only.
          // L1_FF_MULTIBAND TBD
          l1dtpu_meas(l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq,
                      l1_config.params.high_agc,
                      0,
                      l1s.tpu_win,
                      l1s.tpu_offset,adc_active
                   #if(RF_FAM == 61)
                       ,L1_AFC_SCRIPT_MODE
                       ,if_ctl
                   #endif
		  );

            // only one ADC: with the first window
            adc_active = INACTIVE;


          // increment carrier counter for next measurement...
          if(++l1a_l1s_com.full_list.next_to_ctrl >= l1a_l1s_com.full_list_ptr->power_array_size)
          {
            l1a_l1s_com.full_list.next_to_ctrl       = 0; // Go back to the top of the list.
            l1a_l1s_com.full_list.meas_1st_pass_ctrl = 0; // End of 1st pass.
          }

          // Increment tpu window identifier.
          l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);
        }
  #if(RF_FAM == 61)
          l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
  #endif

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


        // Flag measurement control.
        // **************************

        // Set nbr of meas. programmed  "ms_ctrl" to nbmeas.
        // It will be used as 2 tdma delayed to
        // trigger the reading.
        l1a_l1s_com.full_list.ms_ctrl = nbmeas;

        // 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;
      }
    }


    //Time to make reporting.......
    if((!l1a_l1s_com.full_list.meas_1st_pass_read) &&
       ( l1a_l1s_com.full_list.nbr_sat_carrier_read == 0))
    {
      xSignalHeaderRec *fl_msg;

      /*-----------------------------------------------*/
      /* Time to report (1 valid measurement has       */
      /* been performed on each carrier) if:           */
      /*   Cell Selection or PLMN selection, and       */
      /*   The 1st pass has been completed,  and       */
      /*   No more carrier saturated to control, and   */
      /*   No measurement in the pipeline.             */
      /*-----------------------------------------------*/
        // Reset the FSMS_MEAS  process to avoid to keep sending
        // report message to L1A.
        l1a_l1s_com.l1s_en_meas &= FSMS_MEAS_MASK; // Clear Cell Selection/Idle Full List Measurement enable flag.

        // alloc L1C_VALID_MEAS_INFO message...
        fl_msg = os_alloc_sig(sizeof(int));
        DEBUGMSG(status,NU_ALLOC_ERR)
        fl_msg->SignalCode = L1C_VALID_MEAS_INFO;
        // L1_FF_MULTIBAND TBD
        fl_msg->SigP= (void *) l1a_l1s_com.full_list_ptr;

        // send L1C_VALID_MEAS_INFO message...
        os_send_sig(fl_msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

    }//end of reporting
  }// end of FSMS_MEAS


  //====================================================
  //  BA LIST...
  //  -> Idle mode.
  //====================================================

  // When a READ is performed we usueally set "dsp_r_page_used" flag to switch the
  // read page but since I_BAMS is executed in the same frame as Normal Paging (NP),
  // the setting of "dsp_r_page_used" is already done in READ(NP).

  if((l1a_l1s_com.l1s_en_meas & I_BAMS_MEAS)  && (l1a_l1s_com.meas_param & I_BAMS_MEAS))
  // Some changes occured on the BA list or the PAGING PARAMETERS have
  // changed.
  {
    // Reset BA semaphore.
    l1a_l1s_com.meas_param &= I_BAMS_MEAS_MASK;

    /* pch_msg != NULL added below due to the fast pagin feature + power reduction feature 
     * as the measurement can end in potentially 2 TDMA frames itself and an IBA_R message
     * when comes in certail TDMA frames of paging task, both static ctrl index and static
     * read index will be zero */
    /* FreeCalypso TCS211 reconstruction: above change reverted */
    if((static_ctrl_index != 0) || (static_read_index != 0))
    {
   
      // Paging process has been interrupted by a L3 message
      // Deallocate memory for the received message if msg not forwarded to L3.
      // ----------------------------------------------------------------------
      #if (GSM_IDLE_RAM != 1)
        os_free_sig(pch_msg);
        DEBUGMSG(status,NU_DEALLOC_ERR)
      #endif

      pch_msg           = NULL;
      static_ctrl_index = 0;
      static_read_index = 0;

      // Rewind ba counters to come back to the first carrier of this
      // aborted session.
      l1a_l1s_com.ba_list.next_to_read = l1a_l1s_com.ba_list.first_index;
      l1a_l1s_com.ba_list.next_to_ctrl = l1a_l1s_com.ba_list.first_index;

      // Reset flags.
      l1a_l1s_com.ba_list.ms_ctrl      = FALSE;
      l1a_l1s_com.ba_list.ms_ctrl_d    = FALSE;
      l1a_l1s_com.ba_list.ms_ctrl_dd   = FALSE;
    }
  }
  else
  if ((l1a_l1s_com.l1s_en_meas & I_BAMS_MEAS) && !(l1a_l1s_com.meas_param & I_BAMS_MEAS))
  // Idle Neighbor Cells Power Measurements fonction if meas. task still enabled.
  {
    UWORD8   nbr_carrier = l1a_l1s_com.ba_list.nbr_carrier;

    // variables introduced to cope with RACH sent on one frame of the paging block
    static UWORD8 static_nbmeas_to_report = 8;
    static UWORD8 static_nbmeas_ctrl_d  = 0;
    static UWORD8 static_nbmeas_ctrl_dd = 0;

#if 0	/* FreeCalypso TCS211 reconstruction */
    static UWORD8 num_pm[4]={0,0,0,0};
#if (FF_L1_FAST_DECODING == 1)
    static UWORD8 num_pm_fp[2]={0,0};
#endif
    static UWORD8 num_pm_frames = 0; /* number of frames over which measurement is scheduled */
#endif

    UWORD8   nbmeas_ctrl = 0;
#if (FF_L1_FAST_DECODING == 1)
    BOOL schedule_measures = FALSE;
    BOOL fast_decoding = l1s_check_fast_decoding_authorized(NP);
#endif /* FF_L1_FAST_DECODING */
    // ********************
    // READ task if needed
    // ********************
    if(l1a_l1s_com.ba_list.ms_ctrl_dd == TRUE)
    // Background measurements....
    // A measurement controle (set in "l1s_ctrl_ms()" function) was performed
    // 2 tdma earlier, read result now!!
    {
      UWORD16  radio_freq_read;
      UWORD8   ba_index_read;


      l1_check_com_mismatch(I_BA_MEAS_ID);

      for(i=0; i<static_nbmeas_ctrl_dd; i++)
      {
        UWORD32  pm;

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

        // Read power measurement result from DSP.
        pm = (l1s_dsp_com.dsp_db_r_ptr->a_pm[i] & 0xffff) >> 5;
        l1_check_pm_error(pm, I_BA_MEAS_ID);

        #if (TRACE_TYPE==3)
          stats_samples_pm(pm);
        #endif

        ba_index_read = l1a_l1s_com.ba_list.next_to_read;
        radio_freq_read    = l1a_l1s_com.ba_list.A[ba_index_read].radio_freq;

        // Get Input level corresponding to the used IL and pm result.
        IL_for_rxlev = l1ctl_pgc((UWORD8)pm, l1a_l1s_com.ba_list.used_il_dd[i], l1a_l1s_com.ba_list.used_lna_dd[i],
                                 radio_freq_read);

        #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
          RTTL1_FILL_MON_MEAS(pm, IL_for_rxlev, I_BA_MEAS_ID, radio_freq_read)
        #endif


#if 0	/* FreeCalypso TCS211 reconstruction */
	//Check if the message is not empty, else allocate memory
	if (pch_msg == NULL)
        {
          pch_msg = os_alloc_sig(sizeof(T_L1C_RXLEV_PERIODIC_DONE));
          DEBUGMSG(status,NU_ALLOC_ERR)
          pch_msg->SignalCode = L1C_RXLEV_PERIODIC_DONE;
        }
#endif

        // Fill reporting message.
        ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->
          A[static_read_index].radio_freq_no = radio_freq_read;
        ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->
          A[static_read_index].rxlev = l1s_encode_rxlev(IL_for_rxlev);

        // Increment the number of neighbor meas read.
        static_read_index ++;

        // Increment "l1s.next_to_read" field for next measurement...
        if(++l1a_l1s_com.ba_list.next_to_read >= nbr_carrier)
          l1a_l1s_com.ba_list.next_to_read   = 0;

      }//end for

      // Serving cell measurements...
      // Accumulate the new measurement with the partial result.
      // Compensate AGC for current measurement value.
      l1a_l1s_com.Scell_info.meas.acc += l1a_l1s_com.Scell_IL_for_rxlev;
      /* static_s_rxlev_cntr++; */

      // **********
      // Reporting
      // **********
      if (static_read_index==static_nbmeas_to_report)
      {

      #if (GSM_IDLE_RAM == 1)
        if (!READ_TRAFFIC_CONT_STATE)
        {
          CSMI_TrafficControllerOn();
        }
        // 1st paging block, so it's time to allocate L1C_RXLEV_PERIODIC_IND msg
        if (pch_msg == NULL)
        {
          pch_msg = os_alloc_sig(sizeof(T_L1C_RXLEV_PERIODIC_DONE));
          DEBUGMSG(status,NU_ALLOC_ERR)
          pch_msg->SignalCode = L1C_RXLEV_PERIODIC_DONE;
        }

        for(i=0; i<static_nbmeas_to_report; i++)
        {
            ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->A[i].radio_freq_no = l1s.A[i].radio_freq_no;
            ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->A[i].rxlev = l1s.A[i].rxlev;
            // Fill reporting message.
        }
      #endif

        static_read_index = 0;

        // Fill serving cell RXLEV field.
        //#if (FF_L1_FAST_DECODING == 1)
          /* Reporting done after the 2nd NP burst, bursts 3 and 4 are unknown */
          //if (fast_decoding == TRUE)
          //  ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/2);
          //else
          //  ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/4);
//#else /* #if (FF_L1_FAST_DECODING == 1) */
//          ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/4);
//#endif  /* #if (FF_L1_FAST_DECODING == 1) #else */

((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/4);
        // Fill "nbr_of_carriers" field, it is 7 when a RACH coincides with paging block, 8 otherwise.
        ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->nbr_of_carriers = static_nbmeas_to_report;

        // Fill BA identifier field.
        ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->ba_id = l1a_l1s_com.ba_list.ba_id;
// Enhanced RSSI

	#if 0	/* FreeCalypso TCS211 reconstruction */
         ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->qual_acc_idle =qual_acc_idle1[0] ;

         ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->qual_nbr_meas_idle =qual_acc_idle1[1]* TOTAL_NO_OF_BITS_IDLE_MEAS;
	#endif

        // send L1C_RXLEV_PERIODIC_IND message...
        os_send_sig(pch_msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

	#if 0	/* FreeCalypso TCS211 reconstruction */
       // Reseting the value
       qual_acc_idle1[0]= 0;
       qual_acc_idle1[1] =0;
	#endif

        // Reset pointer for debugg.
        pch_msg = NULL;
	/* static_s_rxlev_cntr = 0; */
      }

    }// end of READ

    // **********
    // CTRL task
    // **********
    if (l1a_l1s_com.ba_list.np_ctrl == 1)
    {
      #if (GSM_IDLE_RAM != 1)
      // 1st paging block, so it's time to allocate L1C_RXLEV_PERIODIC_IND msg
        if (pch_msg == NULL)
        {
          pch_msg = os_alloc_sig(sizeof(T_L1C_RXLEV_PERIODIC_DONE));
          DEBUGMSG(status,NU_ALLOC_ERR)
          pch_msg->SignalCode = L1C_RXLEV_PERIODIC_DONE;
	  /* static_s_rxlev_cntr = 0; */
        }
      #endif
      // Reset accumalator for serving measurements.
      l1a_l1s_com.Scell_info.meas.acc = 0;

      // Clear read period counter
      static_read_index = 0;

      // Save first BA index to be measured in this new session.
      l1a_l1s_com.ba_list.first_index = l1a_l1s_com.ba_list.next_to_ctrl;

      // Reset static variables for control of nbmeas per frame
      static_nbmeas_to_report = 8;
      static_nbmeas_ctrl_d  = 0;
      static_nbmeas_ctrl_dd = 0;
    }

    // A PCH burst has been controled, we must make the control of 1 or 2 new measurements.
    if ((static_ctrl_index == (l1a_l1s_com.ba_list.np_ctrl-1)*2) ||
        (static_ctrl_index == (l1a_l1s_com.ba_list.np_ctrl-1)*2 - 1))
    {
      UWORD16  radio_freq_ctrl;
      UWORD8   ba_index_ctrl;

      // check whether RACH has been controlled in the same frame
      // if YES only one PW measurement will be controlled and the number of meas to report is decremented by 1
      if (l1s.tpu_win >= (3 * BP_SPLIT + l1_config.params.tx_ra_load_split + l1_config.params.rx_synth_load_split))
      {
        static_nbmeas_to_report--;
        nbmeas_ctrl = 1;
      }
      else
      {
        nbmeas_ctrl = 2;
      }  /* end else no RACH */

      for(i=0; i<nbmeas_ctrl; i++)
      {
        UWORD8  lna_off;
        WORD32  agc;
#if (L1_FF_MULTIBAND == 1)
        UWORD16 operative_radio_freq;
#endif

        ba_index_ctrl = l1a_l1s_com.ba_list.next_to_ctrl;
        radio_freq_ctrl    = l1a_l1s_com.ba_list.A[ba_index_ctrl].radio_freq;

#if (L1_FF_MULTIBAND == 0)

        // Get AGC according to the last known IL.
        agc     = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level >> 1, PWR_ID);
        lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off;

        // Memorize the IL used for AGC setting.
        l1a_l1s_com.ba_list.used_il[i]  = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
        l1a_l1s_com.ba_list.used_lna[i] = l1a_l1s_com.last_input_level[radio_freq_ctrl - 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_ctrl);

       lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
        // Get AGC according to the last known IL.
        agc     = 
            Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, PWR_ID);

        // Memorize the IL used for AGC setting.
        l1a_l1s_com.ba_list.used_il[i]  = 
            l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
        l1a_l1s_com.ba_list.used_lna[i] = 
            l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;        

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


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

#if(RF_FAM == 61)   // Locosto DCO
       #if (PWMEAS_IF_MODE_FORCE == 0)
           cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID ,
              l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level,
              radio_freq_ctrl,if_threshold);
         #else
           if_ctl = IF_120KHZ_DSP;
           dco_algo_ctl_pw_temp = DCO_IF_0KHZ;
         #endif

         dco_algo_ctl_pw |= ((dco_algo_ctl_pw_temp & 0x03)<< (i*2)) ;
#endif

        // tpu pgm: 1 measurement only.
        l1dtpu_meas(radio_freq_ctrl,
                    agc,
                    lna_off,
                    l1s.tpu_win,
                    l1s.tpu_offset, INACTIVE
                   #if(RF_FAM == 61)
                       ,L1_AFC_SCRIPT_MODE
                       ,if_ctl
                   #endif
		);


        // increment carrier counter for next measurement...
        if(++l1a_l1s_com.ba_list.next_to_ctrl >= nbr_carrier)
          l1a_l1s_com.ba_list.next_to_ctrl = 0;

        #if L2_L3_SIMUL
          #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
          buffer_trace(4, l1s.actual_time.fn, radio_freq,
                       l1s.tpu_win, 0);
          #endif
        #endif

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

        // Increment the number of neighbor meas controled.
        static_ctrl_index ++;
//        static_ctrl_index %=8;
        if (static_ctrl_index >= static_nbmeas_to_report)
          static_ctrl_index = 0;

      }
  #if(RF_FAM == 61)
          l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
  #endif

      l1ddsp_load_monit_task(nbmeas_ctrl, 0);


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


      // Flag measurement control.
      // **************************

      // Set flag "ms_ctrl" to 1. It will be used as 2 tdma delayed for
      // background measurement reading.
      l1a_l1s_com.ba_list.ms_ctrl = TRUE;

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

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

    }//end ctrl

    // Pipeline for tracking of the number of measurements controlled
    static_nbmeas_ctrl_dd = static_nbmeas_ctrl_d;
    static_nbmeas_ctrl_d  = nbmeas_ctrl;

  }//end I_BAMS_MEAS


  //====================================================
  //  BA LIST...
  //  -> Dedicated mode.
  //====================================================

  // When a READ is performed we set dsp_r_page_used flag to switch the read page...
  if(l1a_l1s_com.ba_list.ms_ctrl_dd==TRUE) l1s_dsp_com.dsp_r_page_used = TRUE;

  if((l1a_l1s_com.l1s_en_meas & D_BAMS_MEAS) && (l1a_l1s_com.meas_param & D_BAMS_MEAS))
  // Some changes occured on the BA list or the Dedicated channel have
  // changed.
  {
    #if FF_L1_IT_DSP_DTX
      // Postpone rewind from DTX HISR to L1S to keep same behaviour
      if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
      {
    #endif
    if(l1a_l1s_com.ba_list.ms_ctrl_d == FALSE)
    // Reset BA semaphore.
    // Rem: BA semaphore is reset only if the pipeline ctrl
    // is empty.
    {
      l1a_l1s_com.meas_param &= D_BAMS_MEAS_MASK;
    }

    // Rewind "next_to_ctrl" counter to come back to the next carrier to
    // measure.
    l1a_l1s_com.ba_list.next_to_ctrl = l1a_l1s_com.ba_list.next_to_read;

    // Reset of "ms_ctrl, ms_ctrl_d, msctrl_dd" is done at L1 startup
    // and when SYNCHRO task is executed.
    #if FF_L1_IT_DSP_DTX
      } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
    #endif
  }
  else
  if ( (l1a_l1s_com.l1s_en_meas & D_BAMS_MEAS) &&
      !(l1a_l1s_com.meas_param  & D_BAMS_MEAS) &&
       (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) )
  // Call Dedicated Neighbor Cells Power Measurements fonction
  // if meas. task still enabled and global dedicated mode task enabled.
  {
    UWORD8                 nbr_carrier = l1a_l1s_com.ba_list.nbr_carrier;
    T_CHANNEL_DESCRIPTION *desc_ptr    = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr;
    UWORD32                pm;
    UWORD8                 lna_off;
    WORD32                 agc;

    #if FF_L1_IT_DSP_DTX
      // Read operation to be done from L1S only
      if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
      {
    #endif
    // ********************
    // READ task if needed
    // ********************
    if(l1a_l1s_com.ba_list.ms_ctrl_dd == TRUE)
    // Background measurements....
    // A measurement controle (set in "l1s_ctrl_ms()" function) was performed
    // 2 tdma earlier, read result now!!
    {
      UWORD16 radio_freq_read;
      UWORD8  ba_index_read;

      l1_check_com_mismatch(D_BA_MEAS_ID);

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

      // Read power measurement result from DSP.
      pm = (l1s_dsp_com.dsp_db_r_ptr->a_pm[0] & 0xffff) >> 5;
      l1_check_pm_error(pm, D_BA_MEAS_ID);

      #if (TRACE_TYPE==3)
        stats_samples_pm(pm);
      #endif

      ba_index_read = l1a_l1s_com.ba_list.next_to_read;
      radio_freq_read    = l1a_l1s_com.ba_list.A[ba_index_read].radio_freq;

      // Get Input level corresponding to the used IL and pm result.
      IL_for_rxlev = l1ctl_pgc((UWORD8)pm,l1a_l1s_com.ba_list.used_il_dd[0],l1a_l1s_com.ba_list.used_lna_dd[0],
                               radio_freq_read);

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_MON_MEAS(pm, IL_for_rxlev, D_BA_MEAS_ID, radio_freq_read)
      #endif

      // Accumulate new RXLEV level in the BA list.
      l1a_l1s_com.ba_list.A[ba_index_read].acc += l1s_encode_rxlev(IL_for_rxlev);

      l1a_l1s_com.ba_list.A[ba_index_read].nbr_meas++;

      // Increment "l1s.next_to_read" field for next measurement...
      if(++l1a_l1s_com.ba_list.next_to_read >= nbr_carrier)
        l1a_l1s_com.ba_list.next_to_read = 0;
    }// end of READ

    #if FF_L1_IT_DSP_DTX
      } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
    #endif
    // **********
    // CTRL task
    // **********
    if((desc_ptr->channel_type == SDCCH_4) || (desc_ptr->channel_type == SDCCH_8))
    // case SDCCH...
    {
      UWORD8  ba_index_ctrl;
      UWORD16  radio_freq_ctrl;
#if (L1_FF_MULTIBAND == 1)
      UWORD8 operative_radio_freq;
#endif    


      if(l1s.forbid_meas < 2)
      // We must perform a measurement on every frame except when
      // FB51/SB51/SBCNF51 tasks are running, those tasks are not compatible
      // with neigh. measurement.
      {
          ba_index_ctrl = l1a_l1s_com.ba_list.next_to_ctrl;
          radio_freq_ctrl    = l1a_l1s_com.ba_list.A[ba_index_ctrl].radio_freq;

#if (L1_FF_MULTIBAND == 0)  

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


          // Store IL used for current CTRL in order to be able to build IL from pm
          // in READ phase.
          l1a_l1s_com.ba_list.used_il[0]  = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
          l1a_l1s_com.ba_list.used_lna[0] = l1a_l1s_com.last_input_level[radio_freq_ctrl - 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_ctrl);

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


          // Store IL used for current CTRL in order to be able to build IL from pm
          // in READ phase.
          l1a_l1s_com.ba_list.used_il[0]  = 
            l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
          l1a_l1s_com.ba_list.used_lna[0] = 
            l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;

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

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

#if(RF_FAM == 61)   // Locosto DCO
       #if (PWMEAS_IF_MODE_FORCE == 0)
          cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_VALID ,
             l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level,
             radio_freq_ctrl,if_threshold);
        #else
          if_ctl = IF_120KHZ_DSP;
          dco_algo_ctl_pw = DCO_IF_0KHZ;
        #endif

        l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
#endif

        // TPU pgm: 1 measurement only.
          l1dtpu_meas(radio_freq_ctrl,
                      agc,
                      lna_off,
                      l1s.tpu_win,
                      l1s.tpu_offset, INACTIVE
                   #if(RF_FAM == 61)
                       ,L1_AFC_SCRIPT_MODE
                       ,if_ctl
                   #endif
		  );

          // increment carrier counter for next measurement...
          if(++l1a_l1s_com.ba_list.next_to_ctrl >= nbr_carrier)
            l1a_l1s_com.ba_list.next_to_ctrl = 0;

          #if L2_L3_SIMUL
            #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
              buffer_trace(4, l1s.actual_time.fn, radio_freq,
                           l1s.tpu_win, 0);
            #endif
          #endif

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

          // DSP pgm: 1 measurement only.
          l1ddsp_load_monit_task(1, 0);


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


          // Flag measurement control.
          // **************************

          // Set flag "ms_ctrl" to 1. It will be used as 2 tdma delayed for
          // background measurement reading.
          l1a_l1s_com.ba_list.ms_ctrl = TRUE;

          // 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;
      }
    }
    else
    // case TCH...
    {
      UWORD8                 ba_index_ctrl;
      UWORD16                radio_freq_ctrl;
#if (L1_FF_MULTIBAND == 1)
      UWORD16 operative_radio_freq;
#endif
      
      //T_CHANNEL_DESCRIPTION *desc_ptr   = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; -OMAPS-90550-new

      if(l1s.forbid_meas == 0)
      // We must perform a measurement on every frame except frames 23, 24 (TCH_HS SC0)
      //                                                            24, 25 (TCH_HS SC1 anf TCH_FS)
      // when FB26/SB26/SBCNF26 tasks are running, those task are not compatible
      // with neigh. measurement.
      {
        #if FF_L1_IT_DSP_DTX
          if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
          {
        #endif
          ba_index_ctrl = l1a_l1s_com.ba_list.next_to_ctrl;
          radio_freq_ctrl    = l1a_l1s_com.ba_list.A[ba_index_ctrl].radio_freq;

#if (L1_FF_MULTIBAND == 0)
          
          agc     = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level >> 1, PWR_ID);
          lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off;

          // Store IL used for current CTRL in order to be able to build IL from pm
          // in READ phase.
          l1a_l1s_com.ba_list.used_il[0]  = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
          l1a_l1s_com.ba_list.used_lna[0] = l1a_l1s_com.last_input_level[radio_freq_ctrl - 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_ctrl);
          lna_off = 
            l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;
          agc     = 
            Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, PWR_ID);

          // Store IL used for current CTRL in order to be able to build IL from pm
          // in READ phase.
          l1a_l1s_com.ba_list.used_il[0]  = 
            l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
          l1a_l1s_com.ba_list.used_lna[0] = 
            l1a_l1s_com.last_input_level[operative_radio_freq].lna_off;

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


#if(RF_FAM == 61)   // Locosto DCO
       #if (PWMEAS_IF_MODE_FORCE == 0)
          cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_VALID ,
              l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level,
              radio_freq_ctrl,if_threshold);
        #else
          if_ctl = IF_120KHZ_DSP;
          dco_algo_ctl_pw = DCO_IF_0KHZ;
        #endif

        l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
#endif

          // TPU pgm: 1 measurement only.
          l1dtpu_meas(radio_freq_ctrl,
                      agc,
                      lna_off,
                      l1s.tpu_win,
                      l1s.tpu_offset, INACTIVE
                   #if(RF_FAM == 61)
                       ,L1_AFC_SCRIPT_MODE
                       ,if_ctl
                   #endif
		  );

          // increment carrier counter for next measurement...
          if(++l1a_l1s_com.ba_list.next_to_ctrl >= nbr_carrier)
             l1a_l1s_com.ba_list.next_to_ctrl = 0;

          #if L2_L3_SIMUL
            #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH)
               buffer_trace(4, l1s.actual_time.fn, radio_freq,
                            l1s.tpu_win, 0);
            #endif
          #endif
          // Increment tpu window identifier.
          l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);

          // DSP pgm: 1 measurement only.
          l1ddsp_load_monit_task(1, 0);


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


          // Flag measurement control.
          // **************************

          // Set flag "ms_ctrl" to 1. It will be used as 2 tdma delayed for
          // background measurement reading.
          l1a_l1s_com.ba_list.ms_ctrl = TRUE;

          // 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;
        #if FF_L1_IT_DSP_DTX
          } // if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
        #endif
    }
 }

#if FF_L1_IT_DSP_DTX
   if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
   {
#endif
    // Time to make reporting...
    //--------------------------
    if(l1s.next_time.fn_in_report == 0)
    {
      l1s_dedic_reporting();

      // Check if any NEW BA available, if so download it...
      if(l1a_l1s_com.ba_list.new_list_present == TRUE)
      {
        WORD32 i;

        // Set parameter synchro semaphore for D_BAMS task.
        // This is used to reject any measurement which could
        // be in the C/W/R pipeline.
        l1a_l1s_com.meas_param |= D_BAMS_MEAS;

        // Download new list.
        for(i=0;i<l1a_l1s_com.ba_list.new_list.num_of_chans;i++)
        {
          l1a_l1s_com.ba_list.A[i].radio_freq = l1a_l1s_com.ba_list.new_list.chan_list.A[i];
        }

        l1a_l1s_com.ba_list.ba_id               = l1a_l1s_com.ba_list.new_list.ba_id;
        l1a_l1s_com.ba_list.nbr_carrier         = l1a_l1s_com.ba_list.new_list.num_of_chans;
        l1a_l1s_com.dedic_set.pwrc              = l1a_l1s_com.ba_list.new_list.pwrc;
        l1a_l1s_com.dedic_set.aset->dtx_allowed = l1a_l1s_com.ba_list.new_list.dtx_allowed;

        // Set the TCH mode (DAI mode and DTX) in MCU-DSP com.
        l1ddsp_load_tch_mode(l1a_l1s_com.dedic_set.aset->dai_mode,
                             l1a_l1s_com.dedic_set.aset->dtx_allowed);

        // clear NEW BA present flag.
        l1a_l1s_com.ba_list.new_list_present = 0;
       #if FF_L1_IT_DSP_DTX
         // Initialize timer for fast DTX availabilty
         l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY;
       #endif
      }
    }
#if FF_L1_IT_DSP_DTX
   } //if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
#endif
  }//end D_BAMS_MEAS

#if FF_L1_IT_DSP_DTX
  // Pipelining of control operations to be delayed in DTX interrupt when used.
  if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
  {
#endif
  // Clear np flag.
  //---------------
  l1a_l1s_com.ba_list.np_ctrl   = 0;

  #if L1_GPRS
    // Clear controlled flag pnp_ctrl.
    //-------------------------------
   l1pa_l1ps_com.cr_freq_list.pnp_ctrl = 0;
  #endif

  // C W R pipeline management.
  //---------------------------
  l1a_l1s_com.full_list.ms_ctrl_dd = l1a_l1s_com.full_list.ms_ctrl_d;
  l1a_l1s_com.full_list.ms_ctrl_d  = l1a_l1s_com.full_list.ms_ctrl;
  l1a_l1s_com.full_list.ms_ctrl    = 0;

  l1a_l1s_com.ba_list.ms_ctrl_dd   = l1a_l1s_com.ba_list.ms_ctrl_d;
  l1a_l1s_com.ba_list.ms_ctrl_d    = l1a_l1s_com.ba_list.ms_ctrl;
  l1a_l1s_com.ba_list.ms_ctrl      = FALSE;


  for(i=0; i<C_BA_PM_MEAS; i++)
  {
    l1a_l1s_com.ba_list.used_il_dd[i]  = l1a_l1s_com.ba_list.used_il_d[i];
    l1a_l1s_com.ba_list.used_il_d [i]  = l1a_l1s_com.ba_list.used_il  [i];
    l1a_l1s_com.ba_list.used_lna_dd[i] = l1a_l1s_com.ba_list.used_lna_d[i];
    l1a_l1s_com.ba_list.used_lna_d [i] = l1a_l1s_com.ba_list.used_lna  [i];
  }
#if FF_L1_IT_DSP_DTX
  }
#endif
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#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_end_manager()                                     */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
#if (L1_DYN_DSP_DWNLD == 1)
void l1s_end_manager()
{

  BOOL misc_task_ctrl_dyn_dwnld = FALSE;

  #if L1_GPRS
  #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) || (FF_L1_FAST_DECODING == 1)
    // In case of Fast USF, PDTCH Read operations are not affected by
    // USF validity.
    if ((l1ps_macs_com.rlc_downlink_call == TRUE)
      #if FF_L1_IT_DSP_USF
        && (l1ps_macs_com.usf_status != USF_IT_DSP)
      #endif
      #if FF_L1_IT_DSP_DTX
        && (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
      #endif
      #if (FF_L1_FAST_DECODING == 1)
        && (l1a_apihisr_com.fast_decoding.status != C_FAST_DECODING_PROCESSING)
      #endif
       )
         l1ps_macs_rlc_downlink_call();
  #else
    if (l1ps_macs_com.rlc_downlink_call == TRUE)
      l1ps_macs_rlc_downlink_call();
  #endif
#endif // L1_GPRS

#if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) || (FF_L1_FAST_DECODING == 1)
  // TPU and DSP pages can be switched only if relevant scenario are complete
  // which may be postponed late in the TDMA when Fast USF is used.
  if (TRUE
    #if FF_L1_IT_DSP_USF
      && (l1ps_macs_com.usf_status != USF_AWAITED)
    #endif
    #if FF_L1_IT_DSP_DTX
      && (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
    #endif
    #if (FF_L1_FAST_DECODING == 1)
      && (l1a_apihisr_com.fast_decoding.deferred_control_req == FALSE)
    #endif /*#if (FF_L1_FAST_DECODING == 1)*/
    )
  {
#endif

  // call the gauging algorithm only with paging or Packet paging in Idle mode
  // avoid call with NP during packet Tranfer Mode (NMOII)
  if (l1a_l1s_com.mode == I_MODE)
  l1s_gauging_task();

  if(l1s_dsp_com.dsp_r_page_used == TRUE)
  /*************************************************************/
  /* The "read" page for comm. with DSP has been used in the   */
  /* current TDMA.                                             */
  /* --> clear it!!!                                           */
  /* --> switch it!!!                                          */
  /*************************************************************/
  {
    // clear page.
    l1s_reset_db_dsp_to_mcu(l1s_dsp_com.dsp_db_r_ptr);

    // switch page.
    l1s_dsp_com.dsp_r_page ^= 1;
  }

 if(l1s.dyn_dwnld_state > 0)
    misc_task_ctrl_dyn_dwnld = TRUE;

  #if (AUDIO_TASK == 1)
    if(l1s.dsp_ctrl_reg != NO_CTRL)
    /*************************************************************/
    /* Some controle (RX/TX/MS) have been performed in the       */
    /* current frame. We must close the MCU/DSP comm. page now.  */
    /*************************************************************/
    {
      // Omega power down for TCH/F and TCH/H at release.
      if(l1a_l1s_com.dedic_set.stop_tch == TRUE)
      {
        l1ddsp_stop_tch();
        l1a_l1s_com.dedic_set.stop_tch = FALSE;
      }
      // A misc task is working with a GSM tasks or the DSP requests an IT com.
      // Or the gauging is active or dynamic download activity is active
      #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15)  // with Calypso the DSP can be in Idle3 during the Gauging
        if ( (l1s.l1_audio_it_com)  ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) ||
			 (misc_task_ctrl_dyn_dwnld == TRUE))
      #else
        if ( (l1s.l1_audio_it_com) ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) ||
             (l1s.pw_mgr.gauging_task == ACTIVE) ||
			 (misc_task_ctrl_dyn_dwnld == TRUE))
      #endif
      {
        // When a MISC task is enabled L1S must be ran every frame
        // to be able to enable the frame interrupt for DSP
        l1a_l1s_com.time_to_next_l1s_task = 0;

        l1ddsp_end_scenario(GSM_MISC_CTL);
      }
      else
      {
        l1ddsp_end_scenario(GSM_CTL);
      }
    }
    else // No GSM task
    {
      // A misc task is working without a GSM tasks or the DSP request an IT com.
      // Or the gauging is active or dynamic download activity is active
      #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15)  // with Calypso the DSP can be in Idle3 during the Gauging
        if ( (l1s.l1_audio_it_com) ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) ||
			 (misc_task_ctrl_dyn_dwnld == TRUE))
      #else
        if ( (l1s.l1_audio_it_com) ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) ||
             (l1s.pw_mgr.gauging_task == ACTIVE) ||
			 (misc_task_ctrl_dyn_dwnld == TRUE))
      #endif
      {
        // When a MISC task is enabled L1S must be ran every frame
        // to be able to enable the frame interrupt for DSP
        l1a_l1s_com.time_to_next_l1s_task = 0;
        l1ddsp_end_scenario(MISC_CTL);
      }
    }
  #else
    if(l1s.dsp_ctrl_reg != NO_CTRL)
    /*************************************************************/
    /* Some controle (RX/TX/MS) have been performed in the       */
    /* current frame. We must close the MCU/DSP comm. page now.  */
    /*************************************************************/
    {
      // Omega power down for TCH/F and TCH/H at release.
      if(l1a_l1s_com.dedic_set.stop_tch == TRUE)
      {
        l1ddsp_stop_tch();
        l1a_l1s_com.dedic_set.stop_tch = FALSE;
      }

      l1ddsp_end_scenario(GSM_CTL);
    }
  #endif // AUDIO_TASK == 1



  if(l1s.tpu_ctrl_reg != NO_CTRL)
  /*************************************************************/
  /* Some controle (RX/TX/MS/SYNC) have been performed in the  */
  /* current frame. We must close the MCU/TPU comm. page now.  */
  /*************************************************************/
  {
    l1dtpu_end_scenario();
  }

  // Propagate input level and lna state for Serving (Idle/dedic) tasks
  //-------------------------------------------------------------------
  l1a_l1s_com.Scell_used_IL_dd.input_level = l1a_l1s_com.Scell_used_IL_d.input_level;
  l1a_l1s_com.Scell_used_IL_d.input_level  = l1a_l1s_com.Scell_used_IL.input_level;
  l1a_l1s_com.Scell_used_IL.input_level    = l1_config.params.il_min;

  l1a_l1s_com.Scell_used_IL_dd.lna_off     = l1a_l1s_com.Scell_used_IL_d.lna_off;
  l1a_l1s_com.Scell_used_IL_d.lna_off      = l1a_l1s_com.Scell_used_IL.lna_off;
  l1a_l1s_com.Scell_used_IL.lna_off        = FALSE;

  // Propagate radio_freq for dedic. mode use (hopping).
  //-----------------------------------------------
  l1a_l1s_com.dedic_set.radio_freq_dd = l1a_l1s_com.dedic_set.radio_freq_d;
  l1a_l1s_com.dedic_set.radio_freq_d  = l1a_l1s_com.dedic_set.radio_freq;

  #if L1_GPRS
    // Propagate radio_freq for packet idle mode use (hopping).
    //-----------------------------------------------
    l1pa_l1ps_com.p_idle_param.radio_freq_dd = l1pa_l1ps_com.p_idle_param.radio_freq_d;
    l1pa_l1ps_com.p_idle_param.radio_freq_d  = l1pa_l1ps_com.p_idle_param.radio_freq;
  #endif

#if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) || (FF_L1_FAST_DECODING == 1)
  }
#endif
}
#else
void l1s_end_manager()
{
#if L1_GPRS
  #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX)
    // In case of Fast USF, PDTCH Read operations are not affected by
    // USF validity.
    if ((l1ps_macs_com.rlc_downlink_call == TRUE)
      #if FF_L1_IT_DSP_USF
        && (l1ps_macs_com.usf_status != USF_IT_DSP)
      #endif
      #if FF_L1_IT_DSP_DTX
        && (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP)
      #endif
     )
         l1ps_macs_rlc_downlink_call();
  #else
    if (l1ps_macs_com.rlc_downlink_call == TRUE)
      l1ps_macs_rlc_downlink_call();
  #endif
#endif // L1_GPRS

#if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX)
  // TPU and DSP pages can be switched only if relevant scenario are complete
  // which may be postponed late in the TDMA when Fast USF is used.
  if (TRUE
    #if FF_L1_IT_DSP_USF
      && (l1ps_macs_com.usf_status != USF_AWAITED)
    #endif
    #if FF_L1_IT_DSP_DTX
      && (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED)
    #endif
    )
  {
#endif

  // call the gauging algorithm only with paging or Packet paging in Idle mode
  // avoid call with NP during packet Tranfer Mode (NMOII)
  if (l1a_l1s_com.mode == I_MODE)
  l1s_gauging_task();

  if(l1s_dsp_com.dsp_r_page_used == TRUE)
  /*************************************************************/
  /* The "read" page for comm. with DSP has been used in the   */
  /* current TDMA.                                             */
  /* --> clear it!!!                                           */
  /* --> switch it!!!                                          */
  /*************************************************************/
  {
    // clear page.
    l1s_reset_db_dsp_to_mcu(l1s_dsp_com.dsp_db_r_ptr);

    // switch page.
    l1s_dsp_com.dsp_r_page ^= 1;
  }

  #if (AUDIO_TASK == 1)
    if(l1s.dsp_ctrl_reg != NO_CTRL)
    /*************************************************************/
    /* Some controle (RX/TX/MS) have been performed in the       */
    /* current frame. We must close the MCU/DSP comm. page now.  */
    /*************************************************************/
    {
      // Omega power down for TCH/F and TCH/H at release.
      if(l1a_l1s_com.dedic_set.stop_tch == TRUE)
      {
        l1ddsp_stop_tch();
        l1a_l1s_com.dedic_set.stop_tch = FALSE;
      }
      // A misc task is working with a GSM tasks or the DSP requests an IT com.
      // Or the gauging is active
      #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15)  // with Calypso the DSP can be in Idle3 during the Gauging
        if ( (l1s.l1_audio_it_com)  ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ))
      #else
        if ( (l1s.l1_audio_it_com) ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) ||
             (l1s.pw_mgr.gauging_task == ACTIVE) )
      #endif
      {
        // When a MISC task is enabled L1S must be ran every frame
        // to be able to enable the frame interrupt for DSP
        l1a_l1s_com.time_to_next_l1s_task = 0;

        l1ddsp_end_scenario(GSM_MISC_CTL);
      }
      else
      {
        l1ddsp_end_scenario(GSM_CTL);
      }
    }
    else // No GSM task
    {
      // A misc task is working without a GSM tasks or the DSP request an IT com.
      // Or the gauging is active
      #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15)  // with Calypso the DSP can be in Idle3 during the Gauging
        if ( (l1s.l1_audio_it_com) ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ))
      #else
        if ( (l1s.l1_audio_it_com) ||
             (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) ||
             (l1s.pw_mgr.gauging_task == ACTIVE) )
      #endif
      {
        // When a MISC task is enabled L1S must be ran every frame
        // to be able to enable the frame interrupt for DSP
        l1a_l1s_com.time_to_next_l1s_task = 0;
        l1ddsp_end_scenario(MISC_CTL);
      }
    }
  #else
    if(l1s.dsp_ctrl_reg != NO_CTRL)
    /*************************************************************/
    /* Some controle (RX/TX/MS) have been performed in the       */
    /* current frame. We must close the MCU/DSP comm. page now.  */
    /*************************************************************/
    {
      // Omega power down for TCH/F and TCH/H at release.
      if(l1a_l1s_com.dedic_set.stop_tch == TRUE)
      {
        l1ddsp_stop_tch();
        l1a_l1s_com.dedic_set.stop_tch = FALSE;
      }

      l1ddsp_end_scenario(GSM_CTL);
    }
  #endif // AUDIO_TASK == 1



  if(l1s.tpu_ctrl_reg != NO_CTRL)
  /*************************************************************/
  /* Some controle (RX/TX/MS/SYNC) have been performed in the  */
  /* current frame. We must close the MCU/TPU comm. page now.  */
  /*************************************************************/
  {
    l1dtpu_end_scenario();
  }

  // Propagate input level and lna state for Serving (Idle/dedic) tasks
  //-------------------------------------------------------------------
  l1a_l1s_com.Scell_used_IL_dd.input_level = l1a_l1s_com.Scell_used_IL_d.input_level;
  l1a_l1s_com.Scell_used_IL_d.input_level  = l1a_l1s_com.Scell_used_IL.input_level;
  l1a_l1s_com.Scell_used_IL.input_level    = l1_config.params.il_min;

  l1a_l1s_com.Scell_used_IL_dd.lna_off     = l1a_l1s_com.Scell_used_IL_d.lna_off;
  l1a_l1s_com.Scell_used_IL_d.lna_off      = l1a_l1s_com.Scell_used_IL.lna_off;
  l1a_l1s_com.Scell_used_IL.lna_off        = FALSE;

  // Propagate radio_freq for dedic. mode use (hopping).
  //-----------------------------------------------
  l1a_l1s_com.dedic_set.radio_freq_dd = l1a_l1s_com.dedic_set.radio_freq_d;
  l1a_l1s_com.dedic_set.radio_freq_d  = l1a_l1s_com.dedic_set.radio_freq;

  #if L1_GPRS
    // Propagate radio_freq for packet idle mode use (hopping).
    //-----------------------------------------------
    l1pa_l1ps_com.p_idle_param.radio_freq_dd = l1pa_l1ps_com.p_idle_param.radio_freq_d;
    l1pa_l1ps_com.p_idle_param.radio_freq_d  = l1pa_l1ps_com.p_idle_param.radio_freq;
  #endif

#if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX)
  }
#endif
}
#endif // L1_DSP_DYN_DWNLD
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

//------------------------------------------------------------------------------------------------

/*-------------------------------------------------------*/
/* l1s_dedicated_mode_manager()                          */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1s_dedicated_mode_manager()
{
  T_CHANNEL_DESCRIPTION  *chan1_desc_ptr;
  T_CHANNEL_DESCRIPTION  *chan2_desc_ptr;
  T_MOBILE_ALLOCATION    *alist_ptr;
  xSignalHeaderRec       *msg;
  BOOL                    process_assign_now = TRUE;

#if (FF_L1_TCH_VOCODER_CONTROL == 1)
  // Start vocoder

#if (L1_VOCODER_IF_CHANGE == 1)
    if (l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_ENABLE_COMMAND)
    {
      l1a_l1s_com.dedic_set.sync_tch = TRUE;
      l1a_l1s_com.dedic_set.vocoder_on = TRUE;
      l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_RESET_COMMAND;

      // Triton Audio ON/OFF Changes
#if (L1_AUDIO_MCU_ONOFF == 1)
      l1s.audio_on_off_ctl.l1_audio_switch_on_ul_request++;
      l1s.audio_on_off_ctl.l1_audio_switch_on_dl_request++;
#endif // L1_AUDIO_MCU_ONOFF

      msg = os_alloc_sig(0);
      DEBUGMSG(status,NU_ALLOC_ERR)
      msg->SignalCode = L1_VOCODER_CFG_ENABLE_CON;
      os_send_sig(msg, L1C1_QUEUE);
      DEBUGMSG(status,NU_SEND_QUEUE_ERR)
    }
    else if(l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_DISABLE_COMMAND)
    {
      l1a_l1s_com.dedic_set.vocoder_on = FALSE;
      l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_RESET_COMMAND;

      // Triton Audio ON/OFF Changes
#if (L1_AUDIO_MCU_ONOFF == 1)
      l1s.audio_on_off_ctl.l1_audio_switch_on_ul_request--;
      l1s.audio_on_off_ctl.l1_audio_switch_on_dl_request--;
#endif // L1_AUDIO_MCU_ONOFF

      msg = os_alloc_sig(0);
      DEBUGMSG(status,NU_ALLOC_ERR)
      msg->SignalCode = L1_VOCODER_CFG_DISABLE_CON;
      os_send_sig(msg, L1C1_QUEUE);
      DEBUGMSG(status,NU_SEND_QUEUE_ERR)
    }
#else
  #if (W_A_DSP_PR20037 == 1)
    if (l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_ENABLE_REQ)
    {
      l1a_l1s_com.dedic_set.sync_tch = TRUE;
      l1a_l1s_com.dedic_set.vocoder_on = TRUE;
      l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_ENABLED;
    }
    else if(l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_DISABLE_REQ)
    {
      l1a_l1s_com.dedic_set.vocoder_on = FALSE;
      l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_DISABLED;
    }
  #else // W_A_DSP_PR20037 == 0
    if (l1a_l1s_com.dedic_set.start_vocoder == TRUE)
    {
      l1a_l1s_com.dedic_set.start_vocoder = FALSE;
      l1a_l1s_com.dedic_set.sync_tch = TRUE;
      l1a_l1s_com.dedic_set.vocoder_on = TRUE;
    }
  #endif // W_A_DSP_PR20037
#endif // L1_VOCODER_IF_CHANGE
#endif // FF_L1_TCH_VOCODER_CONTROL == 1

  //=========================================
  // Process the new dedicated parameter set.
  //=========================================

#if ((REL99 == 1) && (FF_BHO == 1))
  if(l1a_l1s_com.dedic_set.long_rem_handover_type != BLIND_HANDOVER)
  {
#endif
  if(    (l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_ASSIGN_REQ)
      || (l1a_l1s_com.dedic_set.SignalCode == MPHC_SYNC_HO_REQ)
      || (l1a_l1s_com.dedic_set.SignalCode == MPHC_ASYNC_HO_REQ)  )
  {
    //Some pre-processing of the ASSIGNMENT/HANDOVER COMMANDS is required to reliably pass
    //GSM 11.10 17.1 where ASSIGNMENT from TCH/F -> TCH/F without
    //a start time must transmit on the new channel within 20ms
    //Also, should reduce muting/click on channel change

    if(    (l1a_l1s_com.dedic_set.fset->neig_sti_fn == -1 )
        && (l1a_l1s_com.dedic_set.fset->chan1.desc.channel_type == TCH_F)
        && (l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type == TCH_F) )
    {
      //ASSIGNMENT from TCH/F -> TCH/F immediately. Must wait until
      //the current FACCH boundary is complete, before processing the assignment
      //as the 20ms timer is started at the end of the last valid speech/FACCH block.

      UWORD32 facch_position = (l1s.next_time.fn_in_report % 13) % 4;

      if(facch_position == 1)
        process_assign_now = TRUE;
      else
        process_assign_now = FALSE;
    }
    else
    {
      process_assign_now = TRUE;
    }
    }
#if ((REL99 == 1) && (FF_BHO == 1))
  }
#endif

  // Now see if channel change commands are pending.....
  if(    (  l1a_l1s_com.dedic_set.SignalCode == MPHC_IMMED_ASSIGN_REQ )
      || ( (l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_ASSIGN_REQ) && (process_assign_now == TRUE) )
      || ( (l1a_l1s_com.dedic_set.SignalCode == MPHC_SYNC_HO_REQ)        && (process_assign_now == TRUE) )
      || ( (l1a_l1s_com.dedic_set.SignalCode == MPHC_ASYNC_HO_REQ)       && (process_assign_now == TRUE) )
      || (  l1a_l1s_com.dedic_set.SignalCode == MPHC_HANDOVER_FAIL_REQ)
      || (  l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANGE_FREQUENCY)  )
  // A new channel is given in fset...
  {
    #if 0	/* FreeCalypso TCS211 reconstruction */
      // Reset DTX AMR status
      #if (AMR == 1)
        l1s.dtx_amr_dl_on=FALSE;
      #endif
    #endif
    // When a Dedicated mode request is pending, L1S must be ran every frame
    // to be able to cope with STI.
    l1a_l1s_com.time_to_next_l1s_task = 0;

    // Set the default channel/description.
    //-------------------------------------

    chan1_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan1.desc;
    chan2_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan2.desc;
    alist_ptr      = &l1a_l1s_com.dedic_set.fset->ma.freq_list;

    // Starting time management.
    //==========================

    if(l1a_l1s_com.dedic_set.fset->neig_sti_fn != -1)
    // Starting time present.
    {
      WORD32  time_diff;
      WORD32  frame_shift=0;
      WORD32  tn_diff;

      tn_diff = l1a_l1s_com.tn_difference;

      if(tn_diff < 0)
      {
        frame_shift -= 1;
        tn_diff     += 8;
      }

      if((l1a_l1s_com.dedic_set.fset->cell_desc.time_alignmt + (tn_diff * BP_DURATION)) >= SWITCH_TIME)
        frame_shift += 1;

      time_diff = ( (l1a_l1s_com.dedic_set.fset->serv_sti_fn - 1) + frame_shift -
                    (l1s.next_time.fn % 42432) + 2*42432) % 42432;

      if(((time_diff >= (32024)) && (time_diff <= (42431))) || (time_diff == 0))
      // Starting time has been passed or the current frame corresponds to STARTING TIME...
      //  -> Reset STI (neig. domain and serv. domain) (set to -1).
      //  -> Channel description must be the one for After STI (default case).
      //  -> Frequency redefinition must be confirmed if any.
      // Rem: numbers come from GSM04.08, $10.5.2.38.
      // Rem: starting time detected 1 frame in adavance, this frame is used by
      //      SYNCHRO task.
      {
        l1a_l1s_com.dedic_set.fset->serv_sti_fn = -1;
        l1a_l1s_com.dedic_set.fset->neig_sti_fn = -1;

        #if (TRACE_TYPE!=0)
          // Trace "starting time" on log file and screen.
          trace_fct(CST_STI_PASSED, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        if(l1a_l1s_com.dedic_set.fset->freq_redef_flag == TRUE)
        // FREQUENCY REDEFINITION must be confirmed.
        {
          xSignalHeaderRec  *conf_msg;

          // Clear FREQUENY REDEFINITION flag.
          l1a_l1s_com.dedic_set.fset->freq_redef_flag = FALSE;

          // Alloc confirmation message...
          conf_msg = os_alloc_sig(sizeof(int));
          DEBUGMSG(status,NU_ALLOC_ERR)
          conf_msg->SignalCode = L1C_REDEF_DONE;

          // Send confirmation message...
          os_send_sig(conf_msg, L1C1_QUEUE);
          DEBUGMSG(status,NU_SEND_QUEUE_ERR)
        }
      }
      else
      //  -> Channel description must be the one for Before STI.
      {
        chan1_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan1.desc_bef_sti;
        chan2_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan2.desc_bef_sti;
        alist_ptr      = &l1a_l1s_com.dedic_set.fset->ma.freq_list_bef_sti;
      }
    }

    // Switch active channel to the new given one.
    //--------------------------------------------

    if(chan1_desc_ptr->channel_type != INVALID_CHANNEL)
    // The ongoing configuration for the new channel is valid.
    {
      UWORD8  current_channel_type = INVALID_CHANNEL;
      UWORD8  current_channel_mode = SIG_ONLY_MODE;
      UWORD8  new_channel_type     = chan1_desc_ptr->channel_type;

      if(l1a_l1s_com.dedic_set.aset != NULL)
      {
        current_channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type;
        current_channel_mode = l1a_l1s_com.dedic_set.aset->chan1.mode;
      }

      #if W_A_DSP1
        if(l1a_l1s_com.dedic_set.SignalCode != MPHC_CHANGE_FREQUENCY)
        {
          old_sacch_DSP_bug = TRUE;
        }
      #endif

      l1a_l1s_com.dedic_set.fset->chan1.desc_ptr = chan1_desc_ptr;
      l1a_l1s_com.dedic_set.fset->chan2.desc_ptr = chan2_desc_ptr;
      l1a_l1s_com.dedic_set.fset->ma.alist_ptr   = alist_ptr;


      // Keep Timing Advance from current active channel.
      if(l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_ASSIGN_REQ)
      {
        l1a_l1s_com.dedic_set.fset->new_timing_advance =
          l1a_l1s_com.dedic_set.aset->new_timing_advance;
        l1a_l1s_com.dedic_set.fset->timing_advance =
          l1a_l1s_com.dedic_set.aset->timing_advance;
      }

      // If current active channel is a TCH channel then we must inform the
      // DSP to stop any vocoder activity when leaving this channel.
      if(((current_channel_type == TCH_F) || (current_channel_type == TCH_H)) &&
         (new_channel_type != TCH_F) &&
         (new_channel_type != TCH_H))
      {
        l1a_l1s_com.dedic_set.stop_tch = TRUE;

	/*
	 * FreeCalypso TCS211 reconstruction: the following code
	 * appears to be a LoCosto-ism, so let's take it out.
	 */
      #if 0
        // If audio enabling was forced by L1S because of a HO failure, do not force it anymore.
        // Restore it in the state required by the MMI if the feature is compiled.
        if (l1a_l1s_com.audio_forced_by_l1s == TRUE)
        {
        #if (L1_EXTERNAL_AUDIO_VOICE_ONOFF == 1)
          if (l1a_l1s_com.audio_onoff_task.parameters.onoff_value == FALSE)
          {
            l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP;
          }
        #else // L1_EXTERNAL_AUDIO_VOICE_ONOFF
          l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP;
        #endif // L1_EXTERNAL_AUDIO_VOICE_ONOFF
          l1a_l1s_com.audio_forced_by_l1s = FALSE;
        }
      #endif
      }

      // The new channel becomes the ACTIVE one.
      l1a_l1s_com.dedic_set.aset = l1a_l1s_com.dedic_set.fset;

      // Active channel is CHAN1 by default.
      l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1);

      // Store new ciphering setting in MCU-DSP com.
      l1ddsp_load_ciph_param(l1a_l1s_com.dedic_set.aset->a5mode,
                             &(l1a_l1s_com.dedic_set.aset->ciph_key));

      // Set the TCH mode (DAI mode and DTX) in MCU-DSP com.
      l1ddsp_load_tch_mode(l1a_l1s_com.dedic_set.aset->dai_mode,
                           l1a_l1s_com.dedic_set.aset->dtx_allowed);

      // Dedicated set TXPWR command must be applied at once.
      l1s.applied_txpwr  = l1a_l1s_com.dedic_set.aset->new_target_txpwr;
      l1s.reported_txpwr = l1s.applied_txpwr;

      // Switch from current mode to DEDICATED MODE.
      l1a_l1s_com.mode = DEDIC_MODE;

      // Enable globally all dedicated tasks.
      l1a_l1s_com.l1s_en_task[DEDIC] = TASK_ENABLED;

      // Set SYNCHRO task enable flag -> synchro to the new serving cell.
      // Set "sync_tch" flag if TCH/F or TCH/H channel whatever the channel mode.
      // Rem: no synchro required when just changing the freq list.
      if(l1a_l1s_com.dedic_set.SignalCode != MPHC_CHANGE_FREQUENCY)
      {
        UWORD8  channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type;

        // TF 12/8/98 - the following line was moved from above to solve bad meas reports
        // after frequency redefinition bug.
        // Given beacon becomes the serving cell, download cell description
        // in the serving cell structure.
        l1a_l1s_com.Scell_info = l1a_l1s_com.dedic_set.aset->cell_desc;

     #if (AMR == 1)
        // Reset DTX AMR status
        l1s.dtx_amr_dl_on=FALSE;
     #endif

        if((channel_type == TCH_F) || (channel_type == TCH_H))
        {
        #if (FF_L1_TCH_VOCODER_CONTROL == 1)
          // With this feature, SACCH reset is controlled by L1, not sync_tch
          l1a_l1s_com.dedic_set.reset_sacch = TRUE;
        #endif
          l1a_l1s_com.dedic_set.sync_tch = TRUE;

          l1a_l1s_com.dedic_set.reset_facch = TRUE;
          // Reset DTX mode flags
          l1s.dtx_ul_on = FALSE;
          l1s.facch_bursts = -1;
        }

        // SYNCHRO task and its associated parameters (tn_difference, dl_tn and
        // dsp_scheduler_mode) are not Enabled/Updated if we are in the specific case:
        // L1A is touching SYNCHRO parameters and leave L1A to go in HISR (L1S)
        // in middle of the update (cf. BUG1339)
        if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
        {
          #if L1_GPRS
            // Select GSM DSP Scheduler.
            l1a_l1s_com.dsp_scheduler_mode = GSM_SCHEDULER;
          #endif

          // Enable SYNCHRO task to achive the new configuration. Since SYNCHRO
          // has the highest priority and the installation of this task in
          // the MFTAB is made after a CLEAR of the MFTAB, we insure that
          // any uncompleted task will be ABORTED.
          l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
        }

        #if IDS
          // Set b_itc (Information transfer capability) bits in d_ra_conf
          l1s_dsp_com.dsp_ndb_ptr->d_ra_conf = (UWORD16) l1a_l1s_com.dedic_set.aset->ids_mode;
        #endif
        #if (AMR == 1)
          // If the new channel mode to apply is an adaptative mode
          // then the AMR parameter must be transmitted to the DSP
           if ( (l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE) ||
               (l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AFS_MODE) )
          {
            // Transmit the AMR ver 1.0 settings to the DSP
            l1ddsp_load_amr_param(l1a_l1s_com.dedic_set.aset->amr_configuration,l1a_l1s_com.dedic_set.aset->cmip);

          #if (L1_AMR_NSYNC == 1)
            // AMR NSYNC bit: set to 0 by load_amr_param, set to 1 if HO from AMR cell to AMR cell, reset by DSP
            if ( (current_channel_mode == TCH_AFS_MODE) || (current_channel_mode == TCH_AHS_MODE) )
            {
            #if (FF_L1_TCH_VOCODER_CONTROL == 1)
              if(l1a_l1s_com.dedic_set.vocoder_on == TRUE)
              {
                l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT);
              }
            #else
              l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT);
            #endif
            }
          #endif

            // Set the flag to tell to DSP that a new AMR config is ready in the API memory
            l1a_l1s_com.dedic_set.sync_amr = TRUE;
          }
        #endif

        #if FF_L1_IT_DSP_DTX
          // Initialize timer for fast DTX availabilty
          l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY;
        #endif
      }

      // Set HO_ACCESS counter according to HO type.
      if(l1a_l1s_com.dedic_set.SignalCode == MPHC_ASYNC_HO_REQ)
      {
        UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type;

        l1a_l1s_com.dedic_set.aset->ho_acc_to_send = -1; // Send HO_ACCESS until...

        if((channel_type == TCH_F) || (channel_type == TCH_H))
          l1a_l1s_com.dedic_set.aset->t3124 = 70;  // Send HO_ACCESS for 320ms.
        else
          l1a_l1s_com.dedic_set.aset->t3124 = 147;   // Send HO_ACCESS for 675ms.
      }
      else
      if(l1a_l1s_com.dedic_set.SignalCode == MPHC_SYNC_HO_REQ)
        l1a_l1s_com.dedic_set.aset->ho_acc_to_send = 4;  // Send 4 HO_ACCESS.
      else
        l1a_l1s_com.dedic_set.aset->ho_acc_to_send = 0;  // No HO_ACCESS to send.

      if(l1a_l1s_com.dedic_set.SignalCode != MPHC_CHANGE_FREQUENCY)
      // Rem: no confirmation msg required when just changing the freq list.
      {
        // alloc confirmation message...
        msg = os_alloc_sig(sizeof(int));
        DEBUGMSG(status,NU_ALLOC_ERR)
        msg->SignalCode = L1C_DEDIC_DONE;

        // send confirmation message...
        os_send_sig(msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

        #if (TRACE_TYPE==5)
          trace_dedic();
        #endif

#if (FF_REPEATED_SACCH == 1)
            l1s.repeated_sacch.buffer_empty = TRUE;       //sacch buffer
            l1s.repeated_sacch.sro = 0;                   //BTS repetition order
            l1s.repeated_sacch.srr = 0;                   //MS repetition request
#endif /* (FF_REPEATED_SACCH == 1) */

#if ((FF_REPEATED_SACCH == 1) && (TRACE_TYPE == 1 || TRACE_TYPE == 4))
        trace_info.repeat_sacch.dl_count = 0;
        trace_info.repeat_sacch.dl_combined_good_count = 0;
	trace_info.repeat_sacch.dl_error_count	= 0;
        trace_info.repeat_sacch.srr= 0;
        trace_info.repeat_sacch.sro= 0;
        trace_info.repeat_sacch.dl_good_norep = 0;
        trace_info.repeat_sacch.dl_buffer_empty = TRUE;
#endif /* ((FF_REPEATED_SACCH == 1) && (TRACE_TYPE == 1 || TRACE_TYPE == 4))*/
        #if (TRACE_TYPE==1) || (TRACE_TYPE==4)
          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 )
        trace_info.facch_dl_combined_good_count = 0;    /* reported and chase combined also(2nd attempt) <=
                                                                                                                         facch_dl_good_block_reported */
        trace_info.facch_dl_repetition_block_count = 0;    /*represents duplicate not passed to PS */
        trace_info.facch_dl_count_all = 0;                          /* ALL FACCHS received good or bad*/
        trace_info.facch_dl_good_block_reported = 0;       /*  facch_dl_count */
        #endif /* (FF_REPEATED_DL_FACCH == 1 ) */
          trace_info.sacch_d_nerr = 0;
        #endif
	#if ( FF_REPEATED_DL_FACCH == 1)
        l1s.repeated_facch.pipeline[0].buffer_empty=l1s.repeated_facch.pipeline[1].buffer_empty=TRUE;
        if ( l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type == TCH_F) /* For TCH/F */
        {
                l1s.repeated_facch.counter_candidate=0;
                l1s.repeated_facch.counter=1;
        }
         if ( l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type == TCH_H) /* For TCH/H */
        {
                // l1s.repeated_facch.counter_candidate=l1s.repeated_facch.counter=0;
               /*  l1s.repeated_facch.counter_candidate=0;
                    l1s.repeated_facch.counter=1;*/
                    l1s.repeated_facch.counter_candidate=l1s.repeated_facch.counter=0;
        }
      #endif  /* (FF_REPEATED_DL_FACCH == 1 ) */
      }

      // Clear dedicated channel trigger message.
      l1a_l1s_com.dedic_set.SignalCode = NULL;

      // Clear the dedicated handover fail mode.
      l1a_l1s_com.dedic_set.handover_fail_mode = FALSE;
    }
  }

  else
  if(l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_MODE_MODIFY_REQ)
  // We must change the current channel mode for the given subchannel.
  {
    UWORD8  channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type;
    UWORD8  channel_mode = l1a_l1s_com.dedic_set.aset->chan1.mode;

    if((channel_type == TCH_F) || (channel_type == TCH_H))
    {
    #if (FF_L1_TCH_VOCODER_CONTROL == 1)
      // With this feature, SACCH reset is controlled by L1, not sync_tch
      l1a_l1s_com.dedic_set.reset_sacch = TRUE;
    #endif
      l1a_l1s_com.dedic_set.sync_tch = TRUE;
    }

    if(l1a_l1s_com.dedic_set.mode_modif.subchannel == l1a_l1s_com.dedic_set.aset->chan1.desc.subchannel)
      l1a_l1s_com.dedic_set.aset->chan1.mode = l1a_l1s_com.dedic_set.mode_modif.channel_mode;
    else
      l1a_l1s_com.dedic_set.aset->chan2.mode = l1a_l1s_com.dedic_set.mode_modif.channel_mode;
    #if (AMR == 1)
      // If the new channel mode to apply is an adaptative mode
      // then the AMR parameter must be transmitted to the DSP
      if ( (l1a_l1s_com.dedic_set.mode_modif.channel_mode == TCH_AHS_MODE) ||
           (l1a_l1s_com.dedic_set.mode_modif.channel_mode == TCH_AFS_MODE) )
      {
        // Transmit the AMR ver 1.0 settings to the DSP
        l1ddsp_load_amr_param(l1a_l1s_com.dedic_set.mode_modif.amr_configuration,C_AMR_CMIP_DEFAULT);

        #if (L1_AMR_NSYNC == 1)
          // AMR NSYNC bit: set to 0 by load_amr_param, set to 1 if HO from AMR cell to AMR cell, reset by DSP
          if ( (channel_mode == TCH_AFS_MODE) || (channel_mode == TCH_AHS_MODE) )
          {
#if (FF_L1_TCH_VOCODER_CONTROL == 1)
            if(l1a_l1s_com.dedic_set.vocoder_on == TRUE)
            {
              l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT);
            }
#else
            l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT);
#endif
          }
        #endif

        // Set the flag to tell to DSP that a new AMR config is ready in the API memory
        l1a_l1s_com.dedic_set.sync_amr = TRUE;
      }
    #endif

    // Reset input msg.
    l1a_l1s_com.dedic_set.SignalCode = NULL;
    #if FF_L1_IT_DSP_DTX
      // Initialize timer for fast DTX availabilty
      l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY;
    #endif
  }

  else
  if(l1a_l1s_com.dedic_set.SignalCode == MPHC_SET_CIPHERING_REQ)
  // Ciphering mode must change.
  {
    // Store new ciphering setting in MCU-DSP com.
    l1ddsp_load_ciph_param(l1a_l1s_com.dedic_set.aset->a5mode,
                           &(l1a_l1s_com.dedic_set.aset->ciph_key));

    // Reset input msg.
    l1a_l1s_com.dedic_set.SignalCode = NULL;
  }

  else
  if(l1a_l1s_com.dedic_set.SignalCode == MPHC_STOP_DEDICATED_REQ)
  // All channel must be aborted...
  {
    // Perform the functions below if there is active dedicated set.
    // This check is to take care of race condition which can happen
    // if MPHC_STOP_DEDICATED_REQ is receivedm before MPHC_HANDOVER_FAIL_REQ
#if 0	/* FreeCalypso TCS211 reconstruction */
    if (l1a_l1s_com.dedic_set.aset!=NULL)
    {
#endif

      // Stop TCH/F and TCH/H (stop Omega) (used in SYNCHRO task).
      UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type;
      if((channel_type == TCH_F) || (channel_type == TCH_H))
      {
        l1a_l1s_com.dedic_set.stop_tch = TRUE;

        /* FreeCalypso change: same situation as earlier in this function */
      #if 0
        // If audio enabling was forced by L1S because of a HO failure, do not force it anymore.
        // Restore it in the state required by the MMI if the feature is compiled.
        if (l1a_l1s_com.audio_forced_by_l1s == TRUE)
        {
        #if (L1_EXTERNAL_AUDIO_VOICE_ONOFF == 1)
          if (l1a_l1s_com.audio_onoff_task.parameters.onoff_value == FALSE)
          {
            l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP;
          }
        #else // L1_EXTERNAL_AUDIO_VOICE_ONOFF
          l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP;
        #endif // L1_EXTERNAL_AUDIO_VOICE_ONOFF
          l1a_l1s_com.audio_forced_by_l1s = FALSE;
        }
      #endif

      #if (AMR == 1)
        // Reset DTX AMR status
        l1s.dtx_amr_dl_on=FALSE;
      #endif

      }

      // Clear d_ra_conf => default value
      l1s_dsp_com.dsp_ndb_ptr->d_ra_conf = 0;

      // Clear ciphering setting in MCU-DSP com.
      l1ddsp_load_ciph_param(0, &(l1a_l1s_com.dedic_set.aset->ciph_key));

      // Reset the global dedicated enable flag.
      l1a_l1s_com.l1s_en_task[DEDIC] = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[DDL]   = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[DUL]   = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[ADL]   = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[AUL]   = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[TCHD]  = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED;
      l1a_l1s_com.l1s_en_task[TCHA]  = TASK_DISABLED;

#if 0	/* FreeCalypso TCS211 reconstruction */
    }
    else
    {
      /* FreeCalypso change: same AUDIO_TASK situation as earlier */
      #if 0
        if (l1a_l1s_com.audio_forced_by_l1s == TRUE)
        {
          #if (L1_EXTERNAL_AUDIO_VOICE_ONOFF == 1)
            if (l1a_l1s_com.audio_onoff_task.parameters.onoff_value == FALSE)
            {
              l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP;
            }
          #else // L1_EXTERNAL_AUDIO_VOICE_ONOFF
            l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP;
          #endif // L1_EXTERNAL_AUDIO_VOICE_ONOFF
          l1a_l1s_com.audio_forced_by_l1s = FALSE;
        }
      #endif
      #if (AMR == 1)
        // Reset DTX AMR status
        l1s.dtx_amr_dl_on=FALSE;
      #endif

      // Clear d_ra_conf => default value
      l1s_dsp_com.dsp_ndb_ptr->d_ra_conf = 0;
    }
#endif	/* FreeCalypso TCS211 reconstruction */

    // Reset input msg.
    l1a_l1s_com.dedic_set.SignalCode = NULL;
    #if ((REL99 == 1) && (FF_BHO == 1))
      // this is required in BHO as you need to retain the previous channel info.
      //This is checked in HO_REQ to L1S.....In normal handover this does not happen
      if(l1a_l1s_com.dedic_set.handover_type == NORMAL_HANDOVER)
      {
        // Reset active dedicated set.
        l1a_l1s_com.dedic_set.aset = NULL;
      }
    #else
      // Reset active dedicated set.
      l1a_l1s_com.dedic_set.aset = NULL;
    #endif

    // SYNCHRO task and its associated parameters (tn_difference, dl_tn and
    // dsp_scheduler_mode) are not Enabled/Updated if we are in the specific case:
    // L1A is touching SYNCHRO parameters and leave L1A to go in HISR (L1S)
    // in middle of the update (cf. BUG1339)
    if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
    {
      // The code shall always goes here as the upper layers are not allowed to send new
      // requests that can change the layer1 timing reference before the MPHC_STOP_DEDICATED_REQ
      // has been confirmed by the MPHC_STOP_DEDICATED_CON.

      // Since SYNCHRO has the highest priority and the installation of
      // this task in the MFTAB is made after a CLEAR of the MFTAB, we
      // insure that any uncompleted task will be ABORTED.
      l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;

      // The dedicated mode will be aborted within the current TDMA frame,
      // L1S confirm to L1A that the dedicated mode is stopped.
      // alloc confirmation message...
      msg = os_alloc_sig(sizeof(int));
      DEBUGMSG(status,NU_ALLOC_ERR)
      msg->SignalCode = L1C_STOP_DEDICATED_DONE;

      // send confirmation message...
      os_send_sig(msg, L1C1_QUEUE);
      DEBUGMSG(status,NU_SEND_QUEUE_ERR)
    }

#if ((REL99 == 1) && (FF_BHO == 1))
    // Check whether above stop dedicated mode procedure is done due
    // to blind handover request.
    if(l1a_l1s_com.dedic_set.handover_type == BLIND_HANDOVER)
    {
      // MPHC_STOP_DEDICATED was due to blind handover.

      // Set semaphores for FBSB task

      // Store the info from request message.
      l1a_l1s_com.nsync_fbsb.radio_freq      = l1a_l1s_com.dedic_set.bcch_carrier_of_nbr_cell;
      l1a_l1s_com.nsync_fbsb.fn_offset       = 0;
      l1a_l1s_com.nsync_fbsb.time_alignmt    = 0;
      l1a_l1s_com.nsync_fbsb.fb_found_attempt = 0;

      // Enable FBSB task
      l1a_l1s_com.l1s_en_task[FBSB] = TASK_ENABLED;
    }
  #endif // #if ((REL99 == 1) && (FF_BHO == 1))
  }

  else
  if((l1a_l1s_com.dedic_set.SignalCode == OML1_START_DAI_TEST_REQ) ||
     (l1a_l1s_com.dedic_set.SignalCode == OML1_STOP_DAI_TEST_REQ))
  // New DAI mode given...
  // We must store the mode in NDB and resynchronize the speech.
  {
    // Set the TCH mode (DAI mode and DTX) in MCU-DSP com.
    l1ddsp_load_tch_mode(l1a_l1s_com.dedic_set.aset->dai_mode,
                         l1a_l1s_com.dedic_set.aset->dtx_allowed);

    // Reset input msg.
    l1a_l1s_com.dedic_set.SignalCode = NULL;
  }

  //=============================================
  // Process the ongoing dedicated parameter set.
  //=============================================

  if((!(l1a_l1s_com.l1s_en_task[SYNCHRO] == TASK_ENABLED)) &&
     (l1a_l1s_com.dedic_set.aset != NULL))
  // No synchro performed this frame.
  //  -> process current active dedicated parameter set.
  {
    // TCH/SDCCH statistics or Frame Error rate :
    // must wait for Dedicated mode setting ....
    #if (TRACE_TYPE==3)
      if (l1_stats.wait_time > 0 ) l1_stats.wait_time--;
    #endif

    //-------------------
    // TXPWR controle...
    //-------------------

    // Save last applied TXPWR to be reported.
    // Get TXPWR to be applied in the next 13 frames.
    if((l1s.next_time.fn_in_report % 13) == 0)
    {
      l1s.reported_txpwr = l1s.applied_txpwr;
      l1s.applied_txpwr  = l1ctl_txpwr(l1a_l1s_com.dedic_set.aset->new_target_txpwr,
                                       l1s.applied_txpwr);
    }

    //----------------------------
    // Timing Advance controle...
    //----------------------------

    // Timing advance is updated for the 1st frame of the reporting period
    // with new value coming from SACCH(L1 header).
    if(l1s.next_time.fn_in_report == 0)
    {
      l1a_l1s_com.dedic_set.aset->timing_advance =
        l1a_l1s_com.dedic_set.aset->new_timing_advance;
    }

    //-------------------------------------
    // Set the default channel/description.
    //-------------------------------------

    chan1_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan1.desc;
    chan2_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan2.desc;
    alist_ptr      = &l1a_l1s_com.dedic_set.aset->ma.freq_list;

    // Active channel is CHAN1 by default.
    //------------------------------------
    l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1);


    //-----------------------------
    // Starting time management...
    //-----------------------------

    if(l1a_l1s_com.dedic_set.aset->serv_sti_fn != -1)
    // Starting time present.
    //-----------------------
    {
      WORD32  time_diff;

      time_diff = (l1a_l1s_com.dedic_set.aset->neig_sti_fn -
                   (l1s.next_time.fn % 42432) + 2*42432) % 42432;

      if(((time_diff >= (32024)) && (time_diff <= (42431))) || (time_diff == 0))
      // Starting time has been passed or the current frame corresponds to STARTING TIME...
      //-----------------------------------------------------------------------------------
      //  -> Reset STI (neig. domain and serv. domain) (set to -1).
      //  -> Channel description must be the one for After STI (default case).
      //  -> Frequency redefinition must be confirmed if any.
      // Rem: numbers come from GSM04.08, $10.5.2.38.
      {
        l1a_l1s_com.dedic_set.aset->serv_sti_fn = -1;
        l1a_l1s_com.dedic_set.aset->neig_sti_fn = -1;

        #if (TRACE_TYPE!=0)
          // Trace "starting time" on log file and screen.
          trace_fct(CST_STI_PASSED, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        if(l1a_l1s_com.dedic_set.aset->freq_redef_flag == TRUE)
        // FREQUENCY REDEFINITION must be confirmed.
        {
          xSignalHeaderRec  *conf_msg;

          // Clear FREQUENY REDEFINITION flag.
          l1a_l1s_com.dedic_set.aset->freq_redef_flag = FALSE;

          // Alloc confirmation message...
          conf_msg = os_alloc_sig(sizeof(int));
          DEBUGMSG(status,NU_ALLOC_ERR)
          conf_msg->SignalCode = L1C_REDEF_DONE;

          // Send confirmation message...
          os_send_sig(conf_msg, L1C1_QUEUE);
          DEBUGMSG(status,NU_SEND_QUEUE_ERR)
        }
        #if FF_L1_IT_DSP_DTX
          // Initialize timer for fast DTX availabilty
          l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY;
        #endif
      }
      else
      //  -> Channel description must be the one for Before STI.
      {
        chan1_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan1.desc_bef_sti;
        chan2_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan2.desc_bef_sti;
        alist_ptr      = &l1a_l1s_com.dedic_set.aset->ma.freq_list_bef_sti;
      }
    }

    //---------------------------
    // Set the active parameters.
    //---------------------------
    l1a_l1s_com.dedic_set.aset->chan1.desc_ptr = chan1_desc_ptr;
    l1a_l1s_com.dedic_set.aset->chan2.desc_ptr = chan2_desc_ptr;
    l1a_l1s_com.dedic_set.aset->ma.alist_ptr   = alist_ptr;

    //-------------------------------------------------------
    // Enable Dedicated mode tasks according to channel type.
    //-------------------------------------------------------
    switch(l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type)
    {
      case SDCCH_8:
      case SDCCH_4:
      {
        l1a_l1s_com.l1s_en_task[DDL]   = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[DUL]   = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[ADL]   = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[AUL]   = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHD]  = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHA]  = TASK_DISABLED;
      }
      break;

      case TCH_F:
      {
        l1a_l1s_com.l1s_en_task[DDL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[DUL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[ADL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[AUL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHD]  = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHTF] = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[TCHA]  = TASK_ENABLED;
      }
      break;

      case TCH_H:
      {
        l1a_l1s_com.l1s_en_task[DDL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[DUL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[ADL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[AUL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHTH] = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[TCHD]  = TASK_ENABLED;
        l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHA]  = TASK_ENABLED;
      }
      break;
    }

    //----------------------------------------------
    // Set the active subchannel (case of 2 TCH/H-).
    //----------------------------------------------

    if(l1a_l1s_com.dedic_set.aset->chan2.desc.channel_type == TCH_H)
    // 2 TCHH channels are maintained... Swap from one to the other each frame.
    {
      UWORD8  fn_mod13;

      // Get FN % 13.
      fn_mod13 = l1s.actual_time.t2;  if(fn_mod13 >= 13) fn_mod13 -= 13;

      if((fn_mod13) == (2*(fn_mod13/2)))
      // Current "FN %13" is EVEN, we must set the active channel pointer
      // to the channel maintaining the subchannel 1.
      {
        if(l1a_l1s_com.dedic_set.aset->chan1.desc.subchannel == 1)
          l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1);
        else
          l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan2);
      }
      else
      // Current "FN %13" is ODD, we must set the active channel pointer
      // to the channel maintaining the subchannel 0.
      {
        if(l1a_l1s_com.dedic_set.aset->chan1.desc.subchannel == 0)
          l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1);
        else
          l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan2);
      }
    }

    //-----------------------------------------------------------------
    // T3124 timer management (HO, physical information management)...
    //-----------------------------------------------------------------

    if(l1a_l1s_com.dedic_set.aset->t3124 != 0)
    // Waiting for "PHYSICAL INFORMATION" message from BTS.
    {
      // Decrement T3124 timer.
      l1a_l1s_com.dedic_set.aset->t3124--;

      if(l1a_l1s_com.dedic_set.aset->t3124 == 0)
      // TIMEOUT: send L1C_HANDOVER_FINISHED message with a TIMEOUT indication.
      {
        UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type;

        // Stop TCH/F and TCH/H (stop Omega) (used in SYNCHRO task)
        if((channel_type == TCH_F) || (channel_type == TCH_H))
        {
          l1a_l1s_com.dedic_set.stop_tch = TRUE;

	/*
	 * FreeCalypso change: same AUDIO_TASK conditional issue as earlier.
	 */
	#if 0
          // CQ: Force the Audio ON to avoid having the DSP reseting the VDLON and producing a pop noise
          // on single ended outputs.
          l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_ON_START;
          l1s.l1_audio_it_com = TRUE;
          l1a_l1s_com.audio_forced_by_l1s = TRUE;
	#endif
        }

	/*
	 * FreeCalypso: the following code has been reconstructed from the
	 * TCS211 binary object; it appears neither in the LoCosto nor
	 * in the TSM30 source.
	 */
        #if (AEC)
	  if((l1s.aec.aec_control & 0x0002) || (l1s.aec.aec_control & 0x0004)) {
	    l1s.aec.aec_control = l1a_l1s_com.aec_task.parameters.aec_control
				  | 0x0001;
	    l1s_dsp_com.dsp_ndb_ptr->d_aec_ctrl = l1s.aec.aec_control;
	  }
        #endif

        // Clear ciphering setting in MCU-DSP com.
        l1ddsp_load_ciph_param(0, &(l1a_l1s_com.dedic_set.aset->ciph_key));

        // Reset the global dedicated enable flag.
        l1a_l1s_com.l1s_en_task[DEDIC] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[DDL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[DUL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[ADL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[AUL]   = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHD]  = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED;
        l1a_l1s_com.l1s_en_task[TCHA]  = TASK_DISABLED;

        // Reset active dedicated set.
        l1a_l1s_com.dedic_set.aset = NULL;

        // Enter to the handover fail mode.
        l1a_l1s_com.dedic_set.handover_fail_mode = TRUE;

        // SYNCHRO task and its associated parameters (tn_difference, dl_tn and
        // dsp_scheduler_mode) are not Enabled/Updated if we are in the specific case:
        // L1A is touching SYNCHRO parameters and leave L1A to go in HISR (L1S)
        // in middle of the update (cf. BUG1339)
        if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
        {
          // Since SYNCHRO has the highest priority and the installation of
          // this task in the MFTAB is made after a CLEAR of the MFTAB, we
          // insure that any uncompleted task will be ABORTED.
          l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
        }

        // Handover access procedure is completed.
        // -> send L1C_HANDOVER_FINISHED message with "cause = TIMEOUT" to L1A.
        l1s_send_ho_finished(HO_TIMEOUT);
      }
    }
  #if FF_L1_IT_DSP_DTX
    // ASET validity check (cleared upon handover timeout)
    if (l1a_l1s_com.dedic_set.aset != NULL)
    {
      // Handover in progress (equals -1 if asynchronous)
      if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0)
        // Initialize timer for fast DTX availabilty
        l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY;

      // Dedicated channel mode change. Fast DTX interrupt can be used after some time
      if (l1a_apihisr_com.dtx.fast_dtx_ready_timer == FAST_DTX_LATENCY)
      {
        // Clear DTX interrupt condition
        l1a_apihisr_com.dtx.pending   = FALSE;
        // Enable TX activity
        l1a_apihisr_com.dtx.tx_active = TRUE;
        // No DTX status awaited
        l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE;

        // Fast DTX shall not be used for a while
        l1a_apihisr_com.dtx.fast_dtx_ready = FALSE;
      }

      // Fast DTX latency timer handling (not on idle frame)
      if ((l1a_apihisr_com.dtx.fast_dtx_ready_timer > 0) && (l1s.next_time.fn_mod13 != 12))
        l1a_apihisr_com.dtx.fast_dtx_ready_timer--;

      // Timeout processed on a DTX block status boundary
      else if (l1a_apihisr_com.dtx.fast_dtx_ready_timer == 0)
      {
        UWORD8 channel_type;
        UWORD8 subchannel;

        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;

        // Wait for DTX status boundary to enable Fast DTX use
        if ((((channel_type == TCH_F) ||
              ((channel_type == TCH_H) && (subchannel == 0))) && // TCH-AFS and TCH-AHS0
             (l1s.actual_time.fn_mod13_mod4 == 3)) ||            // DTX status reported during TDMA3
            (((channel_type == TCH_H) && (subchannel == 1)) &&   // TCH-AHS1
             (l1s.next_time.fn_mod13_mod4 == 1))                 // DTX status reported during TDMA0
           )
        {
          l1a_apihisr_com.dtx.fast_dtx_ready = TRUE;
        }
      }
    }
  #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

#if FF_L1_IT_DSP_USF

  /*-------------------------------------------------------*/
  /* l1usf_apihisr()                                       */
  /*-------------------------------------------------------*/
  /*                                                       */
  /* Description:                                          */
  /* ------------                                          */
  /* This function is called from the HISR handling the    */
  /* processing of the DSP USF IT interrupt. It is         */
  /* triggered upon USF decoding completion, once the      */
  /* results have been reported in API.                    */
  /* Operations executed:                                  */
  /* 1) MACS allocation update                             */
  /* 2) DSP programming                                    */
  /* 3) ABB (APC, ramps) programming                       */
  /* 4) TCR measurement handling                           */
  /* 5) TPU scenario enabling and API DB pages switch      */
  /*                                                       */
  /*-------------------------------------------------------*/

  void l1usf_apihisr(void)
  {
    // Make sure the interrupt was expected
    if (l1ps_macs_com.usf_status == USF_AWAITED)
    {
      // Flags the USF HISR before MACS/L1S update
      l1ps_macs_com.usf_status = USF_IT_DSP;

      // Test if PDTCH task is running
      if (l1s.task_status[PDTCH].current_status != INACTIVE)
      {
        // MACS allocation update (allocation then TPU, DSP and ABB)
        l1ps_ctrl_pdtch(PDTCH, BURST_3);

        // Packet transfer meas. manager update (PM control pipelines)
        l1ps_transfer_meas_manager();

        // End manager update (TPU enable and API DB switches)
        l1s_end_manager();
      }

      // Test if PRACH task is running
      else if (l1s.task_status[PRACH].current_status == ACTIVE)
      {
        // PRACH control
        l1ps_ctrl_prach(PRACH, BURST_3);

        // Packet meas. manager update (PM control pipelines)
        l1ps_meas_manager();

        // End manager update (TPU enable and API DB switches)
        l1s_end_manager();
      }

      // USF validity is no more pending
      l1ps_macs_com.usf_status = USF_AVAILABLE;
    }

    // Clear USF pending condition
    l1a_apihisr_com.usf.pending = FALSE;
  }

#endif // FF_L1_IT_DSP_USF

#if FF_L1_IT_DSP_DTX

  /*-------------------------------------------------------*/
  /* l1dtx_apihisr()                                       */
  /*-------------------------------------------------------*/
  /*                                                       */
  /* Description:                                          */
  /* ------------                                          */
  /* This function is called from the HISR handling the    */
  /* processing of the DSP DTX IT interrupt. It is         */
  /* triggered once DTX status is available and reported   */
  /* in API.                                               */
  /* Operations executed:                                  */
  /* 1) TX/DSP part of TCH programming                     */
  /* 2) Dedicated mode BA list measurements handling       */
  /* 3) TPU scenario enabling and API DB pages switch      */
  /*                                                       */
  /*-------------------------------------------------------*/

  void l1dtx_apihisr(void)
  {
    // Make sure the interrupt was expected
    if (l1a_apihisr_com.dtx.dtx_status == DTX_AWAITED)
    {
      // Flags the DTX HISR before L1S update
      l1a_apihisr_com.dtx.dtx_status = DTX_IT_DSP;

      // Latch TX activity status
      if (l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enc_data)
        l1a_apihisr_com.dtx.tx_active = TRUE;
      else
        l1a_apihisr_com.dtx.tx_active = FALSE;

      // TCH/F is running, invoke its control function
      if (l1a_l1s_com.l1s_en_task[TCHTF] == TASK_ENABLED)
        l1s_ctrl_tchtf(TCHTF, NO_PAR);

      // TCH/H is running, invoke its control function
      else if (l1a_l1s_com.l1s_en_task[TCHTH] == TASK_ENABLED)
        l1s_ctrl_tchth(TCHTH, NO_PAR);

      // Dedicated mode measurement manager
      l1s_meas_manager();

      // End manager update (TPU enable and API DB switches)
      l1s_end_manager();

      // DTX status is no more pending
      l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE;
    }

    // Clear DTX pending condition
    l1a_apihisr_com.dtx.pending = FALSE;
  }

#endif // FF_L1_IT_DSP_DTX

#if (FF_L1_FAST_DECODING == 1)
void l1_fast_decoding_apihisr(void)
{
 /* Tracks if a fast paging burst will be performed, an IT will happen */
  BOOL new_IT_awaited = FALSE;

  /* Clear the pending condition */
  l1a_apihisr_com.fast_decoding.pending = FALSE;

  /* In case semaphore of a task gets set in between force CRC error to be true */
  if(l1a_l1s_com.task_param[l1a_apihisr_com.fast_decoding.task] == SEMAPHORE_SET)
  {
    l1a_apihisr_com.fast_decoding.crc_error = TRUE;
  }
  /* Make sure the interrupt was expected */
  if (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_AWAITED)
  {
    /* Update the status */
    l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_PROCESSING;

    /* Check the NP/PNP burst number, if this is the 4th one nothing has */
    /* to be done (usual scheduling)                                     */
    if (l1a_apihisr_com.fast_decoding.deferred_control_req)
    {
      l1a_apihisr_com.fast_decoding.deferred_control_req = FALSE;

      /* Retrieve decoding status from the DSP */
      if (l1a_apihisr_com.fast_decoding.crc_error)
      {
        /* Block decoding failed, more bursts must be received */
        switch(l1a_apihisr_com.fast_decoding.task)
        {
          case NP:
          {
            l1s_ctrl_snb_dl(NP, l1a_apihisr_com.fast_decoding.burst_id);
            new_IT_awaited = TRUE;
            break;
          } /* case NP: */
#if L1_GPRS
          case PNP:
          {
            l1ps_ctrl_snb_dl(PNP, l1a_apihisr_com.fast_decoding.burst_id);
            new_IT_awaited = TRUE;
            break;
          } /* case PNP: */
#endif /* L1_GPRS */

        case NBCCHS:
          {
            l1s_ctrl_snb_dl(NBCCHS, l1a_apihisr_com.fast_decoding.burst_id);
            new_IT_awaited = TRUE;
            break;
          } /* case NBCCHS */

        } /* switch(l1a_apihisr_com.fast_decoding.task) */
      }   /* end if CRC error */
      else /* if (l1a_apihisr_com.fast_decoding.crc_error == TRUE) */
      {
#if L1_GPRS
        /* Decoding OK so no new control so no new IT to expect */
        /* reading normal burst in packet idle mode on a different timeslot so need to restore synchro*/
        if (   (l1a_apihisr_com.fast_decoding.task == NP)
            && (l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED)
            && (l1s.algo_change_synchro_active)
           )
        {
          /* Ensure that synchro back is executed in the NMO II or III */
          l1s_restore_synchro();
          l1s.ctrl_synch_before = FALSE;
          l1s.algo_change_synchro_active = FALSE;
        }
#endif /* L1_GPRS */
      } /* end else no CRC error */

      /* In any case power measurements schedulers and end of frame processing */
      /* must be executed now                                                  */
#if L1_GPRS
      /* Packet Measurement Manager */
      l1ps_meas_manager();
#endif
      /* Measurement Manager */
      l1s_meas_manager();
      /* End Manager */
      l1s_end_manager();
    }
    else /* if (l1a_apihisr_com.fast_decoding.control_required) */
    {
      /* No new control so no new IT to expect */
    }
  } /* if (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_AWAITED) */
  else
  {
    /* Interrupt received but not expected, this shouldn't happen */
    l1_trace_IT_DSP_error(IT_DSP_ERROR_FAST_DECODING_UNEXP);
  }

  /* Status update depending on CRC and the scheduling of another bursts */
  if (new_IT_awaited)
  {
    /* New IT awaited */
    l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_AWAITED;
  }
  else if (l1a_apihisr_com.fast_decoding.crc_error == FALSE)
  {
    /* No new IT awaited, the CRC is OK, fast decoding is complete */
    l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_COMPLETE;
  }
  else
  {
    /* No new IT awaited and CRC is still fail, typically 4th burst received */
    /* but decoding has failed.                                              */
    l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE;
  }
}   /* end function l1_fast_decoding_apihisr */
#endif /* FF_L1_FAST_DECODING */

//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM