FreeCalypso > hg > leo2moko-debug
diff g23m/condat/ms/src/alr/alr_nc.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/g23m/condat/ms/src/alr/alr_nc.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,6961 @@ +/* ++----------------------------------------------------------------------------- +| Project : GSM-PS +| Modul : ALR_NC ++----------------------------------------------------------------------------- +| 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 Modul defines the SDL process Idle_Neighbour_Cells. ++----------------------------------------------------------------------------- +*/ + +#ifndef ALR_NC_C +#define ALR_NC_C + +#define ENTITY_PL + +/*==== INCLUDES ===================================================*/ +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> +#include "typedefs.h" +#include "message.h" +#include "ccdapi.h" +#include "vsi.h" +#include "custom.h" +#include "gsm.h" +#include "prim.h" +#include "cnf_alr.h" +#include "mon_alr.h" +#include "pei.h" +#include "tok.h" +#include "pcm.h" +#ifdef GPRS +#include "alr_gprs.h" +#endif + +#if !defined(NTRACE) +#define TRACING +#endif /* !TRACING */ + +#include "alr.h" +#include "alr_em.h" + +#if !defined(NTRACE) && defined(TRACING) +LOCAL const char *nc_get_nc_state_str(UBYTE status); +LOCAL const char * const alr_nc_state_trc[18] = { + "INACT", + "IDLE", + "RD_BCCH", + "FB_SB_SYNC", + "FB_SB_FAIL", + "RD_FB_SB", + "RD_SB", + "IDLE_SYNC", + "EXCL", + "FB_SB_SYNC_RR", + "RD_SB_BCCH", + "RD_BCCH_P", + "RD_FB_SB_P", + "RD_SB_P", + "RD_SB_BCCH_P", + "RD_BCCH_RR", + "RD_BCCH_P_RR", + "???"}; +#endif /* !NTRACE && TRACING */ +LOCAL const UBYTE unc_values[] = +{ + 2, 4, 8, 12, 16, 22, 30, NOT_PRESENT_8BIT +}; +/*==== EXPORT =====================================================*/ + +/*==== PRIVAT =====================================================*/ +LOCAL void nc_update_ba_list (USHORT serving_cell, + T_MPH_NEIGHBOURCELL_REQ * ncell_list); +LOCAL UBYTE nc_remove_channel_from_ba_list (USHORT index); +LOCAL UBYTE nc_is_in_ncell_list (USHORT channel, + T_MPH_NEIGHBOURCELL_REQ * ncell_list); +LOCAL void nc_process_status (void); +LOCAL void nc_process_status_sync (void); +LOCAL void nc_process_status_last_bsic (void); +LOCAL void nc_process_status_bcch (void); +LOCAL BOOL nc_ncell_in_plmn_permitted (UBYTE bsic); +LOCAL void nc_find_cells (USHORT * c_found, + USHORT max, + UBYTE limitation, + UBYTE min_rxlev); +LOCAL void nc_store_rxlev (T_MPHC_RXLEV_PERIODIC_IND * report); +LOCAL void nc_rank_ncells (void); +LOCAL void nc_check_status (UBYTE start_list); +LOCAL void nc_build_rr_report_dedi (T_MPH_MEASUREMENT_IND * rr_report); + +LOCAL void nc_store_dedicated (T_MPHC_MEAS_REPORT * report); +LOCAL UBYTE nc_convert_quality (USHORT errors, + USHORT total); +LOCAL void nc_store_bcch (T_MPHC_DATA_IND * data_ind, + USHORT index, + UBYTE which); +LOCAL void nc_stop_bcch (USHORT index, + UBYTE new_status); +LOCAL void nc_stop_sync (USHORT index, + UBYTE new_status); +LOCAL void nc_clean_store_bcch (USHORT index); +LOCAL UBYTE nc_check_bsic (USHORT index, + UBYTE bsic); +#if 0 +#if !defined(NTRACE) && defined(TRACING) +LOCAL UBYTE nc_get_status (USHORT index); +#endif /* !NTRACE && TRACING */ +#endif /* 0|1 */ +LOCAL void nc_restart_bcch (USHORT index); +LOCAL void nc_set_fb_sb_sync_initial (USHORT index); +LOCAL void nc_set_fb_sb_failed (USHORT index, + UBYTE c_sync); +LOCAL UBYTE nc_sys_info_78_required (USHORT index); +LOCAL void nc_sync_failed_attempt (USHORT index); +LOCAL void nc_sync_failed_attempt_dedicated(USHORT index); +LOCAL void nc_build_rr_report (T_MPH_MEASUREMENT_IND* rr_report); +LOCAL void nc_release_bcch (void); +LOCAL void nc_find_list_cells (void); +LOCAL void nc_ncell_list_req (void); +LOCAL void nc_start_eotd_confirm (void); +LOCAL void nc_process_pos_req (T_MPH_NCELL_POS_REQ* pos_req); +LOCAL void nc_check_sync_ind_eotd (T_MPHC_NCELL_SYNC_IND* sync_ind, + USHORT arfcn); +LOCAL void nc_store_eotd (T_eotd_sc_res* p_res, + T_MPHC_NCELL_SYNC_IND* sync_ind, + USHORT arfcn); +LOCAL void nc_sync_ind_last_bsic_req (T_MPHC_NCELL_SYNC_IND* sync_ind, + USHORT index, + USHORT arfcn, + UBYTE bsic); +LOCAL void nc_sync_ind_ncell (T_MPHC_NCELL_SYNC_IND* sync_ind, + USHORT index, + USHORT arfcn, + UBYTE bsic); +LOCAL void nc_clear_last_bsic (void); +#if 0 +Symbol 'nc_stop_all_bcch(void)' 'nc_stop_all_sync(void)' and not referenced at the moment +LOCAL void nc_stop_all_bcch (void); +LOCAL void nc_stop_all_sync (void); +#endif /* 0|1 */ +LOCAL void nc_stop_all (void); +LOCAL void nc_stop_all_inactive (void); +LOCAL void nc_stop_if_active (USHORT i); +LOCAL void nc_ncell_list_req_pos (T_ncell_list* p_ncell_list, + T_ncell_eotd* asd_cell, + USHORT arfcn); +LOCAL void nc_get_timing_eotd (T_ncell_list* p_ncell_list, + T_ncell_eotd* asd_cell); + +LOCAL BOOL nc_is_sync (T_NC * p_ncell); +LOCAL void nc_build_sync_req (USHORT index); +LOCAL void nc_init_pos_ind (USHORT req_id); +LOCAL void nc_enable_conf (void); +LOCAL void nc_disable_conf (BOOL bFree); +LOCAL void nc_start_ncell_confirm (void); +LOCAL void nc_handle_new_strong_cells (void); +LOCAL void nc_check_new_strong_cell (USHORT index, UBYTE o_1of6, UBYTE rxlev); +#ifdef GPRS +LOCAL void nc_rxlev_sc_req (UBYTE rxlev); +LOCAL void nc_inform_grr_of_ncell (USHORT index, + UBYTE type); +LOCAL void remove_ncell_and_inform_grr (USHORT index); +LOCAL void nc_sync_failed_gprs (USHORT index); +LOCAL void nc_check_bsic_pbcch(T_MPH_NEIGHBOURCELL_REQ* ncell_list); +LOCAL void nc_process_status_sync_gprs(void); +#endif /* #ifdef GPRS */ + +#if defined(_SIMULATION_) +LOCAL void trace_nc(void); +#endif /* _SIMULATION_ */ +LOCAL void nc_start_ncsync (void); + +/*==== CONSTANTS ==================================================*/ +#define MAX_L1_SYNC_CNT 12 +#define MAX_L1_BCCH_CNT 6 +#define MAX_L1_SYNC_EOTD_CNT 14 +#define MAX_RR_NCELL_CNT 6 + +#define ONLY_BCC 7 +#define ONLY_BSIC 63 + +#define NC_CHECK_OK 0 +#define NC_CHECK_NCC_FAILED 1 +#define NC_CHECK_BSIC_CHANGED 2 + +#define CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL 0 +#define CHECK_FOR_CONFIRM 1 + +#define DONT_FREE_POS_IND 0 +#define FREE_POS_IND 1 + +/* + * Counter to realize a time interval of 10sec in terms of Control Multiframe + * Idle state : 42 * 51 * 4.615ms = 9885ms + * Dedicated State : 42 * 104/2 * 4.615ms = 10079ms + */ +#define TEN_SECONDS_NCSYNC 42 + +#define TEN_SECONDS 1 +#define TWENTY_SECONDS 2 +#define THIRTY_SECONDS 3 +#define FIVE_MINUTES 30 +#define C_INVALID_SYNC (THIRTY_SECONDS+1) +/* +2 for rounding BCCH reading to confirmation boundary */ +#define C_INVALID_BCCH (FIVE_MINUTES+2+1) + +#ifdef GPRS +#define GRR_SB_FOUND (MPH_BSIC_UNKNOWN+1) +#define GRR_SB_NOT_FOUND NOT_PRESENT_8BIT +#define GRR_SB_UNKNOWN MPH_BSIC_UNKNOWN +#endif + +/*==== VARIABLES ==================================================*/ + +/*==== FUNCTIONS ==================================================*/ +#if defined (WIN32) && !defined (_SIMULATION_) +#define _SIMULATION_ +#endif + +#if defined (_SIMULATION_) +#define TRACING +#endif /* _SIMULATION_ */ + +/* + * some traces + */ +#if defined (TRACING) +#define ALR_TRACE_NC(a) ALR_TRACE(a) +#define ALR_TRACE_NC_CNT(a,b) TRACE_EVENT_P2 ("[%4u] c_sync %d", \ + ARFCN_TO_G23(a)&ARFCN_MASK, b) +#define ALR_TRACE_NC_BSIC_CNF(a) TRACE_EVENT_P1 ("[%4u] NC BSIC CNF passed", \ + ARFCN_TO_G23(a)&ARFCN_MASK) +#define ALR_TRACE_NC_SB_FAILED(a) TRACE_EVENT_P1 ("[%4u] NCELL SB IND failed", \ + ARFCN_TO_G23(a)&ARFCN_MASK) +#define ALR_TRACE_NC_BSIC_REQ(a) TRACE_EVENT_P4 ("[%4u] NC BSIC REQ %d %d %d", \ + a&ARFCN_MASK, GET_STATE (STATE_NC), \ + alr_data->nc_data.cell[LAST_BSIC_REQ].status, \ + alr_data->nc_data.c_bcch_req) +#define ALR_TRACE_NC_BCCH_OK(f,m) TRACE_EVENT_P2 ("[%4u] NCELL BCCH IND passed msg:%d", \ + f&ARFCN_MASK,m) +#define ALR_TRACE_NC_SB_IND_PASSED(f) TRACE_EVENT_P1 ("[%4u] NCELL SB IND passed", \ + f&ARFCN_MASK) +#define ALR_TRACE_NC_RESELECT(a) TRACE_EVENT_P1 ("[%4u] start reselect", a&ARFCN_MASK) +#define ALR_TRACE_NC_FN_TA(_i,f,t) TRACE_EVENT_P3 ("i %d, fn %d, ta %d ", _i, f, t) +#if 0 +#define GET_NC_STATE(i) nc_get_status(i) +#endif /* 0|1 */ +#if defined(_SIMULATION_) +#define ALR_TRACE_ALL_NC() trace_nc() +#else /* _SIMULATION_ */ +#define ALR_TRACE_ALL_NC() +#endif /* _SIMULATION_ */ +#else /* TRACING */ +#define ALR_TRACE_NC(a) +#define ALR_TRACE_NC_CNT(a,b) +#define ALR_TRACE_NC_BSIC_CNF(a) +#define ALR_TRACE_NC_SB_FAILED(a) +#define ALR_TRACE_NC_BSIC_REQ(a) +#define ALR_TRACE_NC_BCCH_OK(f,m) +#define ALR_TRACE_NC_SB_IND_PASSED(f) +#define ALR_TRACE_NC_RESELECT(a) +#define ALR_TRACE_NC_FN_TA(i,f,t) +#define GET_NC_STATE(i) alr_data->nc_data.cell[i].status +#define ALR_TRACE_ALL_NC() +#undef TRACE_EVENT +#undef TRACE_EVENT_P1 +#undef TRACE_EVENT_P2 +#undef TRACE_EVENT_P3 +#undef TRACE_EVENT_P4 +#undef TRACE_EVENT_P5 +#undef TRACE_EVENT_P6 +#undef TRACE_EVENT_P7 +#undef TRACE_EVENT_P8 +#undef TRACE_EVENT_P9 +#define TRACE_EVENT(s) +#define TRACE_EVENT_P1(s,a) +#define TRACE_EVENT_P2(s,a,b) +#define TRACE_EVENT_P3(s,a,b,c) +#define TRACE_EVENT_P4(s,a,b,c,d) +#define TRACE_EVENT_P5(s,a,b,c,d,e) +#define TRACE_EVENT_P6(s,a,b,c,d,e,f) +#define TRACE_EVENT_P7(s,a,b,c,d,e,f,g) +#define TRACE_EVENT_P8(s,a,b,c,d,e,f,g,h) +#define TRACE_EVENT_P9(s,a,b,c,d,e,f,g,h,i) +#endif /* TRACING */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_init | ++--------------------------------------------------------------------+ + + PURPOSE : Initialize Idle Neighbour Cell Process. + +*/ +GLOBAL void nc_init (void) +{ + nc_stop_all(); + alr_data->nc_data.c_ba_arfcn = 0; + alr_data->nc_data.ba_id = ALR_BA_LOW; + alr_data->nc_data.sc_included = FALSE; + alr_data->nc_data.cell[LAST_BSIC_REQ].status = IDLE; + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + alr_data->nc_data.c_reports = (UBYTE)-1; + alr_data->nc_data.cr_cell.ba_arfcn = NOT_PRESENT_16BIT; + alr_data->nc_data.tim_state = NC_TIM_STOPPED; + alr_data->nc_data.c_nc_timer = 0; + if (alr_data->nc_data.ppos_ind NEQ NULL) + { + PFREE(alr_data->nc_data.ppos_ind); + alr_data->nc_data.ppos_ind = NULL; + } + if (alr_data->nc_data.ppos_req NEQ NULL) + { + PFREE(alr_data->nc_data.ppos_req); + alr_data->nc_data.ppos_req = NULL; + } + + /* Initialize the counter for realizing 10sec timer value */ + alr_data->nc_data.c_ncsync_tim = 0; + alr_data->nc_data.ncsync_start_tim = 0; + + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + SET_STATE(STATE_NC, NC_NULL); +} + +#ifdef GPRS +/* ++----------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_GPRS | +| STATE : code ROUTINE : nc_start_pbcch| ++----------------------------------------------------------------------+ + + PURPOSE :Checks whether pbcch is available and sets a relevant state. + +*/ + +GLOBAL void nc_start_pbcch(void) +{ + if(alr_data->gprs_data.ptm AND + alr_data->gprs_data.pbcch) + { + SET_STATE(STATE_NC, NC_PTM_PBCCH); + } + else if(alr_data->gprs_data.pbcch) + { + SET_STATE(STATE_NC, NC_PIM_PBCCH); + } + + nc_enable_conf(); + nc_process_status(); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_GPRS | +| STATE : code ROUTINE : gprs_check_bsic_pbcch | ++--------------------------------------------------------------------+ + + PURPOSE : + +*/ +LOCAL void nc_check_bsic_pbcch(T_MPH_NEIGHBOURCELL_REQ* ncell_list) +{ + TRACE_EVENT("gprs_alr_check_bsic_pbcch"); + if(!alr_data->gprs_data.pbcch) return; + + if(ncell_list->sync_only EQ SYNC_LIST) + { + + USHORT n_rr; /* index of RR neighbor cell list */ + USHORT n_alr; /* index of ALR neighbor cell list */ + UBYTE last_alr; /* last index of ALR neighbor cell list */ + USHORT arfcn; + TRACE_EVENT("pbcch/check bsic"); + + /* + * remove all channels which are not longer member of the + * neighbour cell list. + */ + last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */ + for (n_alr = 0; n_alr < last_alr; n_alr++) + { + arfcn = alr_data->nc_data.cell[n_alr].ba_arfcn; + if (!nc_is_in_ncell_list (arfcn, ncell_list)) + /* AND + (arfcn NEQ alr_data->serving_cell))*/ + { + switch(alr_data->nc_data.cell[n_alr].status) + { + case READ_FB_SB: + case READ_FB_SB_PENDING: + case READ_SB_PENDING: + case READ_SB: + case READ_SB_BCCH: /* in case we come from BCCH */ + case INACTIVE: /* in case we returned from DEDIC */ + case IDLE: /* in case we returned from DEDIC */ + case EXCLUDED: /* in case we returned from DEDIC */ + TRACE_EVENT_P1("rem cell i%d",n_alr); + remove_ncell_and_inform_grr(n_alr); + last_alr = alr_data->nc_data.c_ba_arfcn; + n_alr--; + break; + case FB_SB_SYNC_RR_NOT_INFORMED: + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH: + case FB_SB_SYNC: + case IDLE_SYNC: + case FB_SB_FAILED: + /*state change will be done with check_status*/ + TRACE_EVENT_P1("i%d reset 1o6", n_alr); + alr_data->nc_data.cell[n_alr].one_of_six = FALSE; + alr_data->nc_data.cell[n_alr].one_of_twelve = FALSE; + break; + default: + TRACE_EVENT_P3("i%d,arfcn:%d illegal status %d",n_alr, + alr_data->nc_data.cell[n_alr].ba_arfcn, + alr_data->nc_data.cell[n_alr].status); + break; + } + } + else + { /* ncell is in both lists */ + switch(alr_data->nc_data.cell[n_alr].status) + { + case READ_FB_SB: +// case READ_FB_SB_PENDING: + //case READ_SB_PENDING: + case READ_SB: + break; + case READ_SB_BCCH: /* in case we come from BCCH */ + nc_set_status(n_alr, READ_SB); + break; + case INACTIVE: /* in case we returned from DEDIC */ + case IDLE: /* in case we returned from DEDIC */ + case EXCLUDED: /* in case we returned from DEDIC */ + nc_set_status (n_alr, INACTIVE); + /* ALR does not receive measurements */ + /* set them to idle */ + nc_set_status (n_alr, IDLE); + /* and set it to one_of_six , the rest is done by check_status */ + nc_set_status(n_alr, READ_FB_SB); + break; + case FB_SB_SYNC_RR_NOT_INFORMED: + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH: + nc_set_status(n_alr, FB_SB_SYNC); + break; + default: + break; + } + alr_data->nc_data.cell[n_alr].one_of_six = FALSE; + alr_data->nc_data.cell[n_alr].one_of_twelve = TRUE; + } + } + + /* + * add all new channels. + */ + for (n_rr = 0; + (n_rr < MAX_NEIGHBOURCELLS) AND (last_alr < BA_LIST_SIZE-1); + n_rr++) + { + arfcn = ncell_list->arfcn[n_rr]; + if (arfcn EQ NOT_PRESENT_16BIT) + break; /* no more entries in the RR ncell_list */ + + n_alr = nc_get_index (arfcn); + + if (((n_alr EQ NOT_PRESENT_16BIT) OR (n_alr EQ LAST_BSIC_REQ)) AND + (arfcn NEQ alr_data->serving_cell)) + { + T_NC* pcell = &alr_data->nc_data.cell[last_alr]; + +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] add", last_alr, arfcn); +#endif /* TRACING */ + pcell->ba_arfcn = arfcn; + nc_set_status (last_alr, INACTIVE); + /* ALR does not receive measurements */ + /* set them to idle */ + nc_set_status (last_alr, IDLE); + /* and set it to one_of_six , the rest is done by check_status */ + alr_data->nc_data.cell[last_alr].one_of_six = FALSE; + alr_data->nc_data.cell[last_alr].one_of_twelve = TRUE; + alr_data->nc_data.cell[last_alr].ba_status = IN_BA; + last_alr++; /* increment last index */ + } + } + alr_data->nc_data.c_ba_arfcn = last_alr; /* store new last index */ + ALR_TRACE_ALL_NC (); + + { + UBYTE six=0; + last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */ + for (n_alr = 0; n_alr < last_alr; n_alr++) + { + six += alr_data->nc_data.cell[n_alr].one_of_six; + } + /*XXX change this to handle 12 ncells */ + if(six > 6) + { + TRACE_ERROR("more then six candidates!"); + } + } +#if 0 /*only for easing debugging */ + /* + * Reorder the entries. The goal is that the propably strongest neigbour + * cells + * are measured in the first measurement period of a subsequent + * MPHC_RXLEV_PERIODIC_REQ/IND. The appropriate arfcn's are the first + * ones in + * ncell_list->arfcn + */ + { + T_NC temp, *prr, *palr; + + for (n_rr = 0; n_rr < 7; n_rr++) + { + if(ncell_list->arfcn[n_rr] NEQ NOT_PRESENT_16BIT) + n_alr = nc_get_index (ncell_list->arfcn[n_rr]); + else + break; + + if ( ((n_alr NEQ NOT_PRESENT_16BIT) OR (n_alr NEQ LAST_BSIC_REQ)) AND + n_rr NEQ n_alr) + { + palr = &(alr_data->nc_data.cell[n_alr]); + prr = &(alr_data->nc_data.cell[n_rr]); + memcpy(&temp, palr, sizeof(T_NC)); + memcpy(palr, prr, sizeof(T_NC)); + memcpy(prr, &temp, sizeof(T_NC)); + /*TRACE_EVENT_P4("reordered NC%u[%u] and NC%u[%u]", + n_rr, + ncell_list->arfcn[n_rr], + n_alr, ncell_list->arfcn[n_alr]);*/ + } + } + } +#endif + nc_check_status(CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL); + + if(alr_data->nc_sync_with_grr) + { + TRACE_EVENT("sync_with_grr"); + last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */ + for (n_alr = 0; n_alr < last_alr; n_alr++) + { + switch(alr_data->nc_data.cell[n_alr].status) + { + case IDLE_SYNC: + case FB_SB_SYNC: + case READ_SB: + case READ_SB_PENDING: + case READ_FB_SB_PENDING: + TRACE_EVENT_P1("sync %d",alr_data->nc_data.cell[n_alr].ba_arfcn); + nc_inform_grr_of_ncell(n_alr, GRR_SB_FOUND); + break; + case FB_SB_FAILED: + case EXCLUDED: + case INACTIVE: + case IDLE: + TRACE_EVENT_P1("sync %d",alr_data->nc_data.cell[n_alr].ba_arfcn); + nc_inform_grr_of_ncell(n_alr, GRR_SB_NOT_FOUND); + break; + /* READ_FB_SB ->the cell will be synchronized next + and a result will be returnded anyway */ + default: + break; + } + } + alr_data->nc_sync_with_grr=FALSE; + } + + switch(GET_STATE(STATE_NC)) + { + case NC_PIM_PBCCH: + case NC_PTM_PBCCH: + nc_process_status(); + break; + default: + break; + } + } + else if(ncell_list->sync_only EQ RECONFIRM_SYNC_LIST) + { + nc_ncsync_tim_expiry(); + } + +} + +#endif +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop | ++--------------------------------------------------------------------+ + + PURPOSE : stop the neighbourcell process. Is called by main process + if a recovery with power measurements is started. + +*/ + +GLOBAL void nc_stop (void) +{ + /* + * clean or neighbourcells of the BA and LAST_BSIC_REQ list if needed + */ + nc_stop_all_inactive(); + + /* + * initialize neighbourcell process and stops timer + */ + nc_init(); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_all_inactive | ++--------------------------------------------------------------------+ + + PURPOSE : This stops all activities to bring a channel to state NC_NULL. + +*/ + +LOCAL void nc_stop_all_inactive (void) +{ + UBYTE i, stopped_sync=0, stopped_bcch=0; + /* + * depending on the current status + */ + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + switch (alr_data->nc_data.cell[i].status) + { + case READ_FB_SB_PENDING: + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + /* + * stop the current running request for synchronisation in layer 1. + */ + nc_set_status (i, INACTIVE); + stopped_sync++; + break; + + case READ_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + /* + * stop the current running request for BCCH reading in layer 1. + * If sys info 4 is already stored, but sys info 7 or 8 is requested + * clear also a stored BCCH message. + */ + nc_set_status (i, INACTIVE); + stopped_bcch++; + break; + default: + /* + * sys infos are stored, but RR is still not informed. + * Then clean the stored message + */ + nc_set_status (i, INACTIVE); + break; + } + } + switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status) + { + case READ_FB_SB_PENDING: + nc_set_status (LAST_BSIC_REQ, IDLE); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + stopped_sync++; + break; + case READ_BCCH_PENDING: + nc_set_status (LAST_BSIC_REQ, IDLE); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + stopped_bcch++; + break; + } + + /*send to L1*/ + if (stopped_sync > 0) + { /* stop all synchronizations */ + PALLOC (stop_req, MPHC_STOP_NCELL_SYNC_REQ); + stop_req->radio_freq_array_size = MAX_L1_SYNC_CNT; + PSENDX(L1, stop_req); + } + if (stopped_bcch > 0) + { /* stop all bcch */ + PALLOC (stop_req, MPHC_STOP_NCELL_BCCH_REQ); + stop_req->radio_freq_array_size = MAX_L1_BCCH_CNT; + PSENDX(L1, stop_req); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_all | ++--------------------------------------------------------------------+ + + PURPOSE : This stops all activities to bring a channel + its corresping READ_ state. + +*/ + +LOCAL void nc_stop_all (void) +{ + UBYTE i, stopped_sync=0, stopped_bcch=0; + /* + * depending on the current status + */ + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + switch (alr_data->nc_data.cell[i].status) + { + case READ_FB_SB_PENDING: + nc_set_status (i, READ_FB_SB); + stopped_sync++; + break; + case READ_SB_PENDING: + nc_set_status (i, READ_SB); + stopped_sync++; + break; + case READ_SB_BCCH_PENDING: + nc_set_status (i, READ_SB_BCCH); + stopped_sync++; + break; + case READ_BCCH_PENDING: + nc_set_status (i, READ_BCCH); + stopped_bcch++; + break; + case READ_BCCH_PENDING_RR_NOT_INFORMED: + nc_set_status (i, READ_BCCH_RR_NOT_INFORMED); + stopped_bcch++; + break; + case FB_SB_SYNC_RR_NOT_INFORMED: + nc_set_status (i, READ_BCCH_RR_NOT_INFORMED); + break; + } + } + switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status) + { + case READ_FB_SB_PENDING: + nc_set_status (LAST_BSIC_REQ, READ_FB_SB); + stopped_sync++; + break; + case READ_BCCH_PENDING: + nc_set_status (LAST_BSIC_REQ, READ_BCCH); + stopped_bcch++; + break; + } + /*send to L1*/ + if ( stopped_sync > 0 OR + alr_data->nc_data.c_sync_req > 0 OR + (alr_data->nc_data.eotd_avail AND GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM)) + { /* stop all synchronizations if waiting for any NC synchronization (or 2nd SC in EOTD case) */ + PALLOC (stop_req, MPHC_STOP_NCELL_SYNC_REQ); + stop_req->radio_freq_array_size = MAX_L1_SYNC_CNT; + PSENDX(L1, stop_req); + alr_data->nc_data.c_sync_req=0; + if (alr_data->nc_data.eotd_avail) + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + } + if(stopped_bcch > 0) + { /* stop all bcch */ + PALLOC (stop_req, MPHC_STOP_NCELL_BCCH_REQ); + stop_req->radio_freq_array_size = MAX_L1_BCCH_CNT; + PSENDX(L1, stop_req); + alr_data->nc_data.c_bcch_req=0; + } +} + +#if 0 +Symbol 'nc_stop_all_bcch(void)' not referenced at the moment +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_all_sync | ++--------------------------------------------------------------------+ + + PURPOSE : This stops all sync activities. + +*/ +LOCAL void nc_stop_all_sync (void) +{ + UBYTE i, stopped_sync=0; + /* + * depending on the current status + */ + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + switch (alr_data->nc_data.cell[i].status) + { + case READ_FB_SB_PENDING: + nc_set_status (i, READ_FB_SB); + stopped_sync++; + break; + case READ_SB_PENDING: + nc_set_status (i, READ_SB); + stopped_sync++; + break; + case READ_SB_BCCH_PENDING: + nc_set_status (i, READ_SB_BCCH); + stopped_sync++; + break; + } + } + switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status) + { + case READ_FB_SB_PENDING: + nc_set_status (LAST_BSIC_REQ, READ_FB_SB); + stopped_sync++; + break; + } + /*send to L1*/ + if (stopped_sync > 0) + { /* stop all synchronizations */ + PALLOC (stop_req, MPHC_STOP_NCELL_SYNC_REQ); + stop_req->radio_freq_array_size = MAX_L1_SYNC_CNT; + PSENDX(L1, stop_req); + alr_data->nc_data.c_sync_req=0; + } +} +#endif /* 0|1 */ + +#if 0 +Symbol 'nc_stop_all_bcch(void)' not referenced at the moment +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_all_bcch | ++--------------------------------------------------------------------+ + + PURPOSE : This stops all activities to bring a channel to state NC_NULL. + +*/ +LOCAL void nc_stop_all_bcch (void) +{ + UBYTE i, stopped_bcch=0; + /* + * depending on the current status + */ + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + switch (alr_data->nc_data.cell[i].status) + { + case READ_BCCH_PENDING_RR_NOT_INFORMED: + nc_set_status (i, READ_BCCH_RR_NOT_INFORMED); + stopped_bcch++; + break; + case READ_BCCH_PENDING: + nc_set_status (i, READ_BCCH); + stopped_bcch++; + break; + } + } + switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status) + { + case READ_BCCH_PENDING: + nc_set_status (LAST_BSIC_REQ, READ_BCCH); + stopped_bcch++; + break; + } + /*send to L1*/ + if (stopped_bcch > 0) + { /* stop all bcch */ + PALLOC (stop_req, MPHC_STOP_NCELL_BCCH_REQ); + stop_req->radio_freq_array_size = MAX_L1_BCCH_CNT; + PSENDX(L1, stop_req); + alr_data->nc_data.c_bcch_req=0; + } +} +#endif /* 0|1 */ + +LOCAL void nc_clear_last_bsic(void) +{ + switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status) + { + case READ_BCCH_PENDING: + nc_stop_bcch (LAST_BSIC_REQ, IDLE); + break; + case READ_FB_SB_PENDING: + nc_stop_sync (LAST_BSIC_REQ, IDLE); + break; + } + + nc_set_status(LAST_BSIC_REQ, IDLE); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + +} + +LOCAL void nc_stop_if_active(USHORT i) +{ + /* + * the requested channel number is member of the BA list. + * clear a request to layer 1 if needed. + */ + switch(alr_data->nc_data.cell[i].status) + { + case READ_SB_PENDING: + nc_stop_sync (i, READ_SB); + break; + case READ_SB_BCCH_PENDING: + nc_stop_sync (i, READ_SB_BCCH); + break; + case READ_FB_SB_PENDING: + nc_stop_sync (i, READ_FB_SB); + break; + case READ_BCCH_PENDING: + nc_stop_bcch (i, READ_BCCH); + break; + case READ_BCCH_PENDING_RR_NOT_INFORMED: + nc_stop_bcch (i, READ_BCCH_RR_NOT_INFORMED); + break; + default: + break; + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_ncell_list | ++--------------------------------------------------------------------+ + + PURPOSE : Reception of a new neighbourcell list from RR. + +*/ + +GLOBAL void nc_ncell_list (T_MPH_NEIGHBOURCELL_REQ * mph_neighbourcell_req) +{ + UBYTE i, j; + switch (GET_STATE (STATE_NC)) + { + case NC_DEDICATED: + { + UBYTE c_ba_arfcn; + PALLOC (upd_dedi, MPHC_UPDATE_BA_LIST); + + /* + * mix new list with old list + */ + nc_update_ba_list (alr_data->serving_cell, + mph_neighbourcell_req); + + /* + * create new list for layer 1 + */ + c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + for (i = 0, j = 0; i < c_ba_arfcn; i++) + { + if (alr_data->nc_data.cell[i].ba_status EQ IN_BA) + upd_dedi->chan_list.radio_freq[j++] = + ARFCN_TO_L1(alr_data->nc_data.cell[i].ba_arfcn); + } + + /* + * send new list to layer 1 + */ + upd_dedi->num_of_chans = j; + + alr_data->nc_data.ba_id = ALR_ALLOCATE_NEW_BA ( alr_data->nc_data.ba_id ); + upd_dedi->ba_id = alr_data->nc_data.ba_id; + + upd_dedi->pwrc = alr_data->nc_data.pwrc; + upd_dedi->dtx_allowed = alr_data->nc_data.dtx; + + alr_data->nc_data.update = TRUE; + ma_nc_update_ba_list (upd_dedi); + + } + break; + case NC_CON_EST: /*for PBCCH just update the list, is checked in + nc_check_bsic_pbcch */ +#ifdef GPRS + case NC_PIM_PBCCH: + case NC_PTM_PBCCH: + nc_check_bsic_pbcch(mph_neighbourcell_req); +#endif + break; + default: + /* + * idle mode + */ + ALR_TRACE_NC ("ncell req in idle"); + + /* + * mix new list with old list + */ + nc_update_ba_list (alr_data->serving_cell, mph_neighbourcell_req); + + /* + * configure layer 1 and start monitoring on new list + */ + nc_start_monitoring(); + break; + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_start_monitoring | ++--------------------------------------------------------------------+ + + PURPOSE : Configure layer 1 with a new list for neighbourcell + measurements. + +*/ + +static const UBYTE NO_OF_REPORTS [8] = +{ + 10, 7, 5, 4, 3, 3, 2, 2 +}; + +static const UBYTE INIT_OF_C_REPORTS [8] = +{ + 5, 5, 2, 2, 1, 1, 0, 0 /* empirical for FTA 20.7, 20.19, for TC 084, 047 */ +}; + +static BOOL first_period = FALSE, first_l1_meas = FALSE; + +GLOBAL void nc_start_monitoring (void) +{ + USHORT index, prim_index; + UBYTE report_idx = alr_data->bs_pa_mfrms; + UBYTE c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + PALLOC (update, MPHC_RXLEV_PERIODIC_REQ); + + ALR_TRACE_NC ("nc_start_mon"); + + first_period = first_l1_meas = TRUE; + + alr_data->nc_data.max_reports = NO_OF_REPORTS [report_idx]; + alr_data->nc_data.fn_offset = (report_idx+2) * NO_OF_REPORTS[report_idx] * 51; + + if (alr_data->nc_data.c_reports EQ (UBYTE)-1) /* initial value */ + alr_data->nc_data.c_reports = INIT_OF_C_REPORTS [report_idx]; + else /* don´t touch c_reports except for max_reports is less */ + if (alr_data->nc_data.c_reports >= alr_data->nc_data.max_reports) + alr_data->nc_data.c_reports = alr_data->nc_data.max_reports - 1; + index = nc_get_index(alr_data->serving_cell); + if (index NEQ NOT_PRESENT_16BIT) + alr_data->nc_data.cell[index].c_rxlev = NOT_PRESENT_8BIT; + + /* + * for all neighbourcells: convert channel number + * and fill the primitive to layer 1. + */ + for (index = 0, prim_index = 0; index < c_ba_arfcn; index++) + { + if (alr_data->nc_data.cell[index].ba_status EQ IN_BA) + update->chan_list.radio_freq[prim_index++] = + ARFCN_TO_L1(alr_data->nc_data.cell[index].ba_arfcn); + } + + /* + * set number of channels and band id + */ + update->num_of_chans = (UBYTE)prim_index; + alr_data->nc_data.ba_id = ALR_ALLOCATE_NEW_BA ( alr_data->nc_data.ba_id ); + update->ba_id = alr_data->nc_data.ba_id; + update->next_radio_freq_measured = 0; + +#if defined(_SIMULATION_) + { + char buf[80], o; + o = sprintf (buf, "RXLEV_PERIODIC: c=%d id=%02x:", update->num_of_chans, update->ba_id); + for (index=0; index < update->num_of_chans; index++) + { + if (o > 80-6) + { + TRACE_EVENT (buf); + o = 0; + } + o += sprintf (buf+o, "%u,", update->chan_list.radio_freq[index]); + } + buf[o-1]=0; + TRACE_EVENT (buf); + } +#endif /* _SIMULATION_ */ + + SET_STATE (STATE_NC, NC_IDLE); +/* + TRACE_EVENT_P2("glob reps: %d max_report: %d", + alr_data->nc_data.c_reports, alr_data->nc_data.max_reports); +*/ + + /* + * configure layer 1. + */ + ma_nc_rxlev_periodic_req(update); + + nc_enable_conf(); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_enable_conf | ++--------------------------------------------------------------------+ + + PURPOSE : Maintains what happens after 10 seconds interval. + restarts a pending ncell confirmation +*/ +LOCAL void nc_enable_conf(void) +{ + UBYTE tim_state = alr_data->nc_data.tim_state; + UBYTE st = GET_STATE(STATE_NC); + + TRACE_EVENT("nc_enable_conf()"); + alr_data->nc_data.tim_state = NC_CONF_ENABLED; + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + switch(tim_state) + { + case NC_TIM_STOPPED: + if (alr_data->nc_data.ppos_req) + nc_process_pos_req (alr_data->nc_data.ppos_req); + /* Load the 10sec timer counter variable */ + nc_start_ncsync(); + break; + case NC_CONF_PENDING: + if (alr_data->nc_data.ppos_req) + nc_process_pos_req (alr_data->nc_data.ppos_req); + else + nc_start_ncell_confirm(); + break; + case NC_CONF_DISABLED: + if (alr_data->nc_data.ppos_req) + nc_process_pos_req (alr_data->nc_data.ppos_req); + else if (alr_data->nc_data.c_nc_timer EQ 0) + nc_start_ncell_confirm(); /* a confirmation is to restart */ + break; + default: + break; + } + + +/*XXX add PBCCH here also */ +#ifdef GPRS + if ((st EQ NC_DEDICATED OR st EQ NC_PIM_PBCCH OR st EQ NC_PTM_PBCCH) AND +#else + if ((st EQ NC_DEDICATED) AND +#endif + alr_data->nc_data.c_nc_timer > TEN_SECONDS) + { + alr_data->nc_data.c_nc_timer = TEN_SECONDS; + } + else if (alr_data->nc_data.c_nc_timer EQ 0) + { + if( st EQ NC_DEDICATED OR alr_data->nc_data.eotd_avail +#ifdef GPRS + OR st EQ NC_PIM_PBCCH OR st EQ NC_PTM_PBCCH +#endif + ) + alr_data->nc_data.c_nc_timer = TEN_SECONDS; + else + alr_data->nc_data.c_nc_timer = THIRTY_SECONDS; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_disable_conf | ++--------------------------------------------------------------------+ + + PURPOSE : Maintains what happens after TIM_NCSYNC expiry. + prevents ncell confirmation +*/ +LOCAL void nc_disable_conf(BOOL bFree) +{ + TRACE_EVENT("nc_disable_conf()"); + switch(alr_data->nc_data.tim_state) + { + case NC_TIM_STOPPED: + case NC_CONF_PENDING: + TRACE_ERROR("nc_disable_conf() in unexpected state"); + break; + default: + break; + } + + if(bFree AND (alr_data->nc_data.ppos_ind NEQ NULL)) + { + PFREE(alr_data->nc_data.ppos_ind); + alr_data->nc_data.ppos_ind = NULL; + } + + if(GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) + { + /* + * restart confirmation if it was aborted + * after the first expiry after the POS_REQ is done. + */ + alr_data->nc_data.c_nc_timer = 0; + } + + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + alr_data->nc_data.tim_state = NC_CONF_DISABLED; +} + +LOCAL void nc_start_ncell_confirm(void) +{ + BOOL acquire = FALSE; + + switch(GET_STATE(STATE_NC)) + { + case NC_DEDICATED: + case NC_IDLE: +#ifdef GPRS + case NC_PIM_PBCCH: + case NC_PTM_PBCCH: +#endif + if (alr_data->nc_data.eotd_avail AND + alr_data->nc_data.c_nc_timer EQ 0) + { + alr_data->nc_data.c_nc_timer = TEN_SECONDS; + + nc_stop_all(); + nc_check_status(CHECK_FOR_CONFIRM); + nc_start_eotd_confirm(); + } + else if ((alr_data->nc_data.c_nc_timer EQ 0) OR + (alr_data->nc_data.c_sync_intrupted EQ TRUE) ) + { + /* + * confirm ncells every thirty seconds in idle + * or every 10 seconds in dedicated + */ + if (GET_STATE(STATE_NC) EQ NC_DEDICATED +#ifdef GPRS + OR GET_STATE(STATE_NC) EQ NC_PIM_PBCCH + OR GET_STATE(STATE_NC) EQ NC_PTM_PBCCH +#endif + ) + alr_data->nc_data.c_nc_timer = TEN_SECONDS; + else + alr_data->nc_data.c_nc_timer = THIRTY_SECONDS; + nc_stop_all(); + nc_check_status(CHECK_FOR_CONFIRM); + nc_ncell_list_req(); + /* if a list_req was send we are in NC_CONFIRM + if no list_req was send we are in NC_ACQUIRE + This is needed for PBCCH, because there are + no measurements in ALR to trigger the initial + synchronizations, so we have to check this here + if no list_req was send, when a list_req was send + then we continue with initial sync after the last + sync_ind + */ + if(GET_STATE(STATE_NC_PROC) EQ NC_ACQUIRE) + acquire = TRUE; + + } + else /* acquire ncells (initial or previous failed ones) or + * read bcch + */ + { + acquire = TRUE; + } + + if(acquire EQ TRUE) + { + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + nc_check_status(CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL); + nc_process_status(); + } + break; + default: + TRACE_ERROR("nc_ncsync_tim_expiry in wrong state"); + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_start_ncsync | ++--------------------------------------------------------------------+ + PURPOSE : Assigns/resets c_ncsync_tim counter +*/ +LOCAL void nc_start_ncsync (void) +{ + alr_data->nc_data.c_ncsync_tim = TEN_SECONDS_NCSYNC; + TRACE_EVENT("NCSYNC counter loaded with 10 seconds"); + vsi_t_time(VSI_CALLER &alr_data->nc_data.ncsync_start_tim); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_ncsync_tim_expiry | ++--------------------------------------------------------------------+ + PURPOSE : Called at the end of 10 seconds interval for NCELL synchronization + +*/ +GLOBAL void nc_ncsync_tim_expiry(void) +{ + UBYTE i; + UBYTE c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + T_NC* pcell; + + #ifdef GPRS + if(!alr_data->gprs_data.pbcch) + #endif + { + T_TIME tval; + vsi_t_time(VSI_CALLER &tval); + if(tval<alr_data->nc_data.ncsync_start_tim) + TRACE_EVENT_P2("NCSYNC expiry at %d milliseconds, BS_PA_MFRMS = %d", + ULONG_MAX-alr_data->nc_data.ncsync_start_tim+tval, + alr_data->bs_pa_mfrms+2); + else + TRACE_EVENT_P2("NCSYNC expiry at %d milliseconds, BS_PA_MFRMS = %d", + tval-alr_data->nc_data.ncsync_start_tim, + alr_data->bs_pa_mfrms+2); + } + + + + if (alr_data->nc_data.tim_state NEQ NC_TIM_STOPPED) + { + #ifdef GPRS + if(!alr_data->gprs_data.pbcch) + #endif + { + nc_start_ncsync(); + } + + if (alr_data->nc_data.c_nc_timer > 0) + alr_data->nc_data.c_nc_timer--; + TRACE_EVENT_P1("c_nc_timer %d", alr_data->nc_data.c_nc_timer); + + /* decrement counters */ + for (i=0,pcell = &alr_data->nc_data.cell[0]; i < c_ba_arfcn; i++,pcell++) + { + if (pcell->c_sync > 0 AND pcell->c_sync < C_INVALID_SYNC) + pcell->c_sync--; + if (pcell->c_bcch > 0 AND pcell->c_bcch < C_INVALID_BCCH) + pcell->c_bcch--; + + if(pcell->ba_arfcn NEQ alr_data->serving_cell) + { + switch(pcell->ba_status) + { + case NOT_IN_BA_SHORT: + pcell->ba_status = NOT_IN_BA_LONG; +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] -> NOT_IN_BA_LONG", i, pcell->ba_arfcn); +#endif /* TRACING */ + break; + case NOT_IN_BA_LONG: +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] remove", i, pcell->ba_arfcn); + /* this trace must be performed before the removal to get right results */ +#endif /* TRACING */ + c_ba_arfcn = nc_remove_channel_from_ba_list (i); + i--; + pcell--; + ALR_TRACE_ALL_NC (); + break; + case IN_BA: + /* do nothing */ + break; + } + } + } + } + + switch(alr_data->nc_data.tim_state) + { + case NC_CONF_ENABLED: + nc_start_ncell_confirm(); + break; + case NC_CONF_DISABLED: + alr_data->nc_data.tim_state = NC_CONF_PENDING; + break; + case NC_CONF_PENDING: + TRACE_ERROR("TIM_NCSYNC expiry in unexpected state"); + /* + * this should never happen, but in case ALR is waiting + * more than 20 seconds for the last MPHC_NCELL_SYNC_IND of the + * confirmation procedure and the reason isn't a position request, + * then the confirmation procedure is restarted + */ + if (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM AND + alr_data->nc_data.ppos_req EQ NULL) + { + alr_data->nc_data.c_nc_timer = 0; + nc_start_ncell_confirm(); + } + break; + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_init_pos_ind | ++--------------------------------------------------------------------+ + + PURPOSE : initial setting of a MPH_NCELL_POS_IND + +*/ + +LOCAL void nc_init_pos_ind (USHORT req_id) +{ + memset(&(alr_data->nc_data.ppos_ind->eotd_sc_res), 0, sizeof (T_eotd_sc_res )); + memset(&(alr_data->nc_data.ppos_ind->eotd_sc_res1), 0, sizeof (T_eotd_sc_res1)); + alr_data->nc_data.ppos_ind->c_eotd_nc_res = 0; + alr_data->nc_data.ppos_ind->req_id = req_id; + alr_data->nc_data.ppos_ind->eotd_res = 0; +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_is_sync | ++--------------------------------------------------------------------+ + + PURPOSE : checks whether a ncell is synchronized and timing values + are valid + +*/ +LOCAL BOOL nc_is_sync (T_NC * p_ncell) +{ + switch (p_ncell->status) + { + case FB_SB_SYNC: + case READ_SB: + case READ_SB_BCCH: + case READ_BCCH: + case READ_BCCH_RR_NOT_INFORMED: + case IDLE_SYNC: + return TRUE; + default: + return FALSE; + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_ncell_pos_req | ++--------------------------------------------------------------------+ + + PURPOSE : reception of a ncell_pos_req + +*/ + +void nc_ncell_pos_req (T_MPH_NCELL_POS_REQ* pos_req) +{ + /* if there is an earlier position request disgard it*/ + if (alr_data->nc_data.ppos_req NEQ NULL) + PFREE(alr_data->nc_data.ppos_req); + /* store the request until the end of the respective position indication */ + alr_data->nc_data.ppos_req = pos_req; + + /* + * process the request immediately if confirmation is enabled or + * another measurement is in progress + * (otherwise start processing when confirmation becomes enabled + */ + if ( (alr_data->nc_data.tim_state EQ NC_CONF_ENABLED) OR + (alr_data->nc_data.tim_state EQ NC_CONF_DISABLED AND + GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) ) + nc_process_pos_req(pos_req); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_process_pos_req | ++--------------------------------------------------------------------+ + + PURPOSE : processes a ncell_pos_req + +*/ + +LOCAL void nc_process_pos_req (T_MPH_NCELL_POS_REQ* pos_req) +{ + UBYTE fail=1; + + if (alr_data->nc_data.ppos_ind EQ NULL) + { + PALLOC (pos_ind, MPH_NCELL_POS_IND); + alr_data->nc_data.ppos_ind = pos_ind; + } + + nc_init_pos_ind(pos_req->req_id); + +#if 0 /* allow position requests also in NC_IDLE mode to be able to answer a test SMS */ + switch(GET_STATE(STATE_NC)) + { + case NC_DEDICATED: +#endif /* 0|1 */ + if(alr_data->nc_data.eotd_avail) + { + T_NC* p_ncell; + T_ncell_eotd* p_ncell_pos = &pos_req->ncell_eotd[0]; + T_NC* list_of_asd_1o12 [12]; + T_ncell_eotd* list_of_asd_ba [15]; + T_ncell_eotd* list_of_asd [15]; + T_NC** p_asd_1o12 = &list_of_asd_1o12[0]; + T_ncell_eotd** p_asd_ba = &list_of_asd_ba[0]; + T_ncell_eotd** p_asd = &list_of_asd[0]; + UBYTE c_ba = alr_data->nc_data.c_ba_arfcn; + UBYTE i,j; + UBYTE c_list; + UBYTE found; + + fail=0; + + nc_stop_all(); + + /* + * generate and send an appropriate MPHC_NCELL_LIST_SYNC_REQ + * 1/ take all ncells which are in ASD list and the twelve + * strongest synchronized of the BA list (using timing values + * from former synchronisation) + * 2/ then all ncells which are in ASD list and in the BA list + * (using timings from the ASD list) + * 3/ then rest of ASD cells (using timings from the ASD list) + * 4/ then rest of BA list cells which are synchronized (using + * timing values from former synchronisation) + */ + { + PALLOC (ncell_list_req, MPHC_NCELL_LIST_SYNC_REQ); + ncell_list_req->eotd = TRUE; + + /* for all ncells in ASD list */ + for(j=0; j < MAX_NCELL_EOTD_L1 AND j < pos_req->c_ncell_eotd; + j++, p_ncell_pos++) + { + if (p_ncell_pos->arfcn EQ alr_data->serving_cell) + { + continue; + } + /* look if it is in BA list */ + found=FALSE; + for (i = 0, p_ncell = &alr_data->nc_data.cell[0]; i < c_ba; i++, p_ncell++) + { + if(p_ncell_pos->arfcn EQ p_ncell->ba_arfcn) + { + /* + * if it is in both list then check + * if it is synchronized or not + * and use the correct list + */ + if(nc_is_sync(p_ncell)) + { /* case 1/ */ + *(p_asd_1o12++) = p_ncell; + found=TRUE; + } + else + { /* case 2/ */ + *(p_asd_ba++) = p_ncell_pos; + found=TRUE; + } /* is sync */ + break; + } /*arfcn*/ + } /*ba list*/ + + /* if nothing was found, then it is case 3/ */ + if(!found) + *(p_asd++) = p_ncell_pos; + + } /* asd list */ + + c_list=0; + for(i=0; c_list < MAX_L1_SYNC_CNT AND i < p_asd_1o12-list_of_asd_1o12;i++) + { + nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++], + NULL, + list_of_asd_1o12[i]->ba_arfcn); + } /*asd_1o12 */ + for(i=0 ;c_list < MAX_L1_SYNC_CNT AND i < p_asd_ba-list_of_asd_ba;i++) + { + nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++], + list_of_asd_ba[i], + list_of_asd_ba[i]->arfcn); + + } + for(i=0 ;c_list < MAX_L1_SYNC_CNT AND i < p_asd-list_of_asd;i++) + { + nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++], + list_of_asd[i], + list_of_asd[i]->arfcn); + } + /* + * fill the ncell list req with the remaining synchronized + * neigbour cells of the BA list (case 4/ ) + */ + for (i=0, p_ncell = &alr_data->nc_data.cell[0]; + c_list < MAX_L1_SYNC_CNT AND i < c_ba; + i++, p_ncell++) + { + if (p_ncell->ba_arfcn EQ alr_data->serving_cell) + { + continue; + } + if (nc_is_sync(p_ncell)) + { + USHORT l1_arfcn = ARFCN_TO_L1(p_ncell->ba_arfcn); + found=FALSE; + for (j=0; j < c_list;j++) + { + if (ncell_list_req->ncell_list[j].radio_freq EQ l1_arfcn) + { + found = TRUE; + break; + } + } /* MPHC_NCELL_LIST_SYNC_REQ */ + if (!found) + nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++], + NULL, + p_ncell->ba_arfcn); + } /* is sync */ + } /* BA list */ + + if (c_list > 0) + { + ncell_list_req->list_size = c_list; + alr_data->nc_data.c_sync_req = c_list; + if (c_list < MAX_NCELL_EOTD_L1) + memset(&(ncell_list_req->ncell_list[c_list]), + 0, + (MAX_NCELL_EOTD_L1 - c_list) * sizeof(T_ncell_list)); + + alr_data->nc_data.c_sync_req += 2; /* for the 2 scell ind's */ + nc_disable_conf(DONT_FREE_POS_IND); + SET_STATE(STATE_NC_PROC, NC_CONFIRM); + ma_nc_list_sync_req (ncell_list_req); + TRACE_EVENT_P1("MPHC_NCELL_LIST_SYNC_REQ eotd=TRUE c_sync_req=%u", alr_data->nc_data.c_sync_req); + } + else + fail = TRUE; + }/* PALLOC list_req */ + } /* eotd_avail */ + /* else fail=1*/ +#if 0 + break; + default: + /*fail=1*/ + break; + } /*switch NC_STATE*/ +#endif /* 0|1 */ + + if(fail) + { /* TODO complete ?? */ + alr_data->nc_data.ppos_ind->eotd_res = EOTD_REF; + PSENDX(RR, alr_data->nc_data.ppos_ind); + alr_data->nc_data.ppos_ind = NULL; + PFREE(pos_req); + alr_data->nc_data.ppos_req = NULL; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_ncell_list_req_pos | ++--------------------------------------------------------------------+ + + PURPOSE : Handles cell lists. + +*/ + +LOCAL void nc_ncell_list_req_pos(T_ncell_list* p_ncell_list, + T_ncell_eotd* asd_cell, + USHORT arfcn) +{ + USHORT index = nc_get_index(arfcn); + + p_ncell_list->radio_freq = ARFCN_TO_L1(arfcn); + + if(asd_cell) + { + if(index NEQ NOT_PRESENT_16BIT AND index NEQ LAST_BSIC_REQ AND + alr_data->nc_data.cell[index].status EQ IDLE_SYNC) + { + p_ncell_list->fn_offset = alr_data->nc_data.cell[index].frame_offset; + p_ncell_list->time_alignment = alr_data->nc_data.cell[index].time_align; + p_ncell_list->timing_validity = TV_VALID_TIMING_INFO; + /*TODO what about reception of ncell_sync_ind for this cell + are timing info and counter updated ?*/ + } + else + { + nc_get_timing_eotd(p_ncell_list, asd_cell); + p_ncell_list->timing_validity = TV_VALID_TIMING_INFO; /* TV_APPROX_TIMING_INFO;*/ + } + } /*asd_cell*/ + else + { + if(index NEQ NOT_PRESENT_16BIT AND index NEQ LAST_BSIC_REQ) + { + /* cell is in BA list and 1o12, so use the data we have */ + switch(alr_data->nc_data.cell[index].status) + { + case READ_SB_BCCH: + case READ_BCCH: + nc_set_status(index,READ_SB_BCCH_PENDING); + break; + case READ_SB: + case FB_SB_SYNC: + nc_set_status(index,READ_SB_PENDING); + break; + case READ_FB_SB: + case READ_BCCH_RR_NOT_INFORMED: + case FB_SB_SYNC_RR_NOT_INFORMED: + /*TODO what about reception of ncell_sync_ind for this cell + are timing info and counter updated ?*/ + break; + } /*status*/ + p_ncell_list->fn_offset = alr_data->nc_data.cell[index].frame_offset; + p_ncell_list->time_alignment = alr_data->nc_data.cell[index].time_align; + p_ncell_list->timing_validity = TV_VALID_TIMING_INFO; + } + else + { + TRACE_ERROR("nc_ncell_list_req_pos: asd_cell==0 but cell not in BA"); + } + }/*asd_cell*/ +} + +LOCAL void nc_get_timing_eotd(T_ncell_list* p_ncell_list, + T_ncell_eotd* asd_cell) +{ + USHORT td, adjust = 0, offs; + /* + * The values mfrm_offset, rough_rtd and exp_otd are differences + * between the BTS in question and the reference BTS. + * L1 expects the differences between serving BTS and BTS in question: + * + * +----+----+----+----+----+....+----+----+----+----+----+ serving BTS + * 0 51 + * | + * 0 Net | L1 1250 (5000) + * +---->V<----+ + * \ / + * \ / + * +----+----+----+----+----+....+----+----+----+----+----+ BTS in question + * 0 51 + * +-----Net----->| |<---------L1----------------------+ + * + * time differences are indicated in bits by the net, but expected + * in quarterbits by L1 + */ + + offs = asd_cell->mfrm_offset; + + if (asd_cell->otd_type EQ BOTH_OTD) + { + int diff = asd_cell->rough_rtd - asd_cell->exp_otd; + if (diff >= 850) + adjust = 1; + else if (diff <= -850) + adjust = -1; + /* + * GSM 04.31 section A.2.2.3 version 8.7.0 says that adjust shall be + * equal 0 for -400 <= diff <= 400 and states an error for + * -850 < diff < -450 and for 450 < diff < 850, but doesn't + * describe the behaviour in this cases. + * All this valid and invalid cases are implemented here by + * adjust = 0 + */ + } + + if (asd_cell->otd_type EQ ROUGH_OTD) + td = asd_cell->rough_rtd; + else + { /* + * uncertainty indicates how many bits the search window + * for measurement should be opended earlier than the expected + * value. Because of the subsequent subtraction we have to ADD + * the uncertainty value. + * no special handling for uncertainty value 7 (uncertainty > 30 bits) + * is implemented yet + */ + td = asd_cell->exp_otd + unc_values[asd_cell->uncertainty]; + if (td >= 1250) + offs++; + } + td %= 1250; + + if (td) + { + p_ncell_list->time_alignment = 5000 - 4 * td; + offs++; + } + else + p_ncell_list->time_alignment = 0; + + offs = (offs + adjust) % 51; + + if (offs) + p_ncell_list->fn_offset = 51 - offs; + else + p_ncell_list->fn_offset = 0; +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_start_eotd_confirm | ++--------------------------------------------------------------------+ + + PURPOSE : generates an MPHC_NCELL_LIST_SYNC_REQ from the BA list. +*/ +LOCAL void nc_start_eotd_confirm(void) +{ + /* + * this check is needed for the resume + * in the GPRS case because we need + * to keep the states over a + * start transition + */ + if(alr_data->nc_data.ppos_ind EQ NULL) + { + PALLOC (pos_ind, MPH_NCELL_POS_IND); + alr_data->nc_data.ppos_ind = pos_ind; + } + nc_init_pos_ind (NOT_PRESENT_16BIT); + + /* generate and send an appropriate MPHC_NCELL_LIST_SYNC_REQ */ + nc_ncell_list_req(); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_ncell_list_req | ++--------------------------------------------------------------------+ + + PURPOSE : generates an MPHC_NCELL_LIST_SYNC_REQ based on the 12 + strongest neighbour cells of the BA + +*/ +LOCAL void nc_ncell_list_req (void) +{ + UBYTE c_found = 0, found, i, validity; + USHORT c_ba = alr_data->nc_data.c_ba_arfcn; + T_NC* pcell; + T_ncell_list *pnc; + PALLOC (ncell_list_req, MPHC_NCELL_LIST_SYNC_REQ); + + if (alr_data->nc_data.c_sync_req NEQ 0) + TRACE_EVENT_P1("nc_ncell_list_req with c_sync_req=%u before", alr_data->nc_data.c_sync_req); + + ncell_list_req->eotd = alr_data->nc_data.eotd_avail; + + nc_stop_all(); + for (i = 0, pcell = &alr_data->nc_data.cell[0]; i < c_ba; i++, pcell++) + { + if (alr_data->nc_data.eotd_avail AND pcell->ba_arfcn EQ alr_data->serving_cell) + { + continue; + } + if (pcell->one_of_twelve) + { + switch (pcell->status) + { + case READ_SB: + nc_set_status(nc_get_index(pcell->ba_arfcn), READ_SB_PENDING); + found = TRUE; + validity = TV_VALID_TIMING_INFO; + break; + case READ_SB_BCCH: + nc_set_status(nc_get_index(pcell->ba_arfcn), READ_SB_BCCH_PENDING); + found = TRUE; + validity = TV_VALID_TIMING_INFO; + break; + /* TODO(opt): if !eotd_avail maybe optimize later + case READ_FB_SB: + break*/ + /* + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + case READ_BCCH: + case READ_BCCH_PENDING: + found = TRUE; + validity = TV_VALID_TIMING_INFO; + break;*/ + default: + found = FALSE; + validity = TV_INVALID_TIMING_INFO; + break; + } + + if (found) + { + pnc = &(ncell_list_req->ncell_list[c_found++]); + pnc->radio_freq = ARFCN_TO_L1(pcell->ba_arfcn); + if (validity EQ TV_VALID_TIMING_INFO) + { + pnc->fn_offset = pcell->frame_offset; + pnc->time_alignment = pcell->time_align; + } + else + { + pnc->fn_offset = 0; + pnc->time_alignment = 0; + } + pnc->timing_validity = validity; + } + } + } + + /* + * in case there are no synchronized neighbour cells + * send an empty MPHC_NCELL_LIST_SYNC_REQ to L1 + * (to serve the cursor task later with a position indication + * containing measurements of the serving cell only) + */ + if(c_found OR alr_data->nc_data.eotd_avail) + { + ncell_list_req->list_size = c_found; + alr_data->nc_data.c_sync_req = c_found; + if (c_found < MAX_NCELL_EOTD_L1) + memset(&(ncell_list_req->ncell_list[c_found]), + 0, + (MAX_NCELL_EOTD_L1 - c_found) * sizeof(T_ncell_list)); + + if(alr_data->nc_data.eotd_avail) + /* add the 2 scell sync_ind */ + alr_data->nc_data.c_sync_req += 2; + + nc_disable_conf(DONT_FREE_POS_IND); + SET_STATE(STATE_NC_PROC, NC_CONFIRM); + ma_nc_list_sync_req (ncell_list_req); + TRACE_EVENT_P3("MPHC_NCELL_LIST_SYNC_REQ eotd=%d c_sync_req=%u SC=%u", + alr_data->nc_data.eotd_avail, + alr_data->nc_data.c_sync_req, + alr_data->serving_cell); + } + else + { + PFREE(ncell_list_req); + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + nc_enable_conf(); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_store_eotd | ++--------------------------------------------------------------------+ + + PURPOSE : copies the measurement results into the MPH_NCELL_POS_IND + +*/ +LOCAL void nc_store_eotd (T_eotd_sc_res * p_res, + T_MPHC_NCELL_SYNC_IND * sync_ind, + USHORT arfcn) +{ + p_res->sb_flag = sync_ind->sb_flag; + p_res->bsic = sync_ind->bsic; + p_res->arfcn = arfcn; + memcpy(&(p_res->eotd_crosscor), + &(sync_ind->a_eotd_crosscor), + sizeof(sync_ind->a_eotd_crosscor)); + p_res->d_eotd_nrj = sync_ind->d_eotd_nrj; + p_res->time_tag = sync_ind->time_tag; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_ext_meas_ind | ++--------------------------------------------------------------------+ + + PURPOSE : Notify RR about the end of the end of the Extended + Measurement procedure. + +*/ +GLOBAL void nc_stop_ext_meas_ind (void) +{ + PALLOC ( mph_sync_ind, MPH_SYNC_IND ); + mph_sync_ind->cs = CS_STOP_PLMN_SEARCH; + mph_sync_ind->arfcn = NOT_PRESENT_16BIT; + PSENDX ( RR, mph_sync_ind ); + + if( alr_data->cs_data.p_power_cnf NEQ NULL ) + { + PFREE(alr_data->cs_data.p_power_cnf) + alr_data->cs_data.p_power_cnf = NULL; + } + if( IS_EXT_MEAS_RUNNING )/*alr_data->cs_data.mph_ext_meas_req NEQ NULL */ + { + PFREE ( alr_data->cs_data.mph_ext_meas_req ); + alr_data->cs_data.mph_ext_meas_req = NULL; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_rr_activity | ++--------------------------------------------------------------------+ + + PURPOSE : Stop BCCH reading or PLMN seach originated by RR. + +*/ +GLOBAL void nc_stop_rr_activity (UBYTE stop) +{ + /* + * RR signals stop BCCH reading or stop PLMN search + */ + if( (IS_EXT_MEAS_RUNNING) AND + (alr_data->nc_data.cell[LAST_BSIC_REQ].status EQ READ_FB_SB_PENDING) ) + { + /* + * Wait for MPHC_NCELL_SYNC_IND or MPHC_STOP_NCELL_SYNC_CON + */ + alr_data->cs_data.ext_meas_state_pend = CS_ACTIVE_SYNC; + } + nc_clear_last_bsic(); + + /* + * RR signals end of PLMN search + */ + if (stop) + { + alr_data->plmn_search_running = FALSE; + nc_enable_conf(); + } + + if ( IS_EXT_MEAS_RUNNING AND (alr_data->cs_data.ext_meas_state_pend EQ CS_NULL) ) + { + nc_stop_ext_meas_ind(); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8403) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_bsic_req | ++--------------------------------------------------------------------+ + + PURPOSE : Request of RR to search for frequency correction + burst and synchron burst. + +*/ + +GLOBAL void nc_bsic_req (T_MPH_BSIC_REQ *mph_bsic_req) +{ + USHORT i; + + mph_bsic_req->arfcn &= ARFCN_MASK; + ALR_TRACE_NC_BSIC_REQ (mph_bsic_req->arfcn); + + ALR_EM_NEIGHBOURCELL_BSIC_REQUEST; + + nc_clear_last_bsic(); + + /* + * look if the requested channel number is also in the normal + * BA list to stop it. + */ + i = nc_get_index( mph_bsic_req->arfcn ); + + switch(i) + { + case NOT_PRESENT_16BIT: + case LAST_BSIC_REQ: + break; + default: + nc_stop_if_active(i); + TRACE_ERROR("bsic_req for arfcn which is in BA list"); + break; + } + + + /* + * fill in parameters for BSIC request + */ + nc_set_status (LAST_BSIC_REQ, READ_FB_SB); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = mph_bsic_req->arfcn; + + /* + * forward synchronisation request to layer 1, if not full + */ + if (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT) + { + /* + * reset if we are in NC_CON_EST + */ + + if(GET_STATE(STATE_NC) EQ NC_CON_EST +#ifdef GPRS + AND !alr_data->gprs_data.pbcch +#endif + ) + { + SET_STATE(STATE_NC, NC_IDLE); + } +#ifdef GPRS + else if(GET_STATE(STATE_NC) EQ NC_CON_EST AND + alr_data->gprs_data.pbcch) /* AND */ +/* add later alr_data->gprs_data.pim) */ + { + SET_STATE(STATE_NC, NC_PIM_PBCCH); + } +#endif + + nc_process_status (); + } + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_bcch_ind | ++--------------------------------------------------------------------+ + + PURPOSE : Reception of a system information message for a neighbourcell. + +*/ + +GLOBAL void nc_bcch_ind (T_MPHC_NCELL_BCCH_IND *data_ind) +{ + USHORT index; + UBYTE msg_t = data_ind->l2_frame.content[SI_CONTENTS_MSG_T]; + + if (alr_data->nc_data.cell[LAST_BSIC_REQ].status EQ READ_BCCH_PENDING AND + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn EQ ARFCN_TO_G23(data_ind->radio_freq)) + { + /* + * Cell selection or PLMN available search triggered by RR. + */ + if (data_ind->error_flag NEQ VALID_BLOCK) + { + /* + * Reception of an invalid block + */ + ALR_TRACE_NC ("invalid PLMN BCCH"); + + /* + * indicate BCCH read error to RR, too many errors are controlled by RR + */ + ma_error_ind (CS_BCCH_READ_ERROR, ARFCN_TO_G23(data_ind->radio_freq)); + } + else + { + UBYTE mt = data_ind->l2_frame.content[2]; + + ALR_TRACE_NC ("valid PLMN BCCH"); + + /* + * forward message to RR + */ + ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind); + + switch (mt) + { + case D_SYS_INFO_3: + case D_SYS_INFO_4: + alr_data->nc_data.cell[LAST_BSIC_REQ].blocks_required = 0; + break; + + default: + /* + * Reception of any other message. Shall not happen after + * GSM 5.02 chapter 6.3.1.3 Mapping of BCCH data, but + * is possible for future extensions. + * Read this tc again plus all which are not read until now. + */ + break; + } + } + + /* + * all frames received, then decrement pending BCCH request + */ + if (alr_data->nc_data.cell[LAST_BSIC_REQ].blocks_required EQ 0) + { + + nc_set_status (LAST_BSIC_REQ, IDLE); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + + /* + * L3 may avoid sending a stop message to terminate a NCELL_BCCH process + * if there no more pending request in L1 + */ + if (alr_data->nc_data.c_bcch_req > 0) + { + /* + * stop any ongoing request in layer 1 + */ + ma_nc_stop_ncell_bcch_req(ARFCN_TO_G23(data_ind->radio_freq)); + + /* + * decrement the number of pending requests in layer 1. + */ + alr_data->nc_data.c_bcch_req--; + } + } + else + { + /* + * stop pending request and start again. + */ + nc_restart_bcch (LAST_BSIC_REQ); + } + return ; + } + + /* + * Normal Ncell Handling, get position in neighbourcell list + */ + index = nc_get_index (ARFCN_TO_G23(data_ind->radio_freq)); + + if (index NEQ NOT_PRESENT_16BIT AND + index NEQ LAST_BSIC_REQ AND + (alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING OR + alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED)) + { + /* + * normal member of the neighbourcell list and an answer is expected. + */ + if (data_ind->error_flag EQ VALID_BLOCK) + { + switch (msg_t) + { + case D_SYS_INFO_3: + /* + * Sys Info 3 contains the needed information in any case + */ +#if defined(TRACING) + TRACE_EVENT_P3("NC%u[%d] BCCH ok %s", + index, + alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ? + -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si3"); +#endif /* TRACING */ + if (alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED) + { + /* + * store data if RR is not informed yet about + * synchronisation + */ + nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,0); + nc_set_status (index, FB_SB_SYNC_RR_NOT_INFORMED); + } + else + { + /* + * forward information to RR + */ + ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind); + nc_set_fb_sb_sync_initial (index); + + } + break; + + case D_SYS_INFO_4: + if ((data_ind->l2_frame.content[SI_CONTENTS_CS2] & ONLY_ACS) EQ 0) + { +#if defined(TRACING) + TRACE_EVENT_P3("NC%u[%d] BCCH ok %s", + index, + alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ? + -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si4"); +#endif /* TRACING */ + /* + * additional cell selection info from sys info 7 or 8 is not necessary + */ + if (alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED) + { + /* + * store data if RR is not informed yet about synchronisation + */ + nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,0); + nc_set_status (index, FB_SB_SYNC_RR_NOT_INFORMED); + } + else + { + /* + * forward information to RR + */ + ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind); + nc_set_fb_sb_sync_initial (index); + + } + } + else + { +#if defined(TRACING) + TRACE_EVENT_P3("NC%u[%d] BCCH ok %s", + index, + alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ? + -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si4_n78"); +#endif /* TRACING */ + /* + * additional information from system info 7 or 8 + * is needed for cell reselection purposes + */ + if(alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED) + { + /* + * store data if RR is not informed yet about synchronisation + */ + nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,0); + } + else + { + /* + * forward information to RR + */ + ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind); + } + + /* + * system info 3, 7 or 8 required + * -> tc = 2,6 for normal BCCH or 3,7 for extended BCCH + */ + alr_data->nc_data.cell[index].blocks_required = NCELL_BCCH_SI_3_7_8; + } + break; + + case D_SYS_INFO_7: + case D_SYS_INFO_8: + if (nc_sys_info_78_required (index)) + { +#if defined(TRACING) + TRACE_EVENT_P3("NC%u[%d] BCCH ok %s", + index, + alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ? + -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si78"); +#endif /* TRACING */ + if(alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED) + { + /* + * store data if RR is not informed yet about synchronisation + */ + nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,1); + nc_set_status (index, FB_SB_SYNC_RR_NOT_INFORMED); + } + else + { + /* + * forward information to RR + */ + ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind); + nc_set_fb_sb_sync_initial (index); + + } + } + else + /* + * increment error counter and request tc again. + */ + alr_data->nc_data.cell[index].c_error++; + + break; + + default: + /* + * increment error counter and request tc again. + */ + alr_data->nc_data.cell[index].c_error++; + break; + } + } + else + { + /* + * BCCH reading failed + * + * error counter is incremented and tc shall be read again. + */ + alr_data->nc_data.cell[index].c_error++; + } + + /* + * restart next attempt + */ + if (alr_data->nc_data.cell[index].blocks_required EQ 0) + { + if (alr_data->nc_data.c_bcch_req > 0) + { + /* + * decrement number of pending BCCH requests in layer 1. + */ + alr_data->nc_data.c_bcch_req--; + + /* + * Stop the pending reading, if not all tc-s read + */ + ma_nc_stop_ncell_bcch_req (alr_data->nc_data.cell[index].ba_arfcn); + } + alr_data->nc_data.cell[index].c_attempt = 0; + + /* + * start next request to layer 1 if necessary + */ + nc_process_status (); + } + else + { + if (alr_data->nc_data.cell[index].c_error >= 4) + { + /* + * set status to failed or excluded depending on the failed + * attempt counter and/or restart for this channel. + */ + nc_sync_failed_attempt (index); + + /* + * L3 may avoid sending a stop message to terminate a NCELL_BCCH process + * if there no more pending request in L1 + */ + if (alr_data->nc_data.c_bcch_req > 0) + { + /* + * decrement number of pending BCCH requests in layer 1. + */ + alr_data->nc_data.c_bcch_req--; + + /* + * Stop the pending reading, if not all tc-s read + */ + ma_nc_stop_ncell_bcch_req (alr_data->nc_data.cell[index].ba_arfcn); + } + + /* + * start next request to layer 1 if necessary + */ + nc_process_status (); + } + else + { + /* + * restart the BCCH reading for this TC again. + */ + nc_restart_bcch (index); + } + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_restart_bcch | ++--------------------------------------------------------------------+ + + PURPOSE : Stop old request and start new request to layer 1. + +*/ + +LOCAL void nc_restart_bcch (USHORT index) +{ + PALLOC (ncell_bcch, MPHC_NCELL_BCCH_REQ); + + if (alr_data->nc_data.c_bcch_req > 0) + { + /* + * if necessary stop previous request to avoid on the fly change + */ + ma_nc_stop_ncell_bcch_req(alr_data->nc_data.cell[index].ba_arfcn); + } + + ncell_bcch->radio_freq = ARFCN_TO_L1(alr_data->nc_data.cell[index].ba_arfcn); + ncell_bcch->fn_offset = alr_data->nc_data.cell[index].frame_offset; + ncell_bcch->time_alignment = alr_data->nc_data.cell[index].time_align; + ncell_bcch->tsc = (UBYTE)(alr_data->nc_data.cell[index].bsic & ONLY_BCC); + ncell_bcch->bcch_blocks_required = alr_data->nc_data.cell[index].blocks_required; +#ifdef GPRS + /*if the mobile is in PTM the GPRS_PRIORITY must be set to TOP*/ + if(ma_is_ptm()) + { + ncell_bcch->gprs_prio = GPRS_PRIO_TOP; + } + else +#endif + ncell_bcch->gprs_prio = GPRS_PRIO_NORM; + + /* + * and start next request + */ + ma_nc_bcch_req (ncell_bcch); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_store_sync_ind | ++--------------------------------------------------------------------+ + + PURPOSE : stores the data of an MPHC_NCELL_SYNC_IND end enters + a new state of ncell. + +*/ + +LOCAL void nc_store_sync_ind (USHORT index, + T_MPHC_NCELL_SYNC_IND *sync_ind, + UBYTE new_status) +{ + T_NC* pcell = &alr_data->nc_data.cell[index]; + pcell->bsic = (UBYTE)(sync_ind->bsic & ONLY_BSIC); + pcell->frame_offset = sync_ind->fn_offset; + pcell->time_align = sync_ind->time_alignment; + pcell->tim_valid = TV_VALID_TIMING_INFO; + nc_set_status (index, new_status); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_sync_ind | ++--------------------------------------------------------------------+ + + PURPOSE : Confirmation for a synchronisation request to layer 1. + +*/ + +GLOBAL void nc_sync_ind (T_MPHC_NCELL_SYNC_IND *sync_ind) +{ + USHORT index; + UBYTE bsic = (UBYTE)(sync_ind->bsic & ONLY_BSIC); + USHORT arfcn = ARFCN_TO_G23(sync_ind->radio_freq)&ARFCN_MASK; + index = nc_get_index (arfcn); + + switch (GET_STATE (STATE_NC)) + { + case NC_IDLE: + case NC_DEDICATED: +#ifdef GPRS + case NC_PIM_PBCCH: + case NC_PTM_PBCCH: /*XXX*/ +#endif + TRACE_EVENT_P5("nc_sync_ind[%d] sb_flag=%d fn_offset=%ld time_alignment=%ld bsic=%d", + arfcn, sync_ind->sb_flag, sync_ind->fn_offset, + sync_ind->time_alignment, sync_ind->bsic); + if (alr_data->nc_data.c_sync_req > 0) + alr_data->nc_data.c_sync_req--; + + if (alr_data->nc_data.cell[LAST_BSIC_REQ].status EQ READ_FB_SB_PENDING AND + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn EQ arfcn AND +#ifdef GPRS + (GET_STATE(STATE_NC) EQ NC_IDLE OR GET_STATE(STATE_NC) EQ NC_PIM_PBCCH) + ) +#else + GET_STATE(STATE_NC) EQ NC_IDLE + ) +#endif + { + nc_sync_ind_last_bsic_req(sync_ind,index,arfcn,bsic); + } + else + { + if (index NEQ NOT_PRESENT_16BIT AND + index NEQ LAST_BSIC_REQ) + { + nc_sync_ind_ncell(sync_ind,index,arfcn,bsic); + } /* valid index check */ + else if (alr_data->nc_data.eotd_avail AND + alr_data->nc_data.ppos_ind NEQ NULL) + nc_check_sync_ind_eotd(sync_ind, arfcn); + /* LAST_BSIC_REQ check */ + else if ( (index EQ NOT_PRESENT_16BIT) AND (IS_EXT_MEAS_RUNNING) AND + (GET_STATE(STATE_NC) EQ NC_IDLE)) + { + if ( alr_data->cs_data.ext_meas_state_pend NEQ CS_NULL ) + { + nc_stop_ext_meas_ind(); + alr_data->cs_data.ext_meas_state_pend = CS_NULL; + return; + } + } + } + + if( alr_data->nc_data.c_sync_intrupted EQ TRUE AND alr_data->nc_data.c_sync_req EQ 0) + { + nc_enable_conf(); + alr_data->nc_data.c_sync_intrupted = FALSE; + } + + if(GET_STATE(STATE_NC_PROC) EQ NC_ACQUIRE) + { + nc_process_status(); + } + + break; + default: + break; + } /* STATE_NC */ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_sync_ind_last_bsic_req | ++--------------------------------------------------------------------+ + + PURPOSE : Confirmation of the LAST_BSIC_REQ synchronisation request + +*/ + +LOCAL void nc_sync_ind_last_bsic_req(T_MPHC_NCELL_SYNC_IND* sync_ind, + USHORT index, + USHORT arfcn, + UBYTE bsic) +{ + + /* + * decoding of FB / SB of hplmn cell is in progress + * send confirmation to RR. + */ + PALLOC (mph_bsic_cnf, MPH_BSIC_CNF); + + mph_bsic_cnf->arfcn = arfcn; + mph_bsic_cnf->bsic = bsic; + + if (sync_ind->sb_flag EQ SB_FOUND) + { + ALR_TRACE_NC_BSIC_CNF(sync_ind->radio_freq); + + /* + * FCB and SCB found, set result code + */ + mph_bsic_cnf->cs = CS_NO_ERROR; + + if ( IS_EXT_MEAS_RUNNING ) + { + nc_set_status (LAST_BSIC_REQ, IDLE); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + + if ( alr_data->cs_data.ext_meas_state_pend NEQ CS_NULL ) + { + PFREE ( mph_bsic_cnf ); + nc_stop_ext_meas_ind(); + } + else + { + ma_bsic_cnf (mph_bsic_cnf); + } + return; + } + + ALR_EM_NEIGHBOURCELL_BCCH(EM_AVAIL); + + /* save data for next cell reselection */ + { + T_NC *pcr_cell = &alr_data->nc_data.cr_cell; + pcr_cell->ba_arfcn = arfcn; + pcr_cell->bsic = bsic; + pcr_cell->frame_offset = sync_ind->fn_offset; + pcr_cell->time_align = sync_ind->time_alignment; + } + + ma_bsic_cnf (mph_bsic_cnf); + + nc_store_sync_ind (LAST_BSIC_REQ, sync_ind, READ_BCCH); +#ifdef GPRS + /* don't do the next checks for PBCCH just return + * maybe later TODO(opt) + */ + if (GET_STATE (STATE_NC) EQ NC_PIM_PBCCH OR + GET_STATE (STATE_NC) EQ NC_PTM_PBCCH) + { + return; + } +#endif + + index = nc_get_index (arfcn); + + if(index NEQ LAST_BSIC_REQ AND + index NEQ NOT_PRESENT_16BIT) + { + /* + * check BSIC of the incoming BCCH message + */ + switch (nc_check_bsic (index, bsic)) + { + case NC_CHECK_OK: + /* + * channel has passed NCC permitted check. + */ + switch (alr_data->nc_data.cell[index].status) + { + + case IDLE: + /* This patch helps during parallel search in Limited service. + * Cell synchronised in the last BSIC_REQ fromm RR during parallel + * search is also a part of BA list. In such a case, we store the + * synchrinisation information, so that its can be used later by + * nc_start_reselect. + */ + if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + else + nc_store_sync_ind (index, sync_ind, IDLE_SYNC); + break; + + case READ_FB_SB: + /* + * the channel shall start synchronisation of FB/SB + * so reading of BCCH shall be started. + */ + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + else if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + break; + + case READ_SB: + /* + * the channel shall start synchronisation of SB + * so this is done. + */ + if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + break; + + case FB_SB_FAILED: + /* + * A channel synchronisation has failed in the past. + * Now it is synchronized again. Start BCCH reading + * and send this information to RR after indicating + * the synchronisation with next measurement report. + */ + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + else if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + break; + + + case READ_SB_BCCH: + /* + * the channel shall start synchronisation of SB + * followed by BCCH reading. SB synchronisation + * is done. + */ + if(alr_data->nc_data.cell[index].one_of_six) + nc_store_sync_ind (index, sync_ind, READ_BCCH); + break; + + case READ_FB_SB_PENDING: + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + case READ_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + /* + * REMARK: this shall not happen, because this + * attempt shall be killed if RR requests + * procedure for the channel. + */ + ALR_TRACE_NC ("Abnormal situation sync ind"); + break; + + default: + break; + } + break; + + case NC_CHECK_BSIC_CHANGED: + /* + * BSIC of the channel has changed. + */ + switch (alr_data->nc_data.cell[index].status) + { + case READ_SB: + /* + * the channel shall start synchronisation of SB + * so this is done, but a changed BSIC is stored. + * Read BCCH of the channel and forward to RR. + */ + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + else if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + break; + + case FB_SB_FAILED: + /* + * A channel synchronisation has failed in the past. + * Now it is synchronized again. Start BCCH reading + * and send this information to RR after indicating + * the synchronisation with next measurement report. + */ + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + else if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + break; + + case READ_SB_BCCH: + /* + * the channel shall start synchronisation of SB + * followed by BCCH reading. SB synchronisation + * is done. Read BCCH of the channel and forward to RR. + */ + if(alr_data->nc_data.cell[index].one_of_six) + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + break; + + case READ_FB_SB: + case READ_FB_SB_PENDING: + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + case READ_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + /* + * REMARK: this shall not happen, because this + * attempt shall be killed if RR requests + * procedure for the channel. + */ + ALR_TRACE_NC ("Abnormal situation sync ind (changed BSIC)"); + break; + + default: + break; + } + break; + + case NC_CHECK_NCC_FAILED: + /* + * ncc permitted check failed + */ + nc_set_status (index, EXCLUDED); + break; + + default: + break; + } + } + + ALR_EM_NEIGHBOURCELL_BSIC_CONFIRM(EM_AVAIL); + + } + else + { + /* + * FCB and SCB not found, set result code, + * mark cell[LAST_BSIC_REQ] and cr_cell as invalid + * and send negative answer to RR + */ + mph_bsic_cnf->cs = CS_NO_BCCH_AVAIL; + nc_set_status (LAST_BSIC_REQ, IDLE); + alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT; + alr_data->nc_data.cr_cell.ba_arfcn = NOT_PRESENT_16BIT; + + ma_bsic_cnf (mph_bsic_cnf); + + ALR_EM_NEIGHBOURCELL_BSIC_CONFIRM(EM_NOT_AVAIL); + + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_sync_ind_ncell | ++--------------------------------------------------------------------+ + + PURPOSE : Confirmation of a ncell synchronisation request + +*/ + +LOCAL void nc_sync_ind_ncell(T_MPHC_NCELL_SYNC_IND* sync_ind, + USHORT index, + USHORT arfcn, + UBYTE bsic) +{ +#ifdef GPRS + BOOL bsic_chg = FALSE; +#endif + + if (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) + { + /* eotd confirmation is active */ + if(alr_data->nc_data.eotd_avail) + nc_check_sync_ind_eotd(sync_ind, arfcn); + + TRACE_EVENT_P2("sync_ind[%u] c_sync_req=%u", arfcn, alr_data->nc_data.c_sync_req); + /* + * check if the end of the CONFIRM procedure (LIST_REQ) is + * reached + * this is done here because it is independent from EOTD + */ + if(alr_data->nc_data.c_sync_req EQ 0) + { + nc_enable_conf(); + } + /* + * skip the rest of this function for scell + * because the status for the scell is always FB_SB_SYNC + */ + if(alr_data->nc_data.eotd_avail AND + arfcn EQ alr_data->serving_cell) + return; + } + + if (sync_ind->sb_flag EQ SB_FOUND) + { + /* + * Synchronization successful for a normal member of the BA list. + */ + ALR_TRACE_NC_SB_IND_PASSED(arfcn); + + ALR_EM_NEIGHBOURCELL_SB(EM_AVAIL); + + switch (GET_STATE (STATE_NC)) + { + case NC_IDLE: + case NC_DEDICATED: + /* + * check neighbourcell + */ + switch (nc_check_bsic (index, bsic)) + { + case NC_CHECK_OK: + /* + * channel has passed NCC permitted check. + */ + switch (alr_data->nc_data.cell[index].status) + { + case READ_FB_SB_PENDING: + /* + * initial synchronization to FB and SB + * if the cell is a 1o6 we read the BCCH + * otherwise we just set it to synchronized + */ + + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + { + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + } + else if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + else + { + TRACE_EVENT_P1("sync ind for not 1o12 cell %d", arfcn); + } + break; + + case READ_SB_PENDING: + /* + * confirmation of SB + */ + alr_data->nc_data.cell[index].c_attempt = 0; + if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + else + nc_store_sync_ind (index, sync_ind, IDLE_SYNC); + break; + + case READ_SB_BCCH_PENDING: + /* + * confirmation of SB before reading + * neighbour cell BCCH all five minutes. + */ + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) EQ NC_IDLE) + { + nc_store_sync_ind (index, sync_ind, READ_BCCH); + } + else + { + alr_data->nc_data.cell[index].c_attempt = 0; + if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + else + nc_store_sync_ind (index, sync_ind, IDLE_SYNC); + } + break; + case READ_BCCH_RR_NOT_INFORMED: /*TODO(opt)*/ + case READ_BCCH_PENDING_RR_NOT_INFORMED:/*TODO(opt)*/ + case READ_BCCH:/*TODO(opt)*/ + case READ_BCCH_PENDING:/*TODO(opt)*/ + TRACE_ERROR("sync_ind for ncell in READ_BCCH*"); + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) EQ NC_IDLE) + { + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + } + break; + default: + break; + } /*switch(status)*/ + break; + case NC_CHECK_BSIC_CHANGED: + /* + * channel has passed NCC permitted check, + * but a changed BSIC has been detected. + */ + switch (alr_data->nc_data.cell[index].status) + { + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + /* + * confirmation of SB indicates new BSIC + */ + if(alr_data->nc_data.cell[index].one_of_six AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + { + nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED); + } + else if(alr_data->nc_data.cell[index].one_of_twelve) + { + alr_data->nc_data.cell[index].c_attempt = 0; + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + } + else + { + TRACE_EVENT_P1("sync ind for not 1o12 cell %d", arfcn); + nc_store_sync_ind (index, sync_ind, IDLE_SYNC); + } + break; + + default: + break; + } /*switch(status)*/ + break; + + case NC_CHECK_NCC_FAILED: + /* + * ncc permitted check failed. Attempt again. + * BSIC of a cell may always change. So do not + * exclude this cell in IDLE mode meaurements + */ + if(GET_STATE(STATE_NC) EQ NC_IDLE) + { + alr_data->nc_data.cell[index].c_attempt = 0; + nc_set_fb_sb_failed (index, TEN_SECONDS); + } + else if(GET_STATE(STATE_NC) EQ NC_DEDICATED) + { + alr_data->nc_data.cell[index].c_attempt = 0; + nc_set_fb_sb_failed (index, THIRTY_SECONDS); + } + else + { + nc_set_status (index, EXCLUDED); + } + break; + } + break; +#ifdef GPRS + case NC_PIM_PBCCH: + case NC_PTM_PBCCH: /*XXX*/ + TRACE_EVENT("sync_ind PBCCH"); + switch (alr_data->nc_data.cell[index].status) + { + case READ_FB_SB_PENDING: + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + nc_inform_grr_of_ncell(index, GRR_SB_FOUND); + break; + case READ_SB_PENDING: + if(bsic NEQ alr_data->nc_data.cell[index].bsic) + bsic_chg = TRUE; + else + bsic_chg = FALSE; + + if(alr_data->nc_data.cell[index].one_of_twelve) + nc_store_sync_ind (index, sync_ind, FB_SB_SYNC); + else + nc_store_sync_ind (index, sync_ind, IDLE_SYNC); + + if(bsic_chg) + nc_inform_grr_of_ncell(index, GRR_SB_FOUND); + break; + default: + break; + } + break; + default: + break; +#endif + } /* NC_STATE */ + } + else /* sb_flag EQ FALSE */ + { + /* + * Synchronization failed + */ + ALR_TRACE_NC_SB_FAILED (sync_ind->radio_freq); + if (alr_data->nc_data.cell[index].ba_status EQ IN_BA) + { + switch (alr_data->nc_data.cell[index].status) + { + case READ_FB_SB_PENDING: + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + + ALR_EM_NEIGHBOURCELL_SB(EM_NOT_AVAIL); + + if(GET_STATE(STATE_NC) EQ NC_IDLE) + nc_sync_failed_attempt(index); + else if(GET_STATE(STATE_NC) EQ NC_DEDICATED) + nc_sync_failed_attempt_dedicated(index); +#ifdef GPRS /*XXX*/ + else + nc_sync_failed_gprs(index); +#endif + break; + default: + break; + } + } + else + { /* + * the cell currently or perhaps for a longer time doesn't + * belong to the BA list, no more attempts to synchronize now + */ + switch (alr_data->nc_data.cell[index].status) + { + case READ_FB_SB_PENDING: + nc_set_status (index, IDLE); + break; + case READ_SB_PENDING: + alr_data->nc_data.cell[index].c_attempt++; + alr_data->nc_data.cell[index].tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (index, READ_SB); + break; + case READ_SB_BCCH_PENDING: + alr_data->nc_data.cell[index].c_attempt++; + alr_data->nc_data.cell[index].tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (index, READ_SB_BCCH); + break; + default: + break; + } + } + } /* error_flag check */ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_check_sync_ind_eotd | ++--------------------------------------------------------------------+ + + PURPOSE : copies the measurement results to the MPH_NCELL_POS_IND + while EOTD is active + +*/ +LOCAL void nc_check_sync_ind_eotd (T_MPHC_NCELL_SYNC_IND* sync_ind, USHORT arfcn) +{ + T_MPH_NCELL_POS_IND* ppos_ind; + + if ((ppos_ind = alr_data->nc_data.ppos_ind) EQ NULL) + { + TRACE_ERROR("nc_check_sync_ind_eotd() while alr_data->nc_data.ppos_ind==0"); + return; + } + + if (arfcn EQ alr_data->serving_cell) + { + if (ppos_ind->eotd_res EQ 0) /*0 doesn't mean EOTD_SUCC here + - it indicates that no SC results are present*/ + { + nc_store_eotd(&(ppos_ind->eotd_sc_res), sync_ind, arfcn); + ppos_ind->fn = sync_ind->fn_in_sb; + ppos_ind->eotd_res++; + } + else /*first EOTD results for SC are already present + - now continue with second SC results*/ + { + nc_store_eotd((T_eotd_sc_res*)(&(ppos_ind->eotd_sc_res1)), sync_ind, + arfcn); + ppos_ind->eotd_res = EOTD_SUCC; + ppos_ind->ta = GET_STATE(STATE_NC) EQ NC_DEDICATED ? + alr_data->nc_data.tav : NOT_PRESENT_8BIT; + PSENDX (RR, ppos_ind); + alr_data->nc_data.ppos_ind = NULL; + + if (alr_data->nc_data.ppos_req NEQ NULL) + { + PFREE(alr_data->nc_data.ppos_req); + alr_data->nc_data.ppos_req = NULL; + } + } + } + else + { + if (ppos_ind->c_eotd_nc_res < MAX_NCELL_EOTD_RES) + { + nc_store_eotd((T_eotd_sc_res*)( + &(ppos_ind->eotd_nc_res[ppos_ind->c_eotd_nc_res])) , sync_ind, arfcn); + (ppos_ind->c_eotd_nc_res)++; + } + else + TRACE_ERROR("more than MAX_NCELL_EOTD_RES ncell sync indications"); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_sync_failed_attempt | ++--------------------------------------------------------------------+ + + PURPOSE : A synchronisation attempt has failed during idle mode. + +*/ +LOCAL void nc_sync_failed_attempt (USHORT index) +{ + switch (alr_data->nc_data.cell[index].c_attempt) + { + case 0: + case 1: + case 2: + case 3: + /* + * for attempts 1 to 4 try it again + * after ten seconds + */ + nc_set_fb_sb_failed (index, TEN_SECONDS); + + break; + default: + /* + * if there are more attempts, exclude + * the cell from further attempts + * Store last fieldstrength value + */ + nc_set_status (index, EXCLUDED); + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_sync_failed_attempt_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : A synchronisation attempt has failed during dedicated mode. + +*/ +LOCAL void nc_sync_failed_attempt_dedicated (USHORT index) +{ + /* + * Store last fieldstrength value + */ + switch (alr_data->nc_data.cell[index].c_attempt) + { + case 0: + case 1: + case 2: + /* + * for attempts 1 to 3 try it again immediately + */ + alr_data->nc_data.cell[index].c_attempt++; + if (alr_data->nc_data.cell[index].status EQ READ_FB_SB_PENDING) + alr_data->nc_data.cell[index].tim_valid = TV_INVALID_TIMING_INFO; + else + alr_data->nc_data.cell[index].tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (index, READ_FB_SB); + break; + default: + /* + * if there are more attempts, exclude + * the cell from further attempts + */ + nc_set_status (index, EXCLUDED); + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_start_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : Process signal nc_start_dedicated from SDL process + Main_Control. + +*/ + +GLOBAL void nc_start_dedicated (UBYTE pwrc, UBYTE dtx) +{ + USHORT i; + + switch(GET_STATE(STATE_NC)) + { + case NC_CON_EST: + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + switch (alr_data->nc_data.cell[i].status) + { + case READ_BCCH_RR_NOT_INFORMED: + case FB_SB_SYNC_RR_NOT_INFORMED: + case READ_BCCH: + /* + * BCCH reading is not needed during dedicated mode, + * but SB synchronisation is already done. + * clear a stored BCCH if needed. + */ + nc_set_status (i, FB_SB_SYNC); + break; + + case READ_SB_BCCH: + nc_set_status (i, READ_SB); + break; + + case READ_FB_SB_PENDING: + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + case READ_BCCH_PENDING: + TRACE_ERROR("Abnormal situation nc_start_dedi"); + nc_set_status (i, IDLE); + break; + case FB_SB_FAILED: + nc_set_status (i, IDLE); + break; + case IDLE_SYNC: + if (alr_data->nc_data.cell[i].c_sync > 0) + alr_data->nc_data.cell[i].c_sync = TEN_SECONDS; + break; + default: + break; + } + } + + nc_clear_last_bsic(); + + alr_data->nc_data.pwrc = pwrc; + alr_data->nc_data.dtx = dtx; + + SET_STATE (STATE_NC, NC_DEDICATED); + nc_enable_conf(); + break; + default: + TRACE_ERROR("nc_start_dedicated in wrong state"); + break; + } + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_suspend | ++--------------------------------------------------------------------+ + + PURPOSE : This stops all active processes like FB/SB and BCCH reading + if + - the mobile start connection establishment + - RR requests power measurements parallel to idle mode + - leave dedicated mode. + +*/ + +GLOBAL void nc_suspend (void) +{ + ALR_TRACE_NC( "nc_suspend"); + + switch (GET_STATE(STATE_NC)) + { + case NC_IDLE: + case NC_DEDICATED: + nc_clear_last_bsic(); + nc_stop_all(); + nc_disable_conf(FREE_POS_IND); + + SET_STATE(STATE_NC, NC_CON_EST); + break; + case NC_CON_EST: + break; +#ifdef GPRS + case NC_PIM_PBCCH: + if(alr_data->nc_data.cell[LAST_BSIC_REQ].status NEQ IDLE) + nc_clear_last_bsic(); + /*lint -fallthrough*/ + case NC_PTM_PBCCH: + nc_stop_all(); + nc_disable_conf(FREE_POS_IND); + SET_STATE(STATE_NC, NC_CON_EST); + break; +#endif + default: + break; + } +} + +GLOBAL void nc_suspend_handover (void) +{ + ALR_TRACE_NC( "nc_suspend_handover"); + + switch (GET_STATE(STATE_NC)) + { + case NC_DEDICATED: + nc_stop_all(); + nc_disable_conf(FREE_POS_IND); + break; + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : alr_nc | +| STATE : code ROUTINE : nc_resume | ++--------------------------------------------------------------------+ + + PURPOSE : Only needed for alr_gprs.c + +*/ + +GLOBAL void nc_resume (void) +{ + SET_STATE (STATE_NC, NC_IDLE); + nc_enable_conf(); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_update_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : Process signal nc_update_dedicated from SDL process + Dedi_Control. + +*/ + +GLOBAL void nc_update_dedicated (UBYTE dtx, UBYTE pwrc) +{ + UBYTE i, j; + UBYTE c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + + switch(GET_STATE (STATE_NC)) + { + case NC_DEDICATED: + { + PALLOC (upd_dedi, MPHC_UPDATE_BA_LIST); + + /* + * updated values of pwrc or dtx can be configure + * only by sending a new neighbourcell list to layer 1 + */ + alr_data->nc_data.pwrc = pwrc; + alr_data->nc_data.dtx = dtx; + + for (i = 0, j = 0; i < c_ba_arfcn; i++) + { + if (alr_data->nc_data.cell[i].ba_status EQ IN_BA) + upd_dedi->chan_list.radio_freq[j++] = + ARFCN_TO_L1(alr_data->nc_data.cell[i].ba_arfcn); + } + + upd_dedi->num_of_chans = j; + alr_data->nc_data.ba_id = ALR_ALLOCATE_NEW_BA ( alr_data->nc_data.ba_id ); + upd_dedi->ba_id = alr_data->nc_data.ba_id; + upd_dedi->pwrc = alr_data->nc_data.pwrc; + upd_dedi->dtx_allowed = alr_data->nc_data.dtx; + + alr_data->nc_data.update = TRUE; + ma_nc_update_ba_list (upd_dedi); + } + break; + default: + TRACE_ERROR("nc_update_dedicated in wrong state"); + break; + } +} + +GLOBAL void nc_resume_dedicated(void) +{ + nc_enable_conf(); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_get_fn_time | ++--------------------------------------------------------------------+ + + PURPOSE : Export Procedure to request frame offset and time + alignment of neighbour cells. + + Returns FALSE if timing information not found. + +*/ + +GLOBAL BOOL nc_get_fn_time (USHORT channel, + ULONG *fn, + ULONG *time) +{ + USHORT index; + if( channel EQ alr_data->serving_cell) + { + *fn = 0; + *time = 0; + return TRUE; + } + + /* Check if we have read SYNC on this channel */ + index = nc_get_index (channel); + if (index NEQ NOT_PRESENT_16BIT) + { + *fn = alr_data->nc_data.cell[index].frame_offset; + *time = alr_data->nc_data.cell[index].time_align; + + if( (*fn EQ NOT_PRESENT_32BIT) OR (*time EQ NOT_PRESENT_32BIT)) + { + return FALSE; + } + else + { + return TRUE; + } + } + else + { + *fn = NOT_PRESENT_32BIT; + *time = NOT_PRESENT_32BIT; + return FALSE; + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_start_reselect | ++--------------------------------------------------------------------+ + + PURPOSE : Process signal nc_start_reselect from SDL process + Main_Control. + +*/ + +GLOBAL void nc_start_reselect (USHORT arfcn) +{ + USHORT index; + T_NC *pcell; + + ALR_TRACE_NC_RESELECT(arfcn); + + index = nc_get_index (arfcn); + if (index EQ NOT_PRESENT_16BIT) + { + if (arfcn NEQ alr_data->nc_data.cr_cell.ba_arfcn) + { + ma_error_ind (CS_BCCH_READ_ERROR, arfcn); + return; + } + else + { + pcell = &alr_data->nc_data.cr_cell; + } + } + else + { + pcell = &alr_data->nc_data.cell[index]; + + /* Cannot to reselect to a cell for which the synchronization information + * is not available + */ + if (pcell->bsic EQ NOT_PRESENT_8BIT) + { + ma_error_ind (CS_NC_SYNC_FAILED, arfcn); + return; + } + } + + + { + PALLOC(reselect, MPHC_NEW_SCELL_REQ); + + reselect->radio_freq = ARFCN_TO_L1(arfcn); + reselect->fn_offset = (ULONG)pcell->frame_offset; + reselect->time_alignment = (ULONG)pcell->time_align; + reselect->tsc = pcell->bsic; + alr_data->nc_data.channel = arfcn; + + ALR_TRACE_NC_FN_TA(index, reselect->fn_offset, reselect->time_alignment); + + ALR_EM_CONFIGURE_CELL_RESELECTION; + + ma_new_scell_req(reselect); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_report | ++--------------------------------------------------------------------+ + + PURPOSE : Process signal nc_report from SDL process + Main_Control. + +*/ + +GLOBAL void nc_report (T_MPHC_RXLEV_PERIODIC_IND *rxlev_periodic_ind) +{ + ALR_TRACE_NC("nc_report"); + + + switch(GET_STATE(STATE_NC)) + { + case NC_IDLE: + case NC_CON_EST: + nc_store_rxlev (rxlev_periodic_ind); + +#ifdef GPRS + nc_rxlev_sc_req (rxlev_periodic_ind->s_rxlev); +#endif + nc_check_activity(); + break; + default: + TRACE_ERROR("nc_report in invalid state"); + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_report_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : Process signal nc_report_dedicated from SDL process + Main_Control. + +*/ + +GLOBAL void nc_report_dedicated (T_MPHC_MEAS_REPORT *meas_report) +{ + switch(GET_STATE(STATE_NC)) + { + case NC_DEDICATED: + nc_store_dedicated (meas_report); + nc_check_activity (); + break; + default: + TRACE_ERROR("nc_report_dedicated in wrong state"); + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_update_list | ++--------------------------------------------------------------------+ + + PURPOSE : Procedure to update frame offset and time alignment after + cell change. All values are relative to the actual serving + cell. + +*/ + +#define TDMA_FRAMES_PER_HYPERFRAME 2715648 + +GLOBAL void nc_update_list (USHORT channel) +{ + USHORT index; + USHORT i; + + switch(GET_STATE(STATE_NC)) + { + case NC_CON_EST: + case NC_DEDICATED: + case NC_IDLE: + index = nc_get_index (channel); + if (index NEQ NOT_PRESENT_16BIT) + { + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + if (i NEQ index) + { + ULONG new_frame_offset; + ULONG new_time_align; + + new_frame_offset = (alr_data->nc_data.cell[i].frame_offset - + alr_data->nc_data.cell[index].frame_offset + + TDMA_FRAMES_PER_HYPERFRAME) % + TDMA_FRAMES_PER_HYPERFRAME; + if (alr_data->nc_data.cell[i].time_align >= alr_data->nc_data.cell[index].time_align) + { + new_time_align = alr_data->nc_data.cell[i].time_align - + alr_data->nc_data.cell[index].time_align; + } + else + { + new_time_align = 5000 + alr_data->nc_data.cell[i].time_align - + alr_data->nc_data.cell[index].time_align; + new_frame_offset = (new_frame_offset + 1) % + TDMA_FRAMES_PER_HYPERFRAME; + } /* time_align */ + alr_data->nc_data.cell[i].frame_offset = new_frame_offset; + alr_data->nc_data.cell[i].time_align = new_time_align; + } /* i NEQ index */ + } /* for(all ncells) */ + + ALR_TRACE_NC("set chan to 0"); + + alr_data->nc_data.cell[index].frame_offset = 0; + alr_data->nc_data.cell[index].time_align = 0; + } /* NOT_PRESENT */ + break; + default: + TRACE_ERROR("nc_update_list in invalid state"); + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_add_offset | ++--------------------------------------------------------------------+ + + PURPOSE : If the mobile comes back from dedicated mode all synchronized + neighbourcells make a status transition to READ_BCCH_RR_NOT_INFORMED. + This triggers reading of the neighbourcell BCCH. + +*/ + +GLOBAL void nc_add_offset (void) +{ + USHORT i; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + + for (i = 0; i < c_ba_arfcn; i++) + { + if (alr_data->nc_data.cell[i].ba_arfcn NEQ alr_data->serving_cell) + { + /*XXX c_sync should be the same in idle and dedic also for pbcchc + so no action here */ + switch (alr_data->nc_data.cell[i].status) + { + case FB_SB_SYNC: + case READ_SB: + nc_set_status (i, READ_BCCH_RR_NOT_INFORMED); + break; + default: + break; + + } + } + else + nc_set_status (i, FB_SB_SYNC); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_fill_report_sc_dedi | ++--------------------------------------------------------------------+ + + PURPOSE : Fills the serving cell values for a measurement report. + +*/ + +GLOBAL void nc_fill_report_sc_dedi (T_MPH_MEASUREMENT_IND *rr_report, + UBYTE ncells) +{ + rr_report->valid = TRUE; + rr_report->ncells.no_of_ncells = ncells; + rr_report->arfcn = alr_data->serving_cell; + rr_report->fn_offset = 103; /* average of SDCCH/FACCH */ + rr_report->dtx = alr_data->nc_data.act_dtx; + rr_report->rx_lev_full = (UBYTE)alr_data->nc_data.rxlev_full; + if (rr_report->rx_lev_full > 63) + rr_report->rx_lev_full = 63; + rr_report->rx_lev_sub = (UBYTE)alr_data->nc_data.rxlev_sub; + if (rr_report->rx_lev_sub > 63) + rr_report->rx_lev_sub = 63; + rr_report->rx_qual_full = alr_data->nc_data.rxqual_full; + rr_report->rx_qual_sub = alr_data->nc_data.rxqual_sub; + rr_report->otd = alr_data->nc_data.tav; + + if(ncells EQ 0) + { + /* + * rxlev of SC BCCH channel is not avail + * use approx value (rxlev_sub) + */ + rr_report->bcch_rxlev_of_sc = rr_report->rx_lev_sub; + } + else + { + USHORT index = nc_get_index(alr_data->serving_cell); + if(index EQ NOT_PRESENT_16BIT) + { + TRACE_EVENT("Error SC not present in BA list"); + rr_report->bcch_rxlev_of_sc = rr_report->rx_lev_sub; + } + else + { + if((UBYTE) alr_data->nc_data.cell[index].rxlev_average > 63) + rr_report->bcch_rxlev_of_sc = 63; + else + rr_report->bcch_rxlev_of_sc = (UBYTE)alr_data->nc_data.cell[index].rxlev_average; + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : inform GRR | ++--------------------------------------------------------------------+ + + PURPOSE : inform GRR + +*/ + +#ifdef GPRS +LOCAL void nc_inform_grr_of_ncell (USHORT index, UBYTE type) +{ + PALLOC(rr_rep, MPH_MEASUREMENT_IND); + rr_rep->ncells.no_of_ncells = 1; + rr_rep->ncells.arfcn[0] = alr_data->nc_data.cell[index].ba_arfcn; + if(type EQ GRR_SB_FOUND) + rr_rep->ncells.bsic[0] = alr_data->nc_data.cell[index].bsic; + else + rr_rep->ncells.bsic[0] = type; + rr_rep->gprs_sync = SYNC_RESULTS; + PSENDX(RR,rr_rep); +} + +LOCAL void remove_ncell_and_inform_grr (USHORT index) +{ + nc_inform_grr_of_ncell (index, GRR_SB_UNKNOWN); + nc_remove_channel_from_ba_list(index); +} +#endif + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_build_rr_report | ++--------------------------------------------------------------------+ + + PURPOSE : Fills a measurement report to RR with neighbour cell + information. + +*/ + +LOCAL void nc_build_rr_report (T_MPH_MEASUREMENT_IND *rr_report) +{ + UBYTE c_report; + UBYTE c_ba_list; + T_NC * pcell = alr_data->nc_data.cell; + + c_report = 0; + rr_report->valid = TRUE; + + for (c_ba_list = 0; c_ba_list < alr_data->nc_data.c_ba_arfcn AND + c_report < MAX_RR_NCELL_CNT; c_ba_list++, pcell++) + { + if(pcell->one_of_six AND pcell->ba_status EQ IN_BA) + { + switch (pcell->status) + { + case FB_SB_SYNC_RR_NOT_INFORMED: + /* + * the cell is synchronized but RR has no prior + * knowledge of the cell, but we may have already + * read data from the ncell BCCH. This check is performed + * after sending the measurement report + */ + case FB_SB_SYNC: + case READ_BCCH: + case READ_SB: + case READ_SB_BCCH: + /* + * we may be currently reading this SB/FB or BCCH of the cell + * pass up this cell also + * if READ_FB_SB_PENDING this may be the first time that the + * cell is read so check if the bsic of this cell has been + * read already + */ + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + case READ_BCCH_PENDING: + case READ_FB_SB_PENDING: + if (pcell->ba_arfcn NEQ alr_data->serving_cell AND + pcell->bsic NEQ NOT_PRESENT_8BIT) + { + rr_report->ncells.arfcn[c_report] = pcell->ba_arfcn; + rr_report->ncells.rx_lev[c_report] = (UBYTE)pcell->rxlev_average; + #if defined(_SIMULATION_) + TRACE_EVENT_P3 ("rx_lev%u[%u]=%d", + c_report, rr_report->ncells.arfcn[c_report], + rr_report->ncells.rx_lev[c_report]); + #endif /* _SIMULATION_ */ + rr_report->ncells.bsic[c_report] = pcell->bsic; + rr_report->ncells.time_alignmt[c_report] = pcell->time_align; + rr_report->ncells.frame_offset[c_report++] = pcell->frame_offset; + } + break; + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + case READ_FB_SB: + /* do nothing */ + default: + break; + } + }/* not one_of_six*/ + } + rr_report->ncells.no_of_ncells = c_report; +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_build_nwctrl_rr_report | ++--------------------------------------------------------------------+ + + PURPOSE : Fills a measurement report to RR with neighbour cell + information. + +*/ + + +#ifdef GPRS +GLOBAL void nc_build_nwctrl_rr_report (T_MPH_MEAS_REP_CNF *rr_report) +{ + UBYTE c_report; + UBYTE c_ba_list; + USHORT index; + T_NC * pcell; + + /* + * Store the rxlev average for the serving cell + */ + index = nc_get_index(alr_data->serving_cell); + if ( index NEQ NOT_PRESENT_16BIT ) + { + pcell = &alr_data->nc_data.cell[index]; + rr_report->meas_rep[0].arfcn = alr_data->serving_cell; + rr_report->meas_rep[0].bsic = pcell->bsic; + + if(pcell->c_nc_rxlev) + { + rr_report->meas_rep[0].rx_lev = pcell->nc_rxlev/pcell->c_nc_rxlev; + } +#if defined(_SIMULATION_) + TRACE_EVENT_P3 ("nw_sc__rxlev[%u]=acc : %d, count:%d",rr_report->meas_rep[0].arfcn,pcell->nc_rxlev,pcell->c_nc_rxlev); +#endif /* _SIMULATION_ */ + } + + c_report = 0; + pcell = alr_data->nc_data.cell; + + for (c_ba_list = 0; c_ba_list < alr_data->nc_data.c_ba_arfcn AND + c_report < MAX_RR_NCELL_CNT; c_ba_list++, pcell++) + { + if(pcell->one_of_six AND pcell->ba_status EQ IN_BA) + { + switch (pcell->status) + { + case FB_SB_SYNC_RR_NOT_INFORMED: + /* + * the cell is synchronized but RR has no prior + * knowledge of the cell, but we may have already + * read data from the ncell BCCH. This check is performed + * after sending the measurement report + */ + case FB_SB_SYNC: + case READ_BCCH: + case READ_SB: + case READ_SB_BCCH: + /* + * we may be currently reading this SB/FB or BCCH of the cell + * pass up this cell also + * if READ_FB_SB_PENDING this may be the first time that the + * cell is read so check if the bsic of this cell has been + * read already + */ + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + case READ_BCCH_PENDING: + case READ_FB_SB_PENDING: + if (pcell->ba_arfcn NEQ alr_data->serving_cell AND + pcell->bsic NEQ NOT_PRESENT_8BIT) + { + rr_report->meas_rep[c_report+1].arfcn = pcell->ba_arfcn; + rr_report->meas_rep[c_report+1].bsic = pcell->bsic; + if(pcell->c_nc_rxlev) + { + rr_report->meas_rep[c_report+1].rx_lev = pcell->nc_rxlev/pcell->c_nc_rxlev; + } + +#if defined(_SIMULATION_) + TRACE_EVENT_P3 ("nwctrl_rxlev%u[%u]=%d",c_report+1, rr_report->meas_rep[c_report+1].arfcn,rr_report->meas_rep[c_report+1].rx_lev); +#endif /* _SIMULATION_ */ + c_report++; + } + break; + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + case READ_FB_SB: + /* do nothing */ + default: + break; + } + }/* not one_of_six*/ + } + + if( (c_report + 1 ) < RR_ALR_MEAS_REPORT_SIZE ) + { + rr_report->meas_rep[c_report+1].arfcn = NOT_PRESENT_16BIT ; + rr_report->meas_rep[c_report+1].rx_lev = NOT_PRESENT_8BIT ; + rr_report->meas_rep[c_report+1].bsic = NOT_PRESENT_8BIT ; + } +} +#endif /* ifdef GPRS */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_store_tav | ++--------------------------------------------------------------------+ + + PURPOSE : Stores timing advance receveived with dedicated mode SI's +*/ +GLOBAL void nc_store_tav(USHORT tav) +{ + alr_data->nc_data.tav = tav; +} + + +/* + *======================================================================== + * Helper Functions + *======================================================================== + */ + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_check_status | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the status of the neighbour cells. +*/ + +LOCAL void nc_check_status (UBYTE start_list) +{ + USHORT i; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + T_NC * pcell = alr_data->nc_data.cell; + + for (i = 0; i < c_ba_arfcn; i++, pcell++) + { + if (pcell->ba_arfcn NEQ alr_data->serving_cell) + { + switch (GET_STATE(STATE_NC)) + { + case NC_DEDICATED: + switch (pcell->status) + { + case INACTIVE: + break; + case IDLE: + if (pcell->one_of_twelve) + nc_set_status (i, READ_FB_SB); + if (start_list EQ CHECK_FOR_CONFIRM) + { + if (pcell->tim_valid EQ TV_VALID_TIMING_INFO) + pcell->tim_valid = TV_APPROX_TIMING_INFO; + else if (pcell->tim_valid EQ TV_APPROX_TIMING_INFO) + pcell->tim_valid = TV_INVALID_TIMING_INFO; + } + break; + case READ_FB_SB: + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE); + if (start_list EQ CHECK_FOR_CONFIRM AND pcell->tim_valid EQ TV_APPROX_TIMING_INFO) + pcell->tim_valid = TV_INVALID_TIMING_INFO; + } + break; + case FB_SB_SYNC: + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE_SYNC); + } + else + { + if ( (start_list) AND (alr_data->nc_data.c_sync_intrupted EQ FALSE)) + nc_set_status (i, READ_SB); + } + break; + case IDLE_SYNC: + if (pcell->one_of_twelve) + { + if (pcell->c_sync EQ 0) + nc_set_status (i, READ_FB_SB); + else + nc_set_status (i, FB_SB_SYNC); + } + else + { + if (pcell->c_sync EQ 0) + { + nc_set_status (i, IDLE); + } + } + break; + case READ_SB: + if (pcell->one_of_twelve EQ FALSE) + { + pcell->tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (i, IDLE); + } + break; + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH: + case READ_SB_BCCH: + TRACE_EVENT("unexpected STATE_NC during NC_DEDICATED"); + if (pcell->one_of_twelve) + nc_set_status (i, READ_FB_SB); + else + { + pcell->tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (i, IDLE); + } + break; + + case FB_SB_FAILED: + if (pcell->one_of_twelve EQ FALSE) + nc_set_status (i, IDLE); + else if (pcell->c_sync EQ 0) + nc_set_status (i, READ_FB_SB); + break; + + default: + break; + } + break; + case NC_IDLE: + switch (pcell->status) + { + case INACTIVE: + break; + case IDLE: + if (pcell->one_of_twelve) + nc_set_status (i, READ_FB_SB); + if (start_list EQ CHECK_FOR_CONFIRM) + { + if (pcell->tim_valid EQ TV_VALID_TIMING_INFO) + pcell->tim_valid = TV_APPROX_TIMING_INFO; + else if (pcell->tim_valid EQ TV_APPROX_TIMING_INFO) + pcell->tim_valid = TV_INVALID_TIMING_INFO; + } + break; + case READ_FB_SB: + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE); + if (start_list EQ CHECK_FOR_CONFIRM AND pcell->tim_valid EQ TV_APPROX_TIMING_INFO) + pcell->tim_valid = TV_INVALID_TIMING_INFO; + } + break; + case FB_SB_SYNC: + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE_SYNC); + } + else + { + if (start_list) + nc_set_status (i, READ_SB); + if (pcell->one_of_six AND + pcell->c_bcch EQ 0) + nc_set_status (i, READ_SB_BCCH); + } + break; + case FB_SB_SYNC_RR_NOT_INFORMED: + if (pcell->one_of_six EQ FALSE) + { + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE_SYNC); + } + else + { + nc_set_status (i, FB_SB_SYNC); + } + } + break; + case FB_SB_FAILED: + if (pcell->one_of_twelve EQ FALSE) + nc_set_status (i, IDLE); + else if (pcell->c_sync EQ 0) + nc_set_status (i, READ_FB_SB); + break; + case IDLE_SYNC: + if (pcell->one_of_twelve) + { + if(pcell->one_of_six) + { + if (pcell->c_sync EQ 0) + nc_set_status (i, READ_FB_SB); + else + nc_set_status (i, READ_BCCH_RR_NOT_INFORMED); + } + else + { + if (pcell->c_sync EQ 0) + nc_set_status (i, READ_FB_SB); + else + nc_set_status (i, FB_SB_SYNC); + } + } + else + { + if (pcell->c_sync EQ 0) + { + pcell->tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (i, IDLE); + } + } + break; + case READ_SB: + if (pcell->one_of_twelve EQ FALSE) + { + pcell->tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (i, IDLE); + } + else + { + if (pcell->c_bcch EQ 0) + nc_set_status (i, READ_SB_BCCH); + } + break; + case READ_BCCH: + if (pcell->one_of_six EQ FALSE) + { + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE_SYNC); + } + else + { + nc_set_status (i, FB_SB_SYNC); + } + } + break; + case READ_BCCH_RR_NOT_INFORMED: + if (pcell->one_of_six EQ FALSE) + { + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE_SYNC); + } + else + { + nc_set_status (i, FB_SB_SYNC); + } + } + break; + + case READ_SB_BCCH: + if (pcell->one_of_six EQ FALSE) + { + if (pcell->one_of_twelve) + nc_set_status(i, READ_SB); + else + { + pcell->tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (i, IDLE); + } + } + break; + + default: + break; + } + break; +#ifdef GPRS + case NC_PIM_PBCCH: + case NC_PTM_PBCCH: /*XXX*/ + case NC_CON_EST: /*in case of an updated list in CON_EST */ + switch (pcell->status) + { + case IDLE: + if(pcell->one_of_twelve) + nc_set_status (i, READ_FB_SB); + if (start_list EQ CHECK_FOR_CONFIRM) + { + if (pcell->tim_valid EQ TV_VALID_TIMING_INFO) + pcell->tim_valid = TV_APPROX_TIMING_INFO; + else if (pcell->tim_valid EQ TV_APPROX_TIMING_INFO) + pcell->tim_valid = TV_INVALID_TIMING_INFO; + } + break; + case FB_SB_SYNC: + if(pcell->one_of_twelve EQ FALSE) + nc_set_status (i, IDLE_SYNC); + else + { + if (start_list) + nc_set_status (i, READ_SB); + } + break; + case FB_SB_FAILED: + if(pcell->one_of_twelve EQ FALSE) + remove_ncell_and_inform_grr(i); + else + if(pcell->c_sync EQ 0) + nc_set_status (i, READ_FB_SB); + break; + case READ_FB_SB: + break; + case READ_SB: + if (pcell->one_of_twelve EQ FALSE) + { + pcell->tim_valid = TV_APPROX_TIMING_INFO; + nc_set_status (i, IDLE); + } + break; + case IDLE_SYNC: + if(pcell->c_sync EQ 0) + remove_ncell_and_inform_grr(i); + else + { + if(pcell->one_of_twelve) + nc_set_status (i, FB_SB_SYNC); + } + break; + case READ_BCCH_RR_NOT_INFORMED: + case READ_BCCH: + case FB_SB_SYNC_RR_NOT_INFORMED: + if (pcell->one_of_twelve EQ FALSE) + { + nc_set_status (i, IDLE_SYNC); + } + break; + default: + TRACE_EVENT_P4("wrong state in check_st: i%d a%d 1o6%d st%d", i, + pcell->ba_arfcn, + pcell->one_of_six, + pcell->status); + break; + } +#endif + break; + default: + break; + }/*switch state*/ + } /*if*/ + } /*for*/ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_build_rr_report_dedi | ++--------------------------------------------------------------------+ + + PURPOSE : Fills a measurement report to RR with neighbour cell + information in dedicated mode. + In dedicated mode the serving cell may be included. + +*/ +LOCAL void nc_build_rr_report_dedi (T_MPH_MEASUREMENT_IND *rr_report) +{ + UBYTE c_report = 0; + UBYTE c_ba_list; + UBYTE found = TRUE; + UBYTE index; + UBYTE i; + UBYTE in_report[34]; + T_NC * pcell1; + + memset (in_report, 0, 34); + + for ( i = 0; i < 6 AND found EQ TRUE; i++) + { + found = FALSE; + index = NOT_PRESENT_8BIT; + pcell1 = alr_data->nc_data.cell; + + for (c_ba_list = 0; c_ba_list < alr_data->nc_data.c_ba_arfcn; c_ba_list++, pcell1++) + { + if (in_report[c_ba_list] EQ FALSE AND pcell1->ba_status EQ IN_BA) + { + switch (pcell1->status) + { + case FB_SB_SYNC: + case READ_SB: + case READ_SB_PENDING: + if (nc_ncell_in_plmn_permitted(pcell1->bsic)) + { + if ((pcell1->ba_arfcn NEQ alr_data->serving_cell AND + pcell1->one_of_six) OR + (pcell1->ba_arfcn EQ alr_data->serving_cell AND + alr_data->nc_data.sc_included)) + { + if (index EQ NOT_PRESENT_8BIT) + index = c_ba_list; + else + { + if (pcell1->rxlev_average > + alr_data->nc_data.cell[index].rxlev_average) + index = c_ba_list; + } + } + } + break; + } + } + } + + if (index NEQ NOT_PRESENT_8BIT) + { + T_NC* pcell = &alr_data->nc_data.cell[index]; + found = TRUE; + in_report[index] = TRUE; + + rr_report->ncells.arfcn[c_report] = pcell->ba_arfcn; + + if ((UBYTE)pcell->rxlev_average > 63) + rr_report->ncells.rx_lev[c_report] = 63; + else + rr_report->ncells.rx_lev[c_report] = (UBYTE)pcell->rxlev_average; + + rr_report->ncells.bsic[c_report] = pcell->bsic; + rr_report->ncells.time_alignmt[c_report] = pcell->time_align; + rr_report->ncells.frame_offset[c_report++] = pcell->frame_offset; + } + + } /*for (up to 6 ncells)*/ + /* + * insert serving cell values + */ + nc_fill_report_sc_dedi (rr_report, c_report); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_rank_ncells | ++--------------------------------------------------------------------+ + + PURPOSE : Searches for the six and additionally the twelve strongest neighbourcells. + +*/ +LOCAL void nc_rank_ncells (void) +{ + USHORT c_found, i; + USHORT last = (sizeof alr_data->nc_data.cell / + sizeof alr_data->nc_data.cell[0]); + UBYTE old_1of6[ sizeof alr_data->nc_data.cell / + sizeof alr_data->nc_data.cell[0] ]; + UBYTE num_1of6, hyst_rxlev, nc_conf_active = FALSE; + + num_1of6 = 0; + hyst_rxlev = 63; + alr_data->nc_data.new_strong_cell_detect = FALSE; + + for ( i = 0; i < last; i++ ) + { + old_1of6[i] = alr_data->nc_data.cell[i].one_of_six; + alr_data->nc_data.cell[i].new_strong_cell = FALSE; + + if(old_1of6[i]) + { + num_1of6++; + + if(alr_data->nc_data.cell[i].rxlev_average < hyst_rxlev) + hyst_rxlev = alr_data->nc_data.cell[i].rxlev_average; + } + + alr_data->nc_data.cell[i].one_of_six = FALSE; + + } + + if(num_1of6 < MAX_RR_NCELL_CNT) + hyst_rxlev = 0; + + if((GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) AND + (GET_STATE(STATE_NC) EQ NC_DEDICATED) AND + (!alr_data->nc_data.eotd_avail)) + nc_conf_active = TRUE; + + c_found = 0; + + if ((std EQ STD_DUAL) OR (std EQ STD_DUAL_EGSM) OR (std EQ STD_DUAL_US)) + { + switch (alr_data->nc_data.multiband) + { + case MULTI_BAND_0: + /* Find 6 cells from any band */ + nc_find_cells (&c_found, MAX_RR_NCELL_CNT, NO_BAND_LIMITATION, ALR_RXLEV_AVERAGE_MIN); + break; + case MULTI_BAND_1: + /* Find 1 cell from bands other than Serving cell band */ + nc_find_cells (&c_found, 1, EXCLUDE_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR); + + /* Find 5 cells from the Serving cell band */ + nc_find_cells (&c_found, MAX_RR_NCELL_CNT-1, ONLY_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR); + + /* If number of found cells are less than six, find the remaining from any band. + * Also relax the Rxlev criteria + */ + nc_find_cells (&c_found, (USHORT)(MAX_RR_NCELL_CNT - c_found), NO_BAND_LIMITATION, + ALR_RXLEV_AVERAGE_MIN); + break; + case MULTI_BAND_2: + /* Find 2 cell from bands other than Serving cell band */ + nc_find_cells (&c_found, 2, EXCLUDE_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR); + + /* Find 4 cells from the Serving cell band */ + nc_find_cells (&c_found, MAX_RR_NCELL_CNT-2, ONLY_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR); + + /* If number of found cells are less than six, find the remaining from any band. + * Also relax the Rxlev criteria + */ + nc_find_cells (&c_found, (USHORT)(MAX_RR_NCELL_CNT - c_found), NO_BAND_LIMITATION, + ALR_RXLEV_AVERAGE_MIN); + break; + case MULTI_BAND_3: + /* Find 3 cell from bands other than Serving cell band */ + nc_find_cells (&c_found, 3, EXCLUDE_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR); + + /* Find 3 cells from the Serving cell band */ + nc_find_cells (&c_found, MAX_RR_NCELL_CNT-3, ONLY_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR); + + /* If number of found cells are less than six, find the remaining from any band. + * Also relax the Rxlev criteria + */ + nc_find_cells (&c_found, (USHORT)(MAX_RR_NCELL_CNT - c_found), NO_BAND_LIMITATION, + ALR_RXLEV_AVERAGE_MIN); + break; + } + } + else + nc_find_cells (&c_found, MAX_RR_NCELL_CNT, NO_BAND_LIMITATION, ALR_RXLEV_AVERAGE_MIN); + + for ( i = 0; i < last; i++ ) + { + if (alr_data->nc_data.cell[i].one_of_six AND !old_1of6[i] AND + GET_STATE(STATE_NC) NEQ NC_DEDICATED) + { /* the cell becomes one of six */ + switch (alr_data->nc_data.cell[i].status) + { + case FB_SB_SYNC: + /* the cell is treaded as synchronized, perform BCCH reading ASAP */ + nc_set_status(i, READ_BCCH_RR_NOT_INFORMED); + break; + case READ_SB: + case IDLE_SYNC: + case FB_SB_FAILED: + /* the cell shall be synchronized ASAP, then BCCH info is to send to RR */ + nc_set_status(i, READ_FB_SB); + break; + case READ_SB_PENDING: + /* after receipt of sync ind the BCCH is to read and to send to RR */ + nc_set_status(i, READ_FB_SB_PENDING); + break; + default: + break; + } + } + if (old_1of6[i] AND + !alr_data->nc_data.cell[i].one_of_six AND + alr_data->nc_data.cell[i].status EQ FB_SB_SYNC) + alr_data->nc_data.cell[i].c_attempt = 0; + + /* Check the new strong cell criteria when confirmation is active */ + if(nc_conf_active) + { + nc_check_new_strong_cell(i, old_1of6[i], hyst_rxlev); + + } + } + + nc_find_list_cells(); + + TRACE_EVENT_P1("New strong cell detect:%d", + alr_data->nc_data.new_strong_cell_detect); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_find_cells | ++--------------------------------------------------------------------+ + + PURPOSE : Searches for the six strongest neighbourcells, + using multiband parameter if needed. + Called only in case of the value of 'std' is set to + STD_DUAL, STD_DUAL_EGSM or STD_DUAL_US. + (And therefore only for the combination of + GSM900/E-GSM/DCS1800 or GSM850/PCS1900.) + +*/ +LOCAL void nc_find_cells (USHORT *c_found, USHORT max, UBYTE limitation, + UBYTE min_rxlev) +{ + int i, j; + BOOL limit; + int index; + + + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + T_NC* pcell; + UBYTE band_nc; + UBYTE band_sc = get_band (alr_data->serving_cell); + + if (*c_found >= MAX_RR_NCELL_CNT) + return; + + if (band_sc EQ BAND_E_GSM) + band_sc = BAND_GSM_900; /* equal treatment of E-GSM and GSM900 */ + + for (j = 0, index = 0; (j < max) AND (index NEQ NOT_PRESENT_16BIT); j++) + { + index = NOT_PRESENT_16BIT; + + for (i = 0; i < c_ba_arfcn; i++) + { + pcell = &alr_data->nc_data.cell[i]; + /* + * The six strongest neighbour cells do not include cells + * currently not belonging to BA list + */ + if (pcell->ba_status NEQ IN_BA) + continue; + + switch (pcell->status) + { + case INACTIVE: + case EXCLUDED: + /* + * The six strongest neighbour cells do not include failed ncells. + */ + break; + default: + if (pcell->ba_arfcn NEQ alr_data->serving_cell AND + pcell->one_of_six EQ FALSE AND + pcell->rxlev_average > min_rxlev) /* > -106 dBm */ + { + band_nc = get_band (pcell->ba_arfcn); + if (band_nc EQ BAND_E_GSM) + band_nc = BAND_GSM_900; /* equal treatment of E-GSM and GSM900 */ + + switch (limitation) + { + default: + case NO_BAND_LIMITATION: + limit = FALSE; + break; + case EXCLUDE_SC_BAND: + limit = (band_sc EQ band_nc); + break; + case ONLY_SC_BAND: + limit = (band_sc NEQ band_nc); + break; + } + + if (!limit) + { + if (index EQ NOT_PRESENT_16BIT) + { + index = i; + } + else + { + if (pcell->rxlev_average > + alr_data->nc_data.cell[index].rxlev_average) + { + index = i; + } + } + } + } + break; + } /*ncell status*/ + } + + if (index NEQ NOT_PRESENT_16BIT) + { + alr_data->nc_data.cell[index].one_of_six = TRUE; + (*c_found)++; + } + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_find_list_cells | ++--------------------------------------------------------------------+ + + PURPOSE : Searches for the 6 or 12 strongest neighbourcells + +*/ +LOCAL void nc_find_list_cells (void) +{ + USHORT i, j; + UBYTE found, c_found = 0; + USHORT index; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + T_NC* pcell; + + for (i = 0, pcell = &alr_data->nc_data.cell[0]; i < c_ba_arfcn; i++, pcell++ ) + { + if ((pcell->one_of_twelve = pcell->one_of_six) EQ TRUE) + c_found++; + } + /* + * The flag one_of_six controls the property to include a neighbour cell + * into the measurement report, + * the flag one_of_twelve controls whether the ncell is included into the + * synchronisation confirmation process. In case of EOTD up to 12 cell are + * included, in case of non-EOTD 6 cells are sufficient. + */ + if (!alr_data->nc_data.eotd_avail) + return; + + for (j = c_found, found = TRUE; (j < MAX_L1_SYNC_CNT) AND (found EQ TRUE); j++) + { + index = NOT_PRESENT_16BIT; + found = FALSE; + + for (i = 0; i < c_ba_arfcn; i++) + { + pcell = &alr_data->nc_data.cell[i]; + /* + * The 12 strongest neighbour cells do not include ncells currently not belonging to BA list. + */ + if (pcell->ba_status NEQ IN_BA) + continue; + + switch (pcell->status) + { + case INACTIVE: + case EXCLUDED: + /* + * The 12 strongest neighbour cells do not include failed ncells. + */ + break; + default: + if (pcell->ba_arfcn NEQ alr_data->serving_cell AND + pcell->one_of_twelve EQ FALSE AND + pcell->rxlev_average > ALR_RXLEV_AVERAGE_MIN) /* > -110 dBm */ + { + if (index EQ NOT_PRESENT_16BIT) + { + index = i; + found = TRUE; + } + else + { + if (pcell->rxlev_average > + alr_data->nc_data.cell[index].rxlev_average) + { + index = i; + found = TRUE; + } + } + } + break; + } /*ncell status*/ + } + + if (found AND (index NEQ NOT_PRESENT_16BIT)) + alr_data->nc_data.cell[index].one_of_twelve = TRUE; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_store_rxlev | ++--------------------------------------------------------------------+ + + PURPOSE : Stores the fieldstrength values of the neighbour cells. + Calculates the average of the fieldstrength after five + samples. + +*/ + + +LOCAL void nc_store_rxlev (T_MPHC_RXLEV_PERIODIC_IND *report) +{ + USHORT i; + USHORT index; + UBYTE diff; + int max_attempt; + T_NC* pcell; + + ALR_TRACE_NC("store rxlev"); + /* + * Patch for 20.5 + * The fieldstrength average for a new channel + * increases too slow if more then eight channels + * are in the neighbourcell list, because layer 1 + * sends not raw data every paging period. + */ + if (test_house AND + alr_data->nc_data.c_ba_arfcn > 8) + max_attempt = 3; + else + max_attempt = 5; + + if (alr_data->nc_data.tim_state NEQ NC_TIM_STOPPED) + { + /* Decrement the 10sec timer counter variable by BS_PA_MFRMS */ + alr_data->nc_data.c_ncsync_tim = (UBYTE)(alr_data->nc_data.c_ncsync_tim - alr_data->bs_pa_mfrms - 2); + + if ((signed char)(alr_data->nc_data.c_ncsync_tim) < 0) + alr_data->nc_data.c_ncsync_tim = 0; + + if( alr_data->nc_data.c_ncsync_tim EQ 0 ) + nc_ncsync_tim_expiry(); /* 10 sec have elapsed. Perform all requisite tasks */ + } + + /* serving cell rxlev storage */ + index = nc_get_index (alr_data->serving_cell); + pcell = &alr_data->nc_data.cell[index]; + + if ( (signed char)report->s_rxlev < 0) + report->s_rxlev = 0; + + if (pcell->c_rxlev EQ NOT_PRESENT_8BIT) + { + pcell->c_rxlev = 0; + memset (pcell->rxlev, report->s_rxlev, 5); + } + else + { + pcell->rxlev[pcell->c_rxlev++] = report->s_rxlev; + } + pcell->c_rxlev %= 5; + + /* + * store the results seperately for averaging when NC=1 or NC=2 + */ +#ifdef GPRS + if(alr_data->nwctrl_meas_active) + { + pcell->nc_rxlev += report->s_rxlev; + pcell->c_nc_rxlev++; + } +#endif + + /* + * ncell rxlev storage + */ + for (i = 0; i < report->nbr_of_carriers; i++) + { + /* + * The RX level from TI is signed in the SAP + * we define it as unsigned + */ + if ((signed char) (report->result[i].rxlev) < 0) + { + report->result[i].rxlev = 0; + } + + index = nc_get_index (ARFCN_TO_G23(report->result[i].radio_freq)); + if (index NEQ NOT_PRESENT_16BIT AND + index NEQ LAST_BSIC_REQ AND + ARFCN_TO_G23(report->result[i].radio_freq) NEQ alr_data->serving_cell) + { + int temp; + UBYTE rxlev = report->result[i].rxlev; + pcell = &alr_data->nc_data.cell[index]; + + if (pcell->c_rxlev EQ NOT_PRESENT_8BIT) + { + /* + * if it is a new cell, build an average from the first value + * to speed up fb sb read + */ + pcell->rxlev[0] = rxlev; + pcell->rxlev[1] = rxlev; + pcell->rxlev[2] = rxlev; + pcell->rxlev[3] = rxlev; + pcell->rxlev[4] = rxlev; + pcell->c_rxlev = 0; + } + else + { + pcell->rxlev[pcell->c_rxlev++] = rxlev; + if (pcell->c_rxlev >= (UBYTE)max_attempt) + pcell->c_rxlev = 0; + } + temp = pcell->rxlev[0] + + pcell->rxlev[1] + + pcell->rxlev[2]; + + if (max_attempt EQ 5) + { + temp += pcell->rxlev[3] + + pcell->rxlev[4]; + } + + pcell->rxlev_average = (UBYTE)(temp / max_attempt); + /* + * store the results seperately for averaging when NC=1 or NC=2 + */ +#ifdef GPRS + if(alr_data->nwctrl_meas_active) + { + pcell->nc_rxlev += rxlev; + pcell->c_nc_rxlev++; + } +#endif + + +#if defined(TRACING) + TRACE_EVENT_P4("NC%u[%d] rx=%d av=%d", + index, + pcell->ba_arfcn EQ NOT_PRESENT_16BIT ? -1 : pcell->ba_arfcn&ARFCN_MASK, + report->result[i].rxlev, pcell->rxlev_average); +#endif /* TRACING */ + + switch (pcell->status) + { + case INACTIVE: + nc_set_status (index, IDLE); + break; + case EXCLUDED: + diff = (UBYTE)(pcell->rxlev_average - pcell->last_rxlev); + if (diff < 128 AND diff >= 6) + { + /* + * result is positive and more than 6 dBm + */ + nc_set_status (index, IDLE); + } + break; + default: + break; + } + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_find_serving_cell_entry | ++--------------------------------------------------------------------+ + + PURPOSE : Finds an entry for serving cell + in the BCCH allocation list. + +*/ +LOCAL T_NC* nc_find_serving_cell_entry (USHORT serving_cell) +{ + T_NC* pcell; + USHORT i; + UBYTE last_alr = alr_data->nc_data.c_ba_arfcn; + + if (last_alr < LAST_BSIC_REQ) + { + pcell = &alr_data->nc_data.cell[last_alr]; +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] add", last_alr, serving_cell); +#endif /* TRACING */ + alr_data->nc_data.c_ba_arfcn = last_alr+1; /* store new last index */ + i = last_alr; + ALR_TRACE_ALL_NC (); + } + else + { /* ALR list is full, search for an entry not in state IN_BA */ + for (i = 0, pcell = alr_data->nc_data.cell; i < LAST_BSIC_REQ; i++, pcell++) + { + if (pcell->ba_status NEQ IN_BA) + break; + } /* for (i...) */ + if (i >= LAST_BSIC_REQ) + { /* + * no entry found + * reuse the last entry to make sure there is a place for serving cell + */ + i = LAST_BSIC_REQ-1; + pcell = &alr_data->nc_data.cell[i]; + } + + nc_stop_if_active(i); +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] replace", i, serving_cell); +#endif /* TRACING */ + } + nc_set_status (i, FB_SB_SYNC); + pcell->ba_status = IN_BA; /* even if not in the BA but other functions need it */ + pcell->ba_arfcn = serving_cell; + return pcell; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_add_serving_cell_ba_list| ++--------------------------------------------------------------------+ + + PURPOSE : Adds serving cell to neighbourcell list. + This function is called just before nc_start_reselect + and not after the MPHC_NEW_SCELL_CNF. + +*/ +LOCAL void nc_add_serving_cell_ba_list (USHORT serving_cell) +{ + USHORT index = nc_get_index (serving_cell); + T_NC* pcell; + + /* + * Add serving cell if not included + */ + switch (index) + { + case NOT_PRESENT_16BIT: + case LAST_BSIC_REQ: + /* serving cell isn´t inside the BA list */ + pcell = nc_find_serving_cell_entry(serving_cell); + pcell->bsic = alr_data->nc_data.cr_cell.bsic; + pcell->frame_offset = alr_data->nc_data.cr_cell.frame_offset; + pcell->time_align = alr_data->nc_data.cr_cell.time_align; + break; + + default: + if (index < ELEMENTS(alr_data->nc_data.cell)) + { + /* serving cell is already included in ba list */ + /* For GPRS the scell may not be in FB_SB_SYNC so put it there */ + pcell = &alr_data->nc_data.cell[index]; + + /* Check whether the cell has valid sync info */ + if (pcell->bsic NEQ NOT_PRESENT_8BIT) + { + nc_set_status(index, FB_SB_SYNC); + alr_data->nc_data.cell[index].one_of_six = FALSE; + alr_data->nc_data.cell[index].ba_status = IN_BA; /* even if not in the BA but other functions need it */ + } + } + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_update_ba_list | ++--------------------------------------------------------------------+ + + PURPOSE : Updates the BCCH allocation list. + +*/ + +LOCAL void nc_update_ba_list (USHORT serving_cell, T_MPH_NEIGHBOURCELL_REQ *ncell_list) +{ + USHORT n_rr; /* index of RR neighbor cell list */ + USHORT n_alr; /* index of ALR neighbor cell list */ + UBYTE last_alr; /* last index of ALR neighbor cell list */ + USHORT arfcn; + T_NC* pcell; + + alr_data->nc_data.multiband = ncell_list->multi_band; + + /* + * remove or mark all channels which are not longer member of the + * neighbour cell list. + */ + last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */ + for (n_alr = 0; n_alr < last_alr; n_alr++) + { + pcell = &alr_data->nc_data.cell[n_alr]; + arfcn = pcell->ba_arfcn; + if (!nc_is_in_ncell_list (arfcn, ncell_list) AND + (arfcn NEQ serving_cell)) + { + if (GET_STATE(STATE_NC) EQ NC_IDLE) + { /* the RR neighbor cell list is complete */ + last_alr = nc_remove_channel_from_ba_list (n_alr); +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] remove", n_alr, arfcn); +#endif /* TRACING */ + n_alr--; + ALR_TRACE_ALL_NC (); + } + else + { /* the RR neighbor cell list may be incomplete so mark only the entry */ + if (pcell->ba_status EQ IN_BA) + { + pcell->ba_status = NOT_IN_BA_SHORT; + +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] -> NOT_IN_BA_SHORT", n_alr, arfcn); +#endif /* TRACING */ + } + } + } + } + + /* + * add all new channels. + */ + for (n_rr = 0; n_rr < MAX_NEIGHBOURCELLS; n_rr++) + { + arfcn = ncell_list->arfcn[n_rr]; + if (arfcn EQ NOT_PRESENT_16BIT) + break; /* no more entries in the RR ncell_list */ + + n_alr = nc_get_index (arfcn); + + if (arfcn NEQ serving_cell) + { + if (n_alr EQ NOT_PRESENT_16BIT OR n_alr EQ LAST_BSIC_REQ) + { + if (last_alr < BA_LIST_SIZE) + { + pcell = &alr_data->nc_data.cell[last_alr]; + +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] add", last_alr, arfcn); +#endif /* TRACING */ + pcell->ba_arfcn = arfcn; + nc_set_status (last_alr, INACTIVE); + pcell->ba_status = IN_BA; + last_alr++; /* increment last index */ + } + else + { /* ALR list is full, search for an entry not in state IN_BA */ + USHORT i; + for (i = 0, pcell = alr_data->nc_data.cell; i < BA_LIST_SIZE; i++, pcell++) + { + if (pcell->ba_status NEQ IN_BA AND pcell->ba_arfcn NEQ serving_cell) + { + nc_stop_if_active(i); +#if defined(TRACING) + TRACE_EVENT_P2 ("NC%u[%u] replace", i, arfcn); +#endif /* TRACING */ + pcell->ba_arfcn = arfcn; + nc_set_status (i, INACTIVE); + pcell->ba_status = IN_BA; + break; + } + } /* for (i...) */ + } + } + else + { +#if defined(TRACING) + if (alr_data->nc_data.cell[n_alr].ba_status NEQ IN_BA) + TRACE_EVENT_P2 ("NC%u[%u] -> IN_BA", n_alr, arfcn); +#endif + alr_data->nc_data.cell[n_alr].ba_status = IN_BA; + } + } /* if (arfcn NEQ serving_cell) */ + } + + /* + * store whether SC was included into the BA list by the net + */ + if (nc_is_in_ncell_list (serving_cell, ncell_list)) + { + alr_data->nc_data.sc_included = TRUE; + } + else + { + alr_data->nc_data.sc_included = FALSE; + } + alr_data->nc_data.c_ba_arfcn = last_alr; /* store new last index */ + + /* + * Add serving cell if not included + */ + n_alr = nc_get_index (serving_cell); + switch (n_alr) + { + case NOT_PRESENT_16BIT: + case LAST_BSIC_REQ: + pcell = nc_find_serving_cell_entry(serving_cell); + + pcell->bsic = alr_data->bsic; + pcell->frame_offset = 0; + pcell->time_align = 0; + break; + + default: + /* serving cell is already included */ + pcell = &alr_data->nc_data.cell[n_alr]; + pcell->bsic = alr_data->bsic; + pcell->frame_offset = 0; + pcell->time_align = 0; + pcell->ba_status = IN_BA; /* even if not in the BA but other functions need it */ + nc_set_status (n_alr, FB_SB_SYNC); /* make sure the SC is reported in measurement reports if included into BA list */ + break; + } + + /* + * reset status of neighbour cells with failed + * synchronisation attempts. + */ + for (n_alr = 0; n_alr < last_alr; n_alr++) + { + switch (alr_data->nc_data.cell[n_alr].status) + { + case FB_SB_FAILED: + case EXCLUDED: + alr_data->nc_data.cell[n_alr].tim_valid = TV_INVALID_TIMING_INFO; + nc_set_status (n_alr, IDLE); + break; + } + } + + /* + * Reorder the entries. The goal is that the propably strongest neigbour cells + * are measured in the first measurement period of a subsequent + * MPHC_RXLEV_PERIODIC_REQ/IND. The appropriate arfcn's are the first ones in + * ncell_list->arfcn + */ + if (last_alr > 8) + { + T_NC temp, *prr, *palr; + + for (n_rr = 0; n_rr < 8 && ncell_list->arfcn[n_rr] NEQ NOT_PRESENT_16BIT; n_rr++) + { + n_alr = nc_get_index (ncell_list->arfcn[n_rr]); + if (n_rr NEQ n_alr) + { + palr = &(alr_data->nc_data.cell[n_alr]); + prr = &(alr_data->nc_data.cell[n_rr]); + memcpy(&temp, palr, sizeof(T_NC)); + memcpy(palr, prr, sizeof(T_NC)); + memcpy(prr, &temp, sizeof(T_NC)); + /*TRACE_EVENT_P4("reordered NC%u[%u] and NC%u[%u]", + n_rr, + ncell_list->arfcn[n_rr], + n_alr, ncell_list->arfcn[n_alr]);*/ + } + } + } + + ALR_TRACE_ALL_NC (); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_new_serving_cell | ++--------------------------------------------------------------------+ + + PURPOSE : Store old, set new serving cell, and add to neighbourcell list. + +*/ +GLOBAL void nc_new_serving_cell (USHORT serving_cell) +{ + alr_data->old_serving_cell = alr_data->serving_cell; + alr_data->serving_cell = serving_cell; + alr_data->sc_band = get_band (alr_data->serving_cell); + nc_add_serving_cell_ba_list(serving_cell); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_is_in_ncell_list | ++--------------------------------------------------------------------+ + + PURPOSE : Checks whether a channel is in the ncell_list of RR. + +*/ +LOCAL UBYTE nc_is_in_ncell_list (USHORT channel, T_MPH_NEIGHBOURCELL_REQ *ncell_list) +{ + USHORT i; + + for (i = 0; i < MAX_NEIGHBOURCELLS AND ncell_list->arfcn[i] NEQ NOT_PRESENT_16BIT; i++) + { + if (channel EQ ncell_list->arfcn[i]) + return TRUE; + } + + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_remove_channel_from_ba_list | ++--------------------------------------------------------------------+ + + PURPOSE : Removes one channel from the BCCH allocation. + +*/ + +LOCAL UBYTE nc_remove_channel_from_ba_list (USHORT index) +{ + USHORT i; + UBYTE c_ba_arfcn; + + switch(alr_data->nc_data.cell[index].status) + { + case READ_SB_PENDING: + case READ_SB_BCCH_PENDING: + if ( alr_data->nc_data.eotd_avail AND + ( GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) ) + { + /* we cannot stop this + * because we are using a list_req + */ + nc_set_status(index, INACTIVE); + break; + } + /*lint -fallthrough*/ + case READ_FB_SB_PENDING: + /* + * sync request is ongoing in layer 1. + */ + nc_stop_sync (index, INACTIVE); + break; + case READ_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + /* + * stop pending BCCH request + */ + nc_stop_bcch (index, INACTIVE); + break; + default: + nc_set_status (index, INACTIVE); + break; + } + + c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + for (i = index + 1; i < c_ba_arfcn; i++) + { + memcpy (&alr_data->nc_data.cell[i - 1],&alr_data->nc_data.cell[i],sizeof(T_NC)); /*shift NC*/ + } + memset (&alr_data->nc_data.cell[i - 1],0,sizeof (T_NC));/*delete old content of obsolete ba_list entry*/ + + alr_data->nc_data.c_ba_arfcn--; + return (alr_data->nc_data.c_ba_arfcn); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_get_index | ++--------------------------------------------------------------------+ + + PURPOSE : Calculates the index in the BCCH allocation. + +*/ + +GLOBAL USHORT nc_get_index (USHORT arfcn) +{ + USHORT i; + T_NC *pcell; /* use pointer to increase processing speed */ + USHORT last_alr; /* last index of ALR neighbor cell list */ + + last_alr = alr_data->nc_data.c_ba_arfcn; + pcell = &alr_data->nc_data.cell[0]; /* pointer to first cell */ + for (i = 0; i < last_alr; i++, pcell++) + { + if (arfcn EQ pcell->ba_arfcn) + return i; + } + + if (arfcn EQ alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn) + return LAST_BSIC_REQ; + + return NOT_PRESENT_16BIT; +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_build_sync_req | ++--------------------------------------------------------------------+ + + PURPOSE : Builds an MPHC_NCELL_SYNC_REQ and sends it to L1. + +*/ +LOCAL void nc_build_sync_req (USHORT index) +{ + T_NC * p_ncell = &alr_data->nc_data.cell[index]; + PALLOC (sync_req, MPHC_NCELL_SYNC_REQ); + + sync_req->radio_freq = ARFCN_TO_L1(p_ncell->ba_arfcn); + if (p_ncell->tim_valid EQ TV_INVALID_TIMING_INFO) + { + sync_req->fn_offset = 0; + sync_req->time_alignment = 0; + } + else + { + sync_req->fn_offset = p_ncell->frame_offset; + sync_req->time_alignment = p_ncell->time_align; + } + sync_req->timing_validity = p_ncell->tim_valid; + TRACE_EVENT_P4("nc_build_sync_req[%d] timing_validity=%d fn_offset=%ld, time_alignment=%ld", + p_ncell->ba_arfcn, + sync_req->timing_validity, + sync_req->fn_offset, + sync_req->time_alignment); + ma_nc_sync_req (sync_req); + + ALR_EM_READ_NEIGHBOURCELL_SB; + + nc_set_status (index, READ_FB_SB_PENDING); + alr_data->nc_data.c_sync_req++; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_process_status | ++--------------------------------------------------------------------+ + + PURPOSE : Starts a specific procedure for neighbour cells like + synchronisation to frequency correction burst and + synchron burst, confirmation of synchron burst or + reading of BCCH. With the new ALR interface it's possible + to send up to 12 SYNC_REQ's and BCCH_REQ's. + +*/ + +LOCAL void nc_process_status (void) +{ + UBYTE st = GET_STATE(STATE_NC); + + /* Sync requests for New cells are allowed only in dedicated state + * when eotd is not enabled. Fix for + */ + if(((alr_data->nc_data.eotd_avail) OR ( st NEQ NC_DEDICATED)) AND + (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM)) + return; + +#ifdef GPRS + if((st EQ NC_IDLE AND !ma_is_ptm()) OR + st EQ NC_PIM_PBCCH ) + nc_process_status_last_bsic(); +#else + nc_process_status_last_bsic(); +#endif + + + if(alr_data->plmn_search_running) + return; + +#ifdef GPRS + if(st EQ NC_PIM_PBCCH OR + st EQ NC_PTM_PBCCH ) + nc_process_status_sync_gprs(); + else +#endif + nc_process_status_sync(); + + if(st EQ NC_IDLE) + nc_process_status_bcch(); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_process_status_last_bsic| ++--------------------------------------------------------------------+ + + PURPOSE : When doing idle mode cell selection we use + LAST_BSIC_REQ for storing the information of the cell. + This has priority over normal neighbour cell monitoring. + +*/ + + +LOCAL void nc_process_status_last_bsic(void) +{ + T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ]; + + + switch (pbsic->status) + { + case READ_FB_SB: + if (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT) + { + pbsic->tim_valid = TV_INVALID_TIMING_INFO; + nc_build_sync_req (LAST_BSIC_REQ); + ALR_TRACE_NC ("ncell_sync_req HPLMN"); + + /* If the Mobile is in page mode REORG the NC search cannot be + * performed because L1 is too busy listening to the PCH. Therefore + * the page mode is changed from REORG to REORG_NC_SYNC (NORMAL). + */ + if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR + alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS) + { + page_mode_before_hplmn_search = alr_data->pch_data.pl_idle.page_mode; + alr_data->pch_data.pl_idle.page_mode = PGM_REORG_NC_SYNC; + pch_start_ccch_req (); + ALR_TRACE_NC ("HPLMN search cannot be performed with REORG - possible loss of pagings"); + } + + } + return ; + + case READ_BCCH: + if (alr_data->nc_data.c_bcch_req < MAX_L1_BCCH_CNT) + { + PALLOC (ncell_bcch, MPHC_NCELL_BCCH_REQ); + + ncell_bcch->radio_freq = ARFCN_TO_L1(pbsic->ba_arfcn); + ncell_bcch->fn_offset = pbsic->frame_offset; + ncell_bcch->time_alignment = pbsic->time_align; + /* + * The training sequence code on broadcast and common control channels + * has to be equal to the base station color code see GSM 5.02 + */ + ncell_bcch->tsc = (UBYTE)(pbsic->bsic & ONLY_BCC); + /* + * Read SI 3/4 to get the MNC/MCC + */ + pbsic->blocks_required = + ncell_bcch->bcch_blocks_required = NCELL_BCCH_SI_3_4; + ncell_bcch->gprs_prio = GPRS_PRIO_NORM; + + ma_nc_bcch_req (ncell_bcch); + alr_data->nc_data.c_bcch_req++; + nc_set_status (LAST_BSIC_REQ, READ_BCCH_PENDING); + } + return; + case READ_FB_SB_PENDING: + case READ_BCCH_PENDING: + return; + default: + break; + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_process_status_sync | ++--------------------------------------------------------------------+ + + PURPOSE : Processes cell synchronisation. + +*/ + + + +LOCAL void nc_process_status_sync(void) +{ + USHORT i; + USHORT index; + T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ]; + + /* Sync requests for New cells are allowed only in dedicated state + * when eotd is not enabled. Patch for + */ + if((!alr_data->nc_data.eotd_avail) AND + ( GET_STATE(STATE_NC) EQ NC_DEDICATED) AND + (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM)) + { + if(alr_data->nc_data.new_strong_cell_detect) + nc_handle_new_strong_cells(); + + alr_data->nc_data.new_strong_cell_detect = FALSE; + return; + } + + while (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT) + { + /* + * It is possible to send more sync requests to layer 1 + */ + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + index = NOT_PRESENT_16BIT; + + for (i = 0; i < c_ba_arfcn; i++) + { + /* + * search for the candidate with the highest fieldstrength + */ + T_NC* pcell = &alr_data->nc_data.cell[i]; + + if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND + (pcell->ba_arfcn NEQ alr_data->serving_cell)) + { + switch (pcell->status) + { + case READ_FB_SB: + if (index EQ NOT_PRESENT_16BIT) + index = i; + else + { + if (pcell->rxlev_average > + alr_data->nc_data.cell[index].rxlev_average) + index = i; + } + break; + default: + break; + } + } + } + + if (index NEQ NOT_PRESENT_16BIT) + { + /* + * Request synchronisation for this cell + */ + nc_build_sync_req(index); + ALR_TRACE_NC ("ncell_sync_req"); + } + else + break; /*while loop */ + } /* while( c_sync_req < MAX_L1_SYNC_CNT) */ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_process_status_sync_gprs| ++--------------------------------------------------------------------+ + + PURPOSE : Processes GPRS cell synchronisation. + +*/ + + +#ifdef GPRS /*XXX*/ +LOCAL void nc_process_status_sync_gprs(void) +{ + USHORT i; + T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ]; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + + + for (i = 0; i < c_ba_arfcn AND alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT; i++) + { + /* + * search for the candidate with the highest fieldstrength + */ + T_NC* pcell = &alr_data->nc_data.cell[i]; + + if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND + (pcell->ba_arfcn NEQ alr_data->serving_cell) AND + (pcell->status EQ READ_FB_SB)) + { + /* + * Request synchronisation for this cell + */ + nc_build_sync_req(i); + ALR_TRACE_NC ("ncell_sync_req"); + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_sync_failed_gprs | ++--------------------------------------------------------------------+ + + PURPOSE : Handles synchronisation failed situation + +*/ + + +LOCAL void nc_sync_failed_gprs(USHORT index) +{ + alr_data->nc_data.cell[index].c_sync = 1; /*XXX*/ + nc_set_status (index, FB_SB_FAILED); + nc_inform_grr_of_ncell(index, GRR_SB_NOT_FOUND); +} +#endif + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_process_status_bcch | ++--------------------------------------------------------------------+ + + PURPOSE : Processes CB status + +*/ + + +LOCAL void nc_process_status_bcch(void) +{ + USHORT i; + USHORT index; + T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ]; + + while (alr_data->nc_data.c_bcch_req < MAX_L1_BCCH_CNT) + { + /* + * It is possible to send more BCCH request to layer 1 + */ + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + index = NOT_PRESENT_16BIT; + + for (i = 0; i < c_ba_arfcn; i++) + { + /* + * search for the candidate with the highest fieldstrength + */ + T_NC* pcell = &alr_data->nc_data.cell[i]; + + if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND + (pcell->ba_arfcn NEQ alr_data->serving_cell)) + { + switch (pcell->status) + { + case READ_BCCH: + case READ_BCCH_RR_NOT_INFORMED: + if (index EQ NOT_PRESENT_16BIT) + index = i; + else + { + if (pcell->rxlev_average > + alr_data->nc_data.cell[index].rxlev_average) + index = i; + } + break; + default: + break; + } + } + } + + if (index NEQ NOT_PRESENT_16BIT) + { + /* + * Request BCCH reading for this cell + */ + T_NC* pcell = &alr_data->nc_data.cell[index]; + PALLOC (ncell_bcch, MPHC_NCELL_BCCH_REQ); + + ncell_bcch->radio_freq = ARFCN_TO_L1(pcell->ba_arfcn); + ncell_bcch->fn_offset = pcell->frame_offset; + ncell_bcch->time_alignment = pcell->time_align; + /* + * The training sequence code on broadcast and common control channels + * has to be equal to the Base Station Colour Code (BCC), + * see 3GPP TS 5.02, section 5.2.3 and + * 3GPP TS 03.03, section 4.3.2 Base Station Identify Code (BSIC) + */ + ncell_bcch->tsc = (UBYTE)(pcell->bsic & ONLY_BCC); + pcell->blocks_required = + ncell_bcch->bcch_blocks_required = NCELL_BCCH_SI_3_4; +#ifdef GPRS + /*if the mobile is in PTM the GPRS_PRIORITY must be set to TOP*/ + if(ma_is_ptm()) + { + ncell_bcch->gprs_prio = GPRS_PRIO_TOP; + } + else +#endif + ncell_bcch->gprs_prio = GPRS_PRIO_NORM; + + + ma_nc_bcch_req (ncell_bcch); + + ALR_TRACE_NC("ncell_bcch_read"); + + alr_data->nc_data.c_bcch_req++; + /* + * read a maximum of four blocks + * + * sys info 3 normal BCCH TC 2 or 6 + * sys info 4 normal BCCH TC 3 or 7 + */ + if(pcell->status EQ READ_BCCH) + nc_set_status (index, READ_BCCH_PENDING); + else + nc_set_status (index, READ_BCCH_PENDING_RR_NOT_INFORMED); + } + else + break; /*while loop */ + } /* while(c_bcch_req < MAX_L1_BCCH_CNT)*/ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_ncell_in_plmn_permitted | ++--------------------------------------------------------------------+ + + PURPOSE : checks whether the national colour code (ncc) is member + of the ncc permitted field. + +*/ +static const UBYTE ncc_bit_mask[8] = + { + BIT_0, BIT_1, BIT_2, BIT_3, + BIT_4, BIT_5, BIT_6, BIT_7 + }; + +LOCAL BOOL nc_ncell_in_plmn_permitted (UBYTE bsic) +{ + return ((BOOL) ((UBYTE) (alr_data->ncc_permitted & + ncc_bit_mask[(bsic >> 3) & BIT_012])) NEQ 0); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_store_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : Stores the values of the neighbour cells + and the serving cell. + +*/ +LOCAL void nc_store_dedicated (T_MPHC_MEAS_REPORT *report) +{ + USHORT i; + USHORT index; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + + if (alr_data->nc_data.tim_state NEQ NC_TIM_STOPPED) + { + /* Decrement the 10sec timer counter variable by 2 */ + alr_data->nc_data.c_ncsync_tim = alr_data->nc_data.c_ncsync_tim-2; + + if ((signed char)( alr_data->nc_data.c_ncsync_tim) < 0) + alr_data->nc_data.c_ncsync_tim = 0; + + if( alr_data->nc_data.c_ncsync_tim EQ 0 ) /* 10 sec have elapsed. Perform all requisite tasks */ + nc_ncsync_tim_expiry(); + } + + for (i = 0; i < report->no_of_ncells_meas; i++) + { + T_NC* pcell; + T_res_list* plist = &report->ncell_meas.res_list[i]; + + index = nc_get_index (ARFCN_TO_G23(plist->bcch_freq)); + if ((index EQ NOT_PRESENT_16BIT) OR (index EQ LAST_BSIC_REQ)) + continue; + pcell = &alr_data->nc_data.cell[index]; + + if (plist->rxlev_nbr_meas EQ 0) + pcell->rxlev_average = 0; + else + { + if ((signed short)(plist->rxlev_acc) < 0) + plist->rxlev_acc = 0; + + /* why this casting? - a "real" expression is of type int */ + pcell->rxlev_average = (UBYTE)(plist->rxlev_acc/plist->rxlev_nbr_meas); + } + if (pcell->status EQ INACTIVE) + nc_set_status (index, IDLE); + + if (pcell->status EQ EXCLUDED) + { + int diff; + + diff = pcell->rxlev_average - pcell->last_rxlev; + + if (diff >= 6) + { + /* + * result is positive and more than 6 dBm + */ + nc_set_status (index, IDLE); + } + } + } + + + alr_data->nc_data.act_dtx = report->dtx_used; + + if (report->rxlev_full_nbr_meas EQ 0) + alr_data->nc_data.rxlev_full = 0; + else + { + if ((signed short)(report->rxlev_full_acc) < 0) + report->rxlev_full_acc = 0; + + alr_data->nc_data.rxlev_full = + (UBYTE)(report->rxlev_full_acc / report->rxlev_full_nbr_meas); + } + + if (report->rxlev_sub_nbr_meas EQ 0) + alr_data->nc_data.rxlev_sub = 0; + else + { + if ((signed short)(report->rxlev_sub_acc) < 0) + report->rxlev_sub_acc = 0; + alr_data->nc_data.rxlev_sub = (UBYTE)(report->rxlev_sub_acc / report->rxlev_sub_nbr_meas); + } + + alr_data->nc_data.rxqual_full = + nc_convert_quality (report->rxqual_full_acc_errors, + report->rxqual_full_nbr_bits); + + alr_data->nc_data.rxqual_sub = + nc_convert_quality (report->rxqual_sub_acc_errors, + report->rxqual_sub_nbr_bits); +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_convert_quality | ++--------------------------------------------------------------------+ + + PURPOSE : Calculates the quality Value. + +*/ + +LOCAL UBYTE nc_convert_quality (USHORT errors, USHORT total) +{ + USHORT quality; + + if (total EQ 0) + quality = 0; + else + quality = (USHORT)((errors * 500) / total); + + if (quality EQ 0) + return 0; /* RX_QUAL_0 */ + + if (quality EQ 1) + return 1; /* RX_QUAL_1 */ + + if (quality < 4) + return 2; /* RX_QUAL_2 */ + + if (quality < 8) + return 3; /* RX_QUAL_3 */ + + if (quality < 16) + return 4; /* RX_QUAL_4 */ + + if (quality < 32) + return 5; /* RX_QUAL_5 */ + + if (quality < 64) + return 6; /* RX_QUAL_6 */ + + return 7; /* RX_QUAL_7 */ + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_release_bcch | ++--------------------------------------------------------------------+ + +PURPOSE : Check if we have read the BCCH of a ncell but RR has + not yet received the data because this cell has not + been reported to RR before. +*/ + +LOCAL void nc_release_bcch (void) +{ + USHORT i; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + /* + * for every ncell + */ + for (i = 0; i < c_ba_arfcn; i++) + { + T_NC* pcell = &alr_data->nc_data.cell[i]; + + switch (pcell->status) + { + case FB_SB_SYNC_RR_NOT_INFORMED: + /* + * Reading of the BCCH of the neighbourcell is performed, + * but RR has been just informed with a measurement report + * about synchronisation. + */ + if(pcell->mph_unitdata_ind NEQ NULL) + { + ALR_TRACE_NC ("send 34"); + + /* + * a system info type 3 or 4 message is stored. + * Send the message to RR and clear the internal variable. + */ + PSENDX(RR, pcell->mph_unitdata_ind); + pcell->mph_unitdata_ind = NULL; + } + + if(pcell->mph_unitdata_ind78 NEQ NULL) + { + ALR_TRACE_NC ("send 78"); + + /* + * a system info type 7 or 8 message is stored. + * Send the message to RR and clear the internal variable. + */ + PSENDX(RR, pcell->mph_unitdata_ind78); + pcell->mph_unitdata_ind78 = NULL; + } + + /* + * set status to FB_SB_SYNC, that means RR is completely informed. + */ + nc_set_fb_sb_sync_initial (i); + break; + + default: + break; + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_store_bcch | ++--------------------------------------------------------------------+ + +PURPOSE : Temporarily store BCCH data for ncell. + +*/ + +LOCAL void nc_store_bcch (T_MPHC_DATA_IND* data_ind, USHORT index, UBYTE sys_info_78) +{ + #define SYS_INFO_LEN 24 + + USHORT len_in_bits = SYS_INFO_LEN * BITS_PER_BYTE; + T_NC* pcell = &alr_data->nc_data.cell[index]; + /* + * Allocate a SDU for sending later to RR + */ + PALLOC_SDU (data_out, MPH_UNITDATA_IND, len_in_bits); + + /* + * set length and offset, but cut IE and Pseudo Length + */ + data_out->sdu.l_buf = (SYS_INFO_LEN - 2) * BITS_PER_BYTE; + data_out->sdu.o_buf = 1 * BITS_PER_BYTE; + + /* + * copy content of the message + */ + memcpy (data_out->sdu.buf, &data_ind->l2_frame, SYS_INFO_LEN - 1);/*lint !e419 (Warning -- Apparent data overrun)*/ + + /* + * set BCCH frequency of the message + */ + data_out->arfcn = ARFCN_TO_G23(data_ind->radio_freq)&ARFCN_MASK; + data_out->fn = data_ind->fn; + + if (sys_info_78) + { + ALR_TRACE_NC ("store 78"); + + /* + * if it is a system info 7 or 8 message, free the previous + * stored message, if something is stored and store the new + * one. + */ + if (pcell->mph_unitdata_ind78 NEQ NULL) + { + ALR_TRACE_NC ("store,free old 78"); + + PFREE(pcell->mph_unitdata_ind78); + } + + pcell->mph_unitdata_ind78 = data_out; + + } + else + { + ALR_TRACE_NC ("store 34"); + + /* + * if it is a system info 3 or 4 message, free the previous + * stored message, if something is stored and store the new + * one. + */ + if (pcell->mph_unitdata_ind NEQ NULL) + { + ALR_TRACE_NC( "store,free old 34"); + + PFREE(pcell->mph_unitdata_ind); + } + + pcell->mph_unitdata_ind = data_out; + + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_sys_info_78_required | ++--------------------------------------------------------------------+ + +PURPOSE : The function checks whether sys info 7 or 8 are expected + and required. + +*/ + +LOCAL UBYTE nc_sys_info_78_required (USHORT index) +{ + if (alr_data->nc_data.cell[index].mph_unitdata_ind NEQ 0) + { + T_sdu * sdu = &alr_data->nc_data.cell[index].mph_unitdata_ind->sdu; +/*lint -e415 (Warning -- creation of out-of-bounds pointer)*/ +/*lint -e416 (Warning -- access of out-of-bounds pointer)*/ + if ((sdu->buf[SI_CONTENTS_CS2] & ONLY_ACS) NEQ 0) + return TRUE; +/*lint +e415 (Warning -- creation of out-of-bounds pointer)*/ +/*lint +e416 (Warning -- access of out-of-bounds pointer)*/ + } + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_bcch | ++--------------------------------------------------------------------+ + + PURPOSE : Stop a pending BCCH. + +*/ + +LOCAL void nc_stop_bcch (USHORT index, UBYTE new_status) +{ + /* + * L3 may avoid sending a stop message to terminate a NCELL_BCCH process + * if there no more pending request in L1 + */ + + if (alr_data->nc_data.c_bcch_req > 0) + { + /* + * stop BCCH request in layer 1. + */ + ma_nc_stop_ncell_bcch_req(alr_data->nc_data.cell[index].ba_arfcn); + + /* + * decrement counter of pending requests + */ + alr_data->nc_data.c_bcch_req--; + } + + /* + * set new status + */ + nc_set_status (index, new_status); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_stop_sync | ++--------------------------------------------------------------------+ + + PURPOSE : Stop a pending Sync request. + +*/ + +LOCAL void nc_stop_sync (USHORT index, UBYTE new_status) +{ + /* + * L3 may avoid sending a stop message to terminate a NCELL_SYNC process + * if there no more pending request in L1 + */ + + if (alr_data->nc_data.c_sync_req > 0) + { + /* + * stop sync request in layer 1. + */ + ma_nc_stop_ncell_sync_req (alr_data->nc_data.cell[index].ba_arfcn); + + /* + * decrement counter of pending requests + */ + alr_data->nc_data.c_sync_req--; + /* + * check whether the confirmation procedure is finished indirectly + */ + if (alr_data->nc_data.c_sync_req EQ 0 AND + alr_data->nc_data.eotd_avail EQ FALSE AND + GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) + { + nc_enable_conf(); + } + } + + /* + * set new status + */ + nc_set_status (index, new_status); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_clean_store_bcch | ++--------------------------------------------------------------------+ + + PURPOSE : Clean a stored BCCH. + +*/ + +LOCAL void nc_clean_store_bcch (USHORT index) +{ + T_NC* pcell = &alr_data->nc_data.cell[index]; + if (pcell->mph_unitdata_ind NEQ NULL) + { + ALR_TRACE_NC ("free 34"); + + /* + * a system info type 3 or 4 message is stored + * then free the message and clean the pointer. + */ + + PFREE(pcell->mph_unitdata_ind); + pcell->mph_unitdata_ind = NULL; + + } + + if(pcell->mph_unitdata_ind78 NEQ NULL) + { + ALR_TRACE_NC ("free 78"); + + /* + * a system info type 7 or 8 message is stored + * then free the message and clean the pointer. + */ + + PFREE(pcell->mph_unitdata_ind78); + pcell->mph_unitdata_ind78 = NULL; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_check_bsic | ++--------------------------------------------------------------------+ + + PURPOSE : Check a base station identification code of a neighbourcell + The following return values are possible: + + NC_CHECK_OK : BSIC has not changed and is permitted. + NC_CHECK_NCC_FAILED : NCC permitted check has failed + NC_CHECK_BSIC_CHANGED : a BSIC change has occured + + +*/ + +LOCAL UBYTE nc_check_bsic (USHORT index, UBYTE bsic) +{ + /* + * check only the lowest 6 bits (= NCC + BCC) + */ + bsic = (UBYTE)(bsic & ONLY_BSIC); + + /* + * first check whether ncc is member of the ncc permitted field + */ + if (!nc_ncell_in_plmn_permitted (bsic)) + return NC_CHECK_NCC_FAILED; + + /* + * no bsic stored until now. + */ + if (alr_data->nc_data.cell[index].bsic EQ NOT_PRESENT_8BIT) + return NC_CHECK_OK; + + /* + * check against BSIC changes + */ + if (alr_data->nc_data.cell[index].bsic NEQ bsic) + return NC_CHECK_BSIC_CHANGED; + + /* + * all checks passed + */ + return NC_CHECK_OK; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_check_new_ncc_permitted | ++--------------------------------------------------------------------+ + +PURPOSE : Checks whether status transitions are needed after reception + of a changed NCC permitted field. + +*/ + +GLOBAL void nc_check_new_ncc_permitted (UBYTE new_ncc_permitted) +{ + USHORT i; + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + if (new_ncc_permitted NEQ alr_data->ncc_permitted) + { + /* + * a change has occured, so store new value and check all cells + */ + alr_data->ncc_permitted = new_ncc_permitted; + + for (i = 0; i < c_ba_arfcn; i++) + { + switch (alr_data->nc_data.cell[i].status) + { + case FB_SB_SYNC: + case FB_SB_SYNC_RR_NOT_INFORMED: + case READ_SB: + case READ_BCCH: + case IDLE_SYNC: + case READ_SB_BCCH: + case READ_BCCH_RR_NOT_INFORMED: + if (nc_ncell_in_plmn_permitted(alr_data->nc_data.cell[i].bsic) EQ FALSE) + nc_set_status (i, EXCLUDED); + break; + + case READ_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + if (nc_ncell_in_plmn_permitted(alr_data->nc_data.cell[i].bsic) EQ FALSE) + nc_set_status (i, EXCLUDED); + break; + + case EXCLUDED: + /* + * give channel a new chance + */ + nc_set_status (i, IDLE); + break; + } + } + } +} + +#if !defined(DEFINE_OLD_NC_STATUS) +LOCAL UBYTE nc_get_nc_status(UBYTE status) +{ + UBYTE st; + + switch (status) + { + case INACTIVE:st=0;break; + case IDLE:st=1;break; + case READ_BCCH:st=2;break; + case FB_SB_SYNC:st=3;break; + case FB_SB_FAILED:st=4;break; + case READ_FB_SB:st=5;break; + case READ_SB:st=6;break; + case IDLE_SYNC:st=7;break; + case EXCLUDED:st=8;break; + case FB_SB_SYNC_RR_NOT_INFORMED:st=9;break; + case READ_SB_BCCH:st=10;break; + case READ_BCCH_PENDING:st=11;break; + case READ_FB_SB_PENDING:st=12;break; + case READ_SB_PENDING:st=13;break; + case READ_SB_BCCH_PENDING:st=14;break; + case READ_BCCH_RR_NOT_INFORMED:st=15;break; + case READ_BCCH_PENDING_RR_NOT_INFORMED:st=16;break; + default:st=17;break; + } + + return st; +} +#else /* DEFINE_OLD_NC_STATUS */ +#define nc_get_nc_status(st) (((int)(st) >= 18) ? 18 : (st)) +#endif /* DEFINE_OLD_NC_STATUS */ + +#if !defined(NTRACE) && defined(TRACING) +LOCAL const char * nc_get_nc_state_str(UBYTE status) +{ + return alr_nc_state_trc[nc_get_nc_status(status)]; +} +#endif /* !NTRACE && TRACING */ +#if 0 /* not needed currently */ +#if defined(TRACING) +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_get_status | ++--------------------------------------------------------------------+ + +PURPOSE : The function returns the status for a channel. + +*/ + +LOCAL UBYTE nc_get_status (USHORT index) +{ + /* use pointer to save time and ROM */ + T_NC* pcell = &alr_data->nc_data.cell[index]; + + TRACE_USER_CLASS_P3 (TC_USER1, "NC%u[%d] %s", + index, + pcell->ba_arfcn EQ NOT_PRESENT_16BIT ? -1 : pcell->ba_arfcn&ARFCN_MASK, + nc_get_nc_state_str(pcell->status)); + + return pcell->status; +} +#endif /* TRACING */ +#endif /* 0|1 */ +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_set_status | ++--------------------------------------------------------------------+ + +PURPOSE : The function sets a new status for a channel. Depending on + the new status several variables which are not valid in + the new status are initialised to their default values. + + +*/ + +GLOBAL void nc_set_status (USHORT index, UBYTE new_status) +{ + /* use pointer to save time and ROM */ + T_NC* pcell = &alr_data->nc_data.cell[index]; + +#if defined(TRACING) + TRACE_EVENT_P4 ("NC%u[%d] %s -> %s", + index, + pcell->ba_arfcn EQ NOT_PRESENT_16BIT ? -1 : pcell->ba_arfcn&ARFCN_MASK, + nc_get_nc_state_str(pcell->status), + nc_get_nc_state_str(new_status)); +#endif /* TRACING */ + + switch (new_status) + { + case INACTIVE: + pcell->bsic = NOT_PRESENT_8BIT; + pcell->frame_offset = NOT_PRESENT_32BIT; + pcell->time_align = NOT_PRESENT_32BIT; + pcell->last_rxlev = 0; + pcell->c_rxlev = NOT_PRESENT_8BIT; + pcell->rxlev_average = 0; + memset (pcell->rxlev, 0, 5); + pcell->one_of_six = FALSE; + pcell->one_of_twelve = FALSE; + pcell->c_attempt = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->tim_valid = TV_INVALID_TIMING_INFO; + pcell->blocks_required = 0; + pcell->c_error = 0; + nc_clean_store_bcch (index); + break; + + case IDLE: + pcell->bsic = NOT_PRESENT_8BIT; +/* pcell->frame_offset = 0; + pcell->time_align = 0; + pcell->last_rxlev = 0; */ + pcell->one_of_six = FALSE; + pcell->one_of_twelve = FALSE; + /*pcell->c_attempt = 0;*/ + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->blocks_required = 0; + pcell->c_error = 0; + nc_clean_store_bcch (index); + break; + + case READ_FB_SB: + case READ_FB_SB_PENDING: + pcell->bsic = NOT_PRESENT_8BIT; +/* pcell->frame_offset = 0; + pcell->time_align = 0; */ + pcell->last_rxlev = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->blocks_required = 0; + pcell->c_error = 0; + nc_clean_store_bcch (index); + break; + + case READ_BCCH: + pcell->last_rxlev = 0; + /*pcell->c_attempt = 0;*/ + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->c_error = 0; + pcell->blocks_required = 0; + nc_clean_store_bcch (index); + break; + case READ_BCCH_RR_NOT_INFORMED: + pcell->last_rxlev = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->c_error = 0; + pcell->blocks_required = 0; + nc_clean_store_bcch (index); + break; + + case FB_SB_SYNC_RR_NOT_INFORMED: + pcell->last_rxlev = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->blocks_required = 0; + pcell->c_attempt = 0; + pcell->c_error = 0; + break; + + case FB_SB_SYNC: + pcell->last_rxlev = 0; + pcell->blocks_required = 0; + if (!pcell->one_of_six) + pcell->c_attempt = 0; + pcell->c_error = 0; + pcell->c_sync = C_INVALID_SYNC; + nc_clean_store_bcch (index); + break; + + case READ_SB: + case READ_SB_PENDING: + pcell->last_rxlev = 0; + pcell->c_sync = C_INVALID_SYNC; + pcell->blocks_required = 0; + /*pcell->c_attempt = 0;*/ + pcell->c_error = 0; + nc_clean_store_bcch (index); + break; + + case READ_SB_BCCH: + case READ_SB_BCCH_PENDING: + pcell->last_rxlev = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->blocks_required = 0; + pcell->c_error = 0; + /*pcell->c_attempt = 0;*/ + nc_clean_store_bcch (index); + break; + + + case IDLE_SYNC: + pcell->last_rxlev = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->one_of_six = FALSE; + pcell->one_of_twelve = FALSE; + pcell->c_attempt = 0; + pcell->blocks_required = 0; + pcell->c_error = 0; + pcell->c_sync = alr_data->nc_data.c_nc_timer; /*TODO maybe move this to a function*/ + nc_clean_store_bcch (index); + break; + + case FB_SB_FAILED: + pcell->bsic = NOT_PRESENT_8BIT; + if (pcell->status EQ READ_FB_SB_PENDING) + { + pcell->frame_offset = NOT_PRESENT_32BIT; + pcell->time_align = NOT_PRESENT_32BIT; + pcell->tim_valid = TV_INVALID_TIMING_INFO; + } + else + pcell->tim_valid = TV_APPROX_TIMING_INFO; + pcell->last_rxlev = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->blocks_required = 0; + pcell->c_error = 0; + nc_clean_store_bcch (index); + break; + + case EXCLUDED: + pcell->bsic = NOT_PRESENT_8BIT; + pcell->frame_offset = NOT_PRESENT_32BIT; + pcell->time_align = NOT_PRESENT_32BIT; + pcell->one_of_six = FALSE; + pcell->one_of_twelve = FALSE; + pcell->last_rxlev = pcell->rxlev_average; /* TODO maybe move this to a function */ + pcell->c_attempt = 0; + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + pcell->tim_valid = TV_INVALID_TIMING_INFO; + pcell->blocks_required = 0; + pcell->c_error = 0; + nc_clean_store_bcch (index); + break; + + case READ_BCCH_PENDING: + case READ_BCCH_PENDING_RR_NOT_INFORMED: + pcell->last_rxlev = 0; + /*pcell->c_attempt = 0;*/ + pcell->c_bcch = C_INVALID_BCCH; + pcell->c_sync = C_INVALID_SYNC; + nc_clean_store_bcch (index); + break; + } + + /* + * set new status + */ + pcell->status = new_status; +} + +GLOBAL void nc_check_activity (void) +{ + int i; + switch(GET_STATE(STATE_NC)) + { + case NC_IDLE: + /* count number of reports */ + alr_data->nc_data.c_reports++; + + nc_rank_ncells (); + nc_check_status (CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL); + nc_process_status(); + + if (first_period AND !first_l1_meas) + { + if (alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports OR + alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports - 1) + { + UBYTE all_sync = TRUE; + /* + * for every ncell + */ + for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++) + { + if (alr_data->nc_data.cell[i].status EQ READ_BCCH_PENDING OR + alr_data->nc_data.cell[i].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED) + { + /* not all needed SI are read yet */ + all_sync = FALSE; + break; + } + } + if (!all_sync AND + alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports) + { + /* spend an additional reporting period to give FTA 20.7 a better chance to pass */ + alr_data->nc_data.c_reports--; + first_period = FALSE; + ALR_TRACE_NC ("one additional period"); + } + else if (all_sync AND + alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports - 1) + { + /* skip an additional reporting period to give FTA 20.19 a better chance to pass */ + alr_data->nc_data.c_reports++; + first_period = FALSE; + ALR_TRACE_NC ("one period skipped"); + } + } + } + first_l1_meas = FALSE; + +#if defined(_SIMULATION_) + TRACE_EVENT_P2 ("c_reports=%u/%u", + alr_data->nc_data.c_reports, alr_data->nc_data.max_reports); +#endif /* WIN32 */ + + /* check if 5sec have passed, we then have to inform RR */ + if (alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports) + { + USHORT index, average; + T_NC* pcell; + PALLOC (report, MPH_MEASUREMENT_IND); + memset (report, 0, sizeof (T_MPH_MEASUREMENT_IND)); + + first_period = FALSE; +#ifdef GPRS + report->gprs_sync = NORMAL_MEAS_REP; +#endif + + report->arfcn = alr_data->serving_cell; + + average = 0; + index = nc_get_index(alr_data->serving_cell); + if ( index NEQ NOT_PRESENT_16BIT ) + { + pcell = &alr_data->nc_data.cell[index]; + pcell->rxlev_average = 0; /* Is this really needed? */ + for (i = 0; i < 5; i++) + average += pcell->rxlev[i]; + } + + report->rx_lev_full = (UBYTE) (average / 5); + report->fn_offset = alr_data->nc_data.fn_offset; + + alr_data->nc_data.c_reports = 0; + + nc_build_rr_report (report); + ma_nc_report_res (report); + nc_release_bcch (); + } + break; + case NC_DEDICATED: + nc_rank_ncells (); + nc_check_status (CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL); + nc_process_status(); + { + PALLOC(mph_measurement_ind, MPH_MEASUREMENT_IND); +#ifdef GPRS + mph_measurement_ind->gprs_sync = NORMAL_MEAS_REP; +#endif + nc_build_rr_report_dedi (mph_measurement_ind); + ma_nc_report_res (mph_measurement_ind); + } + break; + default: + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_set_fb_sb_sync_initial | ++--------------------------------------------------------------------+ + +PURPOSE : Inital setting of status FB_SB_SYNC. Counter for SB + confirmation and BCCH re-reading are initialized. + +*/ + +LOCAL void nc_set_fb_sb_sync_initial (USHORT index) +{ + alr_data->nc_data.cell[index].c_bcch = FIVE_MINUTES; + + if(!alr_data->nc_data.eotd_avail) + { + /*round to next confirmation boundary */ + if(alr_data->nc_data.c_nc_timer NEQ THIRTY_SECONDS) + alr_data->nc_data.cell[index].c_bcch += alr_data->nc_data.c_nc_timer; + } + + nc_set_status (index, FB_SB_SYNC); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_set_fb_sb_failed | ++--------------------------------------------------------------------+ + +PURPOSE : Set the status to FB_SB_FAILED, update the attempt counter + and set time until next attempt is started. + +*/ + +LOCAL void nc_set_fb_sb_failed (USHORT index, + UBYTE c_sync) +{ + alr_data->nc_data.cell[index].c_attempt++; + alr_data->nc_data.cell[index].c_sync = c_sync; + nc_set_status (index, FB_SB_FAILED); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_rxlev_sc_req | ++--------------------------------------------------------------------+ + +PURPOSE : A new RXLEV value of the serving cell has been measured. + Inform GPL in case it is necessary. + +*/ +#ifdef GPRS + +LOCAL void nc_rxlev_sc_req (UBYTE rxlev) +{ + if(GET_STATE (STATE_NC) EQ NC_IDLE) + { + PALLOC (rxlev_sc_req, TB_RXLEV_SC_REQ); + + rxlev_sc_req->sc_rxlev = rxlev; + + ma_nc_rxlev_sc_req (rxlev_sc_req); + } +} + +#endif /* #ifdef GPRS */ + +#if defined(_SIMULATION_) +LOCAL void trace_nc(void) +{ + char buf[80]; + int i, o; + T_NC* pcell; + o = sprintf (buf, "NC: "); + + for (i=0,pcell = &alr_data->nc_data.cell[0]; i < alr_data->nc_data.c_ba_arfcn; i++,pcell++) + { + if(pcell->ba_arfcn EQ alr_data->serving_cell) + { + o += sprintf (buf+o, "%u[SC=%u]%u, ", i, pcell->ba_arfcn, pcell->ba_status); + } + else + { + o += sprintf (buf+o, "%u[%u]%u, ", i, pcell->ba_arfcn, pcell->ba_status); + } + if (o > 60) + { + TRACE_EVENT (buf); + o = sprintf (buf, "NC: "); + } + } + if (o>4) + { + buf[o-2]=0; + TRACE_EVENT (buf); + } +} +#endif /* _SIMULATION_ */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_check_new_strong_cell | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the New strong cell criteria + +*/ + +LOCAL void nc_check_new_strong_cell(USHORT index, UBYTE o_1of6, + UBYTE rxlev) +{ + T_NC* pcell = &alr_data->nc_data.cell[index]; + + if((pcell->one_of_six ) AND (!o_1of6)) + { + /* NCELL confirmation active. New 1of6 cell found */ + if((pcell->rxlev_average > rxlev) AND + ((pcell->rxlev_average - rxlev ) >= 5)) + pcell->new_strong_cell = TRUE; + } + else if ((pcell->one_of_six ) AND (o_1of6) AND + (pcell->status EQ READ_FB_SB) AND + (pcell->c_attempt EQ 0 )) + { + /* NCELL confirmation interrupted the sync of last 1of6 cell + * This has to be synchronized again + */ + pcell->new_strong_cell = TRUE; + } + + if(pcell->new_strong_cell) + { + alr_data->nc_data.new_strong_cell_detect = TRUE; + TRACE_EVENT_P1("[%d]New strong cell",pcell->ba_arfcn); + } + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6103) MODULE : ALR_NC | +| STATE : code ROUTINE : nc_handle_new_strong_cells | ++--------------------------------------------------------------------+ + + PURPOSE : Processes cell synchronisation. + +*/ + +LOCAL void nc_handle_new_strong_cells(void) +{ + USHORT i; + USHORT index; + UBYTE first_sync_req = TRUE; + T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ]; + + alr_data->nc_data.c_sync_intrupted = FALSE; + + while (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT) + { + /* + * It is possible to send more sync requests to layer 1 + */ + USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn; + index = NOT_PRESENT_16BIT; + + for (i = 0; i < c_ba_arfcn; i++) + { + /* + * search for "New strong cell" with the highest fieldstrength + */ + T_NC* pcell = &alr_data->nc_data.cell[i]; + + if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND + (pcell->ba_arfcn NEQ alr_data->serving_cell) AND + (pcell->new_strong_cell)) + { + switch (pcell->status) + { + case READ_FB_SB: + if (index EQ NOT_PRESENT_16BIT) + index = i; + else + { + if (pcell->rxlev_average > + alr_data->nc_data.cell[index].rxlev_average) + index = i; + } + break; + default: + break; + } + } + } + + if (index NEQ NOT_PRESENT_16BIT) + { + + if(first_sync_req EQ TRUE) + { + first_sync_req = FALSE; + + if(alr_data->nc_data.c_sync_req > 0) + { + + TRACE_EVENT("RE-SYNC interrupted"); + alr_data->nc_data.c_sync_intrupted = TRUE; + + nc_stop_all(); + + if(!alr_data->nc_data.c_sync_req) + { + alr_data->nc_data.tim_state = NC_CONF_PENDING; + SET_STATE(STATE_NC_PROC, NC_ACQUIRE); + } + } + } /* first_sync_req */ + + /* + * Request synchronisation for this cell + */ + nc_build_sync_req(index); + alr_data->nc_data.cell[index].new_strong_cell = FALSE; + TRACE_EVENT_P1("[%d]N_S_C sync req",alr_data->nc_data.cell[index].ba_arfcn); + } + else + break; /*while loop */ + } /* while( c_sync_req < MAX_L1_SYNC_CNT) */ +} +#endif