view src/cs/layer1/p_cfile/l1p_sync.c @ 478:5e39123540e6

hybrid fw: Openmoko-mimicking AT@BAND command implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 14 Jun 2018 06:04:54 +0000
parents 0740b5ff15f6
children
line wrap: on
line source

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

#define  L1P_SYNC_C

//#pragma DUPLICATE_FOR_INTERNAL_RAM_START

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

#if L1_GPRS

#if (CODE_VERSION == SIMULATION)
  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.h"
  #include "l1_time.h"
  #include <l1_trace.h>
  #if TESTMODE
    #include "l1tm_defty.h"
  #endif
  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_defty.h"
  #endif
  #if (L1_GTT == 1)
    #include "l1gtt_const.h"
    #include "l1gtt_defty.h"
  #endif
  #if (L1_MP3 == 1)
    #include "l1mp3_defty.h"
  #endif
  #if (L1_MIDI == 1)
    #include "l1midi_defty.h"
  #endif
  #include "l1_defty.h"
  #include "cust_os.h"
  #include "l1_msgty.h"
  #include "l1_varex.h"
  #include "l1_signa.h"
  #include "l1_proto.h"

  #if L2_L3_SIMUL
    #include "hw_debug.h"
  #endif

  #include "l1p_cons.h"
  #include "l1p_msgt.h"
  #include "l1p_deft.h"
  #include "l1p_vare.h"
  #include "l1p_prot.h"
  #include "l1p_mfta.h"
  #include "l1p_sign.h"
  #include "l1p_macr.h"
  #include "l1p_proto.h"
#else
  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.h"
  #include "l1_time.h"

  #if TESTMODE
    #include "l1tm_defty.h"
  #endif
  #if (AUDIO_TASK == 1)
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_defty.h"
  #endif
  #if (L1_GTT == 1)
    #include "l1gtt_const.h"
    #include "l1gtt_defty.h"
  #endif
  #if (L1_MP3 == 1)
    #include "l1mp3_defty.h"
  #endif
  #if (L1_MIDI == 1)
    #include "l1midi_defty.h"
  #endif
  #include "l1_defty.h"
  #include "cust_os.h"
  #include "l1_msgty.h"
  #include "l1_varex.h"
  #include "l1_signa.h"
  #include "l1_proto.h"
  #include "l1_trace.h"

  #if L2_L3_SIMUL
    #include "hw_debug.h"
  #endif

  #include "l1p_cons.h"
  #include "l1p_msgt.h"
  #include "l1p_deft.h"
  #include "l1p_vare.h"
  #include "l1p_prot.h"
  #include "l1p_mfta.h"
  #include "l1p_sign.h"
  #include "l1p_macr.h"
#endif

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

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

/*-------------------------------------------------------*/
/* Prototypes of external functions used in this file.   */
/*-------------------------------------------------------*/
void   l1ps_tcr_ctrl           (UWORD8 pm_position);
void   l1pddsp_meas_ctrl       (UWORD8 nbmeas, UWORD8 pm_pos);
void   l1pddsp_meas_read       (UWORD8 nbmeas, UWORD8 *pm_read);
void   l1pctl_transfer_agc_init();
UWORD8 l1pctl_pgc              (UWORD8 pm, UWORD8 last_known_il, UWORD8 lna_off, UWORD16 radio_freq);
void   l1ps_bcch_meas_ctrl     (UWORD8 ts);

//#pragma DUPLICATE_FOR_INTERNAL_RAM_END


#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

/*-------------------------------------------------------*/
/* l1ps_transfer_mode_manager()                          */
/*-------------------------------------------------------*/
/* Parameters :                                          */
/* Return     :                                          */
/* Functionality :                                       */
/*-------------------------------------------------------*/
void l1ps_transfer_mode_manager()
{
  BOOL   block_boundary = TRUE;
  UWORD8 current_assignment_command = NO_TBF;
  #if FF_TBF
    BOOL   tbf_update_synchro_forced = FALSE;
  #endif

  //====================================
  // NEW configuration management
  //====================================

  if(!l1pa_l1ps_com.transfer.semaphore)
  // IF Transfer parameter structure protected,
  //   No action within L1S.
  {
    WORD8  i;
    UWORD8 min_synchro_ts = 7;
    BOOL   new_tbf_installed = FALSE;
    T_PACKET_TA *current_ta_config;

    // In packet transfer mode, we only detect STI at block boundaries in order to udpate the
    // ASET structure after the last Control of the previous TBF
    if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
    {
      if ((l1s.next_time.fn_mod13 != 0)&&(l1s.next_time.fn_mod13 != 4)&&
           (l1s.next_time.fn_mod13 != 8))
      {
        block_boundary = FALSE;
      }
    }
    // Delay STI detection when a poll response hasn't already been answered
    // for transition to Packet transfer mode
    else if (l1a_l1s_com.l1s_en_task[POLL] == TASK_ENABLED)
    {
      block_boundary = FALSE;
    }

    // LOOK FOR NEW ASSIGNMENT...
    //===========================

    // Consider both FREE SET...
    for(i=0;i<2;i++)
    {
      // Is there a new transfer channel provided in "fset[i]"?
      if(((l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_ASSIGNMENT_REQ) && (block_boundary == TRUE)) ||
         (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_SINGLE_BLOCK_REQ))
      {
        if(l1pa_l1ps_com.transfer.fset[i]->tbf_sti.present)
        // Starting time present.
        // Rem: starting time detected 1 frame in advance, this frame is used by
        //      SYNCHRO task.
        {
          WORD32  time_diff;
          WORD8   frame_shift=0;
          WORD8   tn_diff;


          // In packet idle mode, L1 must detect if the synchronization change will happen
          // from a timeslot N to a timeslot M < N because in this case, a frame is skipped
          // and the MS is ready two frames after the synchronization change... a radio
          // block can be missed...
          // In packet transfer, the SYNCHRO task will always been executed on BURST 1, that let
          // 2 frames before the new TBF starts
          if (l1a_l1s_com.l1s_en_task[PDTCH] != TASK_ENABLED)
          {
            frame_shift -= 1;

            tn_diff = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot -
                      l1a_l1s_com.dl_tn;

            if(tn_diff < 0)
              frame_shift -= 1;
          }
//TBF_changes

          #if FF_TBF
            // PDTCH task is enabled
            else
            {
              // Pseudo TBF for Two phase access, new TBF configuration has to
              // be installed for Starting Time taking into account that a
              // SYNCHRO task has to be scheduled before.
              if ((l1pa_l1ps_com.transfer.aset->allocated_tbf == UL_TBF) &&
                  (l1pa_l1ps_com.transfer.aset->pseudo_tbf_two_phase_acc))
              {
                 // Note: We are at block boundary.
                 if ((l1s.next_time.fn_mod13 == 0) || (l1s.next_time.fn_mod13 == 4))
                   frame_shift -= 4;
                 else // i.e. (l1s.next_time.fn_mod13 == 8)
                   frame_shift -= 5;
              }

              // Two phase access establishment on PACCH (therefore there is an
              // ongoing uplink TBF).
              if ((l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == UL_TBF) &&
                  (l1pa_l1ps_com.transfer.fset[i]->pseudo_tbf_two_phase_acc))
              {
                 // Make sure single/multi block allocation
                 // if a synchro task has to be inserted i.e. :
                 // -> we are currently in EGPRS mode
                 // -> and/or we change synchronization timeslot
                 if ( (l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot != l1a_l1s_com.dl_tn)
                    #if L1_EGPRS
                      || (l1pa_l1ps_com.transfer.aset->egprs_param.tbf_mode == TBF_MODE_EGPRS)
                    #endif
                      )
                 {
                   // Note: We are at block boundary.
                   if ((l1s.next_time.fn_mod13 == 0) || (l1s.next_time.fn_mod13 == 4))
                     frame_shift -= 4;
                   else // i.e. (l1s.next_time.fn_mod13 == 8)
                     frame_shift -= 5;
                 }
              }
            }
          #endif


          time_diff = ( (l1pa_l1ps_com.transfer.fset[i]->tbf_sti.absolute_fn) +
                        frame_shift - (l1s.next_time.fn % 42432) + 2*42432) % 42432;

          if((time_diff >= (32024)) && (time_diff <= (42431)))
          // Starting time has been passed...
          //---------------------------------
          {
            // For SINGLE BLOCK case, an error must be reported to L3.
            if(l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_SINGLE_BLOCK_REQ)
            {
              xSignalHeaderRec *msg;

              // Send confirmation msg to L3/MACA.
              msg = os_alloc_sig(sizeof(T_MPHP_SINGLE_BLOCK_CON));
              DEBUGMSG(status,NU_ALLOC_ERR)

              ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->purpose       =
                l1pa_l1ps_com.transfer.fset[i]->assignment_command;
              ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->assignment_id =
                l1pa_l1ps_com.transfer.fset[i]->assignment_id;

              ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->status        = SINGLE_STI_PASSED;

              msg->SignalCode = L1P_SINGLE_BLOCK_CON;

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

              // Do not reset "tbf_sti.present".

              // Ignore the SINGLE BLOCK requested.
              l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL;
            }
            else
            {
              // Reset "tbf_sti.present" flag to take into account the new
              // configuration.
              l1pa_l1ps_com.transfer.fset[i]->tbf_sti.present = FALSE;
            }
          }
          else
          if(time_diff == 0)
          // Starting time corresponds to current frame...
          //----------------------------------------------
          {
            // Reset "tbf_sti.present" flag to take into account the new
            // configuration.
            l1pa_l1ps_com.transfer.fset[i]->tbf_sti.present = FALSE;
          }
          else
          // Starting time hasn't already been reached...
          //---------------------------------------------
          {
            // time_to_next_l1s_task updated with time to sti
            Select_min_time(time_diff, l1a_l1s_com.time_to_next_l1s_task);
          }
        }

        // Do we switch to a new transfer configuration?
        // We have to switch if, new set STI is passed.
        if(!l1pa_l1ps_com.transfer.fset[i]->tbf_sti.present)
        {
          // Install new configuration immediately.
          // Rem: the new channel will start at a block boundary because by construction
          // PDTCH task is started every block boundary.
          T_TRANSFER_SET   *transfer_set;

          // STI has been passed, we must switch to the new config.

          #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 FF_TBF
            // Forces a SYNCHRO task prior to new TBF configuration if
            // -> Coming from 2 phases access TBF
            // -> Coming from (Packet) Idle
            if (((l1pa_l1ps_com.transfer.aset->allocated_tbf == UL_TBF) &&
                 (l1pa_l1ps_com.transfer.aset->pseudo_tbf_two_phase_acc))
                || (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_DISABLED)
               )
            {
               // Can not be merged with test above evaluated only when a
               // starting time is present in the message.
               tbf_update_synchro_forced = TRUE;
            }
          #endif
          if (current_assignment_command == NO_TBF)
            current_assignment_command = l1pa_l1ps_com.transfer.fset[i]->assignment_command;
          else if ((current_assignment_command == UL_TBF) ||
                   (current_assignment_command == DL_TBF))
            current_assignment_command = BOTH_TBF;

          // Check if anything to keep from previous configuration.
          // Select the best timeslot for timebase synchro.

          if(l1pa_l1ps_com.transfer.aset->allocated_tbf != NO_TBF)
          {
            UWORD8  synchro_ts;

            // Check if required to take TA from previous packet assignment
            // if TA not valid in new assignment command
            if ( l1pa_l1ps_com.transfer.fset[i]->packet_ta.ta == 255)
            {
              // new TA value to be taken from previous packet TA
              l1pa_l1ps_com.transfer.fset[i]->packet_ta.ta = l1pa_l1ps_com.transfer.aset->packet_ta.ta;
            }

            switch(l1pa_l1ps_com.transfer.fset[i]->assignment_command)
            {
              case DL_TBF:
              {
                // If any, keep the UL allocation from previous set.
                if((l1pa_l1ps_com.transfer.aset->allocated_tbf == UL_TBF) ||
                   (l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF))
                {
                  T_UL_RESSOURCE_ALLOC *ul_ptr;

                  // Swap the pointers on UL parameter structures
                  ul_ptr = l1pa_l1ps_com.transfer.fset[i]->ul_tbf_alloc;
                  l1pa_l1ps_com.transfer.fset[i]->ul_tbf_alloc  =
                    l1pa_l1ps_com.transfer.aset->ul_tbf_alloc;
                  l1pa_l1ps_com.transfer.aset->ul_tbf_alloc = ul_ptr;

                  l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = BOTH_TBF;
                  l1pa_l1ps_com.transfer.fset[i]->ul_tbf_synchro_timeslot  =
                    l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;

                  // Chose min synchro timeslot from UL and DL TBFs.
                  if(l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot <
                     l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot)
                  {
                    synchro_ts = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;
                  }
                  else
                  {
                    synchro_ts = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot;
                  }
                }

                // No UL TBF running, select the new DL TBF synchro timeslot.
                else
                {
                  synchro_ts = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot;
                }
              }
              break;

              case UL_TBF:
              {
                // If any, keep the DL allocation from previous set.

                if((l1pa_l1ps_com.transfer.aset->allocated_tbf == DL_TBF) ||
                   (l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF))
                {
                  l1pa_l1ps_com.transfer.fset[i]->dl_tbf_alloc  =
                    l1pa_l1ps_com.transfer.aset->dl_tbf_alloc;
                  l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = BOTH_TBF;
                  l1pa_l1ps_com.transfer.fset[i]->dl_tbf_synchro_timeslot  =
                    l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot;

                  // Chose min synchro timeslot from UL and DL TBFs.
                  if(l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot <
                     l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot)
                  {
                    synchro_ts = l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot;
                  }
                  else
                  {
                    synchro_ts = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot;
                  }
                }

                // No DL TBF running, select the new UL TBF synchro timeslot.
                else
                {
                  synchro_ts = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot;
                }

                // Reset Repeat allocation starting time checking
                l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation = FALSE;
                // Reset Allocation Exhaustion detection flag
                l1ps_macs_com.fix_alloc_exhaust_flag                  = FALSE;
              }
              break;

              case BOTH_TBF:
              case NO_TBF:
              default:
              {
                // Nothing to keep, everything (UL & DL) is replaced.
                synchro_ts = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot;

                // Reset Repeat allocation starting time checking
                l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation = FALSE;
                // Reset Allocation Exhaustion detection flag
                l1ps_macs_com.fix_alloc_exhaust_flag                  = FALSE;
              }
              break;

            } // end of switch(...assignment_command)

            if(synchro_ts < min_synchro_ts)
              min_synchro_ts = synchro_ts;

          } // end of if(...allocated_tbf != NO_TBF)

          else
          {
            min_synchro_ts = l1pa_l1ps_com.transfer.fset[i]->transfer_synchro_timeslot;
          }

          // New set becomes active and old becomes free.

          // Save a pointer on currently used PTCCH parameters
          current_ta_config = &l1pa_l1ps_com.transfer.aset->packet_ta;

          transfer_set                                  = l1pa_l1ps_com.transfer.aset;
          l1pa_l1ps_com.transfer.aset                   = l1pa_l1ps_com.transfer.fset[i];
          l1pa_l1ps_com.transfer.fset[i]                = transfer_set;
          l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF;

          l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = min_synchro_ts;

          // Set local flag.
          new_tbf_installed = TRUE;

          if(l1pa_l1ps_com.transfer.aset->SignalCode == MPHP_ASSIGNMENT_REQ)
          // Assignement confirmation message is sent
          {
            xSignalHeaderRec *msg;

            // Send confirmation msg to L3/MACA.
            msg = os_alloc_sig(sizeof(T_L1P_TRANSFER_DONE));
            DEBUGMSG(status,NU_ALLOC_ERR)

            msg->SignalCode = L1P_TRANSFER_DONE;

            ((T_L1P_TRANSFER_DONE *) (msg->SigP))->assignment_id =
              l1pa_l1ps_com.transfer.aset->assignment_id;

            // Insert "t_difference" information in L1P_TRANSFER_DONE msg
            // will be used in Ncell Dedic6 state machine to request a reset
            // or not of the state machine
            ((T_L1P_TRANSFER_DONE *) (msg->SigP))->tn_difference =
              min_synchro_ts - l1a_l1s_com.dl_tn;


            // detect the Transition IDLE -> Transfer
            if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
               ((T_L1P_TRANSFER_DONE *) (msg->SigP))->Transfer_update = TRUE;
            else
               ((T_L1P_TRANSFER_DONE *) (msg->SigP))->Transfer_update = FALSE;


            os_send_sig(msg, L1C1_QUEUE);
            DEBUGMSG(status,NU_SEND_QUEUE_ERR)
          }

          // New config has been acknowledeged, clear SignalCode...
          l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL;
          l1pa_l1ps_com.transfer.aset->SignalCode    = NULL;

        } // end if(...tbf_sti.present)
      } // end of if(...SignalCode == MPHP_ASSIGNMENT_REQ)
    }

    if(new_tbf_installed == TRUE)
    {
      // Start the new configuration
      //----------------------------

      // Enable PACKET tasks.
      {
        // Set assignment_command to the last enabled TBF type.
        // This permits MAC-S to correctly manage TBF boundary conditions.
        l1pa_l1ps_com.transfer.aset->assignment_command = current_assignment_command;

        // Flag the new configuration to MACS.
        l1ps_macs_com.new_set = TRUE;

        // Flag the new configuration in order to update the Read set parameters
        // in the first Read phase of the new TBF
        // This permits to start using the new aset parameters for the first Control of
        // the first block of the new TBF and to keep the parameters needed for the
        // last read phase of the last block of the previous TBF.
        l1ps.read_param.new_set = TRUE;

// TBF_changes
        #if !FF_TBF
        // We need to detect that we just leaving CS/P Idle mode to enter
        // in Packet Transfer mode. Then we have to enable SYNCHRO task on dectection
        // of a mode change (Idle or Packet idle -> Packet transfer).
        // Note: This check can't be gathered with the one done a little bit later
        // on tn_difference and SINGLE task from the fact that the allocated_tbf
        // is checked and PDTCH enabled.
        if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
        {
          if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_DISABLED)
          {
            l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
            l1a_l1s_com.dsp_scheduler_mode = GPRS_SCHEDULER;
          }
        }
        #endif

        // Disable interference measurements
        l1a_l1s_com.l1s_en_task[ITMEAS]  = TASK_DISABLED;

        // Check for Continuous Timing advance procedure.
        // Enable PTCCH task if required.
        if((l1pa_l1ps_com.transfer.aset->packet_ta.ta_index != 255) &&
           (l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn    != 255))
        {
          // No action when the configuration is the same as the current one.
          if((l1pa_l1ps_com.transfer.aset->packet_ta.ta_index != current_ta_config->ta_index) ||
             (l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn    != current_ta_config->ta_tn) ||
             (l1a_l1s_com.l1s_en_task[PTCCH] == TASK_DISABLED))
          // The configuration is different than the current one or no PTCCH is currently running
          // (for example in packet idle)
          {
            // Reset PTCCH execution variables.
            l1pa_l1ps_com.transfer.ptcch.activity   = 0;
            l1pa_l1ps_com.transfer.ptcch.request_dl = FALSE;

            // Enable PTCCH task.
            l1a_l1s_com.l1s_en_task[PTCCH] = TASK_ENABLED;
          }
        }
        else
        // PTCCH is not configured.
        {
          // Disable PTCCH task.
          l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;
        }

        // Transfer AGC initialization
        l1pctl_transfer_agc_init();

        switch(l1pa_l1ps_com.transfer.aset->allocated_tbf)
        {
          case SINGLE_BLOCK_UL:
          {
            // Set SINGLE execution variables.
            l1pa_l1ps_com.transfer.single_block.activity = SINGLE_UL; // UL enabled

            // Enable SINGLE task.
            l1a_l1s_com.l1s_en_task[SINGLE] = TASK_ENABLED;
          }
          break;

          case SINGLE_BLOCK_DL:
          {
            // Set SINGLE execution variables.
            l1pa_l1ps_com.transfer.single_block.activity = SINGLE_DL; // DL enabled

            // Enable SINGLE task.
            l1a_l1s_com.l1s_en_task[SINGLE] = TASK_ENABLED;
          }
          break;

          case TWO_PHASE_ACCESS:
          {
            // Set SINGLE execution variables.
            l1pa_l1ps_com.transfer.single_block.activity |= SINGLE_DL; // DL enabled
            l1pa_l1ps_com.transfer.single_block.activity |= SINGLE_UL; // UL enabled

            // Enable SINGLE task.
            l1a_l1s_com.l1s_en_task[SINGLE] = TASK_ENABLED;
          }
          break;

          default:
          {
            /*
             * FreeCalypso: removal of the following line is
             * TCS211 reconstruction
             */
            //if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)
            //In case of transition idle to transfer the Packet transfer mode is set when synchro is executed
            // Layer 1 internal mode is set to PACKET TRANSFER MODE.
            l1a_l1s_com.mode = PACKET_TRANSFER_MODE;

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

            // Need to disable SINGLE task for two phase access case
            l1a_l1s_com.l1s_en_task[SINGLE] = TASK_DISABLED;
          }
          break;
        } // End switch()

        // 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)
        // Note: tn_difference has to be accumulated in order to cope with the
        // specific case: L1A has just updated tn_difference, dl_tn and dsp_scheduler_mode
        // parameters and we enter in the HISR after the reset of the SYNCHRO Semaphore.
        if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
        {
          // Save the "timeslot difference" between new and old configuration
          // in "tn_difference".
          //   tn_difference -> loaded with the number of timeslot to shift.
          //   dl_tn         -> loaded with the new timeslot.
          l1a_l1s_com.tn_difference += min_synchro_ts - l1a_l1s_com.dl_tn;
          l1a_l1s_com.dl_tn          = min_synchro_ts;

          #if !FF_TBF
          // Enable SYNCHRO task only if lowest allocated timeslot changed
          // or if each time the SINGLE task is enabled
          // In the specific case of the SINGLE task, the GPRS_SCHEDULER
          // has to be selected.
          if((l1a_l1s_com.tn_difference != 0) ||
             (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED))
          {
            l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
            l1a_l1s_com.dsp_scheduler_mode = GPRS_SCHEDULER;
          }
          #else
            // Enable SYNCHRO task if at least one of these conditions fulfilled:
            // -> Change in the timeslot synhronization
            // -> Change of the ongoing TBF mode (synchro_forced)
            // -> Exit of two phase access (synchro_forced)
            // -> Coming from (Packet) Idle (synchro forced)
            // -> SINGLE task enabled
            if((l1a_l1s_com.tn_difference != 0) ||
               (tbf_update_synchro_forced) ||
               (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED))
            {
              l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;

               l1a_l1s_com.dsp_scheduler_mode = GPRS_SCHEDULER;
            }
          #endif
        }
        else
        {}// L1A is touching dl_tn, tn_difference and dsp_scheduler_mode parameters...
      }
    }

    // LOOK FOR TIMING AVANCE UPDATE
    //===============================

    if(l1pa_l1ps_com.transfer.ptcch.ta_update_cmd == TRUE)
    {
      #define CURRENT_TA_CONFIG l1pa_l1ps_com.transfer.aset->packet_ta
      #define NEW_TA_CONFIG     l1pa_l1ps_com.transfer.ptcch.packet_ta

      // Only update if the assignment_id of the running TBF matches with the assignment_id
      // given in the MPHP_TIMING_ADVANCE_REQ message
      if (l1pa_l1ps_com.transfer.ptcch.assignment_id == l1pa_l1ps_com.transfer.aset->assignment_id)
      {
        xSignalHeaderRec *msg;

        // Immediate Update of PACKET TA structure.
        //-----------------------------------------

        // Update TA value only if a new value is provided.
        if(NEW_TA_CONFIG.ta != 255)
          CURRENT_TA_CONFIG.ta = NEW_TA_CONFIG.ta;

        if((NEW_TA_CONFIG.ta_index != 255) &&
           (NEW_TA_CONFIG.ta_tn    != 255))
        // There is a New PTCCH configuration.
        {
          // No action when the configuration is the same as the current one.

          if((NEW_TA_CONFIG.ta_index != CURRENT_TA_CONFIG.ta_index) ||
             (NEW_TA_CONFIG.ta_tn    != CURRENT_TA_CONFIG.ta_tn))
          // The configuration is different than the current one.
          {
            // Download the new configuration.
            CURRENT_TA_CONFIG.ta_index = NEW_TA_CONFIG.ta_index;
            CURRENT_TA_CONFIG.ta_tn    = NEW_TA_CONFIG.ta_tn;

            // Reset PTCCH execution variables.
            l1pa_l1ps_com.transfer.ptcch.activity   = 0;
            l1pa_l1ps_com.transfer.ptcch.request_dl = FALSE;

            // Enable PTCCH task.
            l1a_l1s_com.l1s_en_task[PTCCH] = TASK_ENABLED;
          }
        }
        else
        // PTCCH is not configured.
        {
          // Diable PTCCH task.
          l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;
        }

        // Send confirmation message to L3.
        msg = os_alloc_sig(sizeof(T_MPHP_TIMING_ADVANCE_CON));
        DEBUGMSG(status,NU_ALLOC_ERR)

        msg->SignalCode = L1P_TA_CONFIG_DONE;
        ((T_MPHP_TIMING_ADVANCE_CON *) msg->SigP)->assignment_id =
          l1pa_l1ps_com.transfer.aset->assignment_id;

        os_send_sig(msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

      } // End if "assignment_id of the running TBF matches"

      // Reset Control code.
      l1pa_l1ps_com.transfer.ptcch.ta_update_cmd = FALSE;

    } // End if(...ta_update_cmd == TRUE)

    // LOOK FOR PSI PARAMETERS UPDATE
    //===============================

    if(l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd == TRUE)
    {
      // Update parameters
      l1a_l1s_com.Scell_info.pb        = l1pa_l1ps_com.transfer.psi_param.Scell_pb;
      l1pa_l1ps_com.access_burst_type  = l1pa_l1ps_com.transfer.psi_param.access_burst_type;

      // Reset Control code.
      l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = FALSE;
    }

    /***********************************************************/
    /* TBF release, PDCH release, Repeat allocation, Fixed     */
    /* allocation exhaustion                                   */
    /***********************************************************/

    // These events are only taken into account on block boundaries
    // in order to keep the "aset" structure unchanged for all the control phases
    // of the last block before modification

    if(block_boundary)
    {
      // LOOK FOR TBF TO BE RELEASED...
      //===============================

      if(l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd == TRUE)
      {
        xSignalHeaderRec *msg;

//TBF_changes
        #if !FF_TBF
        switch(l1pa_l1ps_com.transfer.tbf_release_param.released_tbf)
        #else
          UWORD8 released_tbf;

          // Special case if we got a request to release a two phase access TBF:
          // It is registered within ASET structure as an uplink TBF. If we are
          // currently in pseudo TBF for two phase access, we process the request
          // like an uplink release, otherwise we skip it and just send the
          // L1P_TBF_RELEASED to L1A.

          released_tbf = l1pa_l1ps_com.transfer.tbf_release_param.released_tbf;

          if (released_tbf == TWO_PHASE_ACCESS)
          {
            if (l1pa_l1ps_com.transfer.aset->pseudo_tbf_two_phase_acc)
              released_tbf = UL_TBF;
            else
              released_tbf = NO_TBF;
          }

          switch(released_tbf)
       #endif
        {
          case UL_TBF:
          {
            if(l1pa_l1ps_com.transfer.aset->allocated_tbf == UL_TBF)
            {
              // Disable PDTCH task.
              l1a_l1s_com.l1s_en_task[PDTCH] = TASK_DISABLED;
              // Disable PTCCH task.
              l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;

              // Free the active set.
              l1pa_l1ps_com.transfer.aset->allocated_tbf = NO_TBF;
            }
            else
            if(l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF)
            {
              // Still DL_TBF running.
              // We must synchro to the 1st timeslot of DL_TBF.

              // REM: the new configuration is not flagged to MACS via "l1ps_macs_com.new_set"
              // since MACS will detect the alloc change.

              // Active set becomes DL TBF.
              l1pa_l1ps_com.transfer.aset->allocated_tbf = DL_TBF;

              // 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)
              // Note: tn_difference has to be accumulated in order to cope with the
              // specific case: L1A has just updated tn_difference, dl_tn and dsp_scheduler_mode
              // parameters and we enter in the HISR after the reset of the SYNCHRO Semaphore.
              if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
              {
                l1a_l1s_com.tn_difference += l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot - l1a_l1s_com.dl_tn;
                l1a_l1s_com.dl_tn          = l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot;

                // Enable SYNCHRO task only when camp timeslot is changed.
                if(l1a_l1s_com.tn_difference != 0)
                {
                  l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
                }
              }

              // Diable PTCCH if timeslot doesn't match with the remaining DL TBF allocation
              if (!((0x80 >> l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn) &
                    l1pa_l1ps_com.transfer.aset->dl_tbf_alloc.timeslot_alloc))
              {
                // Disable PTCCH task.
                l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;

                #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
                  l1_trace_ptcch_disable();
                #endif
              }

            }

            // Reset Repeat allocation starting time checking
            l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation = FALSE;
            // Reset Allocation Exhaustion detection flag
            l1ps_macs_com.fix_alloc_exhaust_flag                  = FALSE;
            #if L1_EDA
              // Disable FB/SB task detection mechanism for MS class 12
              l1ps_macs_com.fb_sb_task_detect = FALSE;
            #endif
          }
          break;

          case DL_TBF:
          {
            if(l1pa_l1ps_com.transfer.aset->allocated_tbf == DL_TBF)
            {
              // Disable PDTCH task.
              l1a_l1s_com.l1s_en_task[PDTCH] = TASK_DISABLED;
              // Disable PTCCH task.
              l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;

              // Free the active set.
              l1pa_l1ps_com.transfer.aset->allocated_tbf = NO_TBF;
            }
            else
            if(l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF)
            {
              // Still UL_TBF running.
              // We must synchro to the 1st timeslot of UL_TBF.

              // REM: the new configuration is not flagged to MACS via "l1ps_macs_com.new_set"
              // since MACS will detect the alloc change.

              // Active set becomes UL TBF.
              l1pa_l1ps_com.transfer.aset->allocated_tbf = UL_TBF;

              // 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)
              // Note: tn_difference has to be accumulated in order to cope with the
              // specific case: L1A has just updated tn_difference, dl_tn and dsp_scheduler_mode
              // parameters and we enter in the HISR after the reset of the SYNCHRO Semaphore.
              if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
              {
                l1a_l1s_com.tn_difference += l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot - l1a_l1s_com.dl_tn;
                l1a_l1s_com.dl_tn          = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;

                // Enable SYNCHRO task only when camp timeslot is changed.
                if(l1a_l1s_com.tn_difference != 0)
                {
                  l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
                }
              }

              // Diable PTCCH if timeslot doesn't match with the remaining UL TBF allocation
              if (!((0x80 >> l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn) &
                    l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->timeslot_alloc))
              {
                // Disable PTCCH task.
                l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;

                #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
                  l1_trace_ptcch_disable();
                #endif
              }

            }
          }
          break;

          case BOTH_TBF:
          {
            // No more TBF...
            // Disable PDTCH task.
            l1a_l1s_com.l1s_en_task[PDTCH] = TASK_DISABLED;
            // Disable PTCCH task.
            l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;

            // Free the active set.
            l1pa_l1ps_com.transfer.aset->allocated_tbf = NO_TBF;

            // Reset Repeat allocation starting time checking
            l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation = FALSE;
            // Reset Allocation Exhaustion detection flag
            l1ps_macs_com.fix_alloc_exhaust_flag                  = FALSE;
            #if L1_EDA
              // Disable FB/SB task detection mechanism for MS class 12
              l1ps_macs_com.fb_sb_task_detect = FALSE;
            #endif
          }
          break;

        }

        // Send confirmation msg to L3/MACA.
        msg = os_alloc_sig(sizeof(T_L1P_TBF_RELEASED));
        DEBUGMSG(status,NU_ALLOC_ERR)

        msg->SignalCode = L1P_TBF_RELEASED;

        // initialize the TBF type for the confirmation msg
        ((T_L1P_TBF_RELEASED *) msg->SigP)->tbf_type = l1pa_l1ps_com.transfer.tbf_release_param.released_tbf;

        if (l1pa_l1ps_com.transfer.aset->allocated_tbf == NO_TBF)
        {
          /*
           * FreeCalypso: removal of the following line is
           * TCS211 reconstruction
           */
          //l1ps.read_param.assignment_id = 0x01; /* default non initialised value for next tbf */

          ((T_L1P_TBF_RELEASED *) msg->SigP)->released_all = TRUE;

          #if (DSP == 33) || (DSP == 34) || (DSP == 35) || (DSP == 36) || (DSP == 37)
            // Correction of BUG1041: reset of multislot bit in d_bbctrl_gprs
            // when leaving patcket transfer.
            l1ps_dsp_com.pdsp_ndb_ptr->d_bbctrl_gprs = l1_config.params.bbctrl;
          #endif
        }
        else
        {
          ((T_L1P_TBF_RELEASED *) msg->SigP)->released_all = FALSE;
        }

        // Insert "tn_difference" information in L1P_TBF_RELEASED msg
        // will be used in Ncell Dedic6 state machine to request a reset
        // or not of the state machine.
        ((T_L1P_TBF_RELEASED *) (msg->SigP))->tn_difference = l1a_l1s_com.tn_difference;

        os_send_sig(msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

        // Flag the new configuration in order to update the Read set parameters
        // with the "aset" structure modifications in the first PDTCH Read phase
        // after configuration change
        l1ps.read_param.new_set = TRUE;

        // Reset Control code.
        l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd = FALSE;
      }

      // LOOK FOR PDCH TO BE RELEASED...
      //================================

      if(l1pa_l1ps_com.transfer.pdch_release_param.pdch_release_cmd == TRUE)
      {
        xSignalHeaderRec *msg;
        UWORD8           timeslot,timeslot_alloc;

        // PDCH Release only apply if the assignement_id of the running TBF matches
        // with the assignment_id included in the MPHP_PDCH_RELEASE_REQ message
        if (l1pa_l1ps_com.transfer.pdch_release_param.assignment_id == l1pa_l1ps_com.transfer.aset->assignment_id)
        {

          // Update timeslot allocation bitmaps
          l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->timeslot_alloc &= l1pa_l1ps_com.transfer.pdch_release_param.timeslot_available;
          l1pa_l1ps_com.transfer.aset->dl_tbf_alloc.timeslot_alloc  &= l1pa_l1ps_com.transfer.pdch_release_param.timeslot_available;

          // Process the downlink TBF first allocated timeslot
          timeslot_alloc = l1pa_l1ps_com.transfer.aset->dl_tbf_alloc.timeslot_alloc;
          timeslot       = 0;

          while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot)))
          {
            timeslot++;
          }

          l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot   = timeslot;

          // Process the uplink TBF first allocated timeslot
          timeslot_alloc = l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->timeslot_alloc;
          timeslot = 0;
        #if L1_EDA
          // Dynamic allocation mode or Extended Dynamic allocation mode
          if((l1pa_l1ps_com.transfer.aset->mac_mode == DYN_ALLOC) || (l1pa_l1ps_com.transfer.aset->mac_mode == EXT_DYN_ALLOC))
        #else
          // Dynamic allocation mode
          if(l1pa_l1ps_com.transfer.aset->mac_mode == DYN_ALLOC)
        #endif
          {
            while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot)))
            {
              timeslot++;
            }
          }
          else
          // Fixed allocation mode
          if(l1pa_l1ps_com.transfer.aset->mac_mode == FIX_ALLOC_NO_HALF)
          {
            // If the control timeslot hasn't been released
            if (l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->timeslot_alloc &
                 (0x80 >> l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->fixed_alloc.ctrl_timeslot))
            {
              // The first allocated timeslot is the control timeslot
              timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->fixed_alloc.ctrl_timeslot;
            }
            else
            {
              // The first allocated timeslot is found in the allocation bitmap
              while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot)))
              {
                timeslot++;
              }
            }
          }

          l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot   = timeslot;

          // Fill "synchro_timeslot" which will be the frame synchro slot.
          switch(l1pa_l1ps_com.transfer.aset->allocated_tbf)
          {
            case(DL_TBF):
            {
              l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot;
            }
            break;

            case(UL_TBF):
            {
              l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;
            }
            break;

            case(BOTH_TBF):
            {
              if (l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot > l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot)
              {
                l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;
              }
              else
              {
                l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot;
              }
            }
            break;
          }

          // 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)
          // Note: tn_difference has to be accumulated in order to cope with the
          // specific case: L1A has just updated tn_difference, dl_tn and dsp_scheduler_mode
          // parameters and we enter in the HISR after the reset of the SYNCHRO Semaphore.
          if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
          {
            // New synchronization
            l1a_l1s_com.tn_difference += l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot - l1a_l1s_com.dl_tn;
            l1a_l1s_com.dl_tn          = l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot;

            // REM: the new configuration is not flagged to MACS via "l1ps_macs_com.new_set"
            // since MACS will detect the alloc change.

            // Enable SYNCHRO task only when camp timeslot is changed.
            if(l1a_l1s_com.tn_difference != 0)
            {
              l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
            }
          }

          // Disable PTCCH if timeslot doesn't match with the remaining PDCH allocation
          if (!((0x80 >> l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn) &
                l1pa_l1ps_com.transfer.pdch_release_param.timeslot_available))
          {
            // Disable PTCCH task.
            l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED;

            #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
              l1_trace_ptcch_disable();
            #endif
          }

          // Send confirmation msg to L3/MACA.
          msg = os_alloc_sig(sizeof(T_L1P_PDCH_RELEASE_CON));
          DEBUGMSG(status,NU_ALLOC_ERR)

          msg->SignalCode = L1P_PDCH_RELEASED;

          ((T_L1P_PDCH_RELEASE_CON *) msg->SigP)->assignment_id = l1pa_l1ps_com.transfer.pdch_release_param.assignment_id;

          // Insert "tn_difference" information in T_L1P_PDCH_RELEASE_CON msg
          // will be used in Ncell Dedic6 state machine to request a reset
          // or not of the state machine
          ((T_L1P_PDCH_RELEASE_CON *) (msg->SigP))->tn_difference = l1a_l1s_com.tn_difference;

          os_send_sig(msg, L1C1_QUEUE);
          DEBUGMSG(status,NU_SEND_QUEUE_ERR)

          // Flag the new configuration in order to update the Read set parameters
          // with the "aset" structure modifications in the first PDTCH Read phase
          // after configuration change
          l1ps.read_param.new_set = TRUE;

        } // End if "assignment_id matches with the running TBF"

        // Reset Control code.
        l1pa_l1ps_com.transfer.pdch_release_param.pdch_release_cmd = FALSE;
      }

      // LOOK FOR REPEAT ALLOCATION ...
      //================================

      if(l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation)
      {
        UWORD8           timeslot,timeslot_alloc;

        // Starting time checking...
        //--------------------------

        if(l1pa_l1ps_com.transfer.repeat_alloc.tbf_sti.present)
        // Starting time present.
        // Rem: starting time detected 1 frame in advance, this frame is used by
        //      SYNCHRO task.
        {
          WORD32  time_diff;

          // If synchro change occurs, it's always from a timeslot N to N + 1
          time_diff = ( (l1pa_l1ps_com.transfer.repeat_alloc.tbf_sti.absolute_fn - 1)
                         - (l1s.next_time.fn % 42432) + 2*42432) % 42432;

          // Starting time has been passed...
          if(((time_diff >= (32024)) && (time_diff <= (42431))) || (time_diff == 0))
          {
            l1pa_l1ps_com.transfer.repeat_alloc.tbf_sti.present = FALSE;
          }
        } // End if "starting time present"

        // Starting time passed...
        //------------------------

        // If the repeat allocation starts on this frame...
        if (!l1pa_l1ps_com.transfer.repeat_alloc.tbf_sti.present)
        {
          #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

          // Update ts_override and starting time
          l1pa_l1ps_com.transfer.aset->ts_override         = l1pa_l1ps_com.transfer.repeat_alloc.ts_override;
          l1pa_l1ps_com.transfer.aset->tbf_sti.absolute_fn = l1pa_l1ps_com.transfer.repeat_alloc.tbf_sti.absolute_fn;

          // Lowest allocated timeslot for the UL TBF

          // If the downlink control timeslot hasn't been released: it's the downlink control timeslot
          // Else no change
          if (  l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->timeslot_alloc
                & (0x80 >> l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->fixed_alloc.ctrl_timeslot))
          {
            // Synchronization on the downlink control timeslot
            l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->fixed_alloc.ctrl_timeslot;
          }

          // Synchronization

          // If a downlink TBF is enabled
          if ( l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF)
          {
            // Synchronization on the downlink TBF lowest allocated timeslot ?
            if (l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot > l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot)
              l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->dl_tbf_synchro_timeslot;
            else
              l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;
          }
          // Else: synchronization on the uplink TBF lowest allocated timeslot
          else
            l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;

          // 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)
          // Note: tn_difference has to be accumulated in order to cope with the
          // specific case: L1A has just updated tn_difference, dl_tn and dsp_scheduler_mode
          // parameters and we enter in the HISR after the reset of the SYNCHRO Semaphore.
          if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
          {
            l1a_l1s_com.tn_difference += l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot - l1a_l1s_com.dl_tn;
            l1a_l1s_com.dl_tn          = l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot;

            // Enable SYNCHRO task only when camp timeslot is changed.
            if(l1a_l1s_com.tn_difference != 0)
            {
              l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
            }
          }

          // Set assignment_command to the last enabled TBF type.
          // This permits MAC-S to correctly manage TBF boundary conditions.
          if ((current_assignment_command == NO_TBF) || (current_assignment_command == UL_TBF))
            l1pa_l1ps_com.transfer.aset->assignment_command = UL_TBF;
          else
            l1pa_l1ps_com.transfer.aset->assignment_command = BOTH_TBF;

          // Flag the new configuration to MACS.
          l1ps_macs_com.new_set = TRUE;

          // Flag the new configuration in order to update the Read set parameters
          // with the "aset" structure modifications in the first PDTCH Read phase
          // after configuration change
          l1ps.read_param.new_set = TRUE;

          // Reset Repeat allocation starting time checking
          l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation = FALSE;
          // Reset Allocation Exhaustion detection flag
          l1ps_macs_com.fix_alloc_exhaust_flag                  = FALSE;

          // Send confirmation
          {
            xSignalHeaderRec *msg;

            // Send confirmation msg to L3/MACA.
            msg = os_alloc_sig(sizeof(T_L1P_REPEAT_ALLOC_DONE));
            DEBUGMSG(status,NU_ALLOC_ERR)

            msg->SignalCode = L1P_REPEAT_ALLOC_DONE;

            // Insert "tn_difference" information in T_L1P_REPEAT_ALLOC_DONE msg
            // will be used in Ncell Dedic6 state machine to request a reset
            // or not of the state machine
            ((T_L1P_REPEAT_ALLOC_DONE *) (msg->SigP))->tn_difference = l1a_l1s_com.tn_difference;

            os_send_sig(msg, L1C1_QUEUE);
            DEBUGMSG(status,NU_SEND_QUEUE_ERR)
          }

        } // End if "Repeat allocation starts this frame..."
      } // End of "Repeat allocation starting time checking"

      // LOOK FOR FIXED MODE ALLOCATION BITMAP EXHAUSTION ...
      //==================================================

      if(l1ps_macs_com.fix_alloc_exhaust_flag)
      {
        #if (TRACE_TYPE!=0)
          // Trace "starting time" on log file and screen.
          trace_fct(CST_ALLOC_EXHAUSTION, l1a_l1s_com.Scell_info.radio_freq);
        #endif

        // Update uplink TBF synchronization timeslot
        {
          UWORD8 timeslot = 0;
          UWORD8 bitmap   = 0x80;

          while (!(l1pa_l1ps_com.transfer.aset->ul_tbf_alloc->timeslot_alloc & bitmap))
          {
            timeslot ++;
            bitmap >>= 1;
          }

          // Synchronization on the lowest allocated timeslot for uplink tranfer
          l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot = timeslot;
        }

        // New synchronization only done on a timeslot inferior to current synchronization
        // - if a DL TBF is present: the DL TBF synchronization is taken into account
        // - an UL TBF is present: synchronization can only be done on a timeslot number inferior or
        //   equal to the current synchronization
        if (l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot <
            l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot)
        {
          l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.aset->ul_tbf_synchro_timeslot;
        }

        // 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)
        // Note: tn_difference has to be accumulated in order to cope with the
        // specific case: L1A has just updated tn_difference, dl_tn and dsp_scheduler_mode
        // parameters and we enter in the HISR after the reset of the SYNCHRO Semaphore.
        if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET)
        {
          l1a_l1s_com.tn_difference += l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot - l1a_l1s_com.dl_tn;
          l1a_l1s_com.dl_tn          = l1pa_l1ps_com.transfer.aset->transfer_synchro_timeslot;

          // Enable SYNCHRO task only when camp timeslot is changed.
          if(l1a_l1s_com.tn_difference != 0)
          {
            l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
          }
        }

        // Send signal to L1A
        {
          xSignalHeaderRec *msg;

          // Send confirmation msg to L3/MACA.
          msg = os_alloc_sig(sizeof(T_L1P_ALLOC_EXHAUST_DONE));
          DEBUGMSG(status,NU_ALLOC_ERR)

          msg->SignalCode = L1P_ALLOC_EXHAUST_DONE;

          // Insert "tn_difference" information in T_L1P_ALLOC_EXHAUST_DONE msg
          // will be used in Ncell Dedic6 state machine to request a reset
          // or not of the state machine
          ((T_L1P_ALLOC_EXHAUST_DONE *) (msg->SigP))->tn_difference = l1a_l1s_com.tn_difference;

          os_send_sig(msg, L1C1_QUEUE);
          DEBUGMSG(status,NU_SEND_QUEUE_ERR)
        }

        // Flag the new configuration in order to update the Read set parameters
        // with the "aset" structure modifications in the first PDTCH Read phase
        // after configuration change
        l1ps.read_param.new_set = TRUE;

        // Reset flag
        l1ps_macs_com.fix_alloc_exhaust_flag = FALSE;

      } // End if "fixed mode allocation bitmap has exhausted"
    } // End of "block_boundary"
  } // end of if(!l1pa_l1ps_com.transfer.semaphore)
}
//#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

/*-------------------------------------------------------*/
/* l1ps_meas_manager()                                   */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* This function is the tasks manager for Packet Cell    */
/* Reselection.                                          */
/* The followings tasks are handled:                     */
/*                                                       */
/* FSMS_MEAS:                                            */
/*                                                       */
/* P_CRMS_MEAS: Packet Cell Reselection measurement      */
/* in Idle mode. The task includes:                      */
/*    o BA(GPRS) measurement                             */
/*    o Network controlled meas.                         */
/*    o Extended measurement                             */
/* Occurrences are performed in order to satisfy the     */
/* following ETSI constraints:                           */
/* 1. At least one measure of each BA BCCH carrier shall */
/*    be taken for each paging block,                    */
/* 2. A minimum of one measure for each BA BCCH carrier  */
/*    for every 4 second must be performed,              */
/* 3. MS is not required to take more than one sample    */
/*    per second for each BCCH carrier,                  */
/* 4. At least 5 measures per BA BCCH carrier are        */
/*    required for a valid received level average value  */
/*    (RLA_P),                                           */
/* 5. RLA_P shall be based on samples collected over a   */
/*    period of 5s to Max{5s, five consecutive PPCH      */
/*    blocks dedicated to the MS},                       */
/* 6. Samples allocated to each carrier shall as far     */
/*    as possible be uniformly distributed over the      */
/*    evaluation period.                                 */
/*                                                       */
/* A TI condition is include:                            */
/* 7. In order to save power consumption, it will be     */
/*    necessary to use as far as possible the PPCH       */
/*    blocks to perform a maximum of measurements during */
/*    these frames.                                      */
/*                                                       */
/* From the previous constraints, it appears that        */
/* Paging block period needs to be considered to fit     */
/* ETSI consideration.                                   */
/* Tow case are considered:                              */
/*     o PPCH period >= 1s                               */
/*     o PPCH period < 1s                                */
/*                                                       */
/* Once all carriers of the frequency list have been     */
/* measured, a reporting message L1P_CR_MEAS_DONE is     */
/* built and sent to L1A.                                */
/*-------------------------------------------------------*/
void l1ps_meas_manager()
{
  enum states
  {
    NULL_MEAS  = 0,
    PCHTOTAL   = 1,
    TOTAL      = 2,
    MEAS       = 3,
    MEASTOTAL  = 4
  };

  UWORD8  IL_for_rxlev;
  BOOL    init_meas   = FALSE;
#if (RF_FAM == 61)
  UWORD16 dco_algo_ctl_pw = 0;
  UWORD16 dco_algo_ctl_pw_temp = 0;
  UWORD8 if_ctl = 0;
  UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
#endif
  #define  cr_list_size  l1pa_l1ps_com.cres_freq_list.alist->nb_carrier

  static WORD8            remain_carrier;
  static UWORD8           nbr_meas;
  static BOOL             schedule_trigger;
  static xSignalHeaderRec *cr_msg = NULL;
  static WORD16           time_to_wake_up;
  static WORD16           time_to_4s;
  static WORD16           time_to_1s;
  static UWORD32          fn_update;
  static UWORD16          session_done; // Did a session of measures performed in the 4s period
  static UWORD16          session_done_1s; // Did a session of measures performed in the 1s period
  static UWORD8           state;
  static UWORD32          reporting_period; // Parameter used in "reporting_period" computation

#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)*/

  #if FF_L1_IT_DSP_USF
    if (l1ps_macs_com.usf_status != USF_IT_DSP)
    {
  #endif


  //====================================================
  //  RESET MEASUREMENT MACHINES WHEN ABORT EXECUTED.
  //====================================================
  if(l1s.dsp_ctrl_reg & CTRL_ABORT)
  // ABORT task has been controlled, which reset the MCU/DSP communication.
  // We must rewind any measurement activity.
  {
    // Aborted measurements have to be rescheduled
    nbr_meas += l1pa_l1ps_com.cr_freq_list.ms_ctrl_d + l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd;

    // Rewind "next_to_ctrl" counter to come back to the next carrier to
    // measure.
    l1pa_l1ps_com.cr_freq_list.next_to_ctrl = l1pa_l1ps_com.cr_freq_list.next_to_read;

    // Reset flags.
    l1pa_l1ps_com.cr_freq_list.ms_ctrl    = 0;
    l1pa_l1ps_com.cr_freq_list.ms_ctrl_d  = 0;
    l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd = 0;
  }

#if (GSM_IDLE_RAM != 1)
  // Test if task is disabled and cr_msg != NULL, then de-allocate memory
  if (!(l1pa_l1ps_com.l1ps_en_meas & P_CRMS_MEAS) && !(l1pa_l1ps_com.meas_param & P_CRMS_MEAS))
  {
    if(cr_msg != NULL)
    {
      // Cell reselection measurement process has been stopped by L3
      // Deallocate memory for the received message if msg not forwarded to L3.
      // ----------------------------------------------------------------------
      os_free_sig(cr_msg);
      DEBUGMSG(status,NU_DEALLOC_ERR)

      cr_msg = NULL;
    }
  }
#endif

  if((l1pa_l1ps_com.l1ps_en_meas & P_CRMS_MEAS) && (l1pa_l1ps_com.meas_param & P_CRMS_MEAS))
  // Some changes occured on the Frequency list or the PAGING PARAMETERS have
  // changed.
  {
    // Reset Packet Cell Reselection semaphore.
    l1pa_l1ps_com.meas_param &= P_CRMS_MEAS_MASK;

    // Paging process has been interrupted by a L3 message
    // Deallocate memory for the received message if msg not forwarded to L3.
    // ----------------------------------------------------------------------

    //Update Frequency list pointer
    l1pa_l1ps_com.cres_freq_list.alist = l1pa_l1ps_com.cres_freq_list.flist;

    // Rewind frequency list counters to come back to the first carrier of this
    // aborted session.
    l1pa_l1ps_com.cr_freq_list.next_to_read = 0;
    l1pa_l1ps_com.cr_freq_list.next_to_ctrl = 0;

    // Reset flags.
    l1pa_l1ps_com.cr_freq_list.ms_ctrl      = 0;
    l1pa_l1ps_com.cr_freq_list.ms_ctrl_d    = 0;
    l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd   = 0;

    // Initialize timer
    time_to_wake_up  = 0;
    time_to_4s       = 866;
    time_to_1s       = 216;
    fn_update        = l1s.actual_time.fn;

    // Initialize Reporting Period
    reporting_period = l1s.actual_time.fn;

    // Initialize Cell reselection state machine and parameters
    state            = NULL_MEAS;
    session_done     = 0;
    session_done_1s  = 0;
    schedule_trigger = TRUE;
    nbr_meas         = 0;
    init_meas        = TRUE;
  }
  #if FF_L1_IT_DSP_USF
    } // if (l1ps_macs_com.usf_status != USF_IT_DSP)
  #endif

  // Packet Idle Cell Relselection Power Measurements fonction if P_CRMS_MEAS task still enabled.
  // In case L1S has switched in GPRS packet transfer mode and L1S_TRANSFER_DONE message hasn't been processed yet
  // by L1A, no control or read task shall be done.

  if ((l1pa_l1ps_com.l1ps_en_meas & P_CRMS_MEAS) && !(l1pa_l1ps_com.meas_param & P_CRMS_MEAS)
      && (l1a_l1s_com.l1s_en_task[PDTCH]  != TASK_ENABLED))
  {
    #if FF_L1_IT_DSP_USF
      if (l1ps_macs_com.usf_status != USF_IT_DSP)
      {
    #endif
    // Update P_CRMS_MEAS timers
    {
      UWORD16 fn_diff;
      #define current_fn l1s.actual_time.fn

      // Compute Frame Number increment since last L1S activity
      if(current_fn >= fn_update)
        fn_diff = current_fn - fn_update;
      else
        fn_diff = (current_fn + MAX_FN) - fn_update;

      // Update timer
      time_to_4s -= fn_diff;

      if(time_to_4s <= 0)
      {
        time_to_4s  += 866;
        session_done = 0;
      }

      time_to_1s -= fn_diff;

      if(time_to_1s <= 0)
      {
        time_to_1s      += 216;
        session_done_1s  = 0;
      }

      // Note: time to next meas position is negative during the meas.
      // session period
      time_to_wake_up -= fn_diff;

      fn_update = current_fn;
    }

    if(time_to_wake_up == 0)
    {
      // Schedule CR meas position for "PNP period >= 1s" case
      if(l1pa_l1ps_com.pccch.pnp_period >= 216)
      {
        switch (state)
        {
          case PCHTOTAL:
          case TOTAL:
          {
            nbr_meas = cr_list_size;

            // Measures is going to start, set "session_done" flag.
            // "session_done" flag must be set at the begining of a meas. session
            // in order to be able to detect crossing of the 4s boundary
            session_done = 1;
          }
          break;

          case NULL_MEAS:
          {
            nbr_meas = 0;
          }
          break;
        }
      }
      // Schedule CR meas position for "PNP period < 1s" case
      else
      {
        switch (state)
        {
          case NULL_MEAS:
          {
            nbr_meas = 0;
          }
          break;

          case MEAS:
          {
            UWORD8   max_nbmeas;
            WORD16   tpu_win_rest;
            UWORD16  power_meas_split;

            // Compute how many BP_SPLIT remains for cr list meas
            // Rem: we take into account the SYNTH load for 1st RX in next frame.
            // WARNING: only one RX activity is considered in next paging block !!!
            tpu_win_rest = FRAME_SPLIT - (RX_LOAD + l1_config.params.rx_synth_load_split);

            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 (max_nbmeas > NB_MEAS_MAX_GPRS) max_nbmeas = NB_MEAS_MAX_GPRS;

            // There is no more PPCH block before end of 1s period.
            // End remaining carriers.
            nbr_meas = Min(remain_carrier, 4*max_nbmeas);

            // Measures is going to start, set "session_done" flag.
            // "session_done_1s" flag must be set at the begining of a meas. session
            // in order to be able to detect crossing of the 1s boundary
            session_done_1s = 1;

          }
          break;

          case MEASTOTAL:
          {
            nbr_meas = remain_carrier;

            // Measures is going to start, set "session_done" flag.
            // "session_done_1s" flag must be set at the begining of a meas. session
            // in order to be able to detect crossing of the 1s boundary
            session_done_1s = 1;

          }
          break;
        }
      } // End of else ("PNP period < 1s" case)
    }

    /* --------------------------------------------------------------------*/
    /* CTRL and READ phase carrying out. "nbr_meas" measures are performed */
    /* --------------------------------------------------------------------*/

    // ********************
    // READ task if needed
    // ********************
    if(l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd)
    // Background measurements....
    // A measure CTRL was performed 2 tdma earlier, read result now.
    {
      UWORD16  radio_freq_read;
      UWORD8   pm_read[NB_MEAS_MAX_GPRS];
      UWORD8   i;

      #define  next_to_read  l1pa_l1ps_com.cr_freq_list.next_to_read

      // When a READ is performed we set dsp_r_page_used flag to
      // switch the read page.
      l1s_dsp_com.dsp_r_page_used = TRUE;

      l1_check_com_mismatch(CR_MEAS_ID);

      // Read power measurement result from DSP/MCU GPRS interface
      l1pddsp_meas_read(l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd, pm_read);

      for(i=0; i<l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd; i++)
      {
        radio_freq_read = l1pa_l1ps_com.cres_freq_list.alist->freq_list[next_to_read];

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

        #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
          trace_fct(CST_READ_CR_MEAS, radio_freq_read);
        #endif

        l1_check_pm_error(pm_read[i], CR_MEAS_ID);

        // Get Input level corresponding to the used IL and pm result.
        IL_for_rxlev = l1pctl_pgc(((UWORD8)(pm_read[i])),
                                  l1pa_l1ps_com.cr_freq_list.used_il_lna_dd[i].il,
                                  l1pa_l1ps_com.cr_freq_list.used_il_lna_dd[i].lna,
                                  radio_freq_read);

        #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
          RTTL1_FILL_MON_MEAS(pm_read[i], IL_for_rxlev, CR_MEAS_ID, radio_freq_read)
        #endif

        // Check that cr_msg hasn't been erased.
        if (cr_msg == NULL)
        {
          cr_msg = os_alloc_sig(sizeof(T_L1P_CR_MEAS_DONE));
          DEBUGMSG(status,NU_ALLOC_ERR)
          cr_msg->SignalCode = L1P_CR_MEAS_DONE;
        }

        #if (GSM_IDLE_RAM != 1)
          // Fill reporting message.
          ((T_L1P_CR_MEAS_DONE*)(cr_msg->SigP))->
            ncell_meas[next_to_read].rxlev = l1s_encode_rxlev(IL_for_rxlev);
        #else
          // Fill reporting message.
          l1ps.ncell_meas_rxlev[next_to_read] = (WORD8) l1s_encode_rxlev(IL_for_rxlev);
        #endif
        // Increment "next_to_read" field for next measurement...
        if(++next_to_read >= cr_list_size)
          next_to_read = 0;
      }//end for

      // **********
      // Reporting
      // **********
      if(next_to_read == 0)
      {
        #if (GSM_IDLE_RAM == 1)
          // Check if memory for L1P_CR_MEAS_DONE msg is allocated
          if (cr_msg == NULL)
          {
            if (!READ_TRAFFIC_CONT_STATE)
            CSMI_TrafficControllerOn();
            cr_msg = os_alloc_sig(sizeof(T_L1P_CR_MEAS_DONE));
            DEBUGMSG(status,NU_ALLOC_ERR)
            cr_msg->SignalCode = L1P_CR_MEAS_DONE;
          }

          for(i=0; i<cr_list_size; i++)
          {
            ((T_L1P_CR_MEAS_DONE*)(cr_msg->SigP))->ncell_meas[i].rxlev = l1ps.ncell_meas_rxlev[i];
            // Fill reporting message.
          }
        #endif

        // Fill BA identifier field.
        ((T_L1P_CR_MEAS_DONE*)(cr_msg->SigP))->list_id = l1pa_l1ps_com.cres_freq_list.alist->list_id;

        ((T_L1P_CR_MEAS_DONE*)(cr_msg->SigP))->nmeas = cr_list_size;

        // Compute and Fill reporting period value
        if(l1s.actual_time.fn > reporting_period)
          reporting_period = l1s.actual_time.fn - reporting_period;
        else
          reporting_period = l1s.actual_time.fn - reporting_period + MAX_FN;

        ((T_L1P_CR_MEAS_DONE*)(cr_msg->SigP))->reporting_period = (UWORD16)reporting_period;

        reporting_period = l1s.actual_time.fn;

        // send L1P_CR_MEAS_DONE message...
        os_send_sig(cr_msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

        // Reset pointer for debugg.
        cr_msg = NULL;
      }

      // Trigger measurement scheduler when meas. session is completed.
      // Note: A meas. session includes all carriers of the list "PNP period >= 1s case"
      //       or only a sub-set of the CR freq list "PNP period < 1s case"
      if(!(l1pa_l1ps_com.cr_freq_list.ms_ctrl) && !(l1pa_l1ps_com.cr_freq_list.ms_ctrl_d))
        schedule_trigger = TRUE;
    }// end of READ

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_IT_DSP)
    #endif

    // **********
    // CTRL task
    // **********

    #if FF_L1_IT_DSP_USF
      if (l1ps_macs_com.usf_status != USF_AWAITED)
      {
    #endif

    if (nbr_meas > 0)
    {
      if(l1s.forbid_meas < 2)
      {
        UWORD8   max_nbmeas;
        UWORD8   nb_meas_to_perform;
        UWORD16  radio_freq_ctrl;
        UWORD8   i;
        UWORD8   pw_position = 0; // indicates first time slot in frame available for PM
        WORD16   tpu_win_rest;
        UWORD16  power_meas_split;

        #define next_to_ctrl  l1pa_l1ps_com.cr_freq_list.next_to_ctrl

        // Compute how many BP_SPLIT remains for cr 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;
        }

        // Compute number of PM allowed in the Frame
        // Test if we are on a Paging frame
        if(l1pa_l1ps_com.cr_freq_list.pnp_ctrl > 0) pw_position = 1;

        // Test if PRACH controlled in the same frame
        if(l1s.tpu_win >= ((3 * BP_SPLIT) + l1_config.params.tx_ra_load_split
                                          + l1_config.params.rx_synth_load_split))
        {
          pw_position = 4;
        }

        // Compute Number of measures to perform
        nb_meas_to_perform = cr_list_size - next_to_ctrl;

        if(nb_meas_to_perform > max_nbmeas)
          nb_meas_to_perform = max_nbmeas;

        if(nb_meas_to_perform > NB_MEAS_MAX_GPRS)
          nb_meas_to_perform = NB_MEAS_MAX_GPRS;

        if (nb_meas_to_perform > nbr_meas)
          nb_meas_to_perform = nbr_meas;

        for(i=0; i<nb_meas_to_perform; i++)
        {
          UWORD8  lna_off;
          WORD8   agc;
          UWORD8 input_level;
#if (L1_FF_MULTIBAND == 1)
          UWORD16 operative_radio_freq;
#endif
          
          radio_freq_ctrl = l1pa_l1ps_com.cres_freq_list.alist->freq_list[next_to_ctrl];

#if (L1_FF_MULTIBAND == 0)

          // Get AGC according to the last known IL.
          input_level =  l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
          agc     = Cust_get_agc_from_IL(radio_freq_ctrl,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 and LNA used for AGC setting.
          //l1pa_l1ps_com.cr_freq_list.used_il_lna[i]  = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset];
          l1pa_l1ps_com.cr_freq_list.used_il_lna[i].il  = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
          l1pa_l1ps_com.cr_freq_list.used_il_lna[i].lna = 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);

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

          // Memorize the IL and LNA used for AGC setting.
          //l1pa_l1ps_com.cr_freq_list.used_il_lna[i]  = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset];
          l1pa_l1ps_com.cr_freq_list.used_il_lna[i].il  = 
            l1a_l1s_com.last_input_level[operative_radio_freq].input_level;
          l1pa_l1ps_com.cr_freq_list.used_il_lna[i].lna = 
            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_CR_MEAS, -1);
          #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 ,
              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(++next_to_ctrl >= cr_list_size)
            next_to_ctrl = 0;

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

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

        } // End for(...nb_meas_to_perform)

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


        // Program DSP, in order to performed nb_meas_to_perform measures
        // Second argument specifies if a Rx burst will be received in this frame
        l1pddsp_meas_ctrl(nb_meas_to_perform, pw_position);

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


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

        // Set flag "ms_ctrl" to nb_meas_to_perform.
        // It will be used as 2 tdma delayed to trigger Read phase.
        l1pa_l1ps_com.cr_freq_list.ms_ctrl = nb_meas_to_perform;

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

        // Update nbr_meas
        nbr_meas -= nb_meas_to_perform;

        // Update remainig measurements to performed according meas done
        //remain_carrier -= nb_meas_to_perform;

      } //  End of test on is PBCCHS, FB/SB or BCCHN task active
    } //end ctrl

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_AWAITED)

      if (l1ps_macs_com.usf_status != USF_IT_DSP)
      {
    #endif

    // If it's time, update time to next measures position and state
    // Two cases are considered: "pnp_period >= 1s" and "pnp_period < 1s"

    if(schedule_trigger)
    {
      BOOL condition = FALSE;

      schedule_trigger = FALSE;

      // Compute time to next session of measures for "PNP period >= 1s" case
      if(l1pa_l1ps_com.pccch.pnp_period >= 216)
      {
        while(!condition)
        {
          switch(state)
          {
            case NULL_MEAS:
            {
            #if (GSM_IDLE_RAM != 1)
              // Check if memory for L1P_CR_MEAS_DONE msg is allocated
              if (cr_msg == NULL)
              {
                cr_msg = os_alloc_sig(sizeof(T_L1P_CR_MEAS_DONE));
                DEBUGMSG(status,NU_ALLOC_ERR)
                cr_msg->SignalCode = L1P_CR_MEAS_DONE;
              }
            #endif

              if((l1pa_l1ps_com.pccch.time_to_pnp > ((866 * session_done) + time_to_4s)) &&
                 (l1pa_l1ps_com.pccch.pnp_period >= 866))
              {
                state = TOTAL;
                time_to_wake_up = (433 + time_to_4s * session_done);
                condition = TRUE;
              }
              else
              {
                state = PCHTOTAL;
                time_to_wake_up = l1pa_l1ps_com.pccch.time_to_pnp;
                condition = TRUE;
              }
            }
            break;

            case TOTAL:
            case PCHTOTAL:
              state = NULL_MEAS;
            break;
          }
        }
      } // End of "PNP period >= 1s" case
      else
      // Compute time to next session of measures for "PNP period < 1s" case
      {
        while(!condition)
        {
          switch(state)
          {
            case NULL_MEAS:
            {
              // Let's assume a small frequency list size
              // and a PNP period such that PM are performed
              // on first PPCH block and then stopped. PM activity
              // must be re-scheduled at the end of PPCH block.
              if((l1pa_l1ps_com.pccch.time_to_pnp < time_to_1s) && !(init_meas))
              {
                time_to_wake_up  = l1pa_l1ps_com.pccch.time_to_pnp;
                schedule_trigger = TRUE;
                condition        = TRUE;
              }
              else
              {
              #if (GSM_IDLE_RAM == 0)
                // Check if memory for L1P_CR_MEAS_DONE msg is allocated
                if (cr_msg == NULL)
                {
                  cr_msg = os_alloc_sig(sizeof(T_L1P_CR_MEAS_DONE));
                  DEBUGMSG(status,NU_ALLOC_ERR)
                  cr_msg->SignalCode = L1P_CR_MEAS_DONE;
                }
              #endif

                state = MEAS;
                time_to_wake_up = l1pa_l1ps_com.pccch.time_to_pnp;
                remain_carrier  = (WORD8)cr_list_size;
                condition = TRUE;
              }
            }
            break;

            case MEAS:
            {
              UWORD8   max_nbmeas;
              WORD16   tpu_win_rest;
              UWORD16  power_meas_split;

              // Compute how many BP_SPLIT remains for cr list meas
              // Rem: we take into account the SYNTH load for 1st RX in next frame.
              // WARNING: only one RX activity is considered in next paging block !!!
              tpu_win_rest = FRAME_SPLIT - (RX_LOAD + l1_config.params.rx_synth_load_split);

              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 (max_nbmeas > NB_MEAS_MAX_GPRS) max_nbmeas = NB_MEAS_MAX_GPRS;

              // Update number of remaining carrier to measure.
              // Note: std.nbmeas provides max nbr of PM / TDMA
              remain_carrier -= 4 * max_nbmeas;

              if(remain_carrier <= 0)
                state = NULL_MEAS;
              else
              {
                if((l1pa_l1ps_com.pccch.time_to_pnp >= time_to_1s) || !(session_done_1s))
                {
                  state = MEASTOTAL;
                  time_to_wake_up = 1;
                  condition = TRUE;
                }
                else
                {
                  time_to_wake_up = l1pa_l1ps_com.pccch.time_to_pnp;
                  condition = TRUE;
                }
              }
            }
            break;

            case MEASTOTAL:
            {
              #if (GSM_IDLE_RAM != 1)
                // Check if memory for L1P_CR_MEAS_DONE msg is allocated
                if (cr_msg == NULL)
                {
                  cr_msg = os_alloc_sig(sizeof(T_L1P_CR_MEAS_DONE));
                  DEBUGMSG(status,NU_ALLOC_ERR)
                  cr_msg->SignalCode = L1P_CR_MEAS_DONE;
                }
              #endif

                state = MEAS;
                time_to_wake_up = l1pa_l1ps_com.pccch.time_to_pnp;
                remain_carrier  = (WORD8)cr_list_size;
                condition = TRUE;
            }
            break;
          }
        } // End of while
      } // End of else ("PNP period < 1s" case)
    } // End of if(schedule_trigger)

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_IT_DSP)

      if (l1ps_macs_com.usf_status != USF_AWAITED)
      {
    #endif

    // Update time to next L1S task
    if((l1pa_l1ps_com.cr_freq_list.ms_ctrl) ||
       (l1pa_l1ps_com.cr_freq_list.ms_ctrl_d))
    {
      // Still some measurement results to get from DSP
      l1a_l1s_com.time_to_next_l1s_task = 0;
    }
    else
    {
      // No more measurements to read, next session of meas must
      // be at time_to_wake_up
      Select_min_time(time_to_wake_up, l1a_l1s_com.time_to_next_l1s_task);
    }

    // Clear controlled flag pnp_ctrl.
    //-------------------------------
    l1pa_l1ps_com.cr_freq_list.pnp_ctrl = 0;

    // C W R pipeline management.
    //---------------------------
    l1pa_l1ps_com.cr_freq_list.ms_ctrl_dd   = l1pa_l1ps_com.cr_freq_list.ms_ctrl_d;
    l1pa_l1ps_com.cr_freq_list.ms_ctrl_d    = l1pa_l1ps_com.cr_freq_list.ms_ctrl;
    l1pa_l1ps_com.cr_freq_list.ms_ctrl      = 0;

    // C W R pipeline management.
    //---------------------------
    {
      UWORD8 i;

      for(i=0; i<NB_MEAS_MAX_GPRS; i++)
      {
        l1pa_l1ps_com.cr_freq_list.used_il_lna_dd[i]  = l1pa_l1ps_com.cr_freq_list.used_il_lna_d[i];
        l1pa_l1ps_com.cr_freq_list.used_il_lna_d [i]  = l1pa_l1ps_com.cr_freq_list.used_il_lna  [i];
      }
    }

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_AWAITED)
    #endif
  } // End of if: P_CRMS_MEAS enable and associated semaphore = 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

/*-------------------------------------------------------*/
/* l1ps_transfer_meas_manager()                          */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* Whilst in Packet Transfer mode, MS shall continuously */
/* monitor all the BCCH carriers as indicated by a       */
/* frequency list (BA(GPRS), Network Control frequency   */
/* list and Extended list) and the BCCH carrier of the   */
/* serving cell. Received signal level is used to monitor*/
/* the specified neighbour BCCH carriers.                */
/*                                                       */
/* Receive signal level measurement samples shall be     */
/* performed according to the following conditions:       */
/*                                                       */
/* 1) At least 1 measure shall be done every TDMA,       */
/* 2) Up to 2 TDMA frames per PDCH multiframe may be     */
/*    omitted if required for BSIC decoding,             */
/* 3) Running average value (RLA_P) is based on a 5s     */
/*    period and includes at least 5 measure samples,    */
/* 4) The same number of measures shall be taken for all */
/*    BCCH carriers except:                              */
/*    i) For the Serving Cell, where at least 6 measures */
/*       shall be taken per MF52,                        */
/*    ii) if PC_MEAS_CHAN indicates that power control   */
/*        measures shall be made on BCCH.                */
/* 5) Measures used to compute RLA_P shall as far as     */
/*    possible be uniformly distributed,                 */
/*-------------------------------------------------------*/
void l1ps_transfer_meas_manager()
{
  UWORD8   IL_for_rxlev;

  static xSignalHeaderRec *tcr_msg        = NULL;

  static BOOL  tcr_meas_removed           = FALSE;

  #define tcr_next_to_read        l1pa_l1ps_com.tcr_freq_list.tcr_next_to_read
  #define tcr_next_to_ctrl        l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl
  #define last_stored_tcr_to_read l1pa_l1ps_com.tcr_freq_list.last_stored_tcr_to_read


  #if FF_L1_IT_DSP_USF
    if (l1ps_macs_com.usf_status != USF_IT_DSP)
    {
  #endif

  // Test if task is disabled and cr_msg != NULL, then de-allocate memory
  if(tcr_msg != NULL)
  {
    if(!(l1pa_l1ps_com.l1ps_en_meas & P_TCRMS_MEAS) &&
       !(l1pa_l1ps_com.meas_param & P_TCRMS_MEAS))
    {
      // Neighbour measurement process has been stopped by L3
      // Deallocate memory for the received message if msg not forwarded to L3.
      // ----------------------------------------------------------------------
      os_free_sig(tcr_msg);
      DEBUGMSG(status,NU_DEALLOC_ERR)

      tcr_msg = NULL;
    }
  }

  #if FF_L1_IT_DSP_USF
    }  // if (l1ps_macs_com.usf_status != USF_IT_DSP)
  #endif

  if(l1pa_l1ps_com.l1ps_en_meas & P_TCRMS_MEAS)
  {

    #if FF_L1_IT_DSP_USF
      if (l1ps_macs_com.usf_status != USF_IT_DSP)
      {
    #endif

    // Increment l1pa_l1ps_com.tcr_freq_list.cres_meas_report
    if(++l1pa_l1ps_com.tcr_freq_list.cres_meas_report > 103)
      l1pa_l1ps_com.tcr_freq_list.cres_meas_report = 0;

    // Check if it's first time, Neighbour Measurement process is launched.
    // Then initialize fn_report counter and reset semaphore.
    if(l1pa_l1ps_com.meas_param & P_TCRMS_MEAS)
    {
       // Initialize counter used to report measurements
       l1pa_l1ps_com.tcr_freq_list.cres_meas_report = 0;

       // Reset Neighbour Measurements semaphore
       l1pa_l1ps_com.meas_param &= P_TCRMS_MEAS_MASK;
    }

    //====================================================
    //  RESET MEASUREMENT MACHINES WHEN SYNCHRO EXECUTED.
    //====================================================
    if(l1s.tpu_ctrl_reg & CTRL_SYNC)
    // SYNCHRO task has been executed.
    // -> Reset measures made on serving cell,
    // -> Rewind pointer used in Neighbour Cell measurement,
    // -> return.
    {

      // Reset Neighbour Cell measurement machine.
      // Rewind "next_to_ctrl" counter to come back to the next carrier to
      // measure.
      tcr_next_to_ctrl = tcr_next_to_read;

      // Reset flags.
      l1pa_l1ps_com.tcr_freq_list.ms_ctrl      = 0;
      l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d    = 0;
      l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd   = 0;

      // Reset measures made on beacon frequency.
      l1pa_l1ps_com.tcr_freq_list.beacon_meas  = 0;
    }

    // *******************
    // Message Allocation
    // *******************
    // The reporting message must be allocated before READ phase.

    if(l1pa_l1ps_com.tcr_freq_list.cres_meas_report == 2)
    {
      // Memory allocation
      if (tcr_msg == NULL)
      {
         // alloc L1P_TCR_MEAS_DONE message...
        tcr_msg = os_alloc_sig(sizeof(T_MPHP_TCR_MEAS_IND));
        DEBUGMSG(status,NU_ALLOC_ERR)
        tcr_msg->SignalCode = L1P_TCR_MEAS_DONE;
      }

      l1pa_l1ps_com.tcr_freq_list.first_pass_flag = TRUE;
    }

    //------------------------------------------------------
    // READ and CTRL phase of the Neighbour Measurement task
    //------------------------------------------------------

    //-----------
    // READ phase
    //-----------

    // Test if Measurment has been removed (ms_ctrl_d forced to 0) during
    // previous frame, then switch DSP read page.
    if (tcr_meas_removed)
    {
      l1s_dsp_com.dsp_r_page_used = TRUE;
      tcr_meas_removed            = FALSE;
    }

    // Background measurements....
    // A measurement controle was performed 2 tdma earlier, read result now!!
    if(l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd != 0)
    {
      UWORD16  radio_freq_read;
      UWORD8   pm_read;

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

      l1_check_com_mismatch(TCR_MEAS_ID);

      // When a read is performed, we set dsp_r_page_used flag to
      // switch the read page
      l1s_dsp_com.dsp_r_page_used = TRUE;

      // Read power measurement result from DSP/MCU GPRS interface
      l1pddsp_meas_read(l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd, &pm_read);

      l1_check_pm_error(pm_read, TCR_MEAS_ID);

      radio_freq_read = l1pa_l1ps_com.cres_freq_list.alist->freq_list[tcr_next_to_read];

      // Get Input level corresponding to the used IL and pm result.
      IL_for_rxlev = l1pctl_pgc(((UWORD8) (pm_read)),
                                l1pa_l1ps_com.tcr_freq_list.used_il_lna_dd.il,
                                l1pa_l1ps_com.tcr_freq_list.used_il_lna_dd.lna,
                                radio_freq_read);

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_MON_MEAS(pm_read, IL_for_rxlev, TCR_MEAS_ID, radio_freq_read)
      #endif


      if(l1pa_l1ps_com.tcr_freq_list.first_pass_flag)
      {
        // Fill reporting message: Store RXLEV
        ((T_L1P_TCR_MEAS_DONE*)(tcr_msg->SigP))->acc_level[tcr_next_to_read] =
         l1s_encode_rxlev(IL_for_rxlev);

        ((T_L1P_TCR_MEAS_DONE*)(tcr_msg->SigP))->acc_nbmeas[tcr_next_to_read] = 1;
      }
      else
      {
        // Fill reporting message: Accumulate RXLEV
        ((T_L1P_TCR_MEAS_DONE*)(tcr_msg->SigP))->acc_level[tcr_next_to_read] +=
         l1s_encode_rxlev(IL_for_rxlev);

        ((T_L1P_TCR_MEAS_DONE*)(tcr_msg->SigP))->acc_nbmeas[tcr_next_to_read] += 1;

      }

      // Increment "next_to_read" field for next measurement...
      if(++tcr_next_to_read >= l1pa_l1ps_com.cres_freq_list.alist->nb_carrier)
      {
        tcr_next_to_read    = 0;
      }

      // First pass has been completed on all BA list, reset "first_pass_flag"
      if(tcr_next_to_read == last_stored_tcr_to_read)
        l1pa_l1ps_com.tcr_freq_list.first_pass_flag = FALSE;

    } // End of READ phase


    // ************************
    // Reporting & List Update
    // ************************
    if(l1pa_l1ps_com.tcr_freq_list.cres_meas_report == 1)
    {
      if(tcr_msg != NULL)
      {
        // Fill TCR list identifier field.
        ((T_L1P_TCR_MEAS_DONE*)(tcr_msg->SigP))->list_id = l1pa_l1ps_com.cres_freq_list.alist->list_id;

        // send L1P_TCR_MEAS_DONE message...
        os_send_sig(tcr_msg, L1C1_QUEUE);
        DEBUGMSG(status,NU_SEND_QUEUE_ERR)

        // Reset pointer for debugg.
        tcr_msg = NULL;
      }

      // Update Frequency list pointer and reset new list flag
      if(l1pa_l1ps_com.tcr_freq_list.new_list_present)
      {
        //Update Frequency list pointer
        l1pa_l1ps_com.cres_freq_list.alist = l1pa_l1ps_com.cres_freq_list.flist;

        // Test if a Meas has been controlled in previous frame
        // Then set tcr_meas_removed flag in order to switch DSP read page in next frame
        if(l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d != 0)
        {
          tcr_meas_removed = TRUE;
        }

        // Reset pointer
        tcr_next_to_ctrl                             = 0;
        tcr_next_to_read                             = 0;
        l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d        = 0;

        // Reset New list flag
        l1pa_l1ps_com.tcr_freq_list.new_list_present = FALSE;
      }

      // While reporting, save Last "tcr_next_to_read" value to know when reset "first_pass_flag"
      last_stored_tcr_to_read = tcr_next_to_read;
    }

    //-----------
    // CTRL phase
    //-----------

    // CTRL phase is divided in two parts according measures allocated by MACS.
    // CTRL phase must then be exported in CTRL PDTCH function except for the Idle
    // frame where no PDTCH are programmed.
    // A measure can be performed during the idle frame, only if FB/SB/PTCCH
    // and Interference Measurement task is not active.
    if(!(l1pa_l1ps_com.meas_param & P_TCRMS_MEAS))
    {
      if((l1s.actual_time.t2 == 24) || (l1s.actual_time.t2 == 11))
      {
        if(l1s.forbid_meas == 0)
        {
          #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
            trace_fct(CST_CTRL_TCR_MEAS_2,(UWORD32)(-1));
          #endif

          l1ps_tcr_ctrl(0);
        }
      }
    }

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_IT_DSP)
    #endif

    #if FF_L1_IT_DSP_USF
      if (l1ps_macs_com.usf_status != USF_AWAITED)
      {
    #endif

    // Pipe Manager
    l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd = l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d;
    l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d  = l1pa_l1ps_com.tcr_freq_list.ms_ctrl;
    l1pa_l1ps_com.tcr_freq_list.ms_ctrl    = 0;

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_AWAITED)
    #endif

  } // End of if(l1pa_l1ps_com.l1ps_en_meas & P_TCRMS_MEAS)

  /*****************************/
  /* PC_MEAS_CHAN measurements */
  /*****************************/

  // If PC_MEAS_CHAN = 1, then BCCH serving cell carrier must be
  // measured at least 6 times per MF52.
  // CTRL of Serving Cell Carrier is performed two TDMA earlier.
  if(l1pa_l1ps_com.transfer.aset->pc_meas_chan == FALSE)
  {

    #if FF_L1_IT_DSP_USF
      if (l1ps_macs_com.usf_status != USF_IT_DSP)
      {
    #endif

    if(l1s.tpu_ctrl_reg & CTRL_SYNC)
    // SYNCHRO task has been executed.
    {
      l1ps.pc_meas_chan_ctrl = FALSE;
    }

    //-----------
    // READ phase
    //-----------

    if ((l1ps.pc_meas_chan_ctrl == TRUE) &&
        ((l1s.actual_time.t2 == 3) || (l1s.actual_time.t2 == 11)
          || (l1s.actual_time.t2 == 20)))
    {
      UWORD8    pm_read;

      l1_check_com_mismatch(PC_MEAS_CHAN_ID);

      // When a read is performed, we set dsp_r_page_used flag to
      // switch the read page
      l1s_dsp_com.dsp_r_page_used = TRUE;

      // Read power measurement result from DSP/MCU GPRS interface
      l1pddsp_meas_read(1, &pm_read);


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

      l1_check_pm_error(pm_read, PC_MEAS_CHAN_ID);

      l1ps.pc_meas_chan_ctrl = FALSE;

      // Get Input level corresponding to the used IL and pm result.
      IL_for_rxlev = l1pctl_pgc(((UWORD8 )(pm_read)),
                                l1pa_l1ps_com.tcr_freq_list.used_il_lna_dd.il,
                                l1pa_l1ps_com.tcr_freq_list.used_il_lna_dd.lna,
                                l1a_l1s_com.Scell_info.radio_freq);

      #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4)
        RTTL1_FILL_MON_MEAS(pm_read, IL_for_rxlev, PC_MEAS_CHAN_ID, l1a_l1s_com.Scell_info.radio_freq)
      #endif

      if (l1a_l1s_com.mode == PACKET_TRANSFER_MODE)
        // Store RXLEV, before to pass it to maca_power_control() function..
        l1pa_l1ps_com.tcr_freq_list.beacon_meas = l1s_encode_rxlev(IL_for_rxlev);
    }

    //-----------
    // CTRL phase
    //-----------

    // In two phase access, PC_MEAS_CHAN measurements can be done...
    if((l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED) &&
       (l1pa_l1ps_com.transfer.aset->allocated_tbf == TWO_PHASE_ACCESS))
    if (l1s.task_status[NP].current_status != ACTIVE) // avoid conflict with Normal Paging
    if (l1s.task_status[EP].current_status != ACTIVE) // avoid conflict with Extended Paging
    {
      // Measurement on the beacon
      if((l1s.actual_time.t2 == 1) || (l1s.actual_time.t2 == 9) ||
         (l1s.actual_time.t2 == 18))
      {
        // Measurement programming
        // ts 4 is specified for DSP interface ONLY because the power activity
        // must be programmed after RX and/or TX activity (no multislot)
        #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
          trace_fct(CST_CTRL_PC_MEAS_CHAN, (UWORD32)(-1));
        #endif

        l1ps_bcch_meas_ctrl(4);
      }
    }

    #if FF_L1_IT_DSP_USF
      } // if (l1ps_macs_com.usf_status != USF_IT_DSP)
    #endif

  } // End of Meas made on BCCH serving cell

  #if FF_L1_IT_DSP_USF
    if (l1ps_macs_com.usf_status != USF_AWAITED)
    {
  #endif

  if((l1pa_l1ps_com.l1ps_en_meas & P_TCRMS_MEAS) || (l1ps.pc_meas_chan_ctrl == TRUE))
  {
    // C W R pipeline management.
    //---------------------------
    l1pa_l1ps_com.tcr_freq_list.used_il_lna_dd  = l1pa_l1ps_com.tcr_freq_list.used_il_lna_d;
    l1pa_l1ps_com.tcr_freq_list.used_il_lna_d   = l1pa_l1ps_com.tcr_freq_list.used_il_lna;
  }

  #if FF_L1_IT_DSP_USF
    } // if (l1ps_macs_com.usf_status != USF_AWAITED)
  #endif

}
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END
#endif // MOVE_IN_INTERNAL_RAM

//#pragma DUPLICATE_FOR_INTERNAL_RAM_START
#endif
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END