view src/cs/layer1/p_cfile/l1p_asyn.c @ 62:089c1882788c

AT%CBC extended to report Ichg
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 22 Oct 2020 22:37:31 +0000
parents 4e78acac3d88
children
line wrap: on
line source

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

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

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

#define  L1P_ASYN_C

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END         // KEEP IN EXTERNAL MEM otherwise
#endif

//#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"
  #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_time.h"
  #include "l1_ctl.h"

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

  #include "macs_def.h"
  #include "macs_cst.h"
#else
  #include <string.h>
  #include "l1_types.h"
  #include "sys_types.h"
  #include "l1_const.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_time.h"
  #include "l1_ctl.h"

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

  #include "macs_def.h"
  #include "macs_cst.h"
#endif

T_TRANSFER_SET   *l1pa_get_free_transfer_set              (UWORD8  new_tbf);
void              l1pa_transfer_process                   (xSignalHeaderRec *msg);
void              l1pa_access_process                     (xSignalHeaderRec *msg);
void              l1pa_idle_packet_polling_process        (xSignalHeaderRec *msg);
void              l1pa_idle_paging_process                (xSignalHeaderRec *msg);
void              l1pa_cr_meas_process                    (xSignalHeaderRec *msg);
void              l1pa_serving_cell_pbcch_read_process    (xSignalHeaderRec *msg);
void              l1pa_neighbor_cell_pbcch_read_process   (xSignalHeaderRec *msg);
int               l1pa_sort                               (const void *a, const void *b);
void              l1pa_reset_cr_freq_list                 (void);
void              l1pa_tcr_meas_process                   (xSignalHeaderRec *msg);
T_CRES_LIST_PARAM *l1pa_get_free_cres_list_set            (void);
void              l1pa_idle_interference_meas_process     (xSignalHeaderRec *msg);
void              l1pa_transfer_interference_meas_process (xSignalHeaderRec *msg);
void              l1pa_idle_smscb_process                 (xSignalHeaderRec *msg);

// External prototype
void l1pa_send_int_meas_report(UWORD32               SignalCode,
                               T_L1P_ITMEAS_IND     *last_l1s_msg,
                               T_L1A_INT_MEAS_PARAM *first_meas_ptr);
void l1pa_send_confirmation(UWORD32 SignalCode, UWORD8 id);
void l1pa_send_tbf_release_con(UWORD32 SignalCode, UWORD8 tbf_type);

//#pragma DUPLICATE_FOR_INTERNAL_RAM_END

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM > 1))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM == 2
//#pragma GSM_IDLE2_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise


/*-------------------------------------------------------*/
/* l1pa_task()                                           */
/*-------------------------------------------------------*/
/*                                                       */
/* Description:                                          */
/* ------------                                          */
/* L1PA (Layer 1 Asynchronous) task function. This       */
/* function manages the GPRS interface between L3 and L1.*/
/* It is composed with a set of state machine, each      */
/* machine handles a particular GSM functionality. When  */
/* a message is received in L1_C1 message queue, it is   */
/* submitted to every state machine. The one which are   */
/* impacted by the message process it. At the end of     */
/* "l1pa_task()" function, a balance routine is called,  */
/* it enables L1S tasks consequently to the state machine*/
/* requests.                                             */
/*                                                       */
/*-------------------------------------------------------*/
void  l1pa_task(xSignalHeaderRec *msg)
{
  UWORD8  process;

  // Clear L1PA "enable meas and tasks" variables.
  //---------------------------------------------
  for(process=0; process<NBR_L1PA_PROCESSES; process++)
  {
    l1pa.l1pa_en_meas[process] = NO_TASK;
  }

  #if (GSM_IDLE_RAM != 0)
    if ((msg->SignalCode != L1P_PNP_INFO) && (msg->SignalCode != L1P_PEP_INFO))

    #if (GSM_IDLE_RAM > 1) // GPF modified for GSM_IDLE_RAM -> SW still running in Internal RAM
          {
    #endif
            l1s.gsm_idle_ram_ctl.l1s_full_exec = TRUE;
  #endif // GSM_IDLE_RAM

  // Serving Cell Packet System Information Reading
  l1pa_serving_cell_pbcch_read_process(msg);

  // Neighbor Cell Packet System Information Reading
  l1pa_neighbor_cell_pbcch_read_process(msg);

  #if (GSM_IDLE_RAM <= 1)  // GPF modified for GSM_IDLE_RAM -> SW still running in Internal RAM
  {
    // Serving Cell Packet Paging Reading
    l1pa_idle_paging_process(msg);
  }
  #endif
  // Cell reselection measurement process
  l1pa_cr_meas_process(msg);

  // Packet access proccess
  l1pa_access_process(msg);

  // Packet polling process
  l1pa_idle_packet_polling_process(msg);

  // Packet transfer process.
  l1pa_transfer_process(msg);

  // Neighbour Cell Measurement in Packet Transfer mode
  l1pa_tcr_meas_process(msg);

  // Intererence measurements in packet idle mode
  l1pa_idle_interference_meas_process(msg);

  // Intererence measurements in packet transfer mode
  l1pa_transfer_interference_meas_process(msg);

  #if (GSM_IDLE_RAM > 1)  // GPF modified for GSM_IDLE_RAM -> SW still running in Internal RAM
  }else
  {
    // Serving Cell Packet Packet Idle Paging Reading
    l1pa_idle_paging_process(msg);
  }
  #endif
}

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END         // KEEP IN EXTERNAL MEM otherwise
#endif

/*-------------------------------------------------------*/
/* l1pa_access_process()                                 */
/*-------------------------------------------------------*/
/* Description : This state machine handles the packet   */
/* access to the network while in PACKET IDLE mode.      */
/*                                                       */
/* Starting messages:        MPHP_RA_REQ                 */
/*                                                       */
/* Subsequent messages:      MPHP_RA_REQ                 */
/*                                                       */
/* Result messages (input):  L1P_PRA_DONE                */
/*                                                       */
/* Result messages (output): MPHP_RA_CON                 */
/*                                                       */
/* Reset message (input): MPHP_RA_STOP_REQ               */
/*                                                       */
/* Reset message (input): MPHP_RA_STOP_CON               */
/*-------------------------------------------------------*/
void l1pa_access_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET       = 0,
    WAIT_INIT   = 1,
    WAIT_RESULT = 2
  };

  UWORD8   *state      = &l1pa.state[P_ACC];
  UWORD32   SignalCode = msg->SignalCode;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_INIT;

        // Reset PRACH process.
        l1a_l1s_com.l1s_en_task[PRACH]     = TASK_DISABLED;  // Clear PRACH task enable flag.
        l1pa_l1ps_com.pra_info.prach_alloc = 0;
      }
      break;


      case WAIT_INIT:
      {
        if(SignalCode == MPHP_RA_REQ)
        // 1st Random access request message.
        //-----------------------------------
        {

          // Download Transmit power configuration.
          // Given value must be used on 1st TX.
          // TXPWR value supplied by L3 is the max. TX power level the MS may use in the given band
          l1s.applied_txpwr = ((T_MPHP_RA_REQ *)(msg->SigP))->txpwr;


          #if L1_R99
          // Init PRACH process.
            // "rand" parameter chosen by protocol in range [1..4] for R99
            l1pa_l1ps_com.pra_info.rand                 = ((T_MPHP_RA_REQ *)(msg->SigP))->rand;
          #else
          // "rand" parameter from msg is not used for the 1st PRACH.
          l1pa_l1ps_com.pra_info.rand                 = 1; // First PRACH has to be sent immediately
          #endif
          l1pa_l1ps_com.pra_info.channel_request_data = ((T_MPHP_RA_REQ *)(msg->SigP))->channel_request_data;
          l1pa_l1ps_com.pra_info.bs_prach_blks        = ((T_MPHP_RA_REQ *)(msg->SigP))->bs_prach_blks;
          l1pa_l1ps_com.access_burst_type             = ((T_MPHP_RA_REQ *)(msg->SigP))->access_burst_type;

          // Increment rand parameter by 4 in order to avoid conflict between SYNCHRO and
          // PRACH tasks when MPHP_START_PCCCH_REQ and MPHP_RA_REQ are
          // sent at the same time by L3
          l1pa_l1ps_com.pra_info.rand+=4;

          if ((l1pa_l1ps_com.pra_info.bs_prach_blks == 0) || // no blocks allocated
              (l1pa_l1ps_com.pra_info.bs_prach_blks > 12))   // invalid number of blocks
            l1pa_l1ps_com.pra_info.prach_alloc = DYN_PRACH_ALLOC;

          // step in state machine.
          *state = WAIT_RESULT;

          // Change mode to connection establishment part 1.
          l1a_l1s_com.mode = CON_EST_MODE1;

          // Activate PRACH task (no semaphore for UL tasks).
          l1a_l1s_com.l1s_en_task[PRACH] = TASK_ENABLED; // Set PRACH task enable flag.

        }

        // end of process.
        end_process = 1;
      }
      break;

      case WAIT_RESULT:
      {
        if(SignalCode == L1P_RA_DONE)
        // Random access acknowledge message: PRACH sent.
        //-----------------------------------------------
        {
          // Forward result message to L3.
          l1a_send_result(MPHP_RA_CON, msg, GRRM1_QUEUE);

          // Change mode to connection establishment part 2.
          l1a_l1s_com.mode = CON_EST_MODE2;

          // end of process.
          return;
        }

        else
        if(SignalCode == MPHP_RA_REQ)
        // Random access message.
        //-----------------------
        {
          // REM: rand is added the msg content since its current content is the already
          // spent "slots" from the last PRACH sending.
          l1pa_l1ps_com.pra_info.rand                += ((T_MPHP_RA_REQ *)(msg->SigP))->rand + 1;
          l1pa_l1ps_com.pra_info.channel_request_data = ((T_MPHP_RA_REQ *)(msg->SigP))->channel_request_data;
          l1pa_l1ps_com.pra_info.bs_prach_blks        = ((T_MPHP_RA_REQ *)(msg->SigP))->bs_prach_blks;
          l1pa_l1ps_com.access_burst_type             = ((T_MPHP_RA_REQ *)(msg->SigP))->access_burst_type;

          if ((l1pa_l1ps_com.pra_info.bs_prach_blks == 0) || // no blocks allocated
              (l1pa_l1ps_com.pra_info.bs_prach_blks > 12))   // invalid number of blocks
            l1pa_l1ps_com.pra_info.prach_alloc = DYN_PRACH_ALLOC;
//          else
//            l1pa_l1ps_com.pra_info.prach_alloc = FIX_PRACH_ALLOC;
          else
            l1pa_l1ps_com.pra_info.prach_alloc = 0; //must be reset for each burst sent


          // Activate PRACH task (no semaphore for UL tasks).
          l1a_l1s_com.l1s_en_task[PRACH] = TASK_ENABLED;   // Set PRACH task enable flag.

          // end of process.
          return;
        }

        else
        if(SignalCode == MPHP_RA_STOP_REQ)
        // Request to STOP the LINK ACCESS procedure.
        //-------------------------------------------
        {
          UWORD8 i;

          // send confirmation
          l1a_send_confirmation(MPHP_RA_STOP_CON,GRRM1_QUEUE);

          // Store MAX TXPWR value to be used for first Tx PDCH blocks
          for(i = 0; i < 8; i++)
          {
            l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[i] = l1s.applied_txpwr;
          }

          // This process must be reset.
          *state = RESET;
        }

        else
        if(SignalCode == MPHP_POLLING_RESPONSE_REQ)
        // Stop packet access when packet polling initiated.
        //--------------------------------------------------
        {
          // Unacknowledged

          // This process must be reset.
          *state = RESET;
        }

        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          end_process = 1;
        }
      }
      break;
    } // end of "switch".
  } // end of "while"
} // end of procedure.

/*-------------------------------------------------------*/
/* l1pa_cr_meas_process()                                */
/*-------------------------------------------------------*/
/* Description : This state machine handles periodic     */
/* signal strength monitoring on carriers specified      */
/* in a frequency list: BA(GPRS), NC_FREQUENCY_LIST,     */
/* EXT_FREEQUENCY_LIST (respectively: cell reselection   */
/* Network Control and Extended measurements.            */
/*                                                       */
/* Starting messages:        MPHP_CR_MEAS_REQ            */
/* ------------------                                    */
/*  L1 starts then the periodic FREQUENCY list receive   */
/*  level monitoring.                                    */
/*                                                       */
/* Subsequent messages:      MPHP_CR_MEAS_REQ            */
/* --------------------                                  */
/*  The frequency list is updated only when measures     */
/*  on all the carriers of the current list are          */
/*  performed.                                           */
/*                                                       */
/* Result messages (input):  L1P_RXLEV_PERIODIC_DONE     */
/* ------------------------                              */
/*  This is a message reported to L1A from L1S.          */
/*  Reporting is done when last carrier of the frequency */
/*  list is read.                                        */
/*                                                       */
/* Result messages (output): MPHP_CR_MEAS_IND            */
/* -------------------------                             */
/*  This is the periodic reporting message to L3.        */
/*                                                       */
/* Reset messages (input):   MPHP_CR_MEAS_STOP_REQ       */
/* -----------------------                               */
/*  Frequency list measurement process is stopped by     */
/*  this message.                                        */
/*                                                       */
/*-------------------------------------------------------*/
void l1pa_cr_meas_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET       = 0,
    WAIT_INIT   = 1,
    WAIT_RESULT = 2

  };

  UWORD8   *state      = &l1pa.state[CR_MEAS];
  UWORD32   SignalCode = msg->SignalCode;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // step in state machine.
        *state = WAIT_INIT;

        // Reset P_CRMS_MEAS process.
        l1pa_l1ps_com.l1ps_en_meas &= P_CRMS_MEAS_MASK; // Reset Packet Cell Reselection Measurement enable flag.
      }
      break;

      case WAIT_INIT:
      {
        if(SignalCode == MPHP_CR_MEAS_REQ)
        // We receive the Frequency list to be monitored.
        //----------------------------------------------
        {
          UWORD8  i;
          T_CRES_LIST_PARAM  *free_list;

          // Set parameter synchro semaphore for P_CRMS_MEAS task.
          l1pa_l1ps_com.meas_param |= P_CRMS_MEAS;

          // Reset the frequency list structure.
          l1pa_reset_cr_freq_list();

          // Get Ptr to the free Neighbour meas list.
          // The number of carriers in the list and the list
          // identification are initialized.
          free_list = l1pa_get_free_cres_list_set();

          // Set number of carrier in the frequency list.
          free_list->nb_carrier = ((T_MPHP_CR_MEAS_REQ *)(msg->SigP))->nb_carrier;

          // Store ARFCN list in the Packet Cell Reselection structure.
          for(i=0;i<free_list->nb_carrier;i++)
            free_list->freq_list[i] = ((T_MPHP_CR_MEAS_REQ *)(msg->SigP))->radio_freq_no[i];

          // Download Frequency list identifier.
          free_list->list_id = ((T_MPHP_CR_MEAS_REQ *)(msg->SigP))->list_id;

          // Set "flist" with new set of frequency list parameter
          l1pa_l1ps_com.cres_freq_list.flist = free_list;

          // Enable Packet Cell Reselection measurement task.
          l1pa.l1pa_en_meas[CR_MEAS] |= P_CRMS_MEAS;

          // step in state machine.
          *state = WAIT_RESULT;
        }

        // End of process.
        end_process = 1;
      }
      break;

      case WAIT_RESULT:
      {
        if(SignalCode == L1P_CR_MEAS_DONE)
        // One set of measurement has been completed.
        //---------------------------------------------
        {
          // Forward result message to L3.
          l1a_send_result(MPHP_CR_MEAS_IND, msg, GRRM1_QUEUE);

          // End of process.
          end_process = 1;
        }

        else
        if((SignalCode == MPHP_CR_MEAS_STOP_REQ) ||
           (SignalCode == L1P_TRANSFER_DONE)     ||
           (SignalCode == L1C_DEDIC_DONE))
        // Request to STOP this activity.
        //-------------------------------
        {
          // send confirmation message
          l1a_send_confirmation(MPHP_CR_MEAS_STOP_CON,GRRM1_QUEUE);
          // This process must be reset.
          *state = RESET;
        }

        else
        if (SignalCode == MPHP_CR_MEAS_REQ)
        {
          // This process must be reset.
          *state = RESET;
        }

        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          end_process = 1;
        }
      }
      break;
    } // end of "switch".
  } // end of "while"
} // end of procedure.

#if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM > 1))  // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM == 2
//#pragma GSM_IDLE2_DUPLICATE_FOR_INTERNAL_RAM_START         // KEEP IN EXTERNAL MEM otherwise

/*-------------------------------------------------------*/
/* l1pa_idle_paging_process()                            */
/*-------------------------------------------------------*/
/*                                                       */
/*-------------------------------------------------------*/
void l1pa_idle_paging_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET             = 0,
    WAIT_INIT         = 1,
    WAIT_MSG          = 2
  };

  enum pg_mode
  {
    NORM_PG           = 0,
    EXT_PG            = 1,
    REORG_PG          = 2
  };

  UWORD8  *state     = &l1pa.state[PI_SCP];
  UWORD32 SignalCode = msg->SignalCode;
  UWORD16 imsimod;
  UWORD16 split_pg_cycle;
  UWORD16 kcn;
  UWORD8  page_mode;

  BOOL end_process = 0;

  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_INIT;

        // Disable serving cell tasks.
        l1a_l1s_com.l1s_en_task[PALLC]   = TASK_DISABLED;     // Reset PALLC (reorg) task enable flag.
        l1a_l1s_com.l1s_en_task[PNP]     = TASK_DISABLED;     // Reset PNP     task enable flag.
        l1a_l1s_com.l1s_en_task[PEP]     = TASK_DISABLED;     // Reset PEP     task enable flag.

        // No Paging  => no gauging => no Deep sleep
        l1s.pw_mgr.enough_gaug = FALSE;  // forbid Deep sleep

      }
      break;

      case WAIT_INIT:
      {
        if(SignalCode == MPHP_START_PCCCH_REQ)
        {
          // Set semaphores for any PCCCH reading tasks.
          l1a_l1s_com.task_param[PALLC] = SEMAPHORE_SET;
          l1a_l1s_com.task_param[PNP]   = SEMAPHORE_SET;
          l1a_l1s_com.task_param[PEP]   = SEMAPHORE_SET;

          // Request to enter in PACKET PAGING REORGANIZATION or NORMAL mode.
          //----------------------------------------------------------------
          // The initial page mode in the Mobile Station shall be set to paging Reorganization
          // cf 04.08 section 3.3.2.1.1. however current implementation allows to init the Paging
          // procedure either in Reorganization or in Normal paging mode.

          // Download the PAGING PARAMETERS from the command message.
          page_mode                           = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->page_mode;
          imsimod                             = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->imsimod;
          kcn                                 = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->kcn;
          split_pg_cycle                      = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->split_pg_cycle;
          l1pa_l1ps_com.pccch.bs_pag_blks_res = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->bs_pag_blks_res;
          l1pa_l1ps_com.pccch.bs_pbcch_blks   = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->bs_pbcch_blks;
          l1pa_l1ps_com.pccch.frequency_list  = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->frequency_list;
          l1pa_l1ps_com.pccch.packet_chn_desc = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->packet_chn_desc;
          l1a_l1s_com.Scell_info.pb           = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->pb << 2; // Pb format 7.1

          // Number of paging blocks "available" on one PCCCH = number of ppch blocks per MF52 * 64
          // = (12 - BS_PAG_BLKS_RES - BS_PBCCH_BLKS)*64
          l1pa_l1ps_com.pccch.nb_ppch_per_mf52 = (12 - l1pa_l1ps_com.pccch.bs_pag_blks_res - (l1pa_l1ps_com.pccch.bs_pbcch_blks + 1));

          // Compute M.
          l1pa_l1ps_com.pccch.pg_blks_avail    =  l1pa_l1ps_com.pccch.nb_ppch_per_mf52 * 64;

          // (IMSI mod 1000) div (KC*N) (Note: N = 1 for PCCCH)
          l1pa_l1ps_com.pccch.pg_offset        = imsimod / kcn;

          // First Paging Group value: PAGING_GROUP = ((IMSI mod 1000) div ((KC*N)*N)) (for m = 0)
          l1pa_l1ps_com.pccch.first_pg_grp     = (l1pa_l1ps_com.pccch.pg_offset % l1pa_l1ps_com.pccch.pg_blks_avail);

          // Split Paging computation = min (pg_blks_avail, SPLIT_PG_CYCLE)
          l1pa_l1ps_com.pccch.split_pg_value = Min(l1pa_l1ps_com.pccch.pg_blks_avail, split_pg_cycle);

          // Paging Period computation
          l1pa_l1ps_com.pccch.pnp_period = (64*52) / l1pa_l1ps_com.pccch.split_pg_value;

          // Rem: changing the paging parameters changes the place where "Periodic Packet
          //      Measurement" task must be executed. It implies to set semaphore for P_CRMS task.
          l1pa_l1ps_com.meas_param |= P_CRMS_MEAS;

          // Layer 1 internal mode is set to IDLE MODE.
          l1a_l1s_com.mode = I_MODE;

          // In order to keep tn_difference and dl_tn consistent, we need to avoid
          // the execution of the SYNCHRO task with tn_difference updated and
          // dl_tn not yet updated (this can occur if we go in the HISR just after
          // the update of tn_difference). To do this the solution is to use the Semaphore
          // associated to the SYNCHRO task. SYNCHRO task will be schedule only if its
          // associated Semaphore is reset.
          // Note: Due to the specificity of the SYNCHRO task which can be enabled
          // by L1A state machines as by L1S processes, the semaphore can't followed
          // the generic rules of the Semaphore shared between L1A and L1S.
          // We must shift the mobile time setting to the timeslot provided by
          // ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->packet_chn_desc.timeslot_no parameter.
          //   tn_difference -> loaded with the number of timeslot to shift.
          //   dl_tn         -> loaded with the new timeslot.
          l1a_l1s_com.task_param[SYNCHRO] = SEMAPHORE_SET;
          {
            l1a_l1s_com.tn_difference += l1pa_l1ps_com.pccch.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn;
            l1a_l1s_com.dl_tn          = l1pa_l1ps_com.pccch.packet_chn_desc.timeslot_no;

            // Select GPRS DSP Scheduler.
            l1a_l1s_com.dsp_scheduler_mode = GPRS_SCHEDULER;

            // Timing must be shifted to a new timeslot, enables SYNCHRO task..
            l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED;
          }
          l1a_l1s_com.task_param[SYNCHRO] = SEMAPHORE_RESET;
          // Note: The using of the semaphore associated to the SYNCHRO task can't be done
          // as it is for the other semaphores. This is due to the specificity of the SYNCHRO
          // task both touch by L1A and L1S. Here above the semaphore is set prior to touching
          // the SYNCHRO parameters and reset after. In L1S this semaphore is checked. If it's
          // seen SET then L1S will not execute SYNCHRO task nor modify its parameters.

          // Step in state machine.
          *state = WAIT_MSG;

          if(page_mode == REORG_PG)
          // Paging Reorganization mode...
          {
            // Enable Packet Paging Reorganisation tasks.
            l1a_l1s_com.l1s_en_task[PALLC] = TASK_ENABLED;
            l1a_l1s_com.l1s_en_task[PNP]   = TASK_ENABLED;

            // End of process.
            end_process = 1;
          }
          else
          if(page_mode == NORM_PG)
          // Normal Paging mode...
          {
            // Enable Packet Paging tasks in mode "NORMAL".
            l1a_l1s_com.l1s_en_task[PNP]  = TASK_ENABLED;

            // End of process.
            end_process = 1;
          }
          else
          // Extended Paging mode...
          {
            // Initialize Paging State for PAGING_GROUP computation (L1S part)
            l1pa_l1ps_com.pccch.epg_computation = PPCH_POS_NOT_COMP;

            // Enable Packet Paging tasks in mode "EXTENDED".
            l1a_l1s_com.l1s_en_task[PNP]  = TASK_ENABLED;
            l1a_l1s_com.l1s_en_task[PEP]  = TASK_ENABLED;

            // End of process.
            end_process = 1;
          }

        } // end of test on SignalCode == MPHP_START_PCCCH_REQ

        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          end_process = 1;
        }

      } // end of case WAIT_INIT
      break;

      case WAIT_MSG:
      {
        if((SignalCode == L1P_PNP_INFO)   ||
           (SignalCode == L1P_PALLC_INFO) ||
           (SignalCode == L1P_PEP_INFO))
        // Paging Task results
        {
          // Forward result message to L3.
          l1a_send_result(MPHP_DATA_IND, msg, GRRM1_QUEUE);

          // End of process.
          return;
        }

        else
        if(SignalCode == MPHP_START_PCCCH_REQ)
        // New PCCCH configuration is provided.
        //--------------------------------------------------------
          {
          // Step in state machine
            *state = RESET;
          }

        else
        if((SignalCode == MPHP_STOP_PCCCH_REQ) ||
           (SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1C_DEDIC_DONE))
        // Request to STOP any serving cell Packet Paging activity, OR
        // Packet Transfer has just started.
        // In both cases, PCCCH reading must be stopped.
        //--------------------------------------------------------
        {
          // Send confirmation message to L3.
          l1a_send_confirmation(MPHP_STOP_PCCCH_CON,GRRM1_QUEUE);

          // This process must be reset.
          *state = RESET;
        }

        else
        if((SignalCode == L1P_SINGLE_BLOCK_CON) ||
           (SignalCode == MPHP_SINGLE_BLOCK_CON))
        // If Two Phase Access is ongoing: Packet Resource Request
        // msg has been sent to the network. PCCCH reading must be
        // stopped to let PDCH reading going.
        // REM: we must check both L1P/MPHP messages since an other
        // process could have renamed L1P into MPHP.
        //--------------------------------------------------------
        {
          if(((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->purpose == TWO_PHASE_ACCESS)
        {
          // This process must be reset.
          *state = RESET;
        }
        else
        {
            // End of process.
            return;
          }
        }

        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          return;
        }

      } // end of case WAIT_MSG
      break;
    } // end of switch
  } // end of while
} // end of procedure

//#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END
#endif

/*-------------------------------------------------------*/
/* l1pa_idle_packet_polling_process()                    */
/*-------------------------------------------------------*/
/* Description :                    .                    */
/* This state machine handles packet polling after       */
/* initiation of the packet acces procedure, when a      */
/* packet queuing notification is sent by the network    */
/*                                                       */
/* Starting messages:        MPHP_POLLING_RESPONSE_REQ   */
/*                                                       */
/* Subsequent messages:                                  */
/*                                                       */
/* Result messages (input):  L1P_PRA_DONE                */
/*                                                       */
/* Result messages (output): MPHP_POLLING_IND            */
/*                                                       */
/* Reset message (input):                                */
/*                                                       */
/* Reset message (input):                                */
/*-------------------------------------------------------*/
void l1pa_idle_packet_polling_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET       = 0,
    WAIT_INIT   = 1,
    WAIT_RESULT = 2
  };

  UWORD8   *state      = &l1pa.state[P_POLL];
  UWORD32   SignalCode = msg->SignalCode;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_INIT;

        // Reset POLL process.
        l1a_l1s_com.l1s_en_task[POLL] = TASK_DISABLED;  // Clear RAACC task enable flag.
      }
      break;


      case WAIT_INIT:
      {
        if(SignalCode == MPHP_POLLING_RESPONSE_REQ)
        // Polling response request for access procedure.
        //-----------------------------------------------
        {
          UWORD8 i;

          // Init POLL process.
          l1pa_l1ps_com.poll_info.pol_resp_type = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->pol_resp_type;
          l1pa_l1ps_com.poll_info.fn            = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->fn;

         // TXPWR value supplied by L3 is the max. TX power level the MS may use in the given band
          l1s.applied_txpwr                     = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->txpwr;

          // 1 RLC/MAC block is sent:
          // This is a special case, only possible if the MS has a valid TA available from a pending
          // assignment and is pooled for an RLC/MAC block.
          if (l1pa_l1ps_com.poll_info.pol_resp_type == CS1_TYPE_POLL)
          {
            for (i=0; i<24; i++)
            {
              // download 24 bytes from message
              l1pa_l1ps_com.poll_info.chan_req.cs1_data[i] =
                ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->channel_request_data[i];
            }
            l1pa_l1ps_com.poll_info.timing_advance = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->timing_advance;

            // Store MAX TXPWR value to be used for first POLL RESPONSE
            // if not already done by Packet Access process...
            for(i = 0; i < 8; i++)
            {
              l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[i] = l1s.applied_txpwr;
            }
          }
          // 4 identical PRACH are sent
          else
          {
            // UWORD16 = data[1]<<8 | data[0]
            l1pa_l1ps_com.poll_info.chan_req.prach_data[0] =
              ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->channel_request_data[0];
            l1pa_l1ps_com.poll_info.chan_req.prach_data[0] |=
              (((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->channel_request_data[1] << 8);

            l1pa_l1ps_com.poll_info.timing_advance = 0;
          }

          // step in state machine.
          *state = WAIT_RESULT;

          // Change mode to connection establishment part 1.
          l1a_l1s_com.mode = CON_EST_MODE1;

          // Activate POLL task (no semaphore for UL tasks).
          // Enable Paging Reorg and Normal paging tasks.
          l1a_l1s_com.l1s_en_task[POLL] = TASK_ENABLED; // Set PRACH task enable flag.
        }

        // end of process.
        end_process = 1;
      }
      break;

      case WAIT_RESULT:
      {
        if(SignalCode == L1P_POLL_DONE)
        // Random access acqnowledge message.
        //-----------------------------------
        {
          // Forward result message to L3.
          l1a_send_result(MPHP_POLLING_IND, msg, GRRM1_QUEUE);

          // Change mode to connection establishment part 2.
          l1a_l1s_com.mode = CON_EST_MODE2;

          // This state machine has to be reset
          *state = RESET;

          // end of process.
          end_process = 1;
        }

        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          end_process = 1;
        }
      }
      break;
    } // end of "switch".
  } // end of "while"
} // end of procedure.


/*-------------------------------------------------------*/
/* l1pa_transfer_process()                               */
/*-------------------------------------------------------*/
/* Description:                                          */
/* ------------                                          */
/*                                                       */
/* Starting messages:                                    */
/* ------------------                                    */
/*                                                       */
/* Subsequent messages:                                  */
/* --------------------                                  */
/*                                                       */
/* Result messages (input):                              */
/* ------------------------                              */
/*                                                       */
/* Result messages (output):                             */
/* -------------------------                             */
/*                                                       */
/* Reset messages (input):                               */
/* -----------------------                               */
/*                                                       */
/*-------------------------------------------------------*/
void l1pa_transfer_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET       = 0,
    WAIT_MSG    = 1
  };

  UWORD8   *state     = &l1pa.state[TRANSFER];
  UWORD32  SignalCode = msg->SignalCode;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_MSG;

        // Rise transfert parameter semaphore.
        l1pa_l1ps_com.transfer.semaphore = TRUE;
      }
      break;

      case WAIT_MSG:
      {
        switch(SignalCode)
        // switch on input message.
        //-------------------------
        {
          case MPHP_SINGLE_BLOCK_REQ:
          // Repeat fixed allocation.
          //-------------------------
          {
            T_TRANSFER_SET  *free_set;
            UWORD8           purpose;
            UWORD8           i;

            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            purpose = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->purpose;

            // Get Ptr to the free dedicated parameter set.
            // All important fields are initialised.
            free_set = l1pa_get_free_transfer_set(purpose);

            // Fill Transfer mode generic parameters.
            free_set->assignment_id      = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->assignment_id;
            free_set->assignment_command = purpose;
            free_set->allocated_tbf      = purpose;
            free_set->packet_ta          = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->packet_ta;

            if((purpose == SINGLE_BLOCK_DL)||(purpose == SINGLE_BLOCK_UL))
            {
              free_set->packet_ta.ta_index = 255;
              free_set->packet_ta.ta_tn    = 255;
            }

            free_set->dl_pwr_ctl         = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->dl_pwr_ctl;
            if (free_set->dl_pwr_ctl.p0 != 255)
              free_set->dl_pwr_ctl.p0    <<= 2;  // P0 format 7.1
            free_set->tsc                = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->tsc;
            free_set->freq_param         = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->freq_param;
            free_set->tbf_sti            = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->tbf_sti;
            free_set->pc_meas_chan       = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->pc_meas_chan;

            // Download access_burst_type
            l1pa_l1ps_com.transfer.psi_param.access_burst_type    = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->access_burst_type;
            // Keep the same Pb factor
            l1pa_l1ps_com.transfer.psi_param.Scell_pb             = l1a_l1s_com.Scell_info.pb;
            // Enable PSI param updating in order to update access_burst_type in L1S
            l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = TRUE;

            // Fill single block specific parameters.
            for(i=0;i<23;i++)
            {
              l1pa_l1ps_com.transfer.single_block.data_array[i] =
                ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->data_array[i];
            }
            l1pa_l1ps_com.transfer.single_block.tn =
              ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->timeslot_number;

            l1pa_l1ps_com.transfer.single_block.dl_tn_to_restore = l1a_l1s_com.dl_tn;

            // Fill "synchro_timeslot" which will be the frame synchro slot.
            free_set->ul_tbf_synchro_timeslot   = l1pa_l1ps_com.transfer.single_block.tn;
            free_set->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.single_block.tn;

            // Step in state machine.
            *state = WAIT_MSG;

            // Store signalcode.
            free_set->SignalCode = MPHP_SINGLE_BLOCK_REQ;

            // Clear transfer parameter semaphore to let L1S use the new parameters.
            l1pa_l1ps_com.transfer.semaphore = FALSE;

            // end of process.
            end_process = 1;
          }
          break;

          case MPHP_ASSIGNMENT_REQ:
          // Assignement message.
          //---------------------
          {
            static int count =0;

            T_TRANSFER_SET  *free_set;
            UWORD8           assignment_command;
            UWORD8           timeslot_alloc;
            UWORD8           timeslot;	/* TCS211 reconstruction, =0 in TCS3 */

	// TBF_changes

            #if FF_TBF

              BOOL             pseudo_tbf_two_phase_acc;

              // Special case for two phase access (single or multi allocation):
              // It is handled as a pseudo UL TBF using a fixed allocation.
              // Still needs to be flagged to preempt TBF establishment switch in
              // transfer manager.
              if (((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_command == TWO_PHASE_ACCESS)
              {
                ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_command = UL_TBF;
                pseudo_tbf_two_phase_acc = TRUE;
              }
              else
                pseudo_tbf_two_phase_acc = FALSE;
            #endif
            count++ ;

            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            assignment_command = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_command;

            // Get Ptr to the free dedicated parameter set.
            // All important fields are initialised.
            free_set = l1pa_get_free_transfer_set(assignment_command);

            // Download message containt.
            free_set->assignment_id      = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_id;
            free_set->assignment_command = assignment_command;
            free_set->multislot_class    = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->multislot_class;
            free_set->dl_pwr_ctl         = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->dl_pwr_ctl;
            if (free_set->dl_pwr_ctl.p0 != 255)
              free_set->dl_pwr_ctl.p0    <<= 2;  // P0 format 7.1
            free_set->packet_ta          = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->packet_ta;
            free_set->tsc                = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->tsc;
            free_set->freq_param         = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->freq_param;
            free_set->mac_mode           = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->mac_mode;
            free_set->tbf_sti            = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->tbf_sti;
            free_set->interf_meas_enable = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->interf_meas_enable;
            free_set->pc_meas_chan       = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->pc_meas_chan;

// TBF_changes

            #if FF_TBF
              // Two phase access condition is stored in FSET structure to be
              // transfered in ASET for transfer mode manager use.
              free_set->pseudo_tbf_two_phase_acc = pseudo_tbf_two_phase_acc;
            #endif

            // Download access_burst_type
            l1pa_l1ps_com.transfer.psi_param.access_burst_type    = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->access_burst_type;
            // Keep the same Pb factor
            l1pa_l1ps_com.transfer.psi_param.Scell_pb             = l1a_l1s_com.Scell_info.pb;
            // Enable PSI param updating in order to update access_burst_type in L1S
            l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = TRUE;

            switch(assignment_command)
            {
              case DL_TBF:
              {
                free_set->dl_tbf_alloc = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->dl_ressource_alloc;

                if((free_set->allocated_tbf == UL_TBF) ||
                   (free_set->allocated_tbf == BOTH_TBF))
                  free_set->allocated_tbf = BOTH_TBF;
                else
                  free_set->allocated_tbf = DL_TBF;

                // Look for 1st allocated timeslot.
                // MSB=TS0...LSB=TS7
                timeslot_alloc = free_set->dl_tbf_alloc.timeslot_alloc;
                timeslot       = 0;
                while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot)))
                {
                  timeslot++;
                }

                // Fill "synchro_timeslot" which will be the frame synchro slot.
                free_set->dl_tbf_synchro_timeslot   = timeslot;
                free_set->transfer_synchro_timeslot = timeslot;
              }
              break;

              case UL_TBF:
              {
                *(free_set->ul_tbf_alloc) = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->ul_ressource_alloc;

                if((free_set->allocated_tbf == DL_TBF) ||
                   (free_set->allocated_tbf == BOTH_TBF))
                  free_set->allocated_tbf = BOTH_TBF;
                else
                  free_set->allocated_tbf = UL_TBF;

                // Look for 1st allocated timeslot.
                // MSB=TS0...LSB=TS7

                // Dynamic mode: the uplink PDCH are always monitored
                // The 1st allocated timeslot is a RX on the lowest numbered
                // timeslot allocated in uplink
              #if L1_EDA
                if((free_set->mac_mode == DYN_ALLOC) || (free_set->mac_mode == EXT_DYN_ALLOC))
              #else
                if(free_set->mac_mode == DYN_ALLOC)
              #endif
                {
                  timeslot_alloc = free_set->ul_tbf_alloc->timeslot_alloc;

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

                // Fixed mode: the 1st allocated timeslot is the downlink control
                // timeslot allocated by the network, which is a timeslot allocated
                // in uplink
                if(free_set->mac_mode == FIX_ALLOC_NO_HALF)
                {
                  timeslot = free_set->ul_tbf_alloc->fixed_alloc.ctrl_timeslot;
                }

                // Fill "synchro_timeslot" which will be the frame synchro slot.
                free_set->ul_tbf_synchro_timeslot   = timeslot;
                free_set->transfer_synchro_timeslot = timeslot;
              }
              break;

              case BOTH_TBF:
              {
                free_set->dl_tbf_alloc    = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->dl_ressource_alloc;
                *(free_set->ul_tbf_alloc) = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->ul_ressource_alloc;
                free_set->allocated_tbf   = BOTH_TBF;

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

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

                free_set->dl_tbf_synchro_timeslot   = timeslot;

                // Process the uplink TBF first allocated timeslot

                // Dynamic mode: the uplink PDCH are always monitored
                // The 1st allocated timeslot is a RX on the lowest numbered
                // timeslot allocated in uplink
              #if L1_EDA
                if((free_set->mac_mode == DYN_ALLOC) || (free_set->mac_mode == EXT_DYN_ALLOC))
              #else
                if(free_set->mac_mode == DYN_ALLOC)
              #endif
                {
                  timeslot_alloc = free_set->ul_tbf_alloc->timeslot_alloc;

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

                // Fixed mode: the 1st allocated timeslot is the downlink control
                // timeslot allocated by the network, which is a timeslot allocated
                // in uplink
                if(free_set->mac_mode == FIX_ALLOC_NO_HALF)
                {
                  timeslot = free_set->ul_tbf_alloc->fixed_alloc.ctrl_timeslot;
                }

                free_set->ul_tbf_synchro_timeslot   = timeslot;

                // Fill "synchro_timeslot" which will be the frame synchro slot.
                if (free_set->dl_tbf_synchro_timeslot > free_set->ul_tbf_synchro_timeslot)
                {
                  free_set->transfer_synchro_timeslot = free_set->ul_tbf_synchro_timeslot;
                }
                else
                {
                  free_set->transfer_synchro_timeslot = free_set->dl_tbf_synchro_timeslot;
                }

              }
              break;
            }

            // Cancel any pending release on the assigned TBF
            if (l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd == TRUE)
            {
              // If pending released TBF = assigned TBF or assigned TBF = BOTH
              if ((assignment_command == l1pa_l1ps_com.transfer.tbf_release_param.released_tbf) ||
                  (assignment_command == BOTH_TBF))
              {
		/*
		 * FreeCalypso TCS211 reconstruction: in the LoCosto version
		 * the call to l1pa_send_tbl_release_con() came first,
		 * but in the TCS211 object it comes after the two
		 * assignments.
		 */

                // Cancel the TBF release order
                l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd = FALSE;
                l1pa_l1ps_com.transfer.tbf_release_param.released_tbf    = NO_TBF;

		// Send a "TBF Release confirmation" msg to L3  : CQ 46842
		l1pa_send_tbf_release_con(MPHP_TBF_RELEASE_CON,l1pa_l1ps_com.transfer.tbf_release_param.released_tbf);
              }
              // If BOTH TBF release order pending and no BOTH TBF assigned
              else if (l1pa_l1ps_com.transfer.tbf_release_param.released_tbf == BOTH_TBF)
              {
                // Keep the release of the TBF which is not assigned by this message
                if (assignment_command == DL_TBF)
                  l1pa_l1ps_com.transfer.tbf_release_param.released_tbf    = UL_TBF;
                else
                  l1pa_l1ps_com.transfer.tbf_release_param.released_tbf    = DL_TBF;
              }
            }

            // Step in state machine.
            *state = WAIT_MSG;

            // Store signalcode.
            free_set->SignalCode = MPHP_ASSIGNMENT_REQ;

            // Clear transfer parameter semaphore to let L1S use the new parameters.
            l1pa_l1ps_com.transfer.semaphore = FALSE;

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_TRANSFER_DONE:
          // Switch to TRANSFER mode has been done. Send a Assignment confirmation
          // msg to L3.
          {
            l1pa_send_confirmation(MPHP_ASSIGNMENT_CON,
                                   ((T_L1P_TRANSFER_DONE *) msg->SigP)->assignment_id);

            // End of process.
            end_process = 1;
          }
          break;

          case MPHP_TBF_RELEASE_REQ:
          // TBF Release.
          //-------------
          {
            UWORD8 i;

            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            // Cumulate with a possible TBF release request received during the same block period
            if (l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd == TRUE)
            {
              if (l1pa_l1ps_com.transfer.tbf_release_param.released_tbf != ((T_MPHP_TBF_RELEASE_REQ *)(msg->SigP))->tbf_type)
              {
                l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = BOTH_TBF;
              }
            }
            else
            {
              // Enables the TBF release processing in L1S.
              l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd = TRUE;

              // Download msg info into L1PA_L1PS_COM.
              l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = ((T_MPHP_TBF_RELEASE_REQ *)(msg->SigP))->tbf_type;
            }

            // Disable all pending TBFs those type is the same as the released TBF
            for(i = 0; i < 2; i++)
            {
              // Pending assignment
              if (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_ASSIGNMENT_REQ)
              {
              #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 FSET structure as an uplink TBF. If current
                // structure is pseudo TBF for two phase access, we process the request
                // like an uplink release, otherwise we skip it.

                released_tbf = l1pa_l1ps_com.transfer.tbf_release_param.released_tbf;

                if (released_tbf == TWO_PHASE_ACCESS)
                {
                  if (l1pa_l1ps_com.transfer.fset[i]->pseudo_tbf_two_phase_acc)
                    released_tbf = UL_TBF;
                  else
                    released_tbf = NO_TBF;
                }

                switch(released_tbf)
              #endif // FF_TBF
                {
                  case UL_TBF:
                  {
                    if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == UL_TBF)
                    {
                      l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF;
                      l1pa_l1ps_com.transfer.fset[i]->SignalCode    = NULL;
                    }
                    if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == BOTH_TBF)
                    {
                      l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = DL_TBF;
                    }
                  } break;

                  case DL_TBF:
                  {
                    if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == DL_TBF)
                    {
                      l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF;
                      l1pa_l1ps_com.transfer.fset[i]->SignalCode    = NULL;
                    }
                    if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == BOTH_TBF)
                    {
                      l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = UL_TBF;
                    }
                  } break;

                  case BOTH_TBF:
                  {
                    l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF;
                    l1pa_l1ps_com.transfer.fset[i]->SignalCode    = NULL;
                  } break;

                } // End of switch "tbf_release"
              } // End if SignalCode = MPHP_ASSIGNMENT_REQ or MPHP_REPEAT_UL_FIXED_ALLOC
            } // End "for"

            // Clear transfer parameter semaphore to let L1S use the new parameters.
            l1pa_l1ps_com.transfer.semaphore = FALSE;

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_TBF_RELEASED:
          // TBF has been release by L1S. Send a "TBF Release confirmation"
          // msg to L3
          {
            // Send confirmation message to L3.
            l1pa_send_tbf_release_con(MPHP_TBF_RELEASE_CON,((T_L1P_TBF_RELEASED *)(msg->SigP))->tbf_type);

            // End of process.
            end_process = 1;
          }
          break;

          case MPHP_STOP_SINGLE_BLOCK_REQ:
          // Stop SINGLE block activity.
          //----------------------------
          {
            UWORD8 i;

            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            // Disable SINGLE task.
            l1a_l1s_com.l1s_en_task[SINGLE] = TASK_DISABLED;

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

            // Send confirmation message to L3.
            l1a_send_confirmation(MPHP_STOP_SINGLE_BLOCK_CON,GRRM1_QUEUE);

            // disable all pending TBF those type is a single block
            for(i = 0; i < 2; i++)
            {
              // check for pending single block req (MPHP_SINGLE_BLOCK_REQ)
              if (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_SINGLE_BLOCK_REQ)
              {
                // disable the fset corresponding to single blocks
                l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF;
                l1pa_l1ps_com.transfer.fset[i]->SignalCode    = NULL;
              }
            }

            // This process must be reset.
            *state = RESET;

            // end of process.
            end_process = 1;
          }
          break;

          case MPHP_PDCH_RELEASE_REQ:
          // PDCH Release.
          //--------------
          {
            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            // Enables the PDCH release processing in L1S.
            l1pa_l1ps_com.transfer.pdch_release_param.pdch_release_cmd  = TRUE;

            // Download msg info into L1PA_L1PS_COM.
            l1pa_l1ps_com.transfer.pdch_release_param.timeslot_available = ((T_MPHP_PDCH_RELEASE_REQ *)(msg->SigP))->timeslot_available;
            l1pa_l1ps_com.transfer.pdch_release_param.assignment_id      = ((T_MPHP_PDCH_RELEASE_REQ *)(msg->SigP))->assignment_id;

            // Clear transfer parameter semaphore to let L1S use the new parameters.
            l1pa_l1ps_com.transfer.semaphore = FALSE;

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_PDCH_RELEASED:
          // PDCHs have been release by L1S. Send a "PDCH Release confirmation"
          // msg to L3
          {
            // Send confirmation message to L3.
            l1pa_send_confirmation(MPHP_PDCH_RELEASE_CON,
                                   ((T_L1P_PDCH_RELEASE_CON *) msg->SigP)->assignment_id);

            // End of process.
            end_process = 1;
          }
          break;

          case MPHP_TIMING_ADVANCE_REQ:
          // TA configuration.
          //------------------
          {
            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            // Enables the timing advance update in L1S.
            l1pa_l1ps_com.transfer.ptcch.ta_update_cmd = TRUE;

            // Download message content.
            l1pa_l1ps_com.transfer.ptcch.packet_ta     = ((T_MPHP_TIMING_ADVANCE_REQ *)(msg->SigP))->packet_ta;
            l1pa_l1ps_com.transfer.ptcch.assignment_id = ((T_MPHP_TIMING_ADVANCE_REQ *)(msg->SigP))->assignment_id;

            // Clear transfer parameter semaphore to let L1S use the new parameters.
            l1pa_l1ps_com.transfer.semaphore = FALSE;

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_TA_CONFIG_DONE:
          // TA configuration done.
          //-----------------------
          {
            // Send confirmation message to L3.
            l1pa_send_confirmation(MPHP_TIMING_ADVANCE_CON,
                                   ((T_MPHP_TIMING_ADVANCE_CON *) msg->SigP)->assignment_id);

            // end of process.
            end_process = 1;
          }
          break;

          case MPHP_UPDATE_PSI_PARAM_REQ:
          // Update PSI Parameters.
          //----------------------
          {
            // Download msg content
            l1pa_l1ps_com.transfer.psi_param.Scell_pb          = ((T_MPHP_UPDATE_PSI_PARAM_REQ *)(msg->SigP))->pb << 2; // Pb format 7.1
            l1pa_l1ps_com.transfer.psi_param.access_burst_type = ((T_MPHP_UPDATE_PSI_PARAM_REQ *)(msg->SigP))->access_burst_type;

            l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = TRUE;

            // send confirmation message
            l1a_send_confirmation(MPHP_UPDATE_PSI_PARAM_CON,GRRM1_QUEUE);

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_PACCH_INFO:
          // Two Phase Access is ongoing: Packet Resource Request
          // msg has been sent to the network. CCCH reading must be
          // stopped to let PDCH reading going.
          //--------------------------------------------------------
          {
            // Forward result message to RR.
            l1a_send_result(MPHP_DATA_IND, msg, GRRM1_QUEUE);

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_SINGLE_BLOCK_CON:
          // Two Phase Access is ongoing: Packet Resource Request
          // msg has been sent to the network. CCCH reading must be
          // stopped to let PDCH reading going.
          //--------------------------------------------------------
          {
            // Forward result message to RR.
            l1a_send_result(MPHP_SINGLE_BLOCK_CON, msg, GRRM1_QUEUE);

            // This process must be reset.
            *state = RESET;

            // end of process.
            end_process = 1;
          }
          break;

          case MPHP_REPEAT_UL_FIXED_ALLOC_REQ:
          // Repeat uplink fixed mode allocation bitmap
          //-------------------------------------------
          {
            // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
            l1pa_l1ps_com.transfer.semaphore = TRUE;

            // If an UL TBF is running...
            if ((l1pa_l1ps_com.transfer.aset->allocated_tbf == UL_TBF) ||
                (l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF))
            {
              // Download info. from message
              l1pa_l1ps_com.transfer.repeat_alloc = *((T_MPHP_REPEAT_UL_FIXED_ALLOC_REQ *) msg->SigP);
            }

            // Send confirmation if this message was a repeat allocation cancelling
            if (!((T_MPHP_REPEAT_UL_FIXED_ALLOC_REQ *) msg->SigP)->repeat_allocation)
            {
              l1a_send_confirmation(MPHP_REPEAT_UL_FIXED_ALLOC_CON,GRRM1_QUEUE);
            }
            else
            {
              UWORD8 i;

              // Disable all pending UL TBF
              for(i = 0; i < 2; i++)
              {
                // Pending assignment
                if (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_ASSIGNMENT_REQ)
                {
                  switch(l1pa_l1ps_com.transfer.fset[i]->allocated_tbf)
                  {
                    // Remove pending UL TBF
                    case UL_TBF:
                    {
                        l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF;
                        l1pa_l1ps_com.transfer.fset[i]->SignalCode    = NULL;
                    }
                    break;

                    // Change pending BOTH_TBF in pending DL_TBF
                    case BOTH_TBF:
                    {
                        l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = DL_TBF;
                    }
                    break;

                  } // End of switch "allocated_tbf"
                } // End if SignalCode = MPHP_ASSIGNMENT_REQ
              } // End "for"
            }

            // Clear transfer parameter semaphore to let L1S use the new parameters.
            l1pa_l1ps_com.transfer.semaphore = FALSE;

            // end of process.
            end_process = 1;
          }
          break;

          case L1P_REPEAT_ALLOC_DONE:
          {
            // Send confirmation message to L3.
            l1a_send_confirmation(MPHP_REPEAT_UL_FIXED_ALLOC_CON,GRRM1_QUEUE);

            // end of process.
            end_process = 1;
          }
          break;

          default:
          // End of process.
          //----------------
          {
            return;
          }
        } // end of switch(SignalCode)
      } // end of case WAIT_CONFIG.
    } // end of "switch".
  } // end of "while"
} // end of procedure.

/*-------------------------------------------------------*/
/* l1pa_serving_cell_pbcch_read_process()                */
/*-------------------------------------------------------*/
/* Description : This state machine handles Packet       */
/* serving cell PBCCH reading.                           */
/*                                                       */
/* Starting messages:        MPHP_SCELL_PBCCH_REQ        */
/* ------------------                                    */
/*                                                       */
/*  L1 continuously reads the serving cell PBCCH         */
/*  as requested by the scheduling info (PSI1 repeat     */
/*  period and relative position.                        */
/*                                                       */
/* Result messages (input):  L1C_PBCCHS_INFO             */
/* ------------------------                              */
/*  System information data block from L1S.              */
/*                                                       */
/* Reset messages (input):   MPHP_SCELL_PBCCH_STOP_REQ   */
/* -----------------------                               */
/*                                                       */
/*-------------------------------------------------------*/
void l1pa_serving_cell_pbcch_read_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET              = 0,
    WAIT_PBCCHS_CONFIG = 1,
    WAIT_PBCCHS_RESULT = 2,
    PBCCHS_CONFIG      = 3
  };

  UWORD8  *state      = &l1pa.state[SCPB];
  UWORD32  SignalCode = msg->SignalCode;

  #define  PbcchS  l1pa_l1ps_com.pbcchs

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_PBCCHS_CONFIG;

        // Reset PBCCHS process.
        l1a_l1s_com.l1s_en_task[PBCCHS] = TASK_DISABLED;  // Clear PBCCHS task enable flag.
      }
      break;

      case WAIT_PBCCHS_CONFIG:
      {
        // Request to read Normal BCCH from serving cell.
        if(SignalCode == MPHP_SCELL_PBCCH_REQ)
        {
          #define MAX_PSI1_PERIOD  16

          UWORD8  i;

          // Set semaphores for Serving Cell PBCCH reading task.
          l1a_l1s_com.task_param[PBCCHS] = SEMAPHORE_SET;

          // Download message content.
          //--------------------------
          PbcchS.nbr_psi                 = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->nbr_psi;
          PbcchS.bs_pbcch_blks           = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->bs_pbcch_blks;
          PbcchS.packet_chn_desc         = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->packet_chn_desc;
          PbcchS.frequency_list          = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->frequency_list;
          l1a_l1s_com.Scell_info.pb      = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->pb << 2;  // Pb format 7.1
          PbcchS.psi1_repeat_period      = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->psi1_repeat_period;

          // PBCCH Period is: MF52 * psi1_repeat_period
          PbcchS.pbcch_period = 52L * PbcchS.psi1_repeat_period;

          if(PbcchS.nbr_psi == 0)
          // Full PBCCH reading: Emulated throw "relative positions".
          //---------------------------------------------------------
          {
            // Emulate full PBCCH reading throw "relative positions" and a repeat period
            // of 1 MF52.
            //   bs_pbcch_blks= 0 -> Read B0
            //   bs_pbcch_blks= 1 -> Read B0,B6
            //   bs_pbcch_blks= 2 -> Read B0,B6,B3
            //   bs_pbcch_blks= 3 -> Read B0,B6,B3,B9

            PbcchS.nbr_psi      = PbcchS.bs_pbcch_blks+1;
            PbcchS.read_all_psi = TRUE;

            for(i=0;i<PbcchS.nbr_psi;i++)
            {
              ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->relative_position_array[i] = i;
            }
          }

          else
          // PBCCH reading: use provided "relative positions".
          //--------------------------------------------------
          {
            PbcchS.read_all_psi = FALSE;
          }

          // Compute FN offset for each PSI.
          //--------------------------------
          for(i=0;i<l1pa_l1ps_com.pbcchs.nbr_psi;i++)
          {
            WORD8   nbr_mf52;          // Range 0..MAX_PSI1_PERIOD (can be negative along its estimation)
            UWORD8  nbr_rest;          // Range 0..3
            UWORD8  relative_position; // Range 0..4*MAX_PSI1_PERIOD
            UWORD8  psi_period;        // psi1_repeat_period = 1 if nbr_psi = 0

            relative_position = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->relative_position_array[i];

            nbr_mf52 = relative_position / (PbcchS.bs_pbcch_blks+1);
            nbr_rest = relative_position % (PbcchS.bs_pbcch_blks+1);

            // Block B0 is a special case since CTRL phase occurs during
            // the MF52 before.
            if(nbr_rest == 0)
            {
              nbr_mf52 -= 1;

              // Set psi_period to 1 when all PSI have to be read (nbr_psi = 0)
              if(PbcchS.read_all_psi)
                psi_period = 1;
              else
                psi_period = PbcchS.psi1_repeat_period;

              if(nbr_mf52 < 0)
                nbr_mf52 += psi_period;
            }

            PbcchS.offset_array[i]            = (nbr_mf52 * 52L) + PBCCH_POSITION[PbcchS.bs_pbcch_blks][nbr_rest];
            PbcchS.relative_position_array[i] = relative_position;
          }

          // Step in state machine.
          *state = PBCCHS_CONFIG;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process.
          return;
        }
      }
      break;

      case PBCCHS_CONFIG:
      {
        WORD8   tn_pbcch;

        // If PBCCH TS is inferior to L1 synchronization TS, the PBCCH reading
        // control must be done one frame in advance
        if (PbcchS.packet_chn_desc.timeslot_no < l1a_l1s_com.dl_tn)
          PbcchS.control_offset = TRUE;
        else
          PbcchS.control_offset = FALSE;

        // Set "change_synchro" flag to trigger L1S to change the synchro on fly
        // within PBCCHS and to restore current synchro when PBCCHS task is completed.
        if(((PbcchS.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn + 8) % 8) >=4)
        {
          // L1S will make a intra PBCCHS task synchro to current TS + 4.
          PbcchS.change_synchro = TRUE;
          tn_pbcch              = PbcchS.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn - 4;
        }
        else
        {
          // L1S will NOT make the intra PBCCHS task synchro.
          PbcchS.change_synchro = FALSE;
          tn_pbcch              = PbcchS.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn;
        }

        if(tn_pbcch < 0)
          PbcchS.tn_pbcch = tn_pbcch + 8;
        else
          PbcchS.tn_pbcch = tn_pbcch;

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


        // Step in state machine.
        *state = WAIT_PBCCHS_RESULT;

        // End of process.
        end_process = 1;
      }
      break;

      case WAIT_PBCCHS_RESULT:
      {
        if(SignalCode == L1P_PBCCHS_INFO)
        // Serving cell BCCH reading result.
        //----------------------------------
        {
          // Forward result message to L3.
          l1a_send_result(MPHP_DATA_IND, msg, GRRM1_QUEUE);

          // End of process.
          return;
        }

        else
        if(SignalCode == MPHP_SCELL_PBCCH_REQ)
        // Request to re-configure PBCCH reading.
        //--------------------------------------
        {
          // Step in state machine.
          *state = WAIT_PBCCHS_CONFIG;
        }

        else
        if(SignalCode == MPHP_SCELL_PBCCH_STOP_REQ)
        // Request to STOP any serving cell pbcch activity.
        //------------------------------------------------
        {
          // Send confirmation message to L3.
          l1a_send_confirmation(MPHP_SCELL_PBCCH_STOP_CON,GRRM1_QUEUE);

          // This process must be reset.
          *state = RESET;
        }

        else
        // End of packet transfer mode: test PDTCH to be sure that TBF downlink and uplink are released
        if((SignalCode == L1P_TBF_RELEASED) && (((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all))
        {
           // This process must be reset.
          *state = RESET;
        }

        else
        if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_TBF_RELEASED) ||           //change of Time Slot
            (SignalCode  == L1P_REPEAT_ALLOC_DONE) || (SignalCode == L1P_ALLOC_EXHAUST_DONE))
        {
          // Clear PBCCHS  task enable flag.
          l1a_l1s_com.l1s_en_task[PBCCHS] = TASK_DISABLED;

          // Set semaphores for Serving Cell PBCCH reading task.
          l1a_l1s_com.task_param[PBCCHS] = SEMAPHORE_SET;

          // l1a_l1s_com.dl_tn was changed. Check if a change synchro is needed
          *state = PBCCHS_CONFIG; // Step in state machine.
        }

        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          return;
        }
      }
      break;
    } // end of "switch".
  } // end of "while"
} // end of procedure.


/*-------------------------------------------------------*/
/* l1pa_neighbor_cell_pbcch_read_process()                */
/*-------------------------------------------------------*/
/* Description : This state machine handles Packet       */
/* neighbor cell PBCCH reading.                           */
/*                                                       */
/* Starting messages:        MPHP_NCELL_PBCCH_REQ        */
/* ------------------                                    */
/*                                                       */
/*  L1 continuously reads the neighbor cell PBCCH        */
/*  as requested by the scheduling info (PSI1 repeat     */
/*  period and relative position.                        */
/*                                                       */
/* Result messages (input):  L1C_PBCCHN_INFO             */
/* ------------------------                              */
/*  System information data block from L1S.              */
/*                                                       */
/* Reset messages (input):   MPHP_NCELL_PBCCH_STOP_REQ   */
/* -----------------------                               */
/*                                                       */
/*-------------------------------------------------------*/
void l1pa_neighbor_cell_pbcch_read_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET              = 0,
    WAIT_PBCCHN_CONFIG = 1,
    WAIT_PBCCHN_RESULT = 2,
    PBCCHN_CONFIG      = 3
  };

  UWORD8  *state      = &l1pa.state[NCPB];
  UWORD32  SignalCode = msg->SignalCode;

  #define  PbcchN  l1pa_l1ps_com.pbcchn

  static  WORD32  fn_offset_mem;
  static  WORD32  time_alignmt_mem;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_PBCCHN_CONFIG;

        // Reset PBCCHS process.
        l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] = TASK_DISABLED;  // Clear PBCCHN task enable flag used in IDLE mode
        l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] = TASK_DISABLED;  // Clear PBCCHN task enable flag used in Transfer Packet mode
      }
      break;

      case WAIT_PBCCHN_CONFIG:
      {
        // Request to read Normal PBCCH from neighbor cell.
        if(SignalCode == MPHP_NCELL_PBCCH_REQ)
        {
          #define MAX_PSI1_PERIOD  16

          // Set semaphores for Neighbor Cell PBCCH reading task.
          l1a_l1s_com.task_param[PBCCHN_IDLE] = SEMAPHORE_SET;
          l1a_l1s_com.task_param[PBCCHN_TRAN] = SEMAPHORE_SET;

          // Download message content.
          //--------------------------
          PbcchN.bcch_carrier       = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->bcch_carrier;
          PbcchN.bs_pbcch_blks      = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->bs_pbcch_blks;
          PbcchN.packet_chn_desc    = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->packet_chn_desc;
          PbcchN.frequency_list     = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->frequency_list;
          PbcchN.psi1_repeat_period = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->psi1_repeat_period;
          PbcchN.relative_position  = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->relative_position;
          fn_offset_mem             = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->fn_offset;
          time_alignmt_mem          = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->time_alignment;
          PbcchN.pb                 = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->pb  << 2; // Pb format 7.1

          // PBCCH Period is: MF52 * psi1_repeat_period
          PbcchN.pbcch_period = 52L * PbcchN.psi1_repeat_period;

          // Compute FN offset.
          //------------------
          {
            WORD8   nbr_mf52;          // Range 0..MAX_PSI1_PERIOD (can be negative along its estimation)
            UWORD8  nbr_rest;          // Range 0..3
            UWORD8  relative_position; // Range 0..4*MAX_PSI1_PERIOD

            relative_position = PbcchN.relative_position;

            // number of PBCCH blocs
            nbr_mf52 = relative_position / (PbcchN.bs_pbcch_blks+1);
            nbr_rest = relative_position % (PbcchN.bs_pbcch_blks+1);

            // Block B0 is a special case since CTRL phase occurs during the MF52 before.
            if(nbr_rest == 0)
            {
              nbr_mf52 -= 1;

              if(nbr_mf52 < 0)
                nbr_mf52 += PbcchN.psi1_repeat_period;
            }

            PbcchN.offset = (nbr_mf52 * 52L) + PBCCH_POSITION[PbcchN.bs_pbcch_blks][nbr_rest];

            // In case of idle mode
            if (l1a_l1s_com.mode != PACKET_TRANSFER_MODE)
            {
              PbcchN.offset -= 2 ;  // because of the 2 frames for the measurement windows
              // note: PbcchN.offset can not be negative (PbcchN.offset > 12).
            }
          }
          // Step in state machine.
          *state = PBCCHN_CONFIG;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process.
          return;
        }
      }
      break;

      case PBCCHN_CONFIG:
      {
         //==================================================================================
         // choose a relative base time in the neighbor cell in order to simplify the L1S scheduling.
         //==================================================================================
         PbcchN.fn_offset    = fn_offset_mem;
         PbcchN.time_alignmt = time_alignmt_mem;

         //the new relative base time is set in order to have the Neighbor burst in position 0.
         //update with the burts position of the neighor cell     : PbcchN.packet_chn_desc.timeslot_no
         //update according to the current serving cell synchro   : l1a_l1s_com.dl_tn
         PbcchN.time_alignmt += (PbcchN.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn ) * TN_WIDTH;

         // PbcchN.time_alignmt is in [-7TS..+16TS[.
         // more than 1 frame between the serving cell and the neighbor burst
         if ( PbcchN.time_alignmt >= 8*TN_WIDTH)
         {
           PbcchN.time_alignmt -= 8*TN_WIDTH;
           PbcchN.fn_offset --;
         }
         else
         if ( PbcchN.time_alignmt < 0)
         {
           PbcchN.time_alignmt += 8*TN_WIDTH;
           PbcchN.fn_offset ++;
         }

         // Set "change_synchro" flag to trigger L1S to change the synchro on fly
         // within PBCCHN and to restore current synchro when PBCCHN task is completed.
         if (PbcchN.time_alignmt >= 4 * TN_WIDTH)
         {
           PbcchN.time_alignmt -= 4 * TN_WIDTH;
           PbcchN.change_synchro = TRUE;
         }
         else
           PbcchN.change_synchro = FALSE;

         // In case of packet transfer mode
         if (l1a_l1s_com.mode == PACKET_TRANSFER_MODE)
         {
           // Enable Packet Transfer PBCCHN task
           l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] = TASK_ENABLED;

         }
         // in case of Idle mode
         else
         {
           // Enable IDLE PBCCHN task
           l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] = TASK_ENABLED;
         }

         // Step in state machine.
         *state = WAIT_PBCCHN_RESULT;

         // End of process.
         end_process = 1;
      }
      break;

      case WAIT_PBCCHN_RESULT:
      {
        if(SignalCode == L1P_PBCCHN_INFO)
        // Serving cell BCCH reading result.
        //----------------------------------
        {
          // Forward result message to L3.
         l1a_send_result(MPHP_NCELL_PBCCH_IND, msg, GRRM1_QUEUE);

          // This process must be reset.
          *state = RESET;
        }

        else
        if(SignalCode == MPHP_NCELL_PBCCH_REQ)
        // Request to re-configure PBCCH reading.
        //--------------------------------------
        {
          // Step in state machine.
          *state = WAIT_PBCCHN_CONFIG;
        }

        else
        if(SignalCode == MPHP_NCELL_PBCCH_STOP_REQ)
        // Request to STOP any serving cell pbcch activity.
        //------------------------------------------------
        {
          // Send confirmation message to L3.
          l1a_send_confirmation(MPHP_NCELL_PBCCH_STOP_CON,GRRM1_QUEUE);

          // This process must be reset.
          *state = RESET;
        }
        else
        // End of packet transfer mode: test PDTCH to be sure that TBF downlink and uplink are released
        if((SignalCode == L1P_TBF_RELEASED) && (((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all))
        {
           // This process must be reset.
          *state = RESET;
        }
        else
        if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_TBF_RELEASED) ||          //change of Time Slot
            (SignalCode  == L1P_REPEAT_ALLOC_DONE) || (SignalCode == L1P_ALLOC_EXHAUST_DONE))
        {
          // We consider only the case: packet Transfer => packet Transfer,the serving TS may be changed
          // For other cases such as Idle -> Transfer... decision not yet taken.

          // update the PBCCHN parameters
          // Clear PBCCHN_TRAN task disable flag.
          l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] = TASK_DISABLED;

          // Set semaphores for Neighbor Cell PBCCH reading task.
          l1a_l1s_com.task_param[PBCCHN_TRAN] = SEMAPHORE_SET;

          // update the PBCCHN parameters
          *state = PBCCHN_CONFIG;// Step in state machine.
        }
        else
        // No action in this machine for other messages.
        //----------------------------------------------
        {
          // End of process.
          return;
        }
      }
      break;
    } // end of "switch".
  } // end of "while"
} // end of procedure.



/*-------------------------------------------------------*/
/* l1pa_tcr_meas_process()                               */
/*-------------------------------------------------------*/
/* Description : This state machine handles Neigbor cell */
/* measurement process in Packet Transfer mode.          */
/* Measurement are made on a specified frequency list.   */
/* The process is started automatically by L1 (on receipt*/
/* of a L1P_TRANSFER_DONE message from L1S) and doesn't  */
/* need to receive any message from L3.                  */
/* In order to update the frequency list, a              */
/* MHPC_TCR_MEAS_REQ msg will be sent from L3 to L1      */
/*                                                       */
/* Starting messages:        L1P_TRANSFER_DONE           */
/* ------------------                                    */
/*  L1 starts then measures on carriers specified in the */
/*  frequency list. Measures are performed on every      */
/*  frames with the occurence of 1 measure per frame     */
/*                                                       */
/* Subsequent messages:      MPHP_TCR_MEAS_REQ           */
/* --------------------                                  */
/*  The update is not done asap but postponed until the  */
/*  end of the reporting period. Frequency list is       */
/*  updated with the new list.                           */
/*                                                       */
/* Result messages (input):  L1P_TRANSFER_MEAS_DONE      */
/* ------------------------                              */
/*  This is the periodic reporting message sent by L1S.  */
/*  The reporting is done every "reporting period".      */
/*  The beguining of the reporting period is arbitrary   */
/*  and starts when the Neigh Meas task is enabled.      */
/*                                                       */
/* Result messages (output): MPHP_TCR_MEAS_IND           */
/* -------------------------                             */
/*  This is the periodic reporting message to L3.        */
/*                                                       */
/* Reset messages (input):   MPHP_TCR_MEAS_STOP_REQ      */
/* -----------------------                               */
/*  Frequency list neigbor cell measurement process in   */
/*  Packet Transfer mode is stopped by this message.     */
/*                                                       */
/*-------------------------------------------------------*/
void l1pa_tcr_meas_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET       = 0,
    WAIT_INIT   = 1,
    WAIT_RESULT = 3

  };

  UWORD8            *state      = &l1pa.state[TCR_MEAS];
  UWORD32           SignalCode  = msg->SignalCode;
  UWORD8            i;
  UWORD8            list_size;
  T_CRES_LIST_PARAM *free_list;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // step in state machine.
        *state = WAIT_INIT;

        // Reset TCR_MEAS process.
        l1pa_l1ps_com.l1ps_en_meas &= P_TCRMS_MEAS_MASK; // Disable Neighbour Measurement task.
      }
      break;

      case WAIT_INIT:
      {
        if(SignalCode == L1P_TRANSFER_DONE)
        // We enter in Packet Transfer mode.
        //---------------------------------
        {
#if 0	/* FreeCalypso: the following code is not present in TCS211 */
        #if (CODE_VERSION != SIMULATION)
          //no meas when entering in Transfer if no BA list initialized
          //stay in this state and wait for a MPHP_TCR_MEAS_REQ from L3
          if((l1pa_l1ps_com.cres_freq_list.alist->nb_carrier == 0) &&
             (l1pa_l1ps_com.tcr_freq_list.new_list_present == FALSE) && (l1a_l1s_com.ba_list.nbr_carrier == 0))
            return;
        #endif
#endif
          // Set parameter synchro semaphore for P_TCRMS_MEAS task.
          l1pa_l1ps_com.meas_param |= P_TCRMS_MEAS;

          // Reset Neighbour Cell measurement parameters.
          l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl        = 0;
          l1pa_l1ps_com.tcr_freq_list.tcr_next_to_read        = 0;
          l1pa_l1ps_com.tcr_freq_list.last_stored_tcr_to_read = 0;
          l1pa_l1ps_com.tcr_freq_list.first_pass_flag  = TRUE;

          // Initialize counter used to report measurements
          l1pa_l1ps_com.tcr_freq_list.cres_meas_report = 0;


          // If no Packet Idle phase has been done and no BA(GPRS) list has been
          // downloaded, init BA(GPRS) list with BA list used in CS Idle mode.
          if((l1pa_l1ps_com.cres_freq_list.alist->nb_carrier == 0) &&
             (l1pa_l1ps_com.tcr_freq_list.new_list_present == FALSE))
          {
            // Get Ptr to the free Neighbour meas list.
            // The number of carriers in the list and the list
            // identification are initialized.
            free_list = l1pa_get_free_cres_list_set();

            // Download new list within T_CRES_LIST_PARAM structure.
            free_list->nb_carrier = l1a_l1s_com.ba_list.nbr_carrier;

            for(i = 0; i < free_list->nb_carrier; i++)
            {
              free_list->freq_list[i] = l1a_l1s_com.ba_list.A[i].radio_freq;
            }

            free_list->list_id = l1a_l1s_com.ba_list.ba_id;

            // Set "flist" with Circuit Swithed BA frequency list parameters
            l1pa_l1ps_com.cres_freq_list.alist = free_list;
          }

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

          // Enable Packet Transfer Neighbour Measurement task.
          l1pa.l1pa_en_meas[TCR_MEAS] |= P_TCRMS_MEAS;

          // step in state machine.
          *state = WAIT_RESULT;
        }
        else
        if(SignalCode == MPHC_RXLEV_PERIODIC_REQ)
        // We receive the BA list to be monitored in Idle mode
        //----------------------------------------------------
        {
          // When enter in Transfer the Idle list must be used
          // =>reset the packet Transfert list in order to use the Idle list
          l1pa_l1ps_com.cres_freq_list.alist->nb_carrier = 0;
          l1pa_l1ps_com.tcr_freq_list.new_list_present = FALSE;
        }
#if 0	/* FreeCalypso: the following code is not present in TCS211 */
        else
        if(SignalCode == MPHP_TCR_MEAS_REQ)
        // Restart Packet Transfer measurement in TBF after
        // MPHP_TCR_MEAS_STOP_REQ
        // ### Check reason why was missing (s921_bis note)...
        //----------------------------------------------------
        {

          // Set parameter synchro semaphore for P_TCRMS_MEAS task.
          l1pa_l1ps_com.meas_param |= P_TCRMS_MEAS;

          free_list = l1pa_get_free_cres_list_set();


          // Download new list within T_CRES_LIST_PARAM structure.
          free_list->nb_carrier = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->nb_carrier;

          for(i = 0; i < free_list->nb_carrier; i++)
          {
            free_list->freq_list[i] = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->radio_freq_no[i];
          }

          free_list->list_id    = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->list_id;

          // Set "flist" with Circuit Swithed BA frequency list parameters
          l1pa_l1ps_com.cres_freq_list.alist = free_list;

          // Reset Neighbour Cell measurement parameters.
          l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl        = 0;
          l1pa_l1ps_com.tcr_freq_list.tcr_next_to_read        = 0;
          l1pa_l1ps_com.tcr_freq_list.last_stored_tcr_to_read = 0;
          l1pa_l1ps_com.tcr_freq_list.first_pass_flag  = TRUE;

          // Initialize counter used to report measurements
          l1pa_l1ps_com.tcr_freq_list.cres_meas_report = 0;

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

          // Enable Packet Transfer Neighbour Measurement task.
          l1pa.l1pa_en_meas[TCR_MEAS] |= P_TCRMS_MEAS;

          // step in state machine.
          *state = WAIT_RESULT;
        }
#endif

        // End of process.
        end_process = 1;
      }
      break;

      case WAIT_RESULT:
      {
        switch(SignalCode)
        {
          case L1P_TCR_MEAS_DONE:
          // One reporting period has been completed. A set of measures is forward to L3.
          //-----------------------------------------------------------------------------
          {
            // Forward result message to L3.
            l1a_send_result(MPHP_TCR_MEAS_IND, msg, GRRM1_QUEUE);

            // End of process.
            end_process = 1;
          }
          break;

          case MPHP_TCR_MEAS_REQ:
          // Update of the parameters are postponed until end of the reporting period.
          // Parameters are saved in a double buffer.
          {
            // Reset present flag to avoid to mix 2 updates in case of
            // an update already pending within "l1pa_l1ps_com.cres_freq_list.flist".
            l1pa_l1ps_com.tcr_freq_list.new_list_present = FALSE;

            // Get Ptr to the free Neighbour meas list.
            // The number of carriers in the list and the list
            // identification are initialized.
            free_list = l1pa_get_free_cres_list_set();


            // Download new list within T_CRES_LIST_PARAM structure.
            list_size             = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->nb_carrier;
            free_list->nb_carrier = list_size;

            for(i = 0; i < list_size; i++)
            {
              free_list->freq_list[i] = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->radio_freq_no[i];
            }

            free_list->list_id    = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->list_id;

            // Set "flist" with new set of frequency list parameter
            l1pa_l1ps_com.cres_freq_list.flist = free_list;

            // Set present flag only when the list has been downloaded.
            l1pa_l1ps_com.tcr_freq_list.new_list_present = TRUE;

            // End of process.
            end_process = 1;
          }
          break;

          case L1P_TBF_RELEASED:
          {
            // Test if all TBF have been released
            // Then stop Neighbour Measurement process
            if(((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all)
            {
              // This process must be reset.
              *state = RESET;
            }
            else
            {
              return;
            }
          }
          break;

          case MPHP_TCR_MEAS_STOP_REQ:
          // Note: A TBF stop do not imply a stop of the Neighbour Measurement process.
          // L3 has to send a MPHP_TCR_MEAS_STOP message to stop the measurement process.
          {
            // send confirmation message
            l1a_send_confirmation(MPHP_TCR_MEAS_STOP_CON,GRRM1_QUEUE);

            // This process must be reset.
            *state = RESET;
          }
          break;

          default:
          // No action in this machine for other messages.
          // Note: No action is performed on receipt of a L1P_TRANSFER_DONE
          // message. However a SYNCHRO task is programmed, which implies
          // a reset of measures related to the Serving Cell (cf. L1S).
          //--------------------------------------------------------------
          {
            return;
          }
        } // end of switch(SignalCode)
      }
      break;
    } // end of "switch".
  } // end of "while"
} // end of procedure.

/*-------------------------------------------------------*/
/* l1pa_idle_interference_meas_process()                 */
/*-------------------------------------------------------*/
/* Description :                                         */
/*                                                       */
/* Starting messages:        MPHP_INT_MEAS_REQ           */
/*                                                       */
/* This message requests signal strength measurements    */
/* on several channels of a specific carrier.            */
/* Measurements must be done on one search frame and one */
/* PTCCH frame.                                          */
/*                                                       */
/* Result messages (input):  L1PS_ITMEAS_IND             */
/*                                                       */
/* This message is reported to L1A when signal strength  */
/* has been measured on one idle frame (PTCCH or search) */
/*                                                       */
/* Result messages (output): MPHP_INT_MEAS_IND           */
/*                                                       */
/* This message is reported to L3 when measurements have */
/* been done on two contiguous idle frames               */
/*                                                       */
/* Reset message (input):    MPHP_INT_MEAS_STOP_REQ      */
/*                                                       */
/* Interference measurement processing is stopped by     */
/* this message                                          */
/*-------------------------------------------------------*/
void l1pa_idle_interference_meas_process(xSignalHeaderRec *msg)
{
  enum states
  {
    RESET             = 0,
    WAIT_INIT         = 1,
    WAIT_1ST_RESULT   = 2,
    WAIT_2ND_RESULT   = 3
  };

  static   T_L1A_INT_MEAS_PARAM int_meas_param;
  UWORD8   *state      = &l1pa.state[PI_INT_MEAS];
  UWORD32  SignalCode  = msg->SignalCode;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_INIT;

        // Reset ITMEAS process.
        l1a_l1s_com.l1s_en_task[ITMEAS]    = TASK_DISABLED;  // Clear ITMEAS task enable flag.
      }
      break;

      case WAIT_INIT:
      {
        // Interference measurement request
        //---------------------------------
        if (SignalCode == MPHP_INT_MEAS_REQ)
        {
          UWORD8 bitmap,i;

          // Set semaphore
          l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET;

          // Download message content
          l1pa_l1ps_com.itmeas.packet_intm_freq_param  = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->packet_intm_freq_param;
          l1pa_l1ps_com.itmeas.multislot_class         = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->multislot_class;
          int_meas_param.id                           = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->carrier_id;

          // Processing of the 2 possible measurement bitmaps
          //-------------------------------------------------

          // 1- Without Rx on the frame before

          l1pa_l1ps_com.itmeas.idle_tn_no_rx = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->tn;

          // Trb respect after measurements
          // We consider that the timeslot on which the Layer 1 is synchronized is
          // always allocated on the frame after the idle frame.
          // For the Trb multi-slot class parameter respect, we must clear the bits at
          // the right of the interference measurement bitmap
          l1pa_l1ps_com.itmeas.idle_tn_no_rx &= (UWORD8)
                           ~(   0xFF
                             >> (  8 + l1a_l1s_com.dl_tn
                                 - MS_CLASS[l1pa_l1ps_com.itmeas.multislot_class].trb));

          // 2- With a Rx programmed on the frame before
          // Note: This Rx is always on the dl_tn

          l1pa_l1ps_com.itmeas.idle_tn_rx = l1pa_l1ps_com.itmeas.idle_tn_no_rx;

          // Trb respect before measurements
          // The timeslot on which the Layer 1 is synchronized is allocated on the frame
          // before the idle frame.
          // For the Trb multi-slot class parameter respect, we must clear the bits at
          // the left of the interference measurement bitmap
          bitmap = 0x80;

          i = 8 - l1a_l1s_com.dl_tn - MS_CLASS[l1pa_l1ps_com.itmeas.multislot_class].trb;
          if (i > 8)
            bitmap >>= (-i);
          else
            bitmap <<= i;

          for (i = 1; i<= MS_CLASS[l1pa_l1ps_com.itmeas.multislot_class].trb; i++)
          {
            l1pa_l1ps_com.itmeas.idle_tn_rx &= (UWORD8) ~bitmap;
            bitmap <<= 1;
          }

          // Initialize parameters
          l1pa_l1ps_com.itmeas.position        = ANY_IDLE_FRAME;  // First measurement on any idle frame

          // Enable synchronous task
          l1a_l1s_com.l1s_en_task[ITMEAS]      = TASK_ENABLED;

          // Step in state machine
          *state = WAIT_1ST_RESULT;

          // End of process
          end_process = 1;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process.
          end_process = 1;
        }
      }
      break;

      case WAIT_1ST_RESULT:
      {
        // Reporting of 1st measurement session
        //-------------------------------------
        if (SignalCode == L1P_ITMEAS_IND)
        {
          UWORD8  i;

          // Set semaphore
          l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET;

          // Save interference measurements
          for(i=0; i<8; i++)
            int_meas_param.rxlev[i]  = ((T_L1P_ITMEAS_IND *)(msg->SigP))->rxlev[i];

          // Save bitmap
          int_meas_param.meas_bitmap = ((T_L1P_ITMEAS_IND *)(msg->SigP))->meas_bitmap;

           // Save reported fn
          int_meas_param.fn          = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn;

          // Position = complement of reported position
          if (((T_L1P_ITMEAS_IND *)(msg->SigP))->position == PTCCH_FRAME)
            l1pa_l1ps_com.itmeas.position = SEARCH_FRAME;
          else
            l1pa_l1ps_com.itmeas.position = PTCCH_FRAME;

            // Enable ITMEAS
            l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_ENABLED;

          // Step in state machine
          *state = WAIT_2ND_RESULT;

          // End of process
          return;
        }

          else
        if (SignalCode == MPHP_INT_MEAS_STOP_REQ)
          {
          // Send confirmation
          l1a_send_confirmation(MPHP_INT_MEAS_STOP_CON,GRRM1_QUEUE);

          // Reset process
          *state = RESET;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process
          return;
        }
      }
      break;

      case WAIT_2ND_RESULT:
      {
        // Reporting subsequent measurement session
        //-----------------------------------------
        if (SignalCode == L1P_ITMEAS_IND)
        {
          // At least one measurement session has already been reported
          //-----------------------------------------------------------
          UWORD32 reported_fn;

          // Check fn
          // The two measurement sessions must be done in two contiguous idle frames

          // Modulo
          if (((T_L1P_ITMEAS_IND *)(msg->SigP))->fn < int_meas_param.fn)
          {
            reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn + MAX_FN;
          }
          else
          {
            reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn;
          }

          // The two last measurement sessions are enough close
          if ((reported_fn - int_meas_param.fn) == 13)
          {
            // Build and send result msg to L3.
            l1pa_send_int_meas_report(MPHP_INT_MEAS_IND,
                                      ((T_L1P_ITMEAS_IND *)(msg->SigP)),
                                      &int_meas_param);

            // Only one measurement session per request
            *state = RESET;
          }

          // The two last measurement sessions aren't enough close
          else
          {
            // 1st measurement result is no more valid, second result
            // must replace it: this is achieved by WAIT_1ST_RESULT state!!!

            // Step in state machine
            *state = WAIT_1ST_RESULT;
          }
        }

        else
        if (SignalCode == MPHP_INT_MEAS_STOP_REQ)
        {
          // Send confirmation
          l1a_send_confirmation(MPHP_INT_MEAS_STOP_CON,GRRM1_QUEUE);

          // Reset process
          *state = RESET;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process
          return;
        }
      }
      break;

    } // End of "switch"
  } // End of "while"
} // End of "procedure"

/*-------------------------------------------------------*/
/* l1pa_transfer_interference_meas_process()             */
/*-------------------------------------------------------*/
/* Description :                                         */
/*                                                       */
/* Starting messages:        L1P_TRANFSER_DONE           */
/*                                                       */
/* Interference measurement processing starts each time  */
/* a new starting time occurs if the interference        */
/* measurements are enabled                              */
/* Measurements must be done on one search frame and one */
/* PTCCH frame.                                          */
/*                                                       */
/* Result messages (input):  L1PS_ITMEAS_IND             */
/*                                                       */
/* This message is reported to L1A when signal strength  */
/* has been measured on one idle frame (PTCCH or search) */
/*                                                       */
/* Result messages (output): MPHP_TINT_MEAS_IND          */
/*                                                       */
/* This message is reported to L3 when measurements have */
/* been done on two idle frames as close as possible     */
/*                                                       */
/* Reset message (input):    L1P_TBF_RELEASED            */
/*                                                       */
/* Interference measurement processing is stopped when   */
/* all TBF are released                                  */
/*-------------------------------------------------------*/
void l1pa_transfer_interference_meas_process(xSignalHeaderRec *msg)
{
  /* Bitmaps used for the processing of full_allocation */
  /*----------------------------------------------------*/
  const UWORD8 FULL_ALLOCATION[9]=
{
    0x00,
    0x80,
    0xc0,
    0xe0,
    0xf0,
    0xf8,
    0xfc,
    0xfe,
    0xff
  };

  enum states
  {
    RESET             = 0,
    WAIT_INIT         = 1,
    CONFIG            = 2,
    WAIT_1ST_RESULT   = 3,
    WAIT_2ND_RESULT   = 4
  };

  static   T_L1A_INT_MEAS_PARAM int_meas_param;
  UWORD8   *state      = &l1pa.state[PT_INT_MEAS];
  UWORD32  SignalCode  = msg->SignalCode;

  BOOL end_process = 0;
  while(!end_process)
  {
    switch(*state)
    {
      case RESET:
      {
        // Step in state machine.
        *state = WAIT_INIT;

        // Reset ITMEAS process.
        l1a_l1s_com.l1s_en_task[ITMEAS]    = TASK_DISABLED;  // Clear ITMEAS task enable flag.
      }
      break;

      case WAIT_INIT:
      {
        // New channel assignment
        //-----------------------
        if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_REPEAT_ALLOC_DONE) ||
            (SignalCode == L1P_ALLOC_EXHAUST_DONE))
        {
          *state = CONFIG;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process.
          return;
        }
      }
      break;

      case CONFIG:
      {
        // Rise transfert parameter semaphore to prevent L1S to use partial configuration.
        l1pa_l1ps_com.transfer.semaphore = TRUE;

        // If the interference measurements are disabled
        if (l1pa_l1ps_com.transfer.aset->interf_meas_enable == FALSE)
        {
          *state = WAIT_INIT;
        }
        else
        {
          // Set semaphore
          l1a_l1s_com.task_param[ITMEAS]   = SEMAPHORE_SET;

          // Initialize parameters
          l1pa_l1ps_com.itmeas.position    = ANY_IDLE_FRAME;  // First measurement on any idle frame

          // Save assignment ID for the interference measurements reporting message
          int_meas_param.id = l1pa_l1ps_com.transfer.aset->assignment_id;

          // Processing of the measurement bitmap
          l1pa_l1ps_com.itmeas.meas_bitmap = (UWORD8)
               FULL_ALLOCATION[MS_CLASS[l1pa_l1ps_com.transfer.aset->multislot_class].rx] >>
               l1a_l1s_com.dl_tn;

          // Enable synchronous task
          l1a_l1s_com.l1s_en_task[ITMEAS]  = TASK_ENABLED;

          // Step in state machine
          *state = WAIT_1ST_RESULT;
        }

        // Clear transfer parameter semaphore to let L1S use the new parameters.
        l1pa_l1ps_com.transfer.semaphore = FALSE;

        // End of process.
        end_process = 1;
      }
      break;

      case WAIT_1ST_RESULT:
      {
        // Reporting of 1st measurement session
        //-------------------------------------
        if (SignalCode == L1P_ITMEAS_IND)
        {
          UWORD8  i;

          // Set semaphore
          l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET;

          // Save interference measurements
          for(i=0; i<8; i++)
            int_meas_param.rxlev[i]  = ((T_L1P_ITMEAS_IND *)(msg->SigP))->rxlev[i];

          // Save bitmap
          int_meas_param.meas_bitmap = ((T_L1P_ITMEAS_IND *)(msg->SigP))->meas_bitmap;

            // Save reported fn
          int_meas_param.fn          = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn;

          // Position = complement of reported position
          if (((T_L1P_ITMEAS_IND *)(msg->SigP))->position == PTCCH_FRAME)
            l1pa_l1ps_com.itmeas.position = SEARCH_FRAME;
          else
            l1pa_l1ps_com.itmeas.position = PTCCH_FRAME;

            // Enable ITMEAS
            l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_ENABLED;

          // Step in state machine
          *state = WAIT_2ND_RESULT;

            // End of process
            return;
        }

        else
        if (SignalCode == L1P_TRANSFER_DONE)
        // The starting time of a new TBF occurs
        {
          // Reset process
          *state = RESET;
        }

        else
        if (SignalCode == L1P_TBF_RELEASED)
        // A TBF has been released
        {
          // No remaining TBF
          if(((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all)
          {
            // Reset process
            *state = RESET;
          }
          else
          {
            // Enable a new measurement session
            *state = CONFIG;
          }
        }

        else
        if (SignalCode == L1P_PDCH_RELEASED)
        // PDCH have been released
        {
          // Enable a new measurement session
          *state = CONFIG;
        }

        // No action in this machine for other messages.
          else
          {
          // End of process
          return;
        }
      }
      break;

      case WAIT_2ND_RESULT:
      {
        // Reporting subsequent measurement session
        //-----------------------------------------
        if (SignalCode == L1P_ITMEAS_IND)
        {
          // At least one measurement session has already been reported
          //-----------------------------------------------------------
          UWORD32 reported_fn;

          // Check fn
          // The two measurement sessions must be done in two contiguous idle frames

          // Modulo
          if (((T_L1P_ITMEAS_IND *)(msg->SigP))->fn < int_meas_param.fn)
          {
            reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn + MAX_FN;
          }
          else
          {
            reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn;
          }

            // The two last measurement sessions are enough close
          if ((reported_fn - int_meas_param.fn) <= 104)
          {
            // Build and send result msg to L3.
            l1pa_send_int_meas_report(MPHP_TINT_MEAS_IND,
                                      ((T_L1P_ITMEAS_IND *)(msg->SigP)),
                                      &int_meas_param);

              // Enable a new measurement session
              *state = CONFIG;
          }

          // The two last measurement sessions aren't enough close
          else
          {
            // 1st measurement result is no more valid, second result
            // must replace it: this is achieved by WAIT_1ST_RESULT state!!!

            // Step in state machine
            *state = WAIT_1ST_RESULT;
          }
        }

        else

        // New channel assignment
        //-----------------------
        if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_REPEAT_ALLOC_DONE) ||
            (SignalCode == L1P_ALLOC_EXHAUST_DONE))
        {
          // Reset process
          *state = RESET;
        }

        else
        if (SignalCode == L1P_TBF_RELEASED)
        // A TBF has been released
        {
          // No remaining TBF
          if(((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all)
          {
            // Reset process
            *state = RESET;
          }
          else
          {
            // Enable a new measurement session
            *state = CONFIG;
          }
        }

        else
        if (SignalCode == L1P_PDCH_RELEASED)
        // PDCH have been released
        {
          // Enable a new measurement session
          *state = CONFIG;
        }

        // No action in this machine for other messages.
        else
        {
          // End of process
          return;
        }
      }
      break;

    } // End of "switch"
  } // End of "while"
} // End of "procedure"
//#pragma DUPLICATE_FOR_INTERNAL_RAM_START
#endif
//#pragma DUPLICATE_FOR_INTERNAL_RAM_END