view src/g23m-gprs/grr/grr_measf.c @ 621:0d66718e5f33

Calypso chip version mechanism documented
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 07 Oct 2019 03:59:14 +0000
parents 219afcfc6250
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GPRS (8441)
|  Modul   :  GRR
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This module implements local functions for service MEAS of
|             entity GRR.
+----------------------------------------------------------------------------- 
*/ 

#ifndef GRR_MEASF_C
#define GRR_MEASF_C
#endif

#define ENTITY_GRR

/*==== INCLUDES =============================================================*/

#include <string.h>

#include "typedefs.h"   /* to get Condat data types */
#include "vsi.h"        /* to get a lot of macros */
#include "macdef.h"  
#include "gprs.h"  
#include "gsm.h"        /* to get a lot of macros */
#include "ccdapi.h"     /* to get CCD API */
#include "cnf_grr.h"    /* to get cnf-definitions */
#include "mon_grr.h"    /* to get mon-definitions */
#include "prim.h"       /* to get the definitions of used SAP and directions */
#include "message.h"  
#include "grr.h"        /* to get the global entity definitions */
#include "grr_f.h"
#include "grr_measf.h"  /* to get the own definitions */
#include "grr_meass.h"  /* to get the own definitions */
#include "grr_ctrls.h"

/*==== CONST ================================================================*/

#define IDX_UBYTE_INVALID    0xFF             /* invalid index                 */
#define IDX_USHORT_INVALID   0xFFFF           /* invalid index                 */
#define TIME_INVALID         0x7FFFFFFF       /* invalid time, should be the   */
                                              /* largest possible value for an */
                                              /* variable of type LONG         */

#define USE_ALL_TIMESLOTS    0xFF             /* timeslot mask                 */

#define EM_EXT_RPT_TYPE_LEN   2   /* length of EXT reporting type bit field    */
#define EM_ABS_I_LEVEL_LEN    6   /* length of absolute I_LEVEL bit field      */
#define EM_NUM_OF_MEAS_LEN    5   /* length of number of measurement bit field */
#define EM_FREQ_N_LEN         6   /* length of FREQ_N bit field                */
#define EM_BSIC_N_LEN         6   /* length of BSIC_N bit field                */
#define EM_RXLEV_N_LEN        6   /* length of RXLEV_N bit field               */

#ifdef _SIMULATION_
#define GET_EM_RPT_PRD(x)     ((0x01<<(x))*10000) /* multiple of 10 sec., to get */            
                                                  /* a reduced test duration     */
#else /* #ifdef _SIMULATION_ */
#define GET_EM_RPT_PRD(x)     ((0x01<<(x))*60000) /* multiple of 60 sec.         */
#endif /* #ifdef _SIMULATION_ */

#define I_LEVEL_MIN             I_LEVEL_0
#define I_LEVEL_0               0    /* i.lev. is greater than C                  */
#define I_LEVEL_15              15   /* i.lev. is less than or equal to C - 28 dB */    
#define I_LEVEL_MAX             I_LEVEL_15
#define I_LEVEL_GAMMA_0_SKIPPED 0xF0 /* used for tracing                          */
#define I_LEVEL_GAMMA_1_SKIPPED 0xF1 /* used for tracing                          */
#define I_LEVEL_GAMMA_2_SKIPPED 0xF2 /* used for tracing                          */
#define I_LEVEL_GAMMA_3_SKIPPED 0xF3 /* used for tracing                          */
#define I_LEVEL_STATE_MISMATCH  0xFD /* used for tracing                          */
#define I_LEVEL_IDX_TO_SMALL    0xFE /* used for tracing                          */
#define I_LEVEL_NOT_AVAIL       0xFF /* used for tracing                          */

#define NORM_NAVGI_FAC (ULONG)10     /* normalised Navg_i factor                     */

#ifdef _TARGET_

#define MIN_GAMMA_FOR_I_LEVEL_RPTING 4 /* minimum I-LEVEL value of neighbour */
                                       /* cells that will be reported to the */
#else                                  /* network, otherwise I-LEVEL values  */
                                       /* will be reported as not available  */
#define MIN_GAMMA_FOR_I_LEVEL_RPTING 0

#endif /* #ifdef _TARGET_ */

#define MEAS_C_INC_INDEX(index) {                                        \
                                  if( index < (T_C_INDEX)(~0) ) index++; \
                                }

/*==== LOCAL VARS ===========================================================*/

LOCAL T_MEAS_IM_DATA* imeas = NULL; 
                          /* pointer to interference measurement parameter   */
LOCAL T_MEAS_EM_DATA* emeas = NULL;
                          /* pointer to extended measurement parameter       */

#if defined (REL99) AND defined (TI_PS_FF_EMR)
LOCAL BOOL  nc_freq_list_valid = FALSE;
LOCAL BOOL  nc_freq_list_pres = FALSE;
GLOBAL BOOL use_ba_gprs = TRUE;
#endif

/*
 * normalised math.power value 
 *
 * NORM_POW_MIN * ( 2 ** ( k / 2 ) )
 */

GLOBAL const ULONG norm_pow[] = { NORM_POW_MIN, 
                                     1414,    2000,    2828,    4000,    5657,
                                     8000,   11314,   16000,   22627,   32000,
                                    45255,   64000,   90510,  128000,  181019,
                                   256000,  362039,  512000,  724077, 1024000,
                                  1448155, 2048000, 2896309, 4096000, 5792619 };

/*==== LOCAL TYPES===========================================================*/

LOCAL void   meas_im_restart_all_filters ( void                                  );

LOCAL void   meas_im_restart_filter      ( T_MEAS_IM_FILTER     *filter          );

LOCAL void   meas_im_restart_gamma       ( T_MEAS_IM_FILTER     *filter,
                                           UBYTE                 index           );

LOCAL T_MEAS_IM_FILTER*
             meas_im_get_unused_filter   ( void                                  );

LOCAL void   meas_im_update_filter       ( T_MEAS_IM_FILTER     *filter, 
                                           UBYTE                *rxlev,
                                           UBYTE                 state           );

LOCAL BOOL   meas_im_freq_cmp_a          ( USHORT                arfcn1,
                                           USHORT                arfcn2          );

LOCAL BOOL   meas_im_freq_cmp_m          ( T_MEAS_IM_CARRIER    *ma1,
                                           T_MEAS_IM_CARRIER    *ma2             );

LOCAL ULONG  meas_im_get_val_trns        ( void                                  );

LOCAL ULONG  meas_im_get_val_idle        ( void                                  );

LOCAL UBYTE  meas_im_get_number_of_measured_channels
                                         ( void                                  );

LOCAL T_MEAS_IM_FILTER*
             meas_im_get_oldest_filter   ( void                                  );

LOCAL BOOL   meas_im_get_int_meas_freq   ( UBYTE                 index, 
                                           T_MEAS_IM_CARRIER    *carrier,
                                           UBYTE                *ts_mask         );

LOCAL BOOL   meas_im_get_trns_freq       ( T_MEAS_IM_CARRIER    *ma              );

LOCAL BOOL   meas_im_get_idle_freq       ( ULONG                 id, 
                                           T_MEAS_IM_CARRIER    *carrier,
                                           UBYTE                *ts_mask         );

LOCAL void   meas_im_timer_reorg         ( T_TIME                time_to_elapse,
                                           LONG                  time_diff       );

LOCAL void   meas_im_delete_em_rslt      ( void                                  );

LOCAL USHORT meas_im_get_unmsk_int_freq  ( UBYTE                 index           );

LOCAL void   meas_im_start_t_im_sync     ( T_TIME                vld_prd         );

LOCAL ULONG  meas_im_get_paging_period   ( void                                  );

LOCAL void   meas_im_set_freq_par        ( T_p_frequency_par    *freq_par, 
                                           T_MEAS_IM_CARRIER    *carrier         );

LOCAL void   meas_em_init_pmo_seq        ( void                                  );

LOCAL UBYTE  meas_em_build_meas_rpt      ( T_U_MEAS_REPORT      *u_meas_report   );

LOCAL UBYTE  meas_em_extrct_strgst       ( void                                  );

LOCAL UBYTE  meas_em_extrct_strgst_with_bsic
                                         ( void                                  );
LOCAL void   meas_em_req                 ( void                                  );

LOCAL BOOL   meas_em_is_meas_reporting   ( void                                  );

LOCAL void   meas_em_start_t3178         ( T_TIME                time            );

LOCAL void   meas_em_stop_t3178          ( void                                  );

/*==== PRIVATE FUNCTIONS ====================================================*/
/*
+------------------------------------------------------------------------------
| Function    : meas_im_init 
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_init ( T_MEAS_IM_MODE im_mode )
{
  TRACE_FUNCTION( "meas_im_init" );

  INIT_STATE( MEAS_IM, MEAS_IM_NULL );

  imeas = &grr_data->meas_im;

#if !defined (NTRACE)

  imeas->n_im_trace       = 0;

#endif /* #if !defined (NTRACE) */

  imeas->mode             = im_mode;
  imeas->carrier_id       = IDX_USHORT_INVALID;
  imeas->trig_signal      = IM_TRIG_SIGNAL_NULL;
  imeas->v_cs_meas_active = FALSE;

  meas_im_restart_all_filters( );
} /* meas_im_init() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_restart_all_filters
+------------------------------------------------------------------------------
| Description : This function restarts all filters used in context of
|               interference measurements.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_restart_all_filters ( void )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "meas_im_restart_all_filters" );
  
  for( i = 0; i < MAX_IM_CHANNELS; i++ )
  {
    meas_im_restart_filter( &imeas->filter[i] );
  }
} /* meas_im_restart_all_filters() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_restart_filter
+------------------------------------------------------------------------------
| Description : This function restarts all filters for one carrier 
|               used in context of interference measurements.
|
| Parameters  : *filter - Ptr to filter
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_restart_filter ( T_MEAS_IM_FILTER* filter )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "meas_im_restart_filter" );

  for( i = 0; i < CGRLC_MAX_TIMESLOTS; i++ )
  {
    meas_im_restart_gamma( filter, i );
  }
} /* meas_im_restart_filter() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_restart_gamma
+------------------------------------------------------------------------------
| Description : This function restarts an individual filter for 
|               one channel used in context of interference measurements.
|
| Parameters  : *filter - Ptr to filter
|               index   - index of the interference level values
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_restart_gamma ( T_MEAS_IM_FILTER* filter,
                                   UBYTE             index )
{ 
  T_MEAS_IM_GAMMA* gamma = &filter->i_level[index];

  SET_FLAG( filter->used, IM_U_MASK << index, IM_U_UNUSED << index, UBYTE );

  gamma->index       = 0;
  gamma->m_gamma     = IM_I_NONE;
  gamma->gamma       = 0;
  gamma->remain_time = TIME_INVALID;
} /* meas_im_restart_gamma() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_filter
+------------------------------------------------------------------------------
| Description : This function is used to look for the filter that should be
|               updated. It searches for the filter with the same channel
|               description.
|
| Parameters  : *ma     - Ptr to frequency information in MA format
|
+------------------------------------------------------------------------------
*/
GLOBAL T_MEAS_IM_FILTER* meas_im_get_filter ( T_MEAS_IM_CARRIER *ma )
{ 
  UBYTE             i;                    /* used for counting */
  T_MEAS_IM_FILTER *filter       = NULL;  /* found filter      */
  BOOL              filter_found = FALSE; /* indicator         */

  TRACE_FUNCTION( "meas_im_get_filter" );

  i = 0;

  while( i < MAX_IM_CHANNELS AND !filter_found )
  {
    filter = &imeas->filter[i];

    if( ma->hopping )
    {
      if( ma                      NEQ NULL        AND
          filter->used            NEQ IM_U_UNUSED AND
          filter->carrier.hopping EQ  TRUE        AND
          meas_im_freq_cmp_m( ma, &filter->carrier ))
      {
        filter_found = TRUE;
      }
    }  
    else
    {
      if( filter->used            NEQ IM_U_UNUSED AND
          filter->carrier.hopping EQ  FALSE       AND 
          meas_im_freq_cmp_a( ma->alloc.arfcn,  
                              filter->carrier.alloc.arfcn ) )          
      {
        filter_found = TRUE;
      }
    }
    
    i++;
  }

  return( filter_found ? filter : NULL );
} /* meas_im_get_filter() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_unused_filter
+------------------------------------------------------------------------------
| Description : This function is used to look for the first unused filter.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL T_MEAS_IM_FILTER* meas_im_get_unused_filter ( void )
{
  UBYTE             i;             /* used for counting */
  T_MEAS_IM_FILTER *filter = NULL; /* found filter      */

  TRACE_FUNCTION( "meas_im_get_unused_filter" );

  i = 0;

  while( i < MAX_IM_CHANNELS AND filter EQ NULL )
  {
    if( imeas->filter[i].used EQ IM_U_UNUSED )
    {
      filter = &imeas->filter[i];
    }

    i++;
  }

  return( filter );
} /* meas_im_get_unused_filter() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_update_filter
+------------------------------------------------------------------------------
| Description : This function is used to update an interference level filter.
|
| Parameters  : *filter - Ptr to filter
|               *rxlev  - Ptr to measurement values
|               mode    - Packet idle or packet transfer mode
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_update_filter ( T_MEAS_IM_FILTER *filter, 
                                   UBYTE            *rxlev,
                                   UBYTE             state )
{ 
  UBYTE  i;                      /* used for counting                          */
  BOOL   valid_meas     = FALSE; /* indicates if at least one valid            */
                                 /* measurement sample is present              */
  T_TIME time_to_elapse =0;      /* this is the remaining time until           */
                                 /* timer T_IM_SYNC will elpase                */
  LONG   remain_time    = 0;     /* this is the remaining time for an          */
                                 /* individual filter                          */
  ULONG  d;                      /* forgetting factor                          */  
  ULONG  g_value;
  T_MEAS_IM_GAMMA *ilevel; 
                                 /* inteference level                          */
  ULONG  validity;               /* validity period of the measurement results */
  BOOL   v_t_im_sync    = FALSE; /* indicates whether the timer T_IM_SYNC is   */
                                 /* running or not                             */



  TRACE_FUNCTION( "meas_im_update_filter" );

  /* calculate validity period of the measurements */
  if( state EQ MEAS_IDLE )
  {
    validity = meas_im_get_val_idle( );
  }
  else
  {
    validity = meas_im_get_val_trns( );
  }

  /* calculate remaining time */
  time_to_elapse = grr_t_status( T_IM_SYNC );

  if(  time_to_elapse > 0 )
  {
    remain_time = validity - time_to_elapse;
    v_t_im_sync = TRUE;
  }

  for( i = 0; i < CGRLC_MAX_TIMESLOTS; i++ )
  {
    ilevel = &filter->i_level[i];

    if( rxlev[i] NEQ CGRLC_RXLEV_NONE )
    {
      SET_FLAG( filter->used, IM_U_MASK << i, IM_U_USED << i, UBYTE );
      valid_meas = TRUE;

      ilevel->remain_time = remain_time;

#ifdef _SIMULATION_
      TRACE_EVENT_P1("REMAIN_TIME = %d", remain_time);
#endif /* #ifdef (_SIMULATION_) */

      /* counting the iteration index */
      if( NORM_POW_MIN * ilevel->index < norm_pow[psc_db->g_pwr_par.n_avg_i] )
      {
        ilevel->index++;
      }

      /* calculate the forgetting factor */
      d = ( NORM_POW_MIN * NORM_POW_MIN * NORM_NAVGI_FAC ) / 
          MINIMUM( NORM_POW_MIN * ilevel->index,
                   norm_pow[psc_db->g_pwr_par.n_avg_i] );

      /* update the filter */
      g_value = ( ( NORM_POW_MIN * NORM_NAVGI_FAC ) - d ) * ilevel->gamma 
                +
                d * MEAS_ACRCY * rxlev[i];
    
      ilevel->gamma = (T_IM_GAMMA)(g_value / (NORM_POW_MIN * NORM_NAVGI_FAC));

#ifdef _SIMULATION_
      TRACE_EVENT_P2("TS = %d, I-LEVEL = %d", i, ilevel->gamma);
#endif /* #ifdef (_SIMULATION_) */

      /* store the mode in which the measurement was performed */
      if( state EQ MEAS_IDLE )
      {
        SET_FLAG( ilevel->m_gamma, IM_I_MASK_IDL,  IM_I_IDL,  UBYTE );
        SET_FLAG( ilevel->m_gamma, IM_I_MASK_TRNS, IM_I_NONE, UBYTE );
      }
      else
      {
        SET_FLAG( ilevel->m_gamma, IM_I_MASK_TRNS, IM_I_TRNS, UBYTE );
        SET_FLAG( ilevel->m_gamma, IM_I_MASK_IDL,  IM_I_NONE, UBYTE );
      }

    }
  } /* i */

  /*
   * do some administrative stuff only in case there was at least
   * one valid sample reported by Layer 1
   */
  if( valid_meas )
  {
    if( v_t_im_sync )
    {
      if( remain_time < 0 )
      {
        meas_im_timer_reorg( time_to_elapse, remain_time );
      }
    }
    else
    {
      meas_im_start_t_im_sync( (ULONG)validity );
    }
  }
} /* meas_im_update_filter() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_freq_cmp_a
+------------------------------------------------------------------------------
| Description : This function returns whether two frequencies are identical
|               or not.
|
| Parameters  : arfcn1 - First frequency used for comparison
|               arfcn2 - Second frequency used for comparison
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL meas_im_freq_cmp_a ( USHORT arfcn1, USHORT arfcn2 )
{
  return( arfcn1 EQ arfcn2 );
} /* meas_im_freq_cmp_a() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_freq_cmp_m
+------------------------------------------------------------------------------
| Description : This function returns whether two frequency information given
|               in mobile allocation format are identical or not. Channels 
|               that only differ in MAIO are considered the same.
|
| Parameters  : *ma1 - First channel description used for comparison
|               *ma2 - Second channel description used for comparison
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL meas_im_freq_cmp_m ( T_MEAS_IM_CARRIER *ma1, T_MEAS_IM_CARRIER *ma2  )
{
  return
  (
    ma1->alloc.hop_param.hsn EQ ma2->alloc.hop_param.hsn 
    
    AND
    
    memcmp( ma1->alloc.hop_param.arfcn_bit_field, 
            ma2->alloc.hop_param.arfcn_bit_field,
            sizeof( ma1->alloc.hop_param.arfcn_bit_field ) ) EQ 0
  );
} /* meas_im_freq_cmp_m() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_val_trns
+------------------------------------------------------------------------------
| Description : This function returns the validity period of a measurement 
|               performed in packet transfer mode (unit is milliseconds).
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL ULONG meas_im_get_val_trns ( void )
{
  ULONG n_avg_i_half = norm_pow[psc_db->g_pwr_par.n_avg_i] / 2;

  return(ULONG)
    ( ( n_avg_i_half * ( USEC_PER_MF / (ULONG)10 ) ) /
                            ( NORM_POW_MIN * (ULONG)MEAS_ACRCY / (ULONG)10 ) );
} /* meas_im_get_val_trns() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_val_idle
+------------------------------------------------------------------------------
| Description : This function returns the validity period of a measurement 
|               performed in packet idle mode (unit is milliseconds).
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL ULONG meas_im_get_val_idle ( void )
{
  ULONG val_idle      = TIME_INVALID - 1;
  ULONG paging_period = meas_im_get_paging_period( );

  if( paging_period NEQ NO_PAGING )
  {
    ULONG acrcy_n, acrcy_p;
    ULONG novimc_t_navgi = meas_im_get_number_of_measured_channels( ) * 
                           norm_pow[psc_db->g_pwr_par.n_avg_i];

    if     ( paging_period  <= 650000  ) acrcy_p = 10;
    else if( paging_period  <= 6500000 ) acrcy_p = 100;
    else                                 acrcy_p = 1000;

    if     ( novimc_t_navgi <= 130000  ) acrcy_n = 1;
    else if( novimc_t_navgi <= 1300000 ) acrcy_n = 10;
    else                                 acrcy_n = 100;

    val_idle = 
      (ULONG)
        (
          ( MAXIMUM(
                     ( novimc_t_navgi / ( (ULONG)4 * acrcy_n ) ) *
                     ( USEC_PER_MF    / acrcy_p ),
                     ( novimc_t_navgi / ( (ULONG)2 * acrcy_n ) ) *
                     ( paging_period  / acrcy_p )
                   )
          ) / ( NORM_POW_MIN * (ULONG)MEAS_ACRCY / ( acrcy_n * acrcy_p ) ) 
        );
  }

  return val_idle;
} /* meas_im_get_val_idle() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_number_of_measured_channels
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE meas_im_get_number_of_measured_channels ( void )
{
  UBYTE number = psc_db->number_of_valid_int_meas_channels;

  if( imeas->idle_chan.ident[CHN_ID_EM_BASE] NEQ CHN_ID_INVALID )
  {
    number++;
  }

  if( imeas->idle_chan.ident[CHN_ID_PCCCH_BASE] NEQ CHN_ID_INVALID )
  {
    number++;
  }
 
  return( number );
} /* meas_im_get_number_of_measured_channels() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_oldest_filter
+------------------------------------------------------------------------------
| Description : This functions returns a filter that can be used for storing
|               measurement results
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL T_MEAS_IM_FILTER* meas_im_get_oldest_filter ( void )
{
  UBYTE i, j;                           /* used for counting                */
  LONG  remain1    = TIME_INVALID;      /* holds remaining time             */
  LONG  remain2;                        /* holds remaining time             */
  BOOL  all_invalid;                    /* indicates if all remaining times */
                                        /* are invalid                      */
  UBYTE filter_idx = IDX_UBYTE_INVALID; /* index of oldest filter           */
  T_MEAS_IM_GAMMA *ilevel;              /* interference level               */

  TRACE_FUNCTION( "meas_im_get_oldest_filter" );

  for( i = 0; i < MAX_IM_CHANNELS; i++ )
  {
    remain2     = TIME_INVALID;
    all_invalid = TRUE;

    for( j = 0; j < CGRLC_MAX_TIMESLOTS; j++ )
    {
      ilevel = &imeas->filter[i].i_level[j];
  
      if( ilevel->remain_time NEQ TIME_INVALID )
      {
        all_invalid = FALSE;

        if( remain2 EQ TIME_INVALID )
        {
          remain2 = ilevel->remain_time;
        }
        else
        {
          remain2 = MINIMUM( ilevel->remain_time, remain2 );
        }
      }
    }

    if( all_invalid )
    {
      filter_idx = i;
    }
    else if( remain1 EQ TIME_INVALID OR remain1 < remain2 )
    {
      remain1    = remain2;
      filter_idx = i;
    }
  }

  return( filter_idx EQ IDX_UBYTE_INVALID ? NULL : &imeas->filter[i] );
} /* meas_im_get_oldest_filter() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_int_meas_freq
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL meas_im_get_int_meas_freq ( UBYTE              index, 
                                       T_MEAS_IM_CARRIER *carrier,
                                       UBYTE             *ts_mask )
{
  T_p_frequency_par    freq_par;
  T_int_meas_chan_lst *lst   = &psc_db->int_meas_chan_list[index];
  BOOL                 valid = TRUE;

  TRACE_FUNCTION( "meas_im_get_int_meas_freq" );

  if( lst->v_arfcn EQ TRUE )
  {
    carrier->hopping     = FALSE;
    carrier->alloc.arfcn = lst->arfcn;
  }
  else if( lst->v_ma_num_maio EQ TRUE )
  {
    if( ( valid = grr_create_freq_list(  lst->ma_num,
                                         lst->maio,
                                        &freq_par.p_chan_sel,
                                        &freq_par.p_freq_list ) ) EQ TRUE )
    {
      meas_im_set_carrier( carrier, &freq_par );
    }
  }
  else
  {
    valid = FALSE;
  }
  
  *ts_mask = lst->ts_alloc;

  return( valid );
} /* meas_im_get_int_meas_freq() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_trns_freq
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL meas_im_get_trns_freq ( T_MEAS_IM_CARRIER *ma )
{
  TRACE_FUNCTION( "meas_im_get_trns_freq" );

  if( grr_data->tc.v_freq_set EQ TRUE )
  {
    T_p_frequency_par freq_par;

    grr_set_freq_par( &freq_par );
    meas_im_set_carrier( ma, &freq_par );
  }

  return( grr_data->tc.v_freq_set );
} /* meas_im_get_trns_freq() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_idle_freq
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL meas_im_get_idle_freq ( ULONG              id, 
                                   T_MEAS_IM_CARRIER *carrier,
                                   UBYTE             *ts_mask )
{
  BOOL                valid_id = TRUE;
  T_MEAS_IM_IDLE_CHN* chn      = &imeas->idle_chan;

  TRACE_FUNCTION( "meas_im_get_idle_freq" );

  if( id             >= MAX_IM_IDLE_CHANNELS OR 
      chn->ident[id] EQ CHN_ID_INVALID          )
  {
    TRACE_ERROR( "ID invalid in meas_im_get_idle_freq" );
    valid_id = FALSE; 
  }
  else if( id EQ CHN_ID_EM_BASE )
  {
    *ts_mask             = USE_ALL_TIMESLOTS; /* SZML-MEAS/005 */
    carrier->hopping     = FALSE;
    carrier->alloc.arfcn = meas_im_get_unmsk_int_freq( chn->ident[id] );
  }
  else if( id EQ CHN_ID_PCCCH_BASE )
  { 
    T_p_frequency_par freq_par;

    *ts_mask = ( 0x80 >> psc_db->paging_group.pccch[chn->ident[id]].tn );

    grr_get_pccch_freq_par(  chn->ident[id],
                            &freq_par.p_chan_sel,
                            &freq_par.p_freq_list );
    
    meas_im_set_carrier( carrier, &freq_par );
  }
  else
  {
    valid_id = meas_im_get_int_meas_freq( chn->ident[id], carrier, ts_mask );
  }

  return( valid_id );
} /* meas_im_get_idle_freq() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_timer_reorg
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_timer_reorg ( T_TIME time_to_elapse, LONG time_diff )
{
  UBYTE i, j; /* used for counting */

  TRACE_FUNCTION( "meas_im_timer_reorg" );
   
  vsi_t_stop( GRR_handle, T_IM_SYNC );

  for( i = 0; i < MAX_IM_CHANNELS; i++ )
  {
    for( j = 0; j < CGRLC_MAX_TIMESLOTS; j++ )
    {
      if( imeas->filter[i].i_level[j].remain_time NEQ TIME_INVALID )
      {
        imeas->filter[i].i_level[j].remain_time -= time_diff;
      }
    }
  }
    
  meas_im_start_t_im_sync( ( LONG )time_to_elapse + time_diff  );

} /* meas_im_timer_reorg() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_fill_rel_iLevel
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_fill_rel_iLevel ( UBYTE            *v_ilev,
                                      UBYTE            *ilev,
                                      T_MEAS_IM_FILTER *filter,
                                      UBYTE             idx )
{
  UBYTE val; /* holds interference level data */

  *v_ilev = FALSE;

  if( filter NEQ NULL )
  {

#ifdef _TARGET_

    UBYTE state = GET_STATE( MEAS );

    if(
        ( 
          state EQ MEAS_IDLE                                                   
          AND
          IS_FLAGGED( filter->i_level[idx].m_gamma, IM_I_MASK_IDL,  IM_I_IDL  )
        ) 
        OR
        ( 
          state EQ MEAS_TRANSFER       
          AND
          IS_FLAGGED( filter->i_level[idx].m_gamma, IM_I_MASK_TRNS, IM_I_TRNS )  
        )
      )

#endif /* #ifdef _TARGET_ */

    {
      if( NORM_POW_MIN * filter->i_level[idx].index >= 
                                          norm_pow[psc_db->g_pwr_par.n_avg_i] )
      {
        if( filter->i_level[idx].gamma >= 
                                ( MIN_GAMMA_FOR_I_LEVEL_RPTING * MEAS_ACRCY ) ) /*lint !e685*/
        {
          T_C_FILTER *c_filter = &grr_data->meas.c_filter;
          USHORT      c_value;

          if( c_filter->index > 0 )
          {
            c_value = c_filter->value;
          }
          else
          {
            c_value = C_VALUE_DEFAULT;
          }

          /* calculation of interference level */
          if( c_value < filter->i_level[idx].gamma )
          {
            *ilev = I_LEVEL_MIN;
          }
          else
          {
            val = ( c_value - filter->i_level[idx].gamma ) / ( 2 * MEAS_ACRCY ) + 1;
      
            if( val > I_LEVEL_MAX ) *ilev = I_LEVEL_MAX;
            else                    *ilev = val;
          }

          *v_ilev = TRUE;
        }

#if !defined (NTRACE)

        else
        {
          /* prepare proper tracing information */
          switch( filter->i_level[idx].gamma / MEAS_ACRCY )
          {
            case 0: *ilev = I_LEVEL_GAMMA_0_SKIPPED; break;
            case 1: *ilev = I_LEVEL_GAMMA_1_SKIPPED; break;
            case 2: *ilev = I_LEVEL_GAMMA_2_SKIPPED; break;
            case 3: *ilev = I_LEVEL_GAMMA_3_SKIPPED; break;

            default: 
              TRACE_ERROR( "meas_im_fill_rel_iLevel: impossible case" );
              break;
          }
        }

#endif /* #if !defined (NTRACE) */

      }

#if !defined (NTRACE)

      else
      {
        /* prepare proper tracing information */
        *ilev = I_LEVEL_IDX_TO_SMALL;
      }

#endif /* #if !defined (NTRACE) */

    }

#ifdef _TARGET_

  #if !defined (NTRACE)

    else
    {
      /* prepare proper tracing information */
      *ilev = I_LEVEL_STATE_MISMATCH;
    }

  #endif /* #if !defined (NTRACE) */

#endif /* #ifdef _TARGET_ */

  }
  
#if !defined (NTRACE)

  else
  {
    /* prepare proper tracing information */
    *ilev = I_LEVEL_NOT_AVAIL;
  }

#endif /* #if !defined (NTRACE) */

} /* meas_im_fill_rel_iLevel() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_fill_abs_iLevel
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE meas_im_fill_abs_iLevel ( UBYTE            *v_ilev,
                                       UBYTE            *ilev,
                                       T_MEAS_IM_FILTER *filter,
                                       UBYTE             idx )
{
  UBYTE used_bits = PMR_FLAG_LEN;

  *v_ilev = FALSE;

  if( filter NEQ NULL )
  {

#ifdef _TARGET_

    UBYTE state = GET_STATE( MEAS );

    if(
        ( 
          state EQ MEAS_IDLE                                                   
          AND
          IS_FLAGGED( filter->i_level[idx].m_gamma, IM_I_MASK_IDL,  IM_I_IDL  )
        ) 
        OR
        ( 
          state EQ MEAS_TRANSFER       
          AND
          IS_FLAGGED( filter->i_level[idx].m_gamma, IM_I_MASK_TRNS, IM_I_TRNS )  
        )
      )

#endif /* #ifdef _TARGET_ */

    {
      if( NORM_POW_MIN * filter->i_level[idx].index >= 
                                          norm_pow[psc_db->g_pwr_par.n_avg_i] )
      {
        if( filter->i_level[idx].gamma >= 
                                ( MIN_GAMMA_FOR_I_LEVEL_RPTING * MEAS_ACRCY ) ) /*lint !e685*/
        {
          /* calculation of interference level */
          used_bits += EM_ABS_I_LEVEL_LEN;

          *ilev   = (UBYTE)M_ROUND_UP( filter->i_level[idx].gamma, MEAS_ACRCY );
          *v_ilev = TRUE;
        }

#if !defined (NTRACE)

        else
        {
          /* prepare proper tracing information */
          switch( filter->i_level[idx].gamma / MEAS_ACRCY )
          {
            case 0: *ilev = I_LEVEL_GAMMA_0_SKIPPED; break;
            case 1: *ilev = I_LEVEL_GAMMA_1_SKIPPED; break;
            case 2: *ilev = I_LEVEL_GAMMA_2_SKIPPED; break;
            case 3: *ilev = I_LEVEL_GAMMA_3_SKIPPED; break;

            default: 
              TRACE_ERROR( "meas_im_fill_rel_iLevel: impossible case" );
              break;
          }
        }

#endif /* #if !defined (NTRACE) */

      }

#if !defined (NTRACE)

      else
      {
        /* prepare proper tracing information */
        *ilev = I_LEVEL_IDX_TO_SMALL;
      }

#endif /* #if !defined (NTRACE) */

    }

#ifdef _TARGET_

  #if !defined (NTRACE)

    else
    {
      /* prepare proper tracing information */
      *ilev = I_LEVEL_STATE_MISMATCH;
    }

  #endif /* #if !defined (NTRACE) */

#endif /* #ifdef _TARGET_ */

  }

#if !defined (NTRACE)

  else
  {
    /* prepare proper tracing information */
    *ilev = I_LEVEL_NOT_AVAIL;
  }

#endif /* #if !defined (NTRACE) */

  return( used_bits );
} /* meas_im_fill_abs_iLevel() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_delete_em_rslt
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_delete_em_rslt ( void )
{
  T_MEAS_IM_FILTER  *filter;

  TRACE_FUNCTION( "meas_im_delete_em_rslt" );

  if( emeas->xmeas_set.param->em1.param.int_frequency NEQ NOT_SET )
  {
    T_MEAS_IM_CARRIER ma;

    ma.hopping     = FALSE;    
    ma.alloc.arfcn =
      meas_im_get_unmsk_int_freq( emeas->xmeas_set.param->em1.param.int_frequency );
  
    filter = meas_im_get_filter( &ma );

    if( filter NEQ NULL )
    {
      meas_im_restart_filter ( filter );
    }
  }
} /* meas_im_delete_em_rslt() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_unmsk_int_freq
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL USHORT meas_im_get_unmsk_int_freq ( UBYTE index )
{
  USHORT arfcn;

  TRACE_FUNCTION( "meas_im_get_unmsk_int_freq" );

  arfcn = emeas->xmeas_set.param->em1.list.freq[index];
  SET_FLAG( arfcn, EM_VLDTY_ARFCN_MASK, EM_VLD_ARFCN, USHORT );

  return( arfcn );
} /* meas_im_get_unmsk_int_freq() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_start_t_im_sync
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_start_t_im_sync ( T_TIME vld_prd )
{
  TRACE_FUNCTION( "meas_im_start_t_im_sync" );

  if( vld_prd NEQ 0 )
  {
    vsi_t_start( GRR_handle, T_IM_SYNC, vld_prd );

#ifdef _SIMULATION_
    TRACE_EVENT_P1( "T_IM_SYNC: %d ms", vld_prd );
#endif /* #ifdef _SIMULATION_ */

  }
  else
  {
    TRACE_ERROR( "Try to start T_IM_SYNC with 0 ms" );
  }
} /* meas_im_start_t_im_sync() */


/*
+------------------------------------------------------------------------------
| Function    : meas_im_get_paging_period 
+------------------------------------------------------------------------------
| Description : This functon calculates the paging period in microseconds.
|               
|               Please look at GSM 05.02, chapter 6.5.6, Determination of
|               PCCCH_GROUP and PAGING_GROUP for MS in GPRS attached mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL ULONG meas_im_get_paging_period ( void )
{
  ULONG  paging_period = NO_PAGING; /* paging period in MICROSECONDS             */
  USHORT paging_distance;           /* paging period as difference of two paging */
                                    /* groups                                    */
  USHORT paging_group[BL_FOR_PAGE_PERIOD_CALC]; 
                                    /* blocks which are used to page the MS, in  */
                                    /* maximum 2 blocks are needed to calculate  */
                                    /* the paging period                         */
  USHORT M;                         /* number of paging blocks "available" on    */
                                    /* one PCCCH                                 */ 
  USHORT m;                         /* number of paging groups for this MS       */
  USHORT min;                       /* minimum of M and SPLIT_PG_CYCLE           */
  USHORT imsi_mod   = grr_imsi_mod( );
                                    /* IMSI modulo 1000                          */
  USHORT N          = 1;            /* N                                         */
  USHORT res_blocks = psc_db->pccch.bs_pag_blks + psc_db->pccch.bs_pbcch_blks + 1;
                                    /* number of reserved blocks for access      */
                                    /* grant and PBCCH                           */

  TRACE_FUNCTION( "meas_im_get_paging_period" );

  /* see GSM 05.02, Clause 7 Table 7 of 7: Mapping of logical channels onto */
  /* physical channels ( see subclause 6.3, 6.4, 6.5 )                      */
  M = ( res_blocks > ( BLOCK_PER_MF - 1 ) ? 
                            0 : ( BLOCK_PER_MF - res_blocks ) * PAGING_CYCLE );

  /* in case M is equal to zero no paging blocks are reserved */
  if( M NEQ 0 )
  {
    if( grr_data->ms.split_pg_cycle EQ GMMRR_NO_DRX )
    {
      /* in non-DRX mode the MS shall listen to all M blocks per */
      /* multiframe where paging may appear on a PCCCH channel   */
      /* we assume that all paging groups have the same distance */
      /* to its preceding and subsequent paging groups ( equi-   */
      /* distance)                                               */
      paging_period = ( PAGING_CYCLE * USEC_PER_MF ) / M;
    }
    else
    {
      min = MINIMUM( M, grr_data->ms.split_pg_cycle );

      if( min EQ 1 )
      {
        /* in case only one paging group is available the MS is */
        /* paged every PAGING_CYCLE multiframes                 */
        paging_period = PAGING_CYCLE * USEC_PER_MF;
      }  
      else
      {
        /* calculate two paging groups, this is the minimum which */
        /* is needed to calculate a time difference ( paging      */
        /* period ), we assume that all paging groups have the    */
        /* same distance to its preceding and subsequent paging   */
        /* groups ( equi-distance )                               */
        for( m = 0; m < BL_FOR_PAGE_PERIOD_CALC; m++ )
        {
          /* the following statement calculates the paging groups */
          paging_group[m] =
            ( 
              ( ( imsi_mod / ( psc_db->paging_group.kc * N ) ) * N ) +
              ( imsi_mod % N )                                       +
              MAXIMUM( ( m * M ) / grr_data->ms.split_pg_cycle, m )
            ) % M;
        } 

        /* the paging is repeated cyclic every PAGING_CYCLE multiframes, */
        /* this should be taken into account when calculating the time   */
        /* difference between two paging groups                          */
        if( paging_group[1] > paging_group[0] )
        {
          paging_distance = paging_group[1] - paging_group[0];
        }
        else
        {
          paging_distance = M - paging_group[0] + paging_group[1];
        }

        paging_period = ( paging_distance * PAGING_CYCLE * USEC_PER_MF ) / M;
      }
    }
  }

  return( paging_period );
} /* meas_im_get_paging_period() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_init 
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_em_init ( void )
{
  TRACE_FUNCTION( "meas_em_init" );

  INIT_STATE( MEAS_EM, MEAS_EM_NULL );

  emeas = &grr_data->meas_em;

  emeas->xmeas_set.ident = 0;
  emeas->xmeas_set.param = NULL;
  emeas->pmr_snd_ref     = 0;
  
  grr_init_xmeas_struct( &psc_db->ext_pmo );
  meas_em_init_pmo_seq( );
} /* meas_em_init() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_init_pmo_seq
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_em_init_pmo_seq ( void )
{
  UBYTE i;

  TRACE_FUNCTION( "meas_em_init_pmo_seq" );

  grr_init_xmeas_struct( &emeas->pmo.extd );
  grr_init_ncmeas_extd_struct( &emeas->pmo.nc, FALSE );

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  grr_init_enh_param(&emeas->pmo.enh, TRUE);
#endif

  for( i = 0; i < MAX_NR_OF_INSTANCES_OF_PMO; i++ )
  {
    emeas->pmo.prm.instances[i] = FALSE;
    emeas->pmo.prm.idx[i].start = RRGRR_INVALID_IDX;
    emeas->pmo.prm.idx[i].stop  = RRGRR_INVALID_IDX;
  }

  emeas->pmo.prm.count = NOT_SET;
} /* meas_em_init_pmo_seq() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_build_meas_rpt
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : u_meas_report - Pointer to measurement report
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE meas_em_build_meas_rpt ( T_U_MEAS_REPORT *u_meas_report )
{
  UBYTE        used_bits;      /* bits currently used for the measurement report    */
  UBYTE        next_meas_bits; /* bits used for the next element of the             */
                               /* measurement result list                           */

  UBYTE        strg_bsic;
  UBYTE        strg_rxlev;
  UBYTE        rslt_rxlev;
  T_ext_mp_s1  *p_mrpt;

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  UBYTE        psi3_cm = grr_get_psi3_cm();
  BOOL         pbcch_present = grr_is_pbcch_present( );
#endif


  T_xmeas_rep    *xmeas_rep = &u_meas_report->xmeas_rep;

  TRACE_FUNCTION( "meas_em_build_meas_rpt" );

  /* process message type */
  used_bits               = PMR_MSG_TYPE_LEN;
  u_meas_report->msg_type = U_MEAS_REPORT_c;

  /* process TLLI */
  used_bits += PMR_TLLI_LEN;
  grr_set_buf_tlli( &u_meas_report->tlli_value, grr_get_tlli( ) );

  /* process PSI5 change mark */
  used_bits += PMR_FLAG_LEN;

  if( emeas->xmeas_set.param EQ &psc_db->ext_psi5 )
  {
    used_bits += PMR_PSI5_CHNGE_MRK_LEN;

    u_meas_report->v_psi5_cm = TRUE;
    u_meas_report->psi5_cm   = psc_db->psi5_params.psi5_change_mark;
  }
  else if ( emeas->xmeas_set.param EQ &psc_db->ext_pmo )
  {
    u_meas_report->v_psi5_cm = FALSE;
  }
  else
  {
    TRACE_ERROR( "no valid data set in meas_em_build_meas_rpt" );
    return( 0 );
  }
  
  /* process flags */
  used_bits                    += PMR_FLAG_LEN;
  u_meas_report->flag           = 1;
  u_meas_report->v_nc_meas_rep  = FALSE;
  u_meas_report->v_xmeas_rep    = TRUE;

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  /*if(psc_db->network_rel NEQ BSS_NW_REL_97)*/
  {
    used_bits                += PMR_FLAG_LEN;
    u_meas_report->v_release_99_str_pmr = TRUE;
    
    used_bits                += PMR_FLAG_LEN;
    u_meas_report->release_99_str_pmr.v_meas_rep_3g_str = FALSE;
    
    used_bits                += PMR_FLAG_LEN;      
    u_meas_report->release_99_str_pmr.v_ba_psi3_str = TRUE;
    
    used_bits                += PMO_IND_USED_LEN;
    u_meas_report->release_99_str_pmr.ba_psi3_str.pmo_ind_used = psc_db->nc_ms.pmo_ind;
    
    /* 1 bit for u_meas_report->ba_psi3_str.flag */
    used_bits                += PMR_FLAG_LEN;      
    
    /* process BA used, PSI3 change mark and PMO used */
    if( pbcch_present EQ FALSE )
    {
      u_meas_report->release_99_str_pmr.ba_psi3_str.flag = FALSE;
      
      u_meas_report->release_99_str_pmr.ba_psi3_str.v_ba_ind_used = TRUE;
      u_meas_report->release_99_str_pmr.ba_psi3_str.v_ba_ind_used_3g = TRUE;
      
      used_bits                += PMR_BA_IND_USED_LEN;
      u_meas_report->release_99_str_pmr.ba_psi3_str.ba_ind_used = psc_db->ba_ind;
      
      /* Add 1 bit for ba_ind_used_3g */              
      u_meas_report->release_99_str_pmr.ba_psi3_str.ba_ind_used_3g = 0;
      used_bits                += PMR_BA_IND_USED_LEN;
    }
    else
    {
      u_meas_report->release_99_str_pmr.ba_psi3_str.flag = TRUE;
      
      u_meas_report->release_99_str_pmr.ba_psi3_str.v_psi3_cm = TRUE;
      
      used_bits                += PMR_PSI3_CHNGE_MRK_LEN;
      u_meas_report->release_99_str_pmr.ba_psi3_str.psi3_cm = psi3_cm;
    }
  }
#elif defined (REL99)
  used_bits                += PMR_FLAG_LEN;
  u_meas_report->v_release_99_str_pmr = FALSE;
#endif

  /* process report type */
  used_bits            += EM_EXT_RPT_TYPE_LEN;
  xmeas_rep->xrep_type  = emeas->xmeas_set.param->em1.param.reporting_type;
  
  /* process interference measurement results */
  used_bits += PMR_FLAG_LEN;

  if( emeas->xmeas_set.param->em1.param.reporting_type EQ  REP_TYPE_3 AND
      emeas->xmeas_set.param->em1.param.int_frequency  NEQ NOT_SET        )
  {
    T_MEAS_IM_CARRIER ma;

    xmeas_rep->v_ilev_abs = TRUE;
     
    ma.hopping     = FALSE;    
    ma.alloc.arfcn =
      meas_im_get_unmsk_int_freq( emeas->xmeas_set.param->em1.param.int_frequency );

    used_bits += meas_im_get_abs_i_level( &ma, &xmeas_rep->ilev_abs );
  }
  else
  {
    xmeas_rep->v_ilev_abs = FALSE;
  }

  /* process EXT measurement results */
  used_bits              += EM_NUM_OF_MEAS_LEN;
  xmeas_rep->num_meas     = 0;
  xmeas_rep->c_ext_mp_s1  = 0;

  do
  {
    /* calculate length of next measurement result */
    next_meas_bits = EM_FREQ_N_LEN + EM_RXLEV_N_LEN + PMR_FLAG_LEN;
    strg_rxlev     = 0;
    rslt_rxlev     = 0;
    strg_bsic      = EM_INVLD_BSIC;


    switch( emeas->xmeas_set.param->em1.param.reporting_type )
    {
      case( REP_TYPE_1 ):
      case( REP_TYPE_2 ):
        if( emeas->pmr_snd_ref EQ emeas->strg.number )
        {
          next_meas_bits = 0;
        }
        else
        {
          strg_bsic  = emeas->rslt.elem[emeas->strg.refidx[emeas->pmr_snd_ref]].bsic;
          strg_rxlev = emeas->rslt.elem[emeas->strg.refidx[emeas->pmr_snd_ref]].rxlev;

          if( strg_bsic                                        NEQ RRGRR_INVALID_BSIC OR 
              emeas->xmeas_set.param->em1.param.reporting_type EQ  REP_TYPE_2       )
          {
            next_meas_bits += EM_BSIC_N_LEN;
          }
        }
        break;

      case( REP_TYPE_3 ):        
        if( emeas->pmr_snd_ref EQ emeas->rslt.number )
        {
          next_meas_bits = 0;
        }
        else
        {
          rslt_rxlev = emeas->rslt.elem[emeas->pmr_snd_ref].rxlev;
        }
        break;
      default:
        next_meas_bits = 0;        
        TRACE_ERROR( "no valid reporting type in meas_em_build_meas_rpt" );
        break;
    }

    if( next_meas_bits                             NEQ 0              AND
        ( BIT_UL_CTRL_BLOCK_CONTENTS - used_bits ) >=  next_meas_bits     )
    {
      /* copy next measurement result to measurement report */
      xmeas_rep->num_meas++;
      xmeas_rep->c_ext_mp_s1++;
      used_bits += next_meas_bits;
      p_mrpt     = &xmeas_rep->ext_mp_s1[xmeas_rep->c_ext_mp_s1 - 1];

      switch( emeas->xmeas_set.param->em1.param.reporting_type )
      {
        case( REP_TYPE_1 ):
        case( REP_TYPE_2 ):
          p_mrpt->freq_n   = emeas->rslt.elem[emeas->strg.refidx[emeas->pmr_snd_ref]].refidx;
          p_mrpt->rxlev_n  = strg_rxlev;

          if( strg_bsic                                        NEQ RRGRR_INVALID_BSIC OR 
              emeas->xmeas_set.param->em1.param.reporting_type EQ  REP_TYPE_2       )
          {
            p_mrpt->bsic   = strg_bsic;
            p_mrpt->v_bsic = TRUE;
          }
          else
          {
            p_mrpt->v_bsic = FALSE;
          }
          break;

        case( REP_TYPE_3 ):
          p_mrpt->freq_n   = emeas->rslt.elem[emeas->pmr_snd_ref].refidx;
          p_mrpt->rxlev_n  = rslt_rxlev;
          p_mrpt->v_bsic   = FALSE;
          break;
        default:
          TRACE_ERROR( "no valid reporting type in meas_em_build_meas_rpt" );
          break;
      }

      emeas->pmr_snd_ref++;
    }
    else
    {
      next_meas_bits = 0;
    }
  }
  while( next_meas_bits NEQ 0 );

  return( xmeas_rep->num_meas );
} /* meas_em_build_meas_rpt() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_extrct_strgst
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE meas_em_extrct_strgst ( void )
{
  UBYTE i, j;      /* used for couting */
  UBYTE min_rxlev;
  UBYTE min_index;

  TRACE_FUNCTION( "meas_em_extrct_strgst" );

  emeas->strg.number = 0;

  for( i = 0; i < emeas->rslt.number; i++ )
  {
    if( emeas->rslt.elem[i].rxlev NEQ RRGRR_INVALID_RXLEV  )
    {
      if( emeas->strg.number < EM_MAX_STRONG_CARRIER )
      {
        emeas->strg.refidx[emeas->strg.number] = i;
        emeas->strg.number++;
      }
      else
      {
        min_rxlev = 0xFF;
        min_index = 0xFF;
      
        for( j = 0; j < emeas->strg.number; j++ )
        {
          if( emeas->rslt.elem[emeas->strg.refidx[j]].rxlev < min_rxlev  )
          {
            min_rxlev = emeas->rslt.elem[emeas->strg.refidx[j]].rxlev;
            min_index = j;
          }
        }

        if( emeas->rslt.elem[i].rxlev < min_rxlev  )
        {
          if( min_index < EM_MAX_STRONG_CARRIER )
          {
            emeas->strg.refidx[min_index] = i;
          }
          else
          {
            TRACE_ASSERT( min_index < EM_MAX_STRONG_CARRIER );
          }
        }
      }
    }
  }

  return( emeas->strg.number );
} /* meas_em_extrct_strgst() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_extrct_strgst_with_bsic
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE meas_em_extrct_strgst_with_bsic ( void )
{
  UBYTE                i, j;      /* used for couting */

  TRACE_FUNCTION( "meas_em_extrct_strgst_with_bsic" );

  meas_em_extrct_strgst( );

  for( i = 0, j = 0; i < emeas->strg.number; i++ )
  {

    if(
        emeas->rslt.elem[emeas->strg.refidx[i]].bsic      NEQ RRGRR_INVALID_BSIC

        AND

        ((0x01 << ((emeas->rslt.elem[emeas->strg.refidx[i]].bsic & BSIC_NCC_MASK) >> 3)) &
        emeas->xmeas_set.param->em1.param.ncc_permitted ) NEQ 0
      )
    {
      emeas->strg.refidx[j] = emeas->strg.refidx[i];
      j++;
    }
  }

  emeas->strg.number = j;

  return( emeas->strg.number );
} /* meas_em_extrct_strgst_with_bsic() */


/*
+------------------------------------------------------------------------------
| Function    : meas_em_store_rslt
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL meas_em_store_rslt ( T_RRGRR_EXT_MEAS_CNF *rrgrr_em_cnf )
{
  UBYTE i;              /* used for counting */
  BOOL  result = FALSE;

  TRACE_FUNCTION( "meas_em_store_rslt" );

  /* check call reference */
  if( rrgrr_em_cnf->call_ref EQ emeas->xmeas_set.ident - 1 )
  {
    if( rrgrr_em_cnf->xmeas_cause EQ EXT_MEAS_OK )
    {
      T_xmeas_res *em_res;

      result             = TRUE;
      emeas->rslt.number = 0;

      for( i = 0; i < rrgrr_em_cnf->c_xmeas_res; i++ )
      {
        em_res = &rrgrr_em_cnf->xmeas_res[i];
      
        if( em_res->arfcn_idx.idx                                        < 
            emeas->xmeas_set.param->em1.list.number                         AND
            em_res->arfcn_idx.arfcn                                      EQ 
            emeas->xmeas_set.param->em1.list.freq[em_res->arfcn_idx.idx]        )
        {
          emeas->rslt.elem[emeas->rslt.number].refidx = em_res->arfcn_idx.idx;
          emeas->rslt.elem[emeas->rslt.number].rxlev  = em_res->rxlev;
          emeas->rslt.elem[emeas->rslt.number].bsic   = em_res->bsic;

          emeas->rslt.number++;
        }
        else
        {
          TRACE_ERROR( "meas_em_store_rslt: mismatch of ARFCNs" );
        }
      }
    }
    else
    {
      TRACE_EVENT_P1( "meas_em_store_rslt: unexpected cause %d",
                      rrgrr_em_cnf->xmeas_cause  );
    }
  }
  else
  {
    TRACE_EVENT_P2( "meas_em_store_rslt: mismatch of call references %d %d",
                    rrgrr_em_cnf->call_ref, emeas->xmeas_set.ident - 1 );
  }

  return( result );
} /* meas_em_store_rslt() */



/*
+------------------------------------------------------------------------------
| Function    : meas_em_req
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_em_req ( void )
{
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "meas_em_req" );

  {
    PALLOC( em_req, RRGRR_EXT_MEAS_REQ );

    em_req->c_arfcn_idx = 0;
    
    for( i = 0; i < emeas->xmeas_set.param->em1.list.number; i++ )
    {
      if( IS_NOT_FLAGGED( emeas->xmeas_set.param->em1.list.freq[i],
                          EM_VLDTY_ARFCN_MASK,
                          EM_NON_VLD_ARFCN ) )
      {
        em_req->arfcn_idx[em_req->c_arfcn_idx].idx   = i;
        em_req->arfcn_idx[em_req->c_arfcn_idx].arfcn =
                                      emeas->xmeas_set.param->em1.list.freq[i];
        em_req->c_arfcn_idx++;
      }
    }
    
#ifdef _SIMULATION_
    for( i = em_req->c_arfcn_idx; i < RRGRR_MAX_ARFCN_EXT_MEAS; i++ )
    {
      em_req->arfcn_idx[i].arfcn = RRGRR_INVALID_ARFCN;
      em_req->arfcn_idx[i].idx   = RRGRR_INVALID_IDX;
    }
#endif /* #ifdef _SIMULATION_ */

    em_req->call_ref      = emeas->xmeas_set.ident;
    em_req->report_type   = emeas->xmeas_set.param->em1.param.reporting_type;
    em_req->ncc_permitted = emeas->xmeas_set.param->em1.param.ncc_permitted;

    PSEND( hCommRR, em_req );
  }

  emeas->xmeas_set.ident++;

} /* meas_em_req() */


/*
+------------------------------------------------------------------------------
| Function    : meas_em_is_meas_reporting
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL meas_em_is_meas_reporting ( void )
{
  TRACE_FUNCTION( "meas_em_is_meas_reporting" );
  
  return( emeas->xmeas_set.param                NEQ NULL            AND
          emeas->xmeas_set.param->em_order_type EQ  EM_EM1          AND
          GET_STATE( MEAS_EM )                  NEQ MEAS_EM_SUSPEND     );
} /* meas_em_is_meas_reporting() */


/*==== PUBLIC FUNCTIONS =====================================================*/
/*
+------------------------------------------------------------------------------
| Function    : meas_im_new_value
+------------------------------------------------------------------------------
| Description : This function is used to process new interference measurement 
|               samples send by Layer 1 measured in packet transfer or packet
|               transfer mode.
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_new_value ( T_MPHP_INT_MEAS_IND *mphp_int_meas_ind,
                                UBYTE                state )
{ 
  T_MEAS_IM_FILTER *filter;    /* filter to be updated      */
  UBYTE             rx_lev[8];
  UBYTE             dummy;     /* dummy parameter, not used */

  TRACE_FUNCTION( "meas_im_new_value" );

  meas_handle_int_meas_values ( mphp_int_meas_ind, rx_lev );

  if( imeas->carrier_id NEQ mphp_int_meas_ind->carrier_id )
  {
    BOOL valid;

    if( state EQ MEAS_IDLE )
    {
      valid = meas_im_get_idle_freq( mphp_int_meas_ind->carrier_id,
                                     &imeas->carrier,
                                     &dummy );
    }
    else
    {
      valid = meas_im_get_trns_freq( &imeas->carrier );
    }

    if( valid EQ TRUE )
    {
      imeas->carrier_id = ( USHORT )mphp_int_meas_ind->carrier_id;
    }
    else
    {
      TRACE_ERROR( "FATAL ERROR 1 in meas_im_new_value" );
      return;
    }
  }

  filter = meas_im_get_filter( &imeas->carrier );

  if( filter EQ NULL )
  {
    filter = meas_im_get_unused_filter( );

    if( filter EQ NULL )
    {
      filter = meas_im_get_oldest_filter( );

      if( filter EQ NULL )
      {
        TRACE_ERROR( "FATAL ERROR 2 in meas_im_new_value" );
        return;
      }
      else
      {
        meas_im_restart_filter( filter );
      }
    }

    filter->carrier = imeas->carrier;
  }

  meas_im_update_filter( filter, rx_lev, state );

  if( state EQ MEAS_IDLE )
  {
    meas_im_start_idle( );
  }

  meas_im_cgrlc_int_level_req( FALSE );

} /* meas_im_new_value() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_cgrlc_int_level_req 
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_cgrlc_int_level_req ( BOOL init )
{ 
  PALLOC( int_level_req, CGRLC_INT_LEVEL_REQ );

  TRACE_FUNCTION( "meas_im_cgrlc_int_level_req" );

  /*
   *      |            | primitive content | primitive shall
   * init | v_ilev_abs |      changed      |     be sent
   * -----+------------+-------------------+----------------
   *   0  |      0     |         X         |        1       
   *   0  |      0     |         X         |        1       
   *   0  |      1     |         0         |        0        
   *   0  |      1     |         1         |        1        
   *   1  |      0     |         X         |        1        
   *   1  |      0     |         X         |        1        
   *   1  |      1     |         0         |        0        
   *   1  |      1     |         1         |        1         
   */

  memset( int_level_req->ilev, CGRLC_RXLEV_NONE, CGRLC_MAX_TIMESLOTS );

  if( init EQ FALSE AND grr_data->tc.v_freq_set EQ TRUE )
  {
    T_p_frequency_par freq_par;
    T_MEAS_IM_CARRIER ma;
    T_ilev_abs        ilev;

    grr_set_freq_par( &freq_par );
    meas_im_set_carrier( &ma, &freq_par );
    meas_im_get_abs_i_level( &ma, &ilev );

    if( ilev.v_ilevabs0 EQ TRUE ) int_level_req->ilev[0] = ilev.ilevabs0; 
    if( ilev.v_ilevabs1 EQ TRUE ) int_level_req->ilev[1] = ilev.ilevabs1; 
    if( ilev.v_ilevabs2 EQ TRUE ) int_level_req->ilev[2] = ilev.ilevabs2; 
    if( ilev.v_ilevabs3 EQ TRUE ) int_level_req->ilev[3] = ilev.ilevabs3; 
    if( ilev.v_ilevabs4 EQ TRUE ) int_level_req->ilev[4] = ilev.ilevabs4; 
    if( ilev.v_ilevabs5 EQ TRUE ) int_level_req->ilev[5] = ilev.ilevabs5; 
    if( ilev.v_ilevabs6 EQ TRUE ) int_level_req->ilev[6] = ilev.ilevabs6; 
    if( ilev.v_ilevabs7 EQ TRUE ) int_level_req->ilev[7] = ilev.ilevabs7; 
  }

  PSEND( hCommGRLC, int_level_req );

} /* meas_im_cgrlc_int_level_req() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_stop_trns
+------------------------------------------------------------------------------
| Description : This function stops the interference measurements in packet
|               transfer mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_stop_trns ( void )
{
  TRACE_FUNCTION( "meas_im_stop_trns" );

  imeas->carrier_id = IDX_USHORT_INVALID;
} /* meas_im_stop_trns() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_stop_idle
+------------------------------------------------------------------------------
| Description : This function stops the interference measurements in packet
|               idle mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_stop_idle ( void )
{
  TRACE_FUNCTION( "meas_im_stop_idle" );

  {
    PALLOC( mphp_int_meas_stop_req, MPHP_INT_MEAS_STOP_REQ );
    PSEND( hCommL1, mphp_int_meas_stop_req );
  }

  imeas->carrier_id = IDX_USHORT_INVALID;
} /* meas_im_stop_idle() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_prepare_trns
+------------------------------------------------------------------------------
| Description : This function prepares the interference measurements in packet
|               transfer mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_prepare_trns ( void )
{
  TRACE_FUNCTION( "meas_im_prepare_trns" );
} /* meas_im_prepare_trns() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_prepare_idle
+------------------------------------------------------------------------------
| Description : This function prepares the interference measurements in packet
|               idle mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_prepare_idle ( void )
{
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "meas_im_prepare_idle" );

  /* process the carrier indicated in the parameter EXT_FREQUENCY_LIST */
  #if ( ! ( CHN_ID_EM_BASE < MAX_IM_IDLE_CHANNELS ) )
  #error CHN_ID_EM_BASE < MAX_IM_IDLE_CHANNELS required
  #endif

  if( emeas->xmeas_set.param                           NEQ NULL       AND
      emeas->xmeas_set.param->em1.param.reporting_type EQ  REP_TYPE_3 AND
      emeas->xmeas_set.param->em1.param.int_frequency  NEQ NOT_SET        )
  {
    imeas->idle_chan.ident[CHN_ID_EM_BASE] = 
                               emeas->xmeas_set.param->em1.param.int_frequency;
  }
  else
  {
    imeas->idle_chan.ident[CHN_ID_EM_BASE] = CHN_ID_INVALID;
  }

  /* process the monitored PCCCH */
  #if ( ! ( CHN_ID_PCCCH_BASE < MAX_IM_IDLE_CHANNELS ) )
  #error CHN_ID_PCCCH_BASE < MAX_IM_IDLE_CHANNELS required
  #endif

  if( imeas->v_cs_meas_active EQ  TRUE AND
      psc_db->paging_group.kc NEQ 0        )
  {
    UBYTE pccch_group;

    pccch_group = ( UBYTE )( grr_imsi_mod( ) % psc_db->paging_group.kc );
  
    if( pccch_group > psc_db->paging_group.kc - 1 )
    {
      TRACE_ERROR( "pccch_group > psc_db->paging_group.kc - 1 in meas_im_prepare_idle" );
      imeas->idle_chan.ident[CHN_ID_PCCCH_BASE] = CHN_ID_INVALID;
    }
    else
    {
      imeas->idle_chan.ident[CHN_ID_PCCCH_BASE] = pccch_group;
    }
  }
  else
  {
    imeas->idle_chan.ident[CHN_ID_PCCCH_BASE] = CHN_ID_INVALID;
  }

  /* process the carriers indicated by the parameter INT_MEAS_CHANNEL_LIST */
  i = CHN_ID_IM_BASE;

  while( i                      < MAX_IM_IDLE_CHANNELS                      AND
         ( i - CHN_ID_IM_BASE ) < psc_db->number_of_valid_int_meas_channels     )
  {
    imeas->idle_chan.ident[i] = i - CHN_ID_IM_BASE;
    i++;
  }

  while( i < MAX_IM_IDLE_CHANNELS )
  {
    imeas->idle_chan.ident[i] = CHN_ID_INVALID;
    i++;
  }

  /* let's start measurements with the first entry in the idle channel list */
  imeas->idle_chan.index = 0;
} /* meas_im_prepare_idle() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_timer_elapsed
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_timer_elapsed ( void )
{
  UBYTE i, j; /* used for counting */
  LONG  new_remain_time = TIME_INVALID;
  LONG* old_remain_time;

  TRACE_FUNCTION( "meas_im_timer_elapsed" );

  for( i = 0; i < MAX_IM_CHANNELS; i++ )
  {
    for( j = 0; j < CGRLC_MAX_TIMESLOTS; j++ )
    {
      old_remain_time = &imeas->filter[i].i_level[j].remain_time;

      if( *old_remain_time < 0 )
      {
        TRACE_ERROR( "unexpected time value in meas_im_timer_elapsed" );
      }
      if( *old_remain_time EQ 0 )
      {
        *old_remain_time = TIME_INVALID;
      }
      else if ( *old_remain_time NEQ TIME_INVALID    AND
                *old_remain_time <   new_remain_time     )
      {
        new_remain_time = *old_remain_time;
      }
    }
  }
    
  if( new_remain_time NEQ TIME_INVALID )
  {
    meas_im_timer_reorg( 0, new_remain_time );
  }
} /* meas_im_timer_elapsed() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_state_changed
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_state_changed ( UBYTE state )
{
  UBYTE i, j; /* used for counting */

  TRACE_FUNCTION( "meas_im_state_changed" );

  /*
   * the three if-statements below are just used to skip 
   * the following for-loops in all impossible cases
   */ 
  if( grr_data->meas_im.mode EQ IM_MODE_NONE )
  {
    return;
  }
  
  if( ( state                  EQ MEAS_IDLE    OR 
        state                  EQ MEAS_ACCESS      )
      AND 
      ( grr_data->meas_im.mode EQ IM_MODE_TRANSFER ) )
  {
    return;
  }

  if( state                  EQ MEAS_TRANSFER AND 
      grr_data->meas_im.mode EQ IM_MODE_IDLE      )
  {
    return;
  }

  for( i = 0; i < MAX_IM_CHANNELS; i++ )
  {
    for( j = 0; j < CGRLC_MAX_TIMESLOTS; j++ )
    {
      if( ( ( state EQ MEAS_IDLE OR state EQ MEAS_ACCESS )   AND
            IS_FLAGGED( imeas->filter[i].i_level[j].m_gamma, 
                        IM_I_MASK_IDL,  IM_I_IDL  )              )
            OR
          ( ( state EQ MEAS_TRANSFER )                       AND
            IS_FLAGGED( imeas->filter[i].i_level[j].m_gamma,
                        IM_I_MASK_TRNS, IM_I_TRNS )              ) )
      {
        if( imeas->filter[i].i_level[j].remain_time EQ TIME_INVALID )
        {
          meas_im_restart_gamma( &imeas->filter[i], j );
        }
      }
    }
  }
} /* meas_im_state_changed() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_start_idle
+------------------------------------------------------------------------------
| Description : This function starts the interference measurements in packet
|               idle mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL meas_im_start_idle ( void )
{
  T_MEAS_IM_IDLE_CHN* chn         = &imeas->idle_chan;
  UBYTE               ts_mask;
  UBYTE               max_checks  = MAX_IM_IDLE_CHANNELS;
  BOOL                is_started  = FALSE;

  TRACE_FUNCTION( "meas_im_start_idle" );

  while( chn->ident[chn->index] EQ CHN_ID_INVALID AND
         max_checks             >  0                  )
  {
    chn->index = ((chn->index < MAX_IM_IDLE_CHANNELS - 1) ? chn->index + 1 : 0);
    max_checks--;
  }

  if( max_checks > 0 )
  {
    PALLOC( mphp_int_meas_req, MPHP_INT_MEAS_REQ );

    meas_im_get_idle_freq( chn->index, &imeas->carrier, &ts_mask );
    meas_im_set_freq_par( &mphp_int_meas_req->p_frequency_par, &imeas->carrier );

    imeas->carrier_id             =          chn->index;
    mphp_int_meas_req->carrier_id = ( UBYTE )chn->index;

    mphp_int_meas_req->ts_mask    = ts_mask;
    mphp_int_meas_req->m_class    = grr_get_gprs_ms_class( );
          
    PSEND( hCommL1, mphp_int_meas_req );

    is_started = TRUE;

    if( chn->index < MAX_IM_IDLE_CHANNELS )
    {
      chn->index++;
    }
    else
    {
      chn->index = 0;
    }
  }

  return( is_started );
} /* meas_im_start_idle() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_set_freq_par
+------------------------------------------------------------------------------
| Description : 
|
|            Frequency Band    config.       ETSI GSM spec.  coding used in L1
|            GSM 900           STD_900       1-124           1-124
|            E-GSM             STD_EGSM      1-124,          1-124,
|                                            975-1023, 0     125-174
|            PCS 1900          STD_1900      512-810         512-810
|            DCS 1800          STD_1800      512-885         512-885
|            GSM 900/DCS 1800  STD_DUAL      1-124,          1-124,
|                                            512-885         125-498
|            E-GSM/DCS 1800    STD_DUAL_EGSM 1-124,          1-124,
|                                            975-1023,0      125-174,
|                                            512-885         175-548
|            GSM 850           STD_850       128-251         128-251
|            GSM 850/PCS 1900  STD_DUAL_US   128-251,        1-124,
|                                            512-810         125-424
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_im_set_freq_par ( T_p_frequency_par *freq_par, 
                                  T_MEAS_IM_CARRIER *carrier )
{
  TRACE_FUNCTION( "meas_im_set_freq_par" );

  if( carrier->hopping )
  {
    UBYTE  i = 0;
    UBYTE  bit_shift;
    USHORT array_idx;
    USHORT arfcn;

    freq_par->p_chan_sel.hopping       = MPHP_INT_MEAS_HOPPING;
    freq_par->p_chan_sel.p_rf_ch.arfcn = 
      ( ( USHORT )carrier->alloc.hop_param.hsn << 8 ) |
        ( USHORT )carrier->alloc.hop_param.maio;

    for ( array_idx = 0; 
          array_idx < MAX_IM_HOP_ARFCN_BIT_FIELD_SIZE;
          array_idx++ )
    {
      for( bit_shift = 0; bit_shift < 8 AND i < MPHP_NUMC_MA; bit_shift++ )
      {
        if( ( carrier->alloc.hop_param.arfcn_bit_field[array_idx] &
                                                ( 0x01 << bit_shift ) ) NEQ 0 )
        {
          arfcn = ( array_idx * 8 ) + bit_shift;

          switch( std )
          {
            case STD_1900: arfcn += LOW_CHANNEL_1900; break;
            case STD_1800: arfcn += LOW_CHANNEL_1800; break;
            default      :                            break;
          }

          freq_par->p_freq_list.p_rf_chan_no.p_radio_freq[i] = arfcn;
          i++;
        }
      }
    }

    freq_par->p_freq_list.p_rf_chan_cnt = i;
  }
  else
  {
    freq_par->p_chan_sel.hopping       = MPHP_INT_MEAS_STATIC;
    freq_par->p_chan_sel.p_rf_ch.arfcn =
      grr_g23_arfcn_to_l1( carrier->alloc.arfcn );
  }
} /* meas_im_set_freq_par() */

/*
+------------------------------------------------------------------------------
| Function    : meas_im_start_trns
+------------------------------------------------------------------------------
| Description : This function starts the interference measurements in packet
|               transfer mode.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_im_start_trns ( void )
{
  TRACE_FUNCTION( "meas_im_start_trns" );
} /* meas_im_start_trns() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_prcs_meas_order
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : d_meas_order - Pointer to packet measurement order message
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE meas_em_prcs_meas_order ( T_D_MEAS_ORDER *d_meas_order,
                                       T_NC_ORDER     *ctrl_order )
{
  BOOL  is_pmo_ok;
  UBYTE i;
  UBYTE ret_value = PMO_NONE_VLD;

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  UBYTE psi3_cm = grr_get_psi3_cm();
#endif

  TRACE_FUNCTION( "meas_em_prcs_meas_order" );

  TRACE_EVENT_P2( "D_MEAS_ORDER received idx = %d, cnt = %d",
                  d_meas_order->pmo_index, d_meas_order->pmo_cnt );


  /* process the PMO_COUNT and PMO_INDEX parameter */
  if( ( emeas->pmo.prm.count NEQ NOT_SET               AND
        emeas->pmo.prm.count NEQ d_meas_order->pmo_cnt     ) OR
        d_meas_order->pmo_cnt < d_meas_order->pmo_index         )
  {
    TRACE_ERROR( "D_MEAS_ORDER: parameter inconsistent" );
    
    meas_em_init_pmo_seq( );

    return( ret_value );
  }

#if defined (REL99) AND defined (TI_PS_FF_EMR)
   /* Set to ENH params not present by default  */
  if( emeas->pmo.prm.count EQ NOT_SET )
  {
    emeas->pmo.v_enh_meas_param_pmo = FALSE;
    nc_freq_list_pres = FALSE;
    nc_freq_list_valid = FALSE;
    use_ba_gprs = TRUE;
  }
#endif

  emeas->pmo.prm.instances[d_meas_order->pmo_index] = TRUE;
  emeas->pmo.prm.count                              = d_meas_order->pmo_cnt;

  /* process the EXT measurement parameter */
  if( d_meas_order->v_xmeas_par EQ TRUE )
  {
    grr_prcs_xmeas_struct 
      ( &emeas->pmo.extd, &d_meas_order->xmeas_par,
        TRUE, d_meas_order->pmo_index, 
        &emeas->pmo.prm.idx[d_meas_order->pmo_index].start,
        &emeas->pmo.prm.idx[d_meas_order->pmo_index].stop );
  }

  if( d_meas_order->v_nc_meas_par_list EQ TRUE )
  {
    /*
     * process the NC measurement parameter
     *
     * maybe more than one instance of PMO, store data in temporary location
     */
    emeas->v_pmo_nc_ncmeas_param = TRUE;

#if defined (REL99) AND defined (TI_PS_FF_EMR)
    /* Do not get back to BA-GPRS list since NC_FREQ_LIST is present */
    if(d_meas_order->nc_meas_par_list.v_nc_freq_list)
    {
      nc_freq_list_pres = TRUE;
    }
#endif

    grr_prcs_nc_param_struct ( &emeas->pmo.nc.ncmeas.param, 
                               &d_meas_order->nc_meas_par_list.nc_meas_par,
                               d_meas_order->pmo_index );

   
#if defined (REL99) AND defined (TI_PS_FF_EMR)
  /* Check for presence of ENH parameters in PMO. If present, then PSI3_CM or 
     BA_IND will be checked depending on the presence or absence of PBCCH for
     consistency with the BA list existing currently. If consistent, then only
     the PMO NC frequency list is considered. */
    if( d_meas_order->release_98_str_d_meas_order.v_release_99_str_d_meas_order AND 
      (d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.v_enh_meas_param_pmo EQ TRUE) )
    {
      if(grr_is_pbcch_present() AND
        d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.enh_meas_param_pmo.ba_psi3_str.v_psi3_cm)
      {
        if(d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.enh_meas_param_pmo.ba_psi3_str.psi3_cm EQ psi3_cm)
        {
          nc_freq_list_valid = TRUE;
        }
      }
      else if(!grr_is_pbcch_present() AND
        d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.enh_meas_param_pmo.ba_psi3_str.v_ba_ind_used)
      {
        if(d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.enh_meas_param_pmo.ba_psi3_str.ba_ind_used EQ 
          psc_db->ba_ind)
        {
          nc_freq_list_valid = TRUE;
        }
      }
    }
    else
    /* PMO is not checked for BA_IND or PSI3_CM consistency since ENH params
       are absent */
    {
      nc_freq_list_valid = TRUE;
    }

    if(nc_freq_list_valid EQ TRUE)
    {
#endif

      /*
       * process NC_FREQUENCY_LIST
       *
       * maybe more than one instance of PMO, store data in temporary location
       */

    emeas->v_pmo_nc_ncmeas_list_rfreq =
         grr_prcs_nc_freq_list ( &emeas->pmo.nc.ncmeas.list,
                                 &emeas->pmo.nc.rfreq,
                                 d_meas_order->nc_meas_par_list.v_nc_freq_list,
                                 &d_meas_order->nc_meas_par_list.nc_freq_list,
                                 INFO_TYPE_PMO,
                                 d_meas_order->pmo_index );

#if defined (REL99) AND defined (TI_PS_FF_EMR)
    }
  }

  if( d_meas_order->release_98_str_d_meas_order.v_release_99_str_d_meas_order AND 
    (d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.v_enh_meas_param_pmo EQ TRUE) )
  {
    emeas->pmo.v_enh_meas_param_pmo = TRUE;
    /*
    * process the ENH measurement parameter
    *
    * maybe more than one instance of PMO, store data in temporary location
    */
    grr_prcs_enh_param_pmo(&emeas->pmo.enh, &d_meas_order->release_98_str_d_meas_order.release_99_str_d_meas_order.enh_meas_param_pmo, 
      d_meas_order->pmo_index, &emeas->pmo.nc.pmo_ind);
#endif

  }

  for( i  = 0, is_pmo_ok = TRUE;
       i <= emeas->pmo.prm.count AND is_pmo_ok EQ TRUE; 
       i++ )
  {
    if( emeas->pmo.prm.instances[i] EQ FALSE )
    {
      is_pmo_ok = FALSE;
    }
  }

  if( is_pmo_ok )
  {
    /* process EXT measurement service */
    grr_sort_ext_lst_freq ( &emeas->pmo.extd.em1.list, 
                            MAX_NR_OF_INSTANCES_OF_PMO,
                            &emeas->pmo.prm.idx[0] );

    memcpy( &psc_db->ext_pmo, &emeas->pmo.extd, sizeof( psc_db->ext_pmo ) );

    if(    emeas->pmo.extd.em_order_type            NEQ EM_EMPTY     AND 
        !( emeas->pmo.extd.em_order_type            EQ  EM_EM1       AND 
           emeas->pmo.extd.em1.param.reporting_type EQ  REP_TYPE_RES     ) )
    {
      ret_value |= PMO_EXT_VLD;
    }

    /* process NC measurement service */
    
    /* 
     * Before copying the NC parameter store the old value
     * for the network control order
     */
    *ctrl_order = psc_db->nc_ms.ncmeas.param.ctrl_order;

    grr_prcs_nc_param_final ( &psc_db->nc_ms.ncmeas.param,
                              &emeas->v_pmo_nc_ncmeas_param,
                              &emeas->pmo.nc.ncmeas.param );
#if defined (REL99) AND defined (TI_PS_FF_EMR)

    if( (nc_freq_list_pres EQ TRUE) AND
      (psc_db->nc_ms.ncmeas.param.ctrl_order NEQ NC_RESET) )
    {
      use_ba_gprs = FALSE;
    }

    if(rr_get_support_for_emr() AND emeas->pmo.v_enh_meas_param_pmo EQ TRUE)
    {
    /* The ENH parameters that are temporarily stored are moved to final 
      destination after consistent set of PMO is received */
      memcpy(&(psc_db->enh_ms), &(emeas->pmo.enh), sizeof(T_GRR_ENH_PARA));
      psc_db->nc_ms.pmo_ind = emeas->pmo.nc.pmo_ind;
    }
    else
    {
      memset(&(psc_db->enh_ms), 0, sizeof(T_GRR_ENH_PARA));
      psc_db->enh_ms.rept_type = REPORT_TYPE_REP;
      emeas->pmo.v_enh_meas_param_pmo = FALSE;
    }

#endif

    /*
     * At cell re-selection the NC measurement parameters valid for the mobile
     * station in the new cell are brought from the old cell if received in a
     * PACKET MEASUREMENT ORDER message. Storing is done in advance even in
     * case no cell re-selection took place at this time.
     */
    memcpy( &pcr_db->nc_ms.ncmeas.param, &psc_db->nc_ms.ncmeas.param, 
            sizeof( T_NC_PARAM ) );

    pcr_db->nc_ms.ncmeas.param.chng_mrk.curr = 0;
    pcr_db->nc_ms.ncmeas.param.chng_mrk.prev = 0;

#if defined (REL99) AND defined (TI_PS_FF_EMR)
    if(nc_freq_list_valid EQ TRUE)
    {
      grr_prcs_nc_freq_final ( &psc_db->nc_ms.ncmeas.list,
                               &psc_db->nc_ms.rfreq,
                               &emeas->v_pmo_nc_ncmeas_list_rfreq,
                               &emeas->pmo.nc.ncmeas.list,
                               &emeas->pmo.nc.rfreq );
    }

#else
    grr_prcs_nc_freq_final ( &psc_db->nc_ms.ncmeas.list,
                             &psc_db->nc_ms.rfreq,
                             &emeas->v_pmo_nc_ncmeas_list_rfreq,
                             &emeas->pmo.nc.ncmeas.list,
                             &emeas->pmo.nc.rfreq );
#endif

    if( emeas->pmo.nc.ncmeas.param.ctrl_order NEQ NC_EMPTY )
    {
      ret_value |= PMO_NC_VLD;
    }

    meas_em_init_pmo_seq( );
  }

  return( ret_value );
} /* meas_em_prcs_meas_order() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_valid_pmo
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_em_valid_pmo ( void )
{
  TRACE_FUNCTION( "meas_em_valid_pmo" );

  switch( psc_db->ext_pmo.em_order_type )
  {
    case( EM_RESET ):
      meas_em_valid_psi5( );
      break;

    default:
      if( psc_db->ext_pmo.em_order_type EQ EM_EM1 )
      {
        emeas->xmeas_set.param = &psc_db->ext_pmo;
      }
      else
      {
        emeas->xmeas_set.param = NULL;
      }
      break;
  }
} /* meas_em_valid_pmo() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_valid_psi5
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_em_valid_psi5 ( void )
{
  TRACE_FUNCTION( "meas_em_valid_psi5" );

  if( psc_db->ext_psi5.em_order_type EQ EM_EM1 )
  {
    emeas->xmeas_set.param = &psc_db->ext_psi5;
  }
  else
  {
    emeas->xmeas_set.param = NULL;
  }
} /* meas_em_valid_psi5() */


/*
+------------------------------------------------------------------------------
| Function    : meas_em_is_valid_pmo_present
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL meas_em_is_valid_pmo_present ( void )
{
  TRACE_FUNCTION( "meas_em_is_valid_pmo_present" );

  return( psc_db->ext_pmo.em_order_type NEQ EM_EMPTY AND 
          psc_db->ext_pmo.em_order_type NEQ EM_RESET     );
} /* meas_em_is_valid_pmo_present() */


/*
+------------------------------------------------------------------------------
| Function    : meas_em_process_t3178
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_em_process_t3178 ( void )
{
  T_TIME reporting_period;
  T_TIME time_to_go;
  BOOL   tmr_3178_rng_le_rp = FALSE;

  TRACE_FUNCTION( "meas_em_process_t3178" );

  if( meas_em_is_meas_reporting( ) )
  {
    reporting_period = 
          GET_EM_RPT_PRD( emeas->xmeas_set.param->em1.param.reporting_period );

    time_to_go = grr_t_status( T3178 );
    
    if( time_to_go > 0 )
    {
      if( time_to_go > reporting_period )
      {
        meas_em_stop_t3178( );
      }
      else
      {
        tmr_3178_rng_le_rp = TRUE;
      }
    }

    if( reporting_period   NEQ 0     AND 
        tmr_3178_rng_le_rp EQ  FALSE     )
    {
      meas_em_start_t3178( reporting_period );
    }
  }
  else
  {
    meas_em_stop_t3178( );
  }
} /* meas_em_process_t3178() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_start_t3178
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL void meas_em_start_t3178 ( T_TIME time )
{
  TRACE_FUNCTION( "meas_em_start_t3178" );

  vsi_t_start( GRR_handle, T3178, time );

  TRACE_EVENT_P1( "T3178: %d", time );

} /* meas_em_start_t3178() */


/*
+------------------------------------------------------------------------------
| Function    : meas_em_stop_t3178
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void meas_em_stop_t3178 ( void )
{
  TRACE_FUNCTION( "meas_em_stop_t3178" );
  
  if( grr_t_status( T3178 ) > 0 )
  {
    vsi_t_stop( GRR_handle, T3178 );

    TRACE_EVENT( "T3178 stopped" );
  }
} /* meas_em_stop_t3178() */

                                     
/*
+------------------------------------------------------------------------------
| Function    : meas_em_stop_req
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_em_stop_req ( void )
{
  TRACE_FUNCTION( "meas_em_stop_req" );
  
  {
    PALLOC( rrgrr_em_stop_req, RRGRR_EXT_MEAS_STOP_REQ  );
    PSEND( hCommRR, rrgrr_em_stop_req );  
  }
} /* meas_em_stop_req() */

/*
+------------------------------------------------------------------------------
| Function    : meas_em_start
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_em_start ( void )
{

  TRACE_FUNCTION( "meas_em_start" );

  meas_im_delete_em_rslt( );  
  meas_em_req( );  
  meas_em_process_t3178( );


} /* meas_em_start() */


/*
+------------------------------------------------------------------------------
| Function    : meas_em_send_meas_rpt
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL meas_em_send_meas_rpt ( BOOL perform_init )
{
  BOOL            rpt_snd;
  T_U_MEAS_REPORT meas_rpt;

  TRACE_FUNCTION( "meas_em_send_meas_rpt" );

  if( perform_init EQ TRUE )
  {
    emeas->pmr_snd_ref = 0;

    if     ( emeas->xmeas_set.param->em1.param.reporting_type EQ REP_TYPE_1 )
    {
      meas_em_extrct_strgst( );
    }
    else if( emeas->xmeas_set.param->em1.param.reporting_type EQ REP_TYPE_2 )
    {
      meas_em_extrct_strgst_with_bsic( );
    }

  }

  if( meas_em_build_meas_rpt( &meas_rpt ) NEQ 0    OR
      perform_init                        EQ  TRUE    )
  {
    sig_meas_ctrl_meas_report( &meas_rpt );

    rpt_snd = TRUE;
  }
  else
  {
    rpt_snd = FALSE;
  }

  return( rpt_snd );
} /* meas_em_send_meas_rpt() */


/*
+------------------------------------------------------------------------------
| Function    : meas_is_spgc_ccch_supported
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL meas_is_spgc_ccch_supported ( void )
{
  TRACE_FUNCTION( "meas_is_spgc_ccch_supported" );

  return
    ( psc_db->net_ctrl.spgc_ccch_supp.nw_supp EQ GMMRR_SPGC_CCCH_SUPP_YES AND
      psc_db->net_ctrl.spgc_ccch_supp.ms_supp EQ GMMRR_SPGC_CCCH_SUPP_YES     );
} /* meas_is_spgc_ccch_supported() */



/*
+------------------------------------------------------------------------------
| Function    : meas_handle_int_meas_values
+------------------------------------------------------------------------------
| Description : This function ...
|
| Parameters  : mphp_int_meas_ind - pointer to primitive
|               rx_lev            - pointer on array of 8 byte,
|                                   where the results are stored
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_handle_int_meas_values
                      ( T_MPHP_INT_MEAS_IND *mphp_int_meas_ind, UBYTE *rx_lev )
{
  UBYTE             i;      /* used for counting */
  T_int_meas_rxlev *sample;

  TRACE_FUNCTION( "meas_handle_int_meas_values" );

  for ( i = 0; i < CGRLC_MAX_TIMESLOTS; i++ )
  {
    sample = &mphp_int_meas_ind->int_meas_rxlev[i];

    if( sample->rx_lev[0] EQ CGRLC_RXLEV_NONE )
    {
      if( sample->rx_lev[1] EQ CGRLC_RXLEV_NONE )
      {
        rx_lev[i] = CGRLC_RXLEV_NONE;
      }
      else
      {
        rx_lev[i] = sample->rx_lev[1];
      }
    }
    else
    {
      if( sample->rx_lev[1] EQ CGRLC_RXLEV_NONE )
      {
        rx_lev[i] = sample->rx_lev[0];
      }
      else
      {
        rx_lev[i] = MINIMUM( (signed char)( sample->rx_lev[0] ), 
                                          (signed char)( sample->rx_lev[1] ) );
      }
    }
  }

  grr_clip_rxlev ( rx_lev, rx_lev, CGRLC_MAX_TIMESLOTS );

#if !defined (NTRACE)

  if( grr_data->meas_im.n_im_trace & M_IM_TRACE_INPUT_VALUE )
  {
    USHORT rx_lev[8];

    rx_lev[0]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[0].rx_lev[0] << 0;
    rx_lev[0] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[0].rx_lev[1] << 8;
    rx_lev[1]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[1].rx_lev[0] << 0;
    rx_lev[1] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[1].rx_lev[1] << 8;
    rx_lev[2]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[2].rx_lev[0] << 0;
    rx_lev[2] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[2].rx_lev[1] << 8;
    rx_lev[3]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[3].rx_lev[0] << 0;
    rx_lev[3] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[3].rx_lev[1] << 8;
    rx_lev[4]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[4].rx_lev[0] << 0;
    rx_lev[4] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[4].rx_lev[1] << 8;
    rx_lev[5]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[5].rx_lev[0] << 0;
    rx_lev[5] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[5].rx_lev[1] << 8;
    rx_lev[6]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[6].rx_lev[0] << 0;
    rx_lev[6] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[6].rx_lev[1] << 8;
    rx_lev[7]  = ( USHORT )mphp_int_meas_ind->int_meas_rxlev[7].rx_lev[0] << 0;
    rx_lev[7] |= ( USHORT )mphp_int_meas_ind->int_meas_rxlev[7].rx_lev[1] << 8;

    TRACE_EVENT_P8( "meas_handle_int_meas_values: %04X %04X %04X %04X %04X %04X %04X %04X",
                    rx_lev[0], rx_lev[1], rx_lev[2], rx_lev[3], 
                    rx_lev[4], rx_lev[5], rx_lev[6], rx_lev[7] );
  }

#endif /* #if !defined (NTRACE) */

} /* meas_handle_int_meas_values() */

/*
+------------------------------------------------------------------------------
| Function    : meas_c_init
+------------------------------------------------------------------------------
| Description : This function initializes the parameters for deriving the
|               C value.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_c_init ( void )
{
  TRACE_FUNCTION( "meas_c_init" );

  grr_data->meas.c_filter.value = 0;
  grr_data->meas.c_filter.index = 0;
} /* meas_c_init() */

/*
+------------------------------------------------------------------------------
| Function    : meas_c_val_update_pim 
+------------------------------------------------------------------------------
| Description : ... 
|
| Parameters  : -
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_c_val_update_pim ( UBYTE rx_lev )
{ 
  ULONG ff;       /* forgetting factor */  
  ULONG avgw_drx;
  ULONG c_value;
  UBYTE c_block;

  T_C_FILTER *c_filter = &grr_data->meas.c_filter;

  TRACE_FUNCTION( "meas_c_val_update_pim" );

  grr_clip_rxlev ( &c_block, &rx_lev, 1 );

  if( c_block NEQ CGRLC_RXLEV_NONE )
  {
    MEAS_C_INC_INDEX( c_filter->index );

    /* calculate the forgetting factor */
    avgw_drx = 
      ( (NORM_TAVGW_FAC * NORM_TAVGW_FAC *
         norm_pow[psc_db->g_pwr_par.t_avg_w]) / 6 ) / meas_im_get_drx_period_seconds( );

    ff = DRX_NORM_FACTOR / MINIMUM( NORM_TAVGW_FAC * c_filter->index,
                                    MAXIMUM( 5 * NORM_TAVGW_FAC, avgw_drx ) );

    /* update the filter */
    c_value = ( NORM_POW_MIN - ff ) * c_filter->value +
              MEAS_ACRCY * ff * c_block;

    c_filter->value = (T_C_VALUE)( M_ROUND_UP( c_value, NORM_POW_MIN ) );

#ifdef _SIMULATION_
    TRACE_EVENT_P2( "C-Value = %d, C-Index = %d", 
                    c_filter->value, c_filter->index );
#endif /* #ifdef _SIMULATION_ */

    grr_data->pwr_ctrl_valid_flags.v_c_value = TRUE;
  }
  else
  {
#ifdef _SIMULATION_
    TRACE_EVENT( "no valid RXLEV information in meas_c_val_update_pim" );
#endif /* #ifdef _SIMULATION_ */
  }
} /* meas_c_val_update_pim() */

/*
+------------------------------------------------------------------------------
| Function    : meas_handle_pwr_par
+------------------------------------------------------------------------------
| Description : The function meas_handle_pwr_par() .... 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void meas_handle_pwr_par ( void )
{ 
  MCAST( d_ctrl_pwr_ta, D_CTRL_PWR_TA ); /* T_D_CTRL_PWR_TA */

  TRACE_FUNCTION( "meas_handle_pwr_par" );
  
  /* process global power control parameter */
  if( d_ctrl_pwr_ta->v_g_pwr_par )
  {
    grr_store_g_pwr_par( &d_ctrl_pwr_ta->g_pwr_par );
  }
  
  /* process power control parameter */
  if( d_ctrl_pwr_ta->v_pwr_par )
  {
    grr_store_type_pwr_par( &d_ctrl_pwr_ta->pwr_par, FALSE );
  }
} /* meas_handle_pwr_par() */