FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/grr/grr_measf.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/grr/grr_measf.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,3105 @@ +/* ++----------------------------------------------------------------------------- +| 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() */