comparison src/g23m-gsm/alr2/alr_nc.c @ 2:3a14ee9a9843

src/g23m-gsm: same alr2 & alr3 structure as in Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:29:12 +0000
parents
children
comparison
equal deleted inserted replaced
1:fa8dc04885d8 2:3a14ee9a9843
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : GSM-PS
4 | Modul : ALR_NC
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : This Modul defines the SDL process Idle_Neighbour_Cells.
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifndef ALR_NC_C
22 #define ALR_NC_C
23
24 #define ENTITY_PL
25
26 /*==== INCLUDES ===================================================*/
27 #include <string.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include <ctype.h>
31 #include "typedefs.h"
32 #include "message.h"
33 #include "ccdapi.h"
34 #include "vsi.h"
35 #include "custom.h"
36 #include "gsm.h"
37 #include "prim.h"
38 #include "cnf_alr.h"
39 #include "mon_alr.h"
40 #include "pei.h"
41 #include "tok.h"
42 #include "pcm.h"
43 #ifdef GPRS
44 #include "alr_gprs.h"
45 #endif
46
47 #if !defined(NTRACE)
48 #define TRACING
49 #endif /* !TRACING */
50
51 #include "alr.h"
52 #include "alr_em.h"
53
54 #if !defined(NTRACE) && defined(TRACING)
55 LOCAL const char *nc_get_nc_state_str(UBYTE status);
56 LOCAL const char * const alr_nc_state_trc[18] = {
57 "INACT",
58 "IDLE",
59 "RD_BCCH",
60 "FB_SB_SYNC",
61 "FB_SB_FAIL",
62 "RD_FB_SB",
63 "RD_SB",
64 "IDLE_SYNC",
65 "EXCL",
66 "FB_SB_SYNC_RR",
67 "RD_SB_BCCH",
68 "RD_BCCH_P",
69 "RD_FB_SB_P",
70 "RD_SB_P",
71 "RD_SB_BCCH_P",
72 "RD_BCCH_RR",
73 "RD_BCCH_P_RR",
74 "???"};
75 #endif /* !NTRACE && TRACING */
76 LOCAL const UBYTE unc_values[] =
77 {
78 2, 4, 8, 12, 16, 22, 30, NOT_PRESENT_8BIT
79 };
80 /*==== EXPORT =====================================================*/
81
82 /*==== PRIVAT =====================================================*/
83 LOCAL void nc_update_ba_list (USHORT serving_cell,
84 T_MPH_NEIGHBOURCELL_REQ * ncell_list);
85 LOCAL UBYTE nc_remove_channel_from_ba_list (USHORT index);
86 LOCAL UBYTE nc_is_in_ncell_list (USHORT channel,
87 T_MPH_NEIGHBOURCELL_REQ * ncell_list);
88 LOCAL void nc_process_status (void);
89 LOCAL void nc_process_status_sync (void);
90 LOCAL void nc_process_status_last_bsic (void);
91 LOCAL void nc_process_status_bcch (void);
92 LOCAL BOOL nc_ncell_in_plmn_permitted (UBYTE bsic);
93 LOCAL void nc_find_cells (USHORT * c_found,
94 USHORT max,
95 UBYTE limitation,
96 UBYTE min_rxlev);
97 LOCAL void nc_store_rxlev (T_MPHC_RXLEV_PERIODIC_IND * report);
98 LOCAL void nc_rank_ncells (void);
99 LOCAL void nc_check_status (UBYTE start_list);
100 LOCAL void nc_build_rr_report_dedi (T_MPH_MEASUREMENT_IND * rr_report);
101
102 LOCAL void nc_store_dedicated (T_MPHC_MEAS_REPORT * report);
103 LOCAL UBYTE nc_convert_quality (USHORT errors,
104 USHORT total);
105 LOCAL void nc_store_bcch (T_MPHC_DATA_IND * data_ind,
106 USHORT index,
107 UBYTE which);
108 LOCAL void nc_stop_bcch (USHORT index,
109 UBYTE new_status);
110 LOCAL void nc_stop_sync (USHORT index,
111 UBYTE new_status);
112 LOCAL void nc_clean_store_bcch (USHORT index);
113 LOCAL UBYTE nc_check_bsic (USHORT index,
114 UBYTE bsic);
115 #if 0
116 #if !defined(NTRACE) && defined(TRACING)
117 LOCAL UBYTE nc_get_status (USHORT index);
118 #endif /* !NTRACE && TRACING */
119 #endif /* 0|1 */
120 LOCAL void nc_restart_bcch (USHORT index);
121 LOCAL void nc_set_fb_sb_sync_initial (USHORT index);
122 LOCAL void nc_set_fb_sb_failed (USHORT index,
123 UBYTE c_sync);
124 LOCAL UBYTE nc_sys_info_78_required (USHORT index);
125 LOCAL void nc_sync_failed_attempt (USHORT index);
126 LOCAL void nc_sync_failed_attempt_dedicated(USHORT index);
127 LOCAL void nc_build_rr_report (T_MPH_MEASUREMENT_IND* rr_report);
128 LOCAL void nc_release_bcch (void);
129 LOCAL void nc_find_list_cells (void);
130 LOCAL void nc_ncell_list_req (void);
131 LOCAL void nc_start_eotd_confirm (void);
132 LOCAL void nc_process_pos_req (T_MPH_NCELL_POS_REQ* pos_req);
133 LOCAL void nc_check_sync_ind_eotd (T_MPHC_NCELL_SYNC_IND* sync_ind,
134 USHORT arfcn);
135 LOCAL void nc_store_eotd (T_eotd_sc_res* p_res,
136 T_MPHC_NCELL_SYNC_IND* sync_ind,
137 USHORT arfcn);
138 LOCAL void nc_sync_ind_last_bsic_req (T_MPHC_NCELL_SYNC_IND* sync_ind,
139 USHORT index,
140 USHORT arfcn,
141 UBYTE bsic);
142 LOCAL void nc_sync_ind_ncell (T_MPHC_NCELL_SYNC_IND* sync_ind,
143 USHORT index,
144 USHORT arfcn,
145 UBYTE bsic);
146 LOCAL void nc_clear_last_bsic (void);
147 #if 0
148 Symbol 'nc_stop_all_bcch(void)' 'nc_stop_all_sync(void)' and not referenced at the moment
149 LOCAL void nc_stop_all_bcch (void);
150 LOCAL void nc_stop_all_sync (void);
151 #endif /* 0|1 */
152 LOCAL void nc_stop_all (void);
153 LOCAL void nc_stop_all_inactive (void);
154 LOCAL void nc_stop_if_active (USHORT i);
155 LOCAL void nc_ncell_list_req_pos (T_ncell_list* p_ncell_list,
156 T_ncell_eotd* asd_cell,
157 USHORT arfcn);
158 LOCAL void nc_get_timing_eotd (T_ncell_list* p_ncell_list,
159 T_ncell_eotd* asd_cell);
160
161 LOCAL BOOL nc_is_sync (T_NC * p_ncell);
162 LOCAL void nc_build_sync_req (USHORT index);
163 LOCAL void nc_init_pos_ind (USHORT req_id);
164 LOCAL void nc_enable_conf (void);
165 LOCAL void nc_disable_conf (BOOL bFree);
166 LOCAL void nc_start_ncell_confirm (void);
167 LOCAL void nc_handle_new_strong_cells (void);
168 LOCAL void nc_check_new_strong_cell (USHORT index, UBYTE o_1of6, UBYTE rxlev);
169 #ifdef GPRS
170 LOCAL void nc_rxlev_sc_req (UBYTE rxlev);
171 LOCAL void nc_inform_grr_of_ncell (USHORT index,
172 UBYTE type);
173 LOCAL void remove_ncell_and_inform_grr (USHORT index);
174 LOCAL void nc_sync_failed_gprs (USHORT index);
175 LOCAL void nc_check_bsic_pbcch(T_MPH_NEIGHBOURCELL_REQ* ncell_list);
176 LOCAL void nc_process_status_sync_gprs(void);
177 #endif /* #ifdef GPRS */
178
179 #if defined(_SIMULATION_)
180 LOCAL void trace_nc(void);
181 #endif /* _SIMULATION_ */
182 LOCAL void nc_start_ncsync (void);
183
184 /*==== CONSTANTS ==================================================*/
185 #define MAX_L1_SYNC_CNT 12
186 #define MAX_L1_BCCH_CNT 6
187 #define MAX_L1_SYNC_EOTD_CNT 14
188 #define MAX_RR_NCELL_CNT 6
189
190 #define ONLY_BCC 7
191 #define ONLY_BSIC 63
192
193 #define NC_CHECK_OK 0
194 #define NC_CHECK_NCC_FAILED 1
195 #define NC_CHECK_BSIC_CHANGED 2
196
197 #define CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL 0
198 #define CHECK_FOR_CONFIRM 1
199
200 #define DONT_FREE_POS_IND 0
201 #define FREE_POS_IND 1
202
203 /*
204 * Counter to realize a time interval of 10sec in terms of Control Multiframe
205 * Idle state : 42 * 51 * 4.615ms = 9885ms
206 * Dedicated State : 42 * 104/2 * 4.615ms = 10079ms
207 */
208 #define TEN_SECONDS_NCSYNC 42
209
210 #define TEN_SECONDS 1
211 #define TWENTY_SECONDS 2
212 #define THIRTY_SECONDS 3
213 #define FIVE_MINUTES 30
214 #define C_INVALID_SYNC (THIRTY_SECONDS+1)
215 /* +2 for rounding BCCH reading to confirmation boundary */
216 #define C_INVALID_BCCH (FIVE_MINUTES+2+1)
217
218 #ifdef GPRS
219 #define GRR_SB_FOUND (MPH_BSIC_UNKNOWN+1)
220 #define GRR_SB_NOT_FOUND NOT_PRESENT_8BIT
221 #define GRR_SB_UNKNOWN MPH_BSIC_UNKNOWN
222 #endif
223
224 /*==== VARIABLES ==================================================*/
225
226 /*==== FUNCTIONS ==================================================*/
227 #if defined (WIN32) && !defined (_SIMULATION_)
228 #define _SIMULATION_
229 #endif
230
231 #if defined (_SIMULATION_)
232 #define TRACING
233 #endif /* _SIMULATION_ */
234
235 /*
236 * some traces
237 */
238 #if defined (TRACING)
239 #define ALR_TRACE_NC(a) ALR_TRACE(a)
240 #define ALR_TRACE_NC_CNT(a,b) TRACE_EVENT_P2 ("[%4u] c_sync %d", \
241 ARFCN_TO_G23(a)&ARFCN_MASK, b)
242 #define ALR_TRACE_NC_BSIC_CNF(a) TRACE_EVENT_P1 ("[%4u] NC BSIC CNF passed", \
243 ARFCN_TO_G23(a)&ARFCN_MASK)
244 #define ALR_TRACE_NC_SB_FAILED(a) TRACE_EVENT_P1 ("[%4u] NCELL SB IND failed", \
245 ARFCN_TO_G23(a)&ARFCN_MASK)
246 #define ALR_TRACE_NC_BSIC_REQ(a) TRACE_EVENT_P4 ("[%4u] NC BSIC REQ %d %d %d", \
247 a&ARFCN_MASK, GET_STATE (STATE_NC), \
248 alr_data->nc_data.cell[LAST_BSIC_REQ].status, \
249 alr_data->nc_data.c_bcch_req)
250 #define ALR_TRACE_NC_BCCH_OK(f,m) TRACE_EVENT_P2 ("[%4u] NCELL BCCH IND passed msg:%d", \
251 f&ARFCN_MASK,m)
252 #define ALR_TRACE_NC_SB_IND_PASSED(f) TRACE_EVENT_P1 ("[%4u] NCELL SB IND passed", \
253 f&ARFCN_MASK)
254 #define ALR_TRACE_NC_RESELECT(a) TRACE_EVENT_P1 ("[%4u] start reselect", a&ARFCN_MASK)
255 #define ALR_TRACE_NC_FN_TA(_i,f,t) TRACE_EVENT_P3 ("i %d, fn %d, ta %d ", _i, f, t)
256 #if 0
257 #define GET_NC_STATE(i) nc_get_status(i)
258 #endif /* 0|1 */
259 #if defined(_SIMULATION_)
260 #define ALR_TRACE_ALL_NC() trace_nc()
261 #else /* _SIMULATION_ */
262 #define ALR_TRACE_ALL_NC()
263 #endif /* _SIMULATION_ */
264 #else /* TRACING */
265 #define ALR_TRACE_NC(a)
266 #define ALR_TRACE_NC_CNT(a,b)
267 #define ALR_TRACE_NC_BSIC_CNF(a)
268 #define ALR_TRACE_NC_SB_FAILED(a)
269 #define ALR_TRACE_NC_BSIC_REQ(a)
270 #define ALR_TRACE_NC_BCCH_OK(f,m)
271 #define ALR_TRACE_NC_SB_IND_PASSED(f)
272 #define ALR_TRACE_NC_RESELECT(a)
273 #define ALR_TRACE_NC_FN_TA(i,f,t)
274 #define GET_NC_STATE(i) alr_data->nc_data.cell[i].status
275 #define ALR_TRACE_ALL_NC()
276 #undef TRACE_EVENT
277 #undef TRACE_EVENT_P1
278 #undef TRACE_EVENT_P2
279 #undef TRACE_EVENT_P3
280 #undef TRACE_EVENT_P4
281 #undef TRACE_EVENT_P5
282 #undef TRACE_EVENT_P6
283 #undef TRACE_EVENT_P7
284 #undef TRACE_EVENT_P8
285 #undef TRACE_EVENT_P9
286 #define TRACE_EVENT(s)
287 #define TRACE_EVENT_P1(s,a)
288 #define TRACE_EVENT_P2(s,a,b)
289 #define TRACE_EVENT_P3(s,a,b,c)
290 #define TRACE_EVENT_P4(s,a,b,c,d)
291 #define TRACE_EVENT_P5(s,a,b,c,d,e)
292 #define TRACE_EVENT_P6(s,a,b,c,d,e,f)
293 #define TRACE_EVENT_P7(s,a,b,c,d,e,f,g)
294 #define TRACE_EVENT_P8(s,a,b,c,d,e,f,g,h)
295 #define TRACE_EVENT_P9(s,a,b,c,d,e,f,g,h,i)
296 #endif /* TRACING */
297
298 /*
299 +--------------------------------------------------------------------+
300 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
301 | STATE : code ROUTINE : nc_init |
302 +--------------------------------------------------------------------+
303
304 PURPOSE : Initialize Idle Neighbour Cell Process.
305
306 */
307 GLOBAL void nc_init (void)
308 {
309 nc_stop_all();
310 alr_data->nc_data.c_ba_arfcn = 0;
311 alr_data->nc_data.ba_id = ALR_BA_LOW;
312 alr_data->nc_data.sc_included = FALSE;
313 alr_data->nc_data.cell[LAST_BSIC_REQ].status = IDLE;
314 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
315 alr_data->nc_data.c_reports = (UBYTE)-1;
316 alr_data->nc_data.cr_cell.ba_arfcn = NOT_PRESENT_16BIT;
317 alr_data->nc_data.tim_state = NC_TIM_STOPPED;
318 alr_data->nc_data.c_nc_timer = 0;
319 if (alr_data->nc_data.ppos_ind NEQ NULL)
320 {
321 PFREE(alr_data->nc_data.ppos_ind);
322 alr_data->nc_data.ppos_ind = NULL;
323 }
324 if (alr_data->nc_data.ppos_req NEQ NULL)
325 {
326 PFREE(alr_data->nc_data.ppos_req);
327 alr_data->nc_data.ppos_req = NULL;
328 }
329
330 /* Initialize the counter for realizing 10sec timer value */
331 alr_data->nc_data.c_ncsync_tim = 0;
332 alr_data->nc_data.ncsync_start_tim = 0;
333
334 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
335 SET_STATE(STATE_NC, NC_NULL);
336 }
337
338 #ifdef GPRS
339 /*
340 +----------------------------------------------------------------------+
341 | PROJECT : GSM-PS (6103) MODULE : ALR_GPRS |
342 | STATE : code ROUTINE : nc_start_pbcch|
343 +----------------------------------------------------------------------+
344
345 PURPOSE :Checks whether pbcch is available and sets a relevant state.
346
347 */
348
349 GLOBAL void nc_start_pbcch(void)
350 {
351 if(alr_data->gprs_data.ptm AND
352 alr_data->gprs_data.pbcch)
353 {
354 SET_STATE(STATE_NC, NC_PTM_PBCCH);
355 }
356 else if(alr_data->gprs_data.pbcch)
357 {
358 SET_STATE(STATE_NC, NC_PIM_PBCCH);
359 }
360
361 nc_enable_conf();
362 nc_process_status();
363 }
364
365 /*
366 +--------------------------------------------------------------------+
367 | PROJECT : GSM-PS (6103) MODULE : ALR_GPRS |
368 | STATE : code ROUTINE : gprs_check_bsic_pbcch |
369 +--------------------------------------------------------------------+
370
371 PURPOSE :
372
373 */
374 LOCAL void nc_check_bsic_pbcch(T_MPH_NEIGHBOURCELL_REQ* ncell_list)
375 {
376 TRACE_EVENT("gprs_alr_check_bsic_pbcch");
377 if(!alr_data->gprs_data.pbcch) return;
378
379 if(ncell_list->sync_only EQ SYNC_LIST)
380 {
381
382 USHORT n_rr; /* index of RR neighbor cell list */
383 USHORT n_alr; /* index of ALR neighbor cell list */
384 UBYTE last_alr; /* last index of ALR neighbor cell list */
385 USHORT arfcn;
386 TRACE_EVENT("pbcch/check bsic");
387
388 /*
389 * remove all channels which are not longer member of the
390 * neighbour cell list.
391 */
392 last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */
393 for (n_alr = 0; n_alr < last_alr; n_alr++)
394 {
395 arfcn = alr_data->nc_data.cell[n_alr].ba_arfcn;
396 if (!nc_is_in_ncell_list (arfcn, ncell_list))
397 /* AND
398 (arfcn NEQ alr_data->serving_cell))*/
399 {
400 switch(alr_data->nc_data.cell[n_alr].status)
401 {
402 case READ_FB_SB:
403 case READ_FB_SB_PENDING:
404 case READ_SB_PENDING:
405 case READ_SB:
406 case READ_SB_BCCH: /* in case we come from BCCH */
407 case INACTIVE: /* in case we returned from DEDIC */
408 case IDLE: /* in case we returned from DEDIC */
409 case EXCLUDED: /* in case we returned from DEDIC */
410 TRACE_EVENT_P1("rem cell i%d",n_alr);
411 remove_ncell_and_inform_grr(n_alr);
412 last_alr = alr_data->nc_data.c_ba_arfcn;
413 n_alr--;
414 break;
415 case FB_SB_SYNC_RR_NOT_INFORMED:
416 case READ_BCCH_RR_NOT_INFORMED:
417 case READ_BCCH:
418 case FB_SB_SYNC:
419 case IDLE_SYNC:
420 case FB_SB_FAILED:
421 /*state change will be done with check_status*/
422 TRACE_EVENT_P1("i%d reset 1o6", n_alr);
423 alr_data->nc_data.cell[n_alr].one_of_six = FALSE;
424 alr_data->nc_data.cell[n_alr].one_of_twelve = FALSE;
425 break;
426 default:
427 TRACE_EVENT_P3("i%d,arfcn:%d illegal status %d",n_alr,
428 alr_data->nc_data.cell[n_alr].ba_arfcn,
429 alr_data->nc_data.cell[n_alr].status);
430 break;
431 }
432 }
433 else
434 { /* ncell is in both lists */
435 switch(alr_data->nc_data.cell[n_alr].status)
436 {
437 case READ_FB_SB:
438 // case READ_FB_SB_PENDING:
439 //case READ_SB_PENDING:
440 case READ_SB:
441 break;
442 case READ_SB_BCCH: /* in case we come from BCCH */
443 nc_set_status(n_alr, READ_SB);
444 break;
445 case INACTIVE: /* in case we returned from DEDIC */
446 case IDLE: /* in case we returned from DEDIC */
447 case EXCLUDED: /* in case we returned from DEDIC */
448 nc_set_status (n_alr, INACTIVE);
449 /* ALR does not receive measurements */
450 /* set them to idle */
451 nc_set_status (n_alr, IDLE);
452 /* and set it to one_of_six , the rest is done by check_status */
453 nc_set_status(n_alr, READ_FB_SB);
454 break;
455 case FB_SB_SYNC_RR_NOT_INFORMED:
456 case READ_BCCH_RR_NOT_INFORMED:
457 case READ_BCCH:
458 nc_set_status(n_alr, FB_SB_SYNC);
459 break;
460 default:
461 break;
462 }
463 alr_data->nc_data.cell[n_alr].one_of_six = FALSE;
464 alr_data->nc_data.cell[n_alr].one_of_twelve = TRUE;
465 }
466 }
467
468 /*
469 * add all new channels.
470 */
471 for (n_rr = 0;
472 (n_rr < MAX_NEIGHBOURCELLS) AND (last_alr < BA_LIST_SIZE-1);
473 n_rr++)
474 {
475 arfcn = ncell_list->arfcn[n_rr];
476 if (arfcn EQ NOT_PRESENT_16BIT)
477 break; /* no more entries in the RR ncell_list */
478
479 n_alr = nc_get_index (arfcn);
480
481 if (((n_alr EQ NOT_PRESENT_16BIT) OR (n_alr EQ LAST_BSIC_REQ)) AND
482 (arfcn NEQ alr_data->serving_cell))
483 {
484 T_NC* pcell = &alr_data->nc_data.cell[last_alr];
485
486 #if defined(TRACING)
487 TRACE_EVENT_P2 ("NC%u[%u] add", last_alr, arfcn);
488 #endif /* TRACING */
489 pcell->ba_arfcn = arfcn;
490 nc_set_status (last_alr, INACTIVE);
491 /* ALR does not receive measurements */
492 /* set them to idle */
493 nc_set_status (last_alr, IDLE);
494 /* and set it to one_of_six , the rest is done by check_status */
495 alr_data->nc_data.cell[last_alr].one_of_six = FALSE;
496 alr_data->nc_data.cell[last_alr].one_of_twelve = TRUE;
497 alr_data->nc_data.cell[last_alr].ba_status = IN_BA;
498 last_alr++; /* increment last index */
499 }
500 }
501 alr_data->nc_data.c_ba_arfcn = last_alr; /* store new last index */
502 ALR_TRACE_ALL_NC ();
503
504 {
505 UBYTE six=0;
506 last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */
507 for (n_alr = 0; n_alr < last_alr; n_alr++)
508 {
509 six += alr_data->nc_data.cell[n_alr].one_of_six;
510 }
511 /*XXX change this to handle 12 ncells */
512 if(six > 6)
513 {
514 TRACE_ERROR("more then six candidates!");
515 }
516 }
517 #if 0 /*only for easing debugging */
518 /*
519 * Reorder the entries. The goal is that the propably strongest neigbour
520 * cells
521 * are measured in the first measurement period of a subsequent
522 * MPHC_RXLEV_PERIODIC_REQ/IND. The appropriate arfcn's are the first
523 * ones in
524 * ncell_list->arfcn
525 */
526 {
527 T_NC temp, *prr, *palr;
528
529 for (n_rr = 0; n_rr < 7; n_rr++)
530 {
531 if(ncell_list->arfcn[n_rr] NEQ NOT_PRESENT_16BIT)
532 n_alr = nc_get_index (ncell_list->arfcn[n_rr]);
533 else
534 break;
535
536 if ( ((n_alr NEQ NOT_PRESENT_16BIT) OR (n_alr NEQ LAST_BSIC_REQ)) AND
537 n_rr NEQ n_alr)
538 {
539 palr = &(alr_data->nc_data.cell[n_alr]);
540 prr = &(alr_data->nc_data.cell[n_rr]);
541 memcpy(&temp, palr, sizeof(T_NC));
542 memcpy(palr, prr, sizeof(T_NC));
543 memcpy(prr, &temp, sizeof(T_NC));
544 /*TRACE_EVENT_P4("reordered NC%u[%u] and NC%u[%u]",
545 n_rr,
546 ncell_list->arfcn[n_rr],
547 n_alr, ncell_list->arfcn[n_alr]);*/
548 }
549 }
550 }
551 #endif
552 nc_check_status(CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL);
553
554 if(alr_data->nc_sync_with_grr)
555 {
556 TRACE_EVENT("sync_with_grr");
557 last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */
558 for (n_alr = 0; n_alr < last_alr; n_alr++)
559 {
560 switch(alr_data->nc_data.cell[n_alr].status)
561 {
562 case IDLE_SYNC:
563 case FB_SB_SYNC:
564 case READ_SB:
565 case READ_SB_PENDING:
566 case READ_FB_SB_PENDING:
567 TRACE_EVENT_P1("sync %d",alr_data->nc_data.cell[n_alr].ba_arfcn);
568 nc_inform_grr_of_ncell(n_alr, GRR_SB_FOUND);
569 break;
570 case FB_SB_FAILED:
571 case EXCLUDED:
572 case INACTIVE:
573 case IDLE:
574 TRACE_EVENT_P1("sync %d",alr_data->nc_data.cell[n_alr].ba_arfcn);
575 nc_inform_grr_of_ncell(n_alr, GRR_SB_NOT_FOUND);
576 break;
577 /* READ_FB_SB ->the cell will be synchronized next
578 and a result will be returnded anyway */
579 default:
580 break;
581 }
582 }
583 alr_data->nc_sync_with_grr=FALSE;
584 }
585
586 switch(GET_STATE(STATE_NC))
587 {
588 case NC_PIM_PBCCH:
589 case NC_PTM_PBCCH:
590 nc_process_status();
591 break;
592 default:
593 break;
594 }
595 }
596 else if(ncell_list->sync_only EQ RECONFIRM_SYNC_LIST)
597 {
598 nc_ncsync_tim_expiry();
599 }
600
601 }
602
603 #endif
604 /*
605 +--------------------------------------------------------------------+
606 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
607 | STATE : code ROUTINE : nc_stop |
608 +--------------------------------------------------------------------+
609
610 PURPOSE : stop the neighbourcell process. Is called by main process
611 if a recovery with power measurements is started.
612
613 */
614
615 GLOBAL void nc_stop (void)
616 {
617 /*
618 * clean or neighbourcells of the BA and LAST_BSIC_REQ list if needed
619 */
620 nc_stop_all_inactive();
621
622 /*
623 * initialize neighbourcell process and stops timer
624 */
625 nc_init();
626 }
627
628 /*
629 +--------------------------------------------------------------------+
630 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
631 | STATE : code ROUTINE : nc_stop_all_inactive |
632 +--------------------------------------------------------------------+
633
634 PURPOSE : This stops all activities to bring a channel to state NC_NULL.
635
636 */
637
638 LOCAL void nc_stop_all_inactive (void)
639 {
640 UBYTE i, stopped_sync=0, stopped_bcch=0;
641 /*
642 * depending on the current status
643 */
644 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
645 {
646 switch (alr_data->nc_data.cell[i].status)
647 {
648 case READ_FB_SB_PENDING:
649 case READ_SB_PENDING:
650 case READ_SB_BCCH_PENDING:
651 /*
652 * stop the current running request for synchronisation in layer 1.
653 */
654 nc_set_status (i, INACTIVE);
655 stopped_sync++;
656 break;
657
658 case READ_BCCH_PENDING:
659 case READ_BCCH_PENDING_RR_NOT_INFORMED:
660 /*
661 * stop the current running request for BCCH reading in layer 1.
662 * If sys info 4 is already stored, but sys info 7 or 8 is requested
663 * clear also a stored BCCH message.
664 */
665 nc_set_status (i, INACTIVE);
666 stopped_bcch++;
667 break;
668 default:
669 /*
670 * sys infos are stored, but RR is still not informed.
671 * Then clean the stored message
672 */
673 nc_set_status (i, INACTIVE);
674 break;
675 }
676 }
677 switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status)
678 {
679 case READ_FB_SB_PENDING:
680 nc_set_status (LAST_BSIC_REQ, IDLE);
681 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
682 stopped_sync++;
683 break;
684 case READ_BCCH_PENDING:
685 nc_set_status (LAST_BSIC_REQ, IDLE);
686 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
687 stopped_bcch++;
688 break;
689 }
690
691 /*send to L1*/
692 if (stopped_sync > 0)
693 { /* stop all synchronizations */
694 PALLOC (stop_req, MPHC_STOP_NCELL_SYNC_REQ);
695 stop_req->radio_freq_array_size = MAX_L1_SYNC_CNT;
696 PSENDX(L1, stop_req);
697 }
698 if (stopped_bcch > 0)
699 { /* stop all bcch */
700 PALLOC (stop_req, MPHC_STOP_NCELL_BCCH_REQ);
701 stop_req->radio_freq_array_size = MAX_L1_BCCH_CNT;
702 PSENDX(L1, stop_req);
703 }
704 }
705
706 /*
707 +--------------------------------------------------------------------+
708 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
709 | STATE : code ROUTINE : nc_stop_all |
710 +--------------------------------------------------------------------+
711
712 PURPOSE : This stops all activities to bring a channel
713 its corresping READ_ state.
714
715 */
716
717 LOCAL void nc_stop_all (void)
718 {
719 UBYTE i, stopped_sync=0, stopped_bcch=0;
720 /*
721 * depending on the current status
722 */
723 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
724 {
725 switch (alr_data->nc_data.cell[i].status)
726 {
727 case READ_FB_SB_PENDING:
728 nc_set_status (i, READ_FB_SB);
729 stopped_sync++;
730 break;
731 case READ_SB_PENDING:
732 nc_set_status (i, READ_SB);
733 stopped_sync++;
734 break;
735 case READ_SB_BCCH_PENDING:
736 nc_set_status (i, READ_SB_BCCH);
737 stopped_sync++;
738 break;
739 case READ_BCCH_PENDING:
740 nc_set_status (i, READ_BCCH);
741 stopped_bcch++;
742 break;
743 case READ_BCCH_PENDING_RR_NOT_INFORMED:
744 nc_set_status (i, READ_BCCH_RR_NOT_INFORMED);
745 stopped_bcch++;
746 break;
747 case FB_SB_SYNC_RR_NOT_INFORMED:
748 nc_set_status (i, READ_BCCH_RR_NOT_INFORMED);
749 break;
750 }
751 }
752 switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status)
753 {
754 case READ_FB_SB_PENDING:
755 nc_set_status (LAST_BSIC_REQ, READ_FB_SB);
756 stopped_sync++;
757 break;
758 case READ_BCCH_PENDING:
759 nc_set_status (LAST_BSIC_REQ, READ_BCCH);
760 stopped_bcch++;
761 break;
762 }
763 /*send to L1*/
764 if ( stopped_sync > 0 OR
765 alr_data->nc_data.c_sync_req > 0 OR
766 (alr_data->nc_data.eotd_avail AND GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM))
767 { /* stop all synchronizations if waiting for any NC synchronization (or 2nd SC in EOTD case) */
768 PALLOC (stop_req, MPHC_STOP_NCELL_SYNC_REQ);
769 stop_req->radio_freq_array_size = MAX_L1_SYNC_CNT;
770 PSENDX(L1, stop_req);
771 alr_data->nc_data.c_sync_req=0;
772 if (alr_data->nc_data.eotd_avail)
773 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
774 }
775 if(stopped_bcch > 0)
776 { /* stop all bcch */
777 PALLOC (stop_req, MPHC_STOP_NCELL_BCCH_REQ);
778 stop_req->radio_freq_array_size = MAX_L1_BCCH_CNT;
779 PSENDX(L1, stop_req);
780 alr_data->nc_data.c_bcch_req=0;
781 }
782 }
783
784 #if 0
785 Symbol 'nc_stop_all_bcch(void)' not referenced at the moment
786 /*
787 +--------------------------------------------------------------------+
788 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
789 | STATE : code ROUTINE : nc_stop_all_sync |
790 +--------------------------------------------------------------------+
791
792 PURPOSE : This stops all sync activities.
793
794 */
795 LOCAL void nc_stop_all_sync (void)
796 {
797 UBYTE i, stopped_sync=0;
798 /*
799 * depending on the current status
800 */
801 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
802 {
803 switch (alr_data->nc_data.cell[i].status)
804 {
805 case READ_FB_SB_PENDING:
806 nc_set_status (i, READ_FB_SB);
807 stopped_sync++;
808 break;
809 case READ_SB_PENDING:
810 nc_set_status (i, READ_SB);
811 stopped_sync++;
812 break;
813 case READ_SB_BCCH_PENDING:
814 nc_set_status (i, READ_SB_BCCH);
815 stopped_sync++;
816 break;
817 }
818 }
819 switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status)
820 {
821 case READ_FB_SB_PENDING:
822 nc_set_status (LAST_BSIC_REQ, READ_FB_SB);
823 stopped_sync++;
824 break;
825 }
826 /*send to L1*/
827 if (stopped_sync > 0)
828 { /* stop all synchronizations */
829 PALLOC (stop_req, MPHC_STOP_NCELL_SYNC_REQ);
830 stop_req->radio_freq_array_size = MAX_L1_SYNC_CNT;
831 PSENDX(L1, stop_req);
832 alr_data->nc_data.c_sync_req=0;
833 }
834 }
835 #endif /* 0|1 */
836
837 #if 0
838 Symbol 'nc_stop_all_bcch(void)' not referenced at the moment
839 /*
840 +--------------------------------------------------------------------+
841 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
842 | STATE : code ROUTINE : nc_stop_all_bcch |
843 +--------------------------------------------------------------------+
844
845 PURPOSE : This stops all activities to bring a channel to state NC_NULL.
846
847 */
848 LOCAL void nc_stop_all_bcch (void)
849 {
850 UBYTE i, stopped_bcch=0;
851 /*
852 * depending on the current status
853 */
854 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
855 {
856 switch (alr_data->nc_data.cell[i].status)
857 {
858 case READ_BCCH_PENDING_RR_NOT_INFORMED:
859 nc_set_status (i, READ_BCCH_RR_NOT_INFORMED);
860 stopped_bcch++;
861 break;
862 case READ_BCCH_PENDING:
863 nc_set_status (i, READ_BCCH);
864 stopped_bcch++;
865 break;
866 }
867 }
868 switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status)
869 {
870 case READ_BCCH_PENDING:
871 nc_set_status (LAST_BSIC_REQ, READ_BCCH);
872 stopped_bcch++;
873 break;
874 }
875 /*send to L1*/
876 if (stopped_bcch > 0)
877 { /* stop all bcch */
878 PALLOC (stop_req, MPHC_STOP_NCELL_BCCH_REQ);
879 stop_req->radio_freq_array_size = MAX_L1_BCCH_CNT;
880 PSENDX(L1, stop_req);
881 alr_data->nc_data.c_bcch_req=0;
882 }
883 }
884 #endif /* 0|1 */
885
886 LOCAL void nc_clear_last_bsic(void)
887 {
888 switch (alr_data->nc_data.cell[LAST_BSIC_REQ].status)
889 {
890 case READ_BCCH_PENDING:
891 nc_stop_bcch (LAST_BSIC_REQ, IDLE);
892 break;
893 case READ_FB_SB_PENDING:
894 nc_stop_sync (LAST_BSIC_REQ, IDLE);
895 break;
896 }
897
898 nc_set_status(LAST_BSIC_REQ, IDLE);
899 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
900
901 }
902
903 LOCAL void nc_stop_if_active(USHORT i)
904 {
905 /*
906 * the requested channel number is member of the BA list.
907 * clear a request to layer 1 if needed.
908 */
909 switch(alr_data->nc_data.cell[i].status)
910 {
911 case READ_SB_PENDING:
912 nc_stop_sync (i, READ_SB);
913 break;
914 case READ_SB_BCCH_PENDING:
915 nc_stop_sync (i, READ_SB_BCCH);
916 break;
917 case READ_FB_SB_PENDING:
918 nc_stop_sync (i, READ_FB_SB);
919 break;
920 case READ_BCCH_PENDING:
921 nc_stop_bcch (i, READ_BCCH);
922 break;
923 case READ_BCCH_PENDING_RR_NOT_INFORMED:
924 nc_stop_bcch (i, READ_BCCH_RR_NOT_INFORMED);
925 break;
926 default:
927 break;
928 }
929 }
930 /*
931 +--------------------------------------------------------------------+
932 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
933 | STATE : code ROUTINE : nc_ncell_list |
934 +--------------------------------------------------------------------+
935
936 PURPOSE : Reception of a new neighbourcell list from RR.
937
938 */
939
940 GLOBAL void nc_ncell_list (T_MPH_NEIGHBOURCELL_REQ * mph_neighbourcell_req)
941 {
942 UBYTE i, j;
943 switch (GET_STATE (STATE_NC))
944 {
945 case NC_DEDICATED:
946 {
947 UBYTE c_ba_arfcn;
948 PALLOC (upd_dedi, MPHC_UPDATE_BA_LIST);
949
950 /*
951 * mix new list with old list
952 */
953 nc_update_ba_list (alr_data->serving_cell,
954 mph_neighbourcell_req);
955
956 /*
957 * create new list for layer 1
958 */
959 c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
960 for (i = 0, j = 0; i < c_ba_arfcn; i++)
961 {
962 if (alr_data->nc_data.cell[i].ba_status EQ IN_BA)
963 upd_dedi->chan_list.radio_freq[j++] =
964 ARFCN_TO_L1(alr_data->nc_data.cell[i].ba_arfcn);
965 }
966
967 /*
968 * send new list to layer 1
969 */
970 upd_dedi->num_of_chans = j;
971
972 alr_data->nc_data.ba_id = ALR_ALLOCATE_NEW_BA ( alr_data->nc_data.ba_id );
973 upd_dedi->ba_id = alr_data->nc_data.ba_id;
974
975 upd_dedi->pwrc = alr_data->nc_data.pwrc;
976 upd_dedi->dtx_allowed = alr_data->nc_data.dtx;
977
978 alr_data->nc_data.update = TRUE;
979 ma_nc_update_ba_list (upd_dedi);
980
981 }
982 break;
983 case NC_CON_EST: /*for PBCCH just update the list, is checked in
984 nc_check_bsic_pbcch */
985 #ifdef GPRS
986 case NC_PIM_PBCCH:
987 case NC_PTM_PBCCH:
988 nc_check_bsic_pbcch(mph_neighbourcell_req);
989 #endif
990 break;
991 default:
992 /*
993 * idle mode
994 */
995 ALR_TRACE_NC ("ncell req in idle");
996
997 /*
998 * mix new list with old list
999 */
1000 nc_update_ba_list (alr_data->serving_cell, mph_neighbourcell_req);
1001
1002 /*
1003 * configure layer 1 and start monitoring on new list
1004 */
1005 nc_start_monitoring();
1006 break;
1007 }
1008 }
1009
1010
1011 /*
1012 +--------------------------------------------------------------------+
1013 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1014 | STATE : code ROUTINE : nc_start_monitoring |
1015 +--------------------------------------------------------------------+
1016
1017 PURPOSE : Configure layer 1 with a new list for neighbourcell
1018 measurements.
1019
1020 */
1021
1022 static const UBYTE NO_OF_REPORTS [8] =
1023 {
1024 10, 7, 5, 4, 3, 3, 2, 2
1025 };
1026
1027 static const UBYTE INIT_OF_C_REPORTS [8] =
1028 {
1029 5, 5, 2, 2, 1, 1, 0, 0 /* empirical for FTA 20.7, 20.19, for TC 084, 047 */
1030 };
1031
1032 static BOOL first_period = FALSE, first_l1_meas = FALSE;
1033
1034 GLOBAL void nc_start_monitoring (void)
1035 {
1036 USHORT index, prim_index;
1037 UBYTE report_idx = alr_data->bs_pa_mfrms;
1038 UBYTE c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
1039 PALLOC (update, MPHC_RXLEV_PERIODIC_REQ);
1040
1041 ALR_TRACE_NC ("nc_start_mon");
1042
1043 first_period = first_l1_meas = TRUE;
1044
1045 alr_data->nc_data.max_reports = NO_OF_REPORTS [report_idx];
1046 alr_data->nc_data.fn_offset = (report_idx+2) * NO_OF_REPORTS[report_idx] * 51;
1047
1048 if (alr_data->nc_data.c_reports EQ (UBYTE)-1) /* initial value */
1049 alr_data->nc_data.c_reports = INIT_OF_C_REPORTS [report_idx];
1050 else /* don´t touch c_reports except for max_reports is less */
1051 if (alr_data->nc_data.c_reports >= alr_data->nc_data.max_reports)
1052 alr_data->nc_data.c_reports = alr_data->nc_data.max_reports - 1;
1053 index = nc_get_index(alr_data->serving_cell);
1054 if (index NEQ NOT_PRESENT_16BIT)
1055 alr_data->nc_data.cell[index].c_rxlev = NOT_PRESENT_8BIT;
1056
1057 /*
1058 * for all neighbourcells: convert channel number
1059 * and fill the primitive to layer 1.
1060 */
1061 for (index = 0, prim_index = 0; index < c_ba_arfcn; index++)
1062 {
1063 if (alr_data->nc_data.cell[index].ba_status EQ IN_BA)
1064 update->chan_list.radio_freq[prim_index++] =
1065 ARFCN_TO_L1(alr_data->nc_data.cell[index].ba_arfcn);
1066 }
1067
1068 /*
1069 * set number of channels and band id
1070 */
1071 update->num_of_chans = (UBYTE)prim_index;
1072 alr_data->nc_data.ba_id = ALR_ALLOCATE_NEW_BA ( alr_data->nc_data.ba_id );
1073 update->ba_id = alr_data->nc_data.ba_id;
1074 update->next_radio_freq_measured = 0;
1075
1076 #if defined(_SIMULATION_)
1077 {
1078 char buf[80], o;
1079 o = sprintf (buf, "RXLEV_PERIODIC: c=%d id=%02x:", update->num_of_chans, update->ba_id);
1080 for (index=0; index < update->num_of_chans; index++)
1081 {
1082 if (o > 80-6)
1083 {
1084 TRACE_EVENT (buf);
1085 o = 0;
1086 }
1087 o += sprintf (buf+o, "%u,", update->chan_list.radio_freq[index]);
1088 }
1089 buf[o-1]=0;
1090 TRACE_EVENT (buf);
1091 }
1092 #endif /* _SIMULATION_ */
1093
1094 SET_STATE (STATE_NC, NC_IDLE);
1095 /*
1096 TRACE_EVENT_P2("glob reps: %d max_report: %d",
1097 alr_data->nc_data.c_reports, alr_data->nc_data.max_reports);
1098 */
1099
1100 /*
1101 * configure layer 1.
1102 */
1103 ma_nc_rxlev_periodic_req(update);
1104
1105 nc_enable_conf();
1106 }
1107 /*
1108 +--------------------------------------------------------------------+
1109 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1110 | STATE : code ROUTINE : nc_enable_conf |
1111 +--------------------------------------------------------------------+
1112
1113 PURPOSE : Maintains what happens after 10 seconds interval.
1114 restarts a pending ncell confirmation
1115 */
1116 LOCAL void nc_enable_conf(void)
1117 {
1118 UBYTE tim_state = alr_data->nc_data.tim_state;
1119 UBYTE st = GET_STATE(STATE_NC);
1120
1121 TRACE_EVENT("nc_enable_conf()");
1122 alr_data->nc_data.tim_state = NC_CONF_ENABLED;
1123 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
1124 switch(tim_state)
1125 {
1126 case NC_TIM_STOPPED:
1127 if (alr_data->nc_data.ppos_req)
1128 nc_process_pos_req (alr_data->nc_data.ppos_req);
1129 /* Load the 10sec timer counter variable */
1130 nc_start_ncsync();
1131 break;
1132 case NC_CONF_PENDING:
1133 if (alr_data->nc_data.ppos_req)
1134 nc_process_pos_req (alr_data->nc_data.ppos_req);
1135 else
1136 nc_start_ncell_confirm();
1137 break;
1138 case NC_CONF_DISABLED:
1139 if (alr_data->nc_data.ppos_req)
1140 nc_process_pos_req (alr_data->nc_data.ppos_req);
1141 else if (alr_data->nc_data.c_nc_timer EQ 0)
1142 nc_start_ncell_confirm(); /* a confirmation is to restart */
1143 break;
1144 default:
1145 break;
1146 }
1147
1148
1149 /*XXX add PBCCH here also */
1150 #ifdef GPRS
1151 if ((st EQ NC_DEDICATED OR st EQ NC_PIM_PBCCH OR st EQ NC_PTM_PBCCH) AND
1152 #else
1153 if ((st EQ NC_DEDICATED) AND
1154 #endif
1155 alr_data->nc_data.c_nc_timer > TEN_SECONDS)
1156 {
1157 alr_data->nc_data.c_nc_timer = TEN_SECONDS;
1158 }
1159 else if (alr_data->nc_data.c_nc_timer EQ 0)
1160 {
1161 if( st EQ NC_DEDICATED OR alr_data->nc_data.eotd_avail
1162 #ifdef GPRS
1163 OR st EQ NC_PIM_PBCCH OR st EQ NC_PTM_PBCCH
1164 #endif
1165 )
1166 alr_data->nc_data.c_nc_timer = TEN_SECONDS;
1167 else
1168 alr_data->nc_data.c_nc_timer = THIRTY_SECONDS;
1169 }
1170 }
1171
1172 /*
1173 +--------------------------------------------------------------------+
1174 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1175 | STATE : code ROUTINE : nc_disable_conf |
1176 +--------------------------------------------------------------------+
1177
1178 PURPOSE : Maintains what happens after TIM_NCSYNC expiry.
1179 prevents ncell confirmation
1180 */
1181 LOCAL void nc_disable_conf(BOOL bFree)
1182 {
1183 TRACE_EVENT("nc_disable_conf()");
1184 switch(alr_data->nc_data.tim_state)
1185 {
1186 case NC_TIM_STOPPED:
1187 case NC_CONF_PENDING:
1188 TRACE_ERROR("nc_disable_conf() in unexpected state");
1189 break;
1190 default:
1191 break;
1192 }
1193
1194 if(bFree AND (alr_data->nc_data.ppos_ind NEQ NULL))
1195 {
1196 PFREE(alr_data->nc_data.ppos_ind);
1197 alr_data->nc_data.ppos_ind = NULL;
1198 }
1199
1200 if(GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM)
1201 {
1202 /*
1203 * restart confirmation if it was aborted
1204 * after the first expiry after the POS_REQ is done.
1205 */
1206 alr_data->nc_data.c_nc_timer = 0;
1207 }
1208
1209 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
1210 alr_data->nc_data.tim_state = NC_CONF_DISABLED;
1211 }
1212
1213 LOCAL void nc_start_ncell_confirm(void)
1214 {
1215 BOOL acquire = FALSE;
1216
1217 switch(GET_STATE(STATE_NC))
1218 {
1219 case NC_DEDICATED:
1220 case NC_IDLE:
1221 #ifdef GPRS
1222 case NC_PIM_PBCCH:
1223 case NC_PTM_PBCCH:
1224 #endif
1225 if (alr_data->nc_data.eotd_avail AND
1226 alr_data->nc_data.c_nc_timer EQ 0)
1227 {
1228 alr_data->nc_data.c_nc_timer = TEN_SECONDS;
1229
1230 nc_stop_all();
1231 nc_check_status(CHECK_FOR_CONFIRM);
1232 nc_start_eotd_confirm();
1233 }
1234 else if ((alr_data->nc_data.c_nc_timer EQ 0) OR
1235 (alr_data->nc_data.c_sync_intrupted EQ TRUE) )
1236 {
1237 /*
1238 * confirm ncells every thirty seconds in idle
1239 * or every 10 seconds in dedicated
1240 */
1241 if (GET_STATE(STATE_NC) EQ NC_DEDICATED
1242 #ifdef GPRS
1243 OR GET_STATE(STATE_NC) EQ NC_PIM_PBCCH
1244 OR GET_STATE(STATE_NC) EQ NC_PTM_PBCCH
1245 #endif
1246 )
1247 alr_data->nc_data.c_nc_timer = TEN_SECONDS;
1248 else
1249 alr_data->nc_data.c_nc_timer = THIRTY_SECONDS;
1250 nc_stop_all();
1251 nc_check_status(CHECK_FOR_CONFIRM);
1252 nc_ncell_list_req();
1253 /* if a list_req was send we are in NC_CONFIRM
1254 if no list_req was send we are in NC_ACQUIRE
1255 This is needed for PBCCH, because there are
1256 no measurements in ALR to trigger the initial
1257 synchronizations, so we have to check this here
1258 if no list_req was send, when a list_req was send
1259 then we continue with initial sync after the last
1260 sync_ind
1261 */
1262 if(GET_STATE(STATE_NC_PROC) EQ NC_ACQUIRE)
1263 acquire = TRUE;
1264
1265 }
1266 else /* acquire ncells (initial or previous failed ones) or
1267 * read bcch
1268 */
1269 {
1270 acquire = TRUE;
1271 }
1272
1273 if(acquire EQ TRUE)
1274 {
1275 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
1276 nc_check_status(CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL);
1277 nc_process_status();
1278 }
1279 break;
1280 default:
1281 TRACE_ERROR("nc_ncsync_tim_expiry in wrong state");
1282 break;
1283 }
1284 }
1285
1286 /*
1287 +--------------------------------------------------------------------+
1288 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1289 | STATE : code ROUTINE : nc_start_ncsync |
1290 +--------------------------------------------------------------------+
1291 PURPOSE : Assigns/resets c_ncsync_tim counter
1292 */
1293 LOCAL void nc_start_ncsync (void)
1294 {
1295 alr_data->nc_data.c_ncsync_tim = TEN_SECONDS_NCSYNC;
1296 TRACE_EVENT("NCSYNC counter loaded with 10 seconds");
1297 vsi_t_time(VSI_CALLER &alr_data->nc_data.ncsync_start_tim);
1298 }
1299
1300 /*
1301 +--------------------------------------------------------------------+
1302 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1303 | STATE : code ROUTINE : nc_ncsync_tim_expiry |
1304 +--------------------------------------------------------------------+
1305 PURPOSE : Called at the end of 10 seconds interval for NCELL synchronization
1306
1307 */
1308 GLOBAL void nc_ncsync_tim_expiry(void)
1309 {
1310 UBYTE i;
1311 UBYTE c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
1312 T_NC* pcell;
1313
1314 #ifdef GPRS
1315 if(!alr_data->gprs_data.pbcch)
1316 #endif
1317 {
1318 T_TIME tval;
1319 vsi_t_time(VSI_CALLER &tval);
1320 if(tval<alr_data->nc_data.ncsync_start_tim)
1321 TRACE_EVENT_P2("NCSYNC expiry at %d milliseconds, BS_PA_MFRMS = %d",
1322 ULONG_MAX-alr_data->nc_data.ncsync_start_tim+tval,
1323 alr_data->bs_pa_mfrms+2);
1324 else
1325 TRACE_EVENT_P2("NCSYNC expiry at %d milliseconds, BS_PA_MFRMS = %d",
1326 tval-alr_data->nc_data.ncsync_start_tim,
1327 alr_data->bs_pa_mfrms+2);
1328 }
1329
1330
1331
1332 if (alr_data->nc_data.tim_state NEQ NC_TIM_STOPPED)
1333 {
1334 #ifdef GPRS
1335 if(!alr_data->gprs_data.pbcch)
1336 #endif
1337 {
1338 nc_start_ncsync();
1339 }
1340
1341 if (alr_data->nc_data.c_nc_timer > 0)
1342 alr_data->nc_data.c_nc_timer--;
1343 TRACE_EVENT_P1("c_nc_timer %d", alr_data->nc_data.c_nc_timer);
1344
1345 /* decrement counters */
1346 for (i=0,pcell = &alr_data->nc_data.cell[0]; i < c_ba_arfcn; i++,pcell++)
1347 {
1348 if (pcell->c_sync > 0 AND pcell->c_sync < C_INVALID_SYNC)
1349 pcell->c_sync--;
1350 if (pcell->c_bcch > 0 AND pcell->c_bcch < C_INVALID_BCCH)
1351 pcell->c_bcch--;
1352
1353 if(pcell->ba_arfcn NEQ alr_data->serving_cell)
1354 {
1355 switch(pcell->ba_status)
1356 {
1357 case NOT_IN_BA_SHORT:
1358 pcell->ba_status = NOT_IN_BA_LONG;
1359 #if defined(TRACING)
1360 TRACE_EVENT_P2 ("NC%u[%u] -> NOT_IN_BA_LONG", i, pcell->ba_arfcn);
1361 #endif /* TRACING */
1362 break;
1363 case NOT_IN_BA_LONG:
1364 #if defined(TRACING)
1365 TRACE_EVENT_P2 ("NC%u[%u] remove", i, pcell->ba_arfcn);
1366 /* this trace must be performed before the removal to get right results */
1367 #endif /* TRACING */
1368 c_ba_arfcn = nc_remove_channel_from_ba_list (i);
1369 i--;
1370 pcell--;
1371 ALR_TRACE_ALL_NC ();
1372 break;
1373 case IN_BA:
1374 /* do nothing */
1375 break;
1376 }
1377 }
1378 }
1379 }
1380
1381 switch(alr_data->nc_data.tim_state)
1382 {
1383 case NC_CONF_ENABLED:
1384 nc_start_ncell_confirm();
1385 break;
1386 case NC_CONF_DISABLED:
1387 alr_data->nc_data.tim_state = NC_CONF_PENDING;
1388 break;
1389 case NC_CONF_PENDING:
1390 TRACE_ERROR("TIM_NCSYNC expiry in unexpected state");
1391 /*
1392 * this should never happen, but in case ALR is waiting
1393 * more than 20 seconds for the last MPHC_NCELL_SYNC_IND of the
1394 * confirmation procedure and the reason isn't a position request,
1395 * then the confirmation procedure is restarted
1396 */
1397 if (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM AND
1398 alr_data->nc_data.ppos_req EQ NULL)
1399 {
1400 alr_data->nc_data.c_nc_timer = 0;
1401 nc_start_ncell_confirm();
1402 }
1403 break;
1404 }
1405 }
1406 /*
1407 +--------------------------------------------------------------------+
1408 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1409 | STATE : code ROUTINE : nc_init_pos_ind |
1410 +--------------------------------------------------------------------+
1411
1412 PURPOSE : initial setting of a MPH_NCELL_POS_IND
1413
1414 */
1415
1416 LOCAL void nc_init_pos_ind (USHORT req_id)
1417 {
1418 memset(&(alr_data->nc_data.ppos_ind->eotd_sc_res), 0, sizeof (T_eotd_sc_res ));
1419 memset(&(alr_data->nc_data.ppos_ind->eotd_sc_res1), 0, sizeof (T_eotd_sc_res1));
1420 alr_data->nc_data.ppos_ind->c_eotd_nc_res = 0;
1421 alr_data->nc_data.ppos_ind->req_id = req_id;
1422 alr_data->nc_data.ppos_ind->eotd_res = 0;
1423 }
1424 /*
1425 +--------------------------------------------------------------------+
1426 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1427 | STATE : code ROUTINE : nc_is_sync |
1428 +--------------------------------------------------------------------+
1429
1430 PURPOSE : checks whether a ncell is synchronized and timing values
1431 are valid
1432
1433 */
1434 LOCAL BOOL nc_is_sync (T_NC * p_ncell)
1435 {
1436 switch (p_ncell->status)
1437 {
1438 case FB_SB_SYNC:
1439 case READ_SB:
1440 case READ_SB_BCCH:
1441 case READ_BCCH:
1442 case READ_BCCH_RR_NOT_INFORMED:
1443 case IDLE_SYNC:
1444 return TRUE;
1445 default:
1446 return FALSE;
1447 }
1448 }
1449 /*
1450 +--------------------------------------------------------------------+
1451 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1452 | STATE : code ROUTINE : nc_ncell_pos_req |
1453 +--------------------------------------------------------------------+
1454
1455 PURPOSE : reception of a ncell_pos_req
1456
1457 */
1458
1459 void nc_ncell_pos_req (T_MPH_NCELL_POS_REQ* pos_req)
1460 {
1461 /* if there is an earlier position request disgard it*/
1462 if (alr_data->nc_data.ppos_req NEQ NULL)
1463 PFREE(alr_data->nc_data.ppos_req);
1464 /* store the request until the end of the respective position indication */
1465 alr_data->nc_data.ppos_req = pos_req;
1466
1467 /*
1468 * process the request immediately if confirmation is enabled or
1469 * another measurement is in progress
1470 * (otherwise start processing when confirmation becomes enabled
1471 */
1472 if ( (alr_data->nc_data.tim_state EQ NC_CONF_ENABLED) OR
1473 (alr_data->nc_data.tim_state EQ NC_CONF_DISABLED AND
1474 GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) )
1475 nc_process_pos_req(pos_req);
1476 }
1477 /*
1478 +--------------------------------------------------------------------+
1479 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1480 | STATE : code ROUTINE : nc_process_pos_req |
1481 +--------------------------------------------------------------------+
1482
1483 PURPOSE : processes a ncell_pos_req
1484
1485 */
1486
1487 LOCAL void nc_process_pos_req (T_MPH_NCELL_POS_REQ* pos_req)
1488 {
1489 UBYTE fail=1;
1490
1491 if (alr_data->nc_data.ppos_ind EQ NULL)
1492 {
1493 PALLOC (pos_ind, MPH_NCELL_POS_IND);
1494 alr_data->nc_data.ppos_ind = pos_ind;
1495 }
1496
1497 nc_init_pos_ind(pos_req->req_id);
1498
1499 #if 0 /* allow position requests also in NC_IDLE mode to be able to answer a test SMS */
1500 switch(GET_STATE(STATE_NC))
1501 {
1502 case NC_DEDICATED:
1503 #endif /* 0|1 */
1504 if(alr_data->nc_data.eotd_avail)
1505 {
1506 T_NC* p_ncell;
1507 T_ncell_eotd* p_ncell_pos = &pos_req->ncell_eotd[0];
1508 T_NC* list_of_asd_1o12 [12];
1509 T_ncell_eotd* list_of_asd_ba [15];
1510 T_ncell_eotd* list_of_asd [15];
1511 T_NC** p_asd_1o12 = &list_of_asd_1o12[0];
1512 T_ncell_eotd** p_asd_ba = &list_of_asd_ba[0];
1513 T_ncell_eotd** p_asd = &list_of_asd[0];
1514 UBYTE c_ba = alr_data->nc_data.c_ba_arfcn;
1515 UBYTE i,j;
1516 UBYTE c_list;
1517 UBYTE found;
1518
1519 fail=0;
1520
1521 nc_stop_all();
1522
1523 /*
1524 * generate and send an appropriate MPHC_NCELL_LIST_SYNC_REQ
1525 * 1/ take all ncells which are in ASD list and the twelve
1526 * strongest synchronized of the BA list (using timing values
1527 * from former synchronisation)
1528 * 2/ then all ncells which are in ASD list and in the BA list
1529 * (using timings from the ASD list)
1530 * 3/ then rest of ASD cells (using timings from the ASD list)
1531 * 4/ then rest of BA list cells which are synchronized (using
1532 * timing values from former synchronisation)
1533 */
1534 {
1535 PALLOC (ncell_list_req, MPHC_NCELL_LIST_SYNC_REQ);
1536 ncell_list_req->eotd = TRUE;
1537
1538 /* for all ncells in ASD list */
1539 for(j=0; j < MAX_NCELL_EOTD_L1 AND j < pos_req->c_ncell_eotd;
1540 j++, p_ncell_pos++)
1541 {
1542 if (p_ncell_pos->arfcn EQ alr_data->serving_cell)
1543 {
1544 continue;
1545 }
1546 /* look if it is in BA list */
1547 found=FALSE;
1548 for (i = 0, p_ncell = &alr_data->nc_data.cell[0]; i < c_ba; i++, p_ncell++)
1549 {
1550 if(p_ncell_pos->arfcn EQ p_ncell->ba_arfcn)
1551 {
1552 /*
1553 * if it is in both list then check
1554 * if it is synchronized or not
1555 * and use the correct list
1556 */
1557 if(nc_is_sync(p_ncell))
1558 { /* case 1/ */
1559 *(p_asd_1o12++) = p_ncell;
1560 found=TRUE;
1561 }
1562 else
1563 { /* case 2/ */
1564 *(p_asd_ba++) = p_ncell_pos;
1565 found=TRUE;
1566 } /* is sync */
1567 break;
1568 } /*arfcn*/
1569 } /*ba list*/
1570
1571 /* if nothing was found, then it is case 3/ */
1572 if(!found)
1573 *(p_asd++) = p_ncell_pos;
1574
1575 } /* asd list */
1576
1577 c_list=0;
1578 for(i=0; c_list < MAX_L1_SYNC_CNT AND i < p_asd_1o12-list_of_asd_1o12;i++)
1579 {
1580 nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++],
1581 NULL,
1582 list_of_asd_1o12[i]->ba_arfcn);
1583 } /*asd_1o12 */
1584 for(i=0 ;c_list < MAX_L1_SYNC_CNT AND i < p_asd_ba-list_of_asd_ba;i++)
1585 {
1586 nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++],
1587 list_of_asd_ba[i],
1588 list_of_asd_ba[i]->arfcn);
1589
1590 }
1591 for(i=0 ;c_list < MAX_L1_SYNC_CNT AND i < p_asd-list_of_asd;i++)
1592 {
1593 nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++],
1594 list_of_asd[i],
1595 list_of_asd[i]->arfcn);
1596 }
1597 /*
1598 * fill the ncell list req with the remaining synchronized
1599 * neigbour cells of the BA list (case 4/ )
1600 */
1601 for (i=0, p_ncell = &alr_data->nc_data.cell[0];
1602 c_list < MAX_L1_SYNC_CNT AND i < c_ba;
1603 i++, p_ncell++)
1604 {
1605 if (p_ncell->ba_arfcn EQ alr_data->serving_cell)
1606 {
1607 continue;
1608 }
1609 if (nc_is_sync(p_ncell))
1610 {
1611 USHORT l1_arfcn = ARFCN_TO_L1(p_ncell->ba_arfcn);
1612 found=FALSE;
1613 for (j=0; j < c_list;j++)
1614 {
1615 if (ncell_list_req->ncell_list[j].radio_freq EQ l1_arfcn)
1616 {
1617 found = TRUE;
1618 break;
1619 }
1620 } /* MPHC_NCELL_LIST_SYNC_REQ */
1621 if (!found)
1622 nc_ncell_list_req_pos(&ncell_list_req->ncell_list[c_list++],
1623 NULL,
1624 p_ncell->ba_arfcn);
1625 } /* is sync */
1626 } /* BA list */
1627
1628 if (c_list > 0)
1629 {
1630 ncell_list_req->list_size = c_list;
1631 alr_data->nc_data.c_sync_req = c_list;
1632 if (c_list < MAX_NCELL_EOTD_L1)
1633 memset(&(ncell_list_req->ncell_list[c_list]),
1634 0,
1635 (MAX_NCELL_EOTD_L1 - c_list) * sizeof(T_ncell_list));
1636
1637 alr_data->nc_data.c_sync_req += 2; /* for the 2 scell ind's */
1638 nc_disable_conf(DONT_FREE_POS_IND);
1639 SET_STATE(STATE_NC_PROC, NC_CONFIRM);
1640 ma_nc_list_sync_req (ncell_list_req);
1641 TRACE_EVENT_P1("MPHC_NCELL_LIST_SYNC_REQ eotd=TRUE c_sync_req=%u", alr_data->nc_data.c_sync_req);
1642 }
1643 else
1644 fail = TRUE;
1645 }/* PALLOC list_req */
1646 } /* eotd_avail */
1647 /* else fail=1*/
1648 #if 0
1649 break;
1650 default:
1651 /*fail=1*/
1652 break;
1653 } /*switch NC_STATE*/
1654 #endif /* 0|1 */
1655
1656 if(fail)
1657 { /* TODO complete ?? */
1658 alr_data->nc_data.ppos_ind->eotd_res = EOTD_REF;
1659 PSENDX(RR, alr_data->nc_data.ppos_ind);
1660 alr_data->nc_data.ppos_ind = NULL;
1661 PFREE(pos_req);
1662 alr_data->nc_data.ppos_req = NULL;
1663 }
1664 }
1665
1666 /*
1667 +--------------------------------------------------------------------+
1668 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1669 | STATE : code ROUTINE : nc_ncell_list_req_pos |
1670 +--------------------------------------------------------------------+
1671
1672 PURPOSE : Handles cell lists.
1673
1674 */
1675
1676 LOCAL void nc_ncell_list_req_pos(T_ncell_list* p_ncell_list,
1677 T_ncell_eotd* asd_cell,
1678 USHORT arfcn)
1679 {
1680 USHORT index = nc_get_index(arfcn);
1681
1682 p_ncell_list->radio_freq = ARFCN_TO_L1(arfcn);
1683
1684 if(asd_cell)
1685 {
1686 if(index NEQ NOT_PRESENT_16BIT AND index NEQ LAST_BSIC_REQ AND
1687 alr_data->nc_data.cell[index].status EQ IDLE_SYNC)
1688 {
1689 p_ncell_list->fn_offset = alr_data->nc_data.cell[index].frame_offset;
1690 p_ncell_list->time_alignment = alr_data->nc_data.cell[index].time_align;
1691 p_ncell_list->timing_validity = TV_VALID_TIMING_INFO;
1692 /*TODO what about reception of ncell_sync_ind for this cell
1693 are timing info and counter updated ?*/
1694 }
1695 else
1696 {
1697 nc_get_timing_eotd(p_ncell_list, asd_cell);
1698 p_ncell_list->timing_validity = TV_VALID_TIMING_INFO; /* TV_APPROX_TIMING_INFO;*/
1699 }
1700 } /*asd_cell*/
1701 else
1702 {
1703 if(index NEQ NOT_PRESENT_16BIT AND index NEQ LAST_BSIC_REQ)
1704 {
1705 /* cell is in BA list and 1o12, so use the data we have */
1706 switch(alr_data->nc_data.cell[index].status)
1707 {
1708 case READ_SB_BCCH:
1709 case READ_BCCH:
1710 nc_set_status(index,READ_SB_BCCH_PENDING);
1711 break;
1712 case READ_SB:
1713 case FB_SB_SYNC:
1714 nc_set_status(index,READ_SB_PENDING);
1715 break;
1716 case READ_FB_SB:
1717 case READ_BCCH_RR_NOT_INFORMED:
1718 case FB_SB_SYNC_RR_NOT_INFORMED:
1719 /*TODO what about reception of ncell_sync_ind for this cell
1720 are timing info and counter updated ?*/
1721 break;
1722 } /*status*/
1723 p_ncell_list->fn_offset = alr_data->nc_data.cell[index].frame_offset;
1724 p_ncell_list->time_alignment = alr_data->nc_data.cell[index].time_align;
1725 p_ncell_list->timing_validity = TV_VALID_TIMING_INFO;
1726 }
1727 else
1728 {
1729 TRACE_ERROR("nc_ncell_list_req_pos: asd_cell==0 but cell not in BA");
1730 }
1731 }/*asd_cell*/
1732 }
1733
1734 LOCAL void nc_get_timing_eotd(T_ncell_list* p_ncell_list,
1735 T_ncell_eotd* asd_cell)
1736 {
1737 USHORT td, adjust = 0, offs;
1738 /*
1739 * The values mfrm_offset, rough_rtd and exp_otd are differences
1740 * between the BTS in question and the reference BTS.
1741 * L1 expects the differences between serving BTS and BTS in question:
1742 *
1743 * +----+----+----+----+----+....+----+----+----+----+----+ serving BTS
1744 * 0 51
1745 * |
1746 * 0 Net | L1 1250 (5000)
1747 * +---->V<----+
1748 * \ /
1749 * \ /
1750 * +----+----+----+----+----+....+----+----+----+----+----+ BTS in question
1751 * 0 51
1752 * +-----Net----->| |<---------L1----------------------+
1753 *
1754 * time differences are indicated in bits by the net, but expected
1755 * in quarterbits by L1
1756 */
1757
1758 offs = asd_cell->mfrm_offset;
1759
1760 if (asd_cell->otd_type EQ BOTH_OTD)
1761 {
1762 int diff = asd_cell->rough_rtd - asd_cell->exp_otd;
1763 if (diff >= 850)
1764 adjust = 1;
1765 else if (diff <= -850)
1766 adjust = -1;
1767 /*
1768 * GSM 04.31 section A.2.2.3 version 8.7.0 says that adjust shall be
1769 * equal 0 for -400 <= diff <= 400 and states an error for
1770 * -850 < diff < -450 and for 450 < diff < 850, but doesn't
1771 * describe the behaviour in this cases.
1772 * All this valid and invalid cases are implemented here by
1773 * adjust = 0
1774 */
1775 }
1776
1777 if (asd_cell->otd_type EQ ROUGH_OTD)
1778 td = asd_cell->rough_rtd;
1779 else
1780 { /*
1781 * uncertainty indicates how many bits the search window
1782 * for measurement should be opended earlier than the expected
1783 * value. Because of the subsequent subtraction we have to ADD
1784 * the uncertainty value.
1785 * no special handling for uncertainty value 7 (uncertainty > 30 bits)
1786 * is implemented yet
1787 */
1788 td = asd_cell->exp_otd + unc_values[asd_cell->uncertainty];
1789 if (td >= 1250)
1790 offs++;
1791 }
1792 td %= 1250;
1793
1794 if (td)
1795 {
1796 p_ncell_list->time_alignment = 5000 - 4 * td;
1797 offs++;
1798 }
1799 else
1800 p_ncell_list->time_alignment = 0;
1801
1802 offs = (offs + adjust) % 51;
1803
1804 if (offs)
1805 p_ncell_list->fn_offset = 51 - offs;
1806 else
1807 p_ncell_list->fn_offset = 0;
1808 }
1809 /*
1810 +--------------------------------------------------------------------+
1811 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1812 | STATE : code ROUTINE : nc_start_eotd_confirm |
1813 +--------------------------------------------------------------------+
1814
1815 PURPOSE : generates an MPHC_NCELL_LIST_SYNC_REQ from the BA list.
1816 */
1817 LOCAL void nc_start_eotd_confirm(void)
1818 {
1819 /*
1820 * this check is needed for the resume
1821 * in the GPRS case because we need
1822 * to keep the states over a
1823 * start transition
1824 */
1825 if(alr_data->nc_data.ppos_ind EQ NULL)
1826 {
1827 PALLOC (pos_ind, MPH_NCELL_POS_IND);
1828 alr_data->nc_data.ppos_ind = pos_ind;
1829 }
1830 nc_init_pos_ind (NOT_PRESENT_16BIT);
1831
1832 /* generate and send an appropriate MPHC_NCELL_LIST_SYNC_REQ */
1833 nc_ncell_list_req();
1834 }
1835
1836 /*
1837 +--------------------------------------------------------------------+
1838 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1839 | STATE : code ROUTINE : nc_ncell_list_req |
1840 +--------------------------------------------------------------------+
1841
1842 PURPOSE : generates an MPHC_NCELL_LIST_SYNC_REQ based on the 12
1843 strongest neighbour cells of the BA
1844
1845 */
1846 LOCAL void nc_ncell_list_req (void)
1847 {
1848 UBYTE c_found = 0, found, i, validity;
1849 USHORT c_ba = alr_data->nc_data.c_ba_arfcn;
1850 T_NC* pcell;
1851 T_ncell_list *pnc;
1852 PALLOC (ncell_list_req, MPHC_NCELL_LIST_SYNC_REQ);
1853
1854 if (alr_data->nc_data.c_sync_req NEQ 0)
1855 TRACE_EVENT_P1("nc_ncell_list_req with c_sync_req=%u before", alr_data->nc_data.c_sync_req);
1856
1857 ncell_list_req->eotd = alr_data->nc_data.eotd_avail;
1858
1859 nc_stop_all();
1860 for (i = 0, pcell = &alr_data->nc_data.cell[0]; i < c_ba; i++, pcell++)
1861 {
1862 if (alr_data->nc_data.eotd_avail AND pcell->ba_arfcn EQ alr_data->serving_cell)
1863 {
1864 continue;
1865 }
1866 if (pcell->one_of_twelve)
1867 {
1868 switch (pcell->status)
1869 {
1870 case READ_SB:
1871 nc_set_status(nc_get_index(pcell->ba_arfcn), READ_SB_PENDING);
1872 found = TRUE;
1873 validity = TV_VALID_TIMING_INFO;
1874 break;
1875 case READ_SB_BCCH:
1876 nc_set_status(nc_get_index(pcell->ba_arfcn), READ_SB_BCCH_PENDING);
1877 found = TRUE;
1878 validity = TV_VALID_TIMING_INFO;
1879 break;
1880 /* TODO(opt): if !eotd_avail maybe optimize later
1881 case READ_FB_SB:
1882 break*/
1883 /*
1884 case READ_BCCH_RR_NOT_INFORMED:
1885 case READ_BCCH_PENDING_RR_NOT_INFORMED:
1886 case READ_BCCH:
1887 case READ_BCCH_PENDING:
1888 found = TRUE;
1889 validity = TV_VALID_TIMING_INFO;
1890 break;*/
1891 default:
1892 found = FALSE;
1893 validity = TV_INVALID_TIMING_INFO;
1894 break;
1895 }
1896
1897 if (found)
1898 {
1899 pnc = &(ncell_list_req->ncell_list[c_found++]);
1900 pnc->radio_freq = ARFCN_TO_L1(pcell->ba_arfcn);
1901 if (validity EQ TV_VALID_TIMING_INFO)
1902 {
1903 pnc->fn_offset = pcell->frame_offset;
1904 pnc->time_alignment = pcell->time_align;
1905 }
1906 else
1907 {
1908 pnc->fn_offset = 0;
1909 pnc->time_alignment = 0;
1910 }
1911 pnc->timing_validity = validity;
1912 }
1913 }
1914 }
1915
1916 /*
1917 * in case there are no synchronized neighbour cells
1918 * send an empty MPHC_NCELL_LIST_SYNC_REQ to L1
1919 * (to serve the cursor task later with a position indication
1920 * containing measurements of the serving cell only)
1921 */
1922 if(c_found OR alr_data->nc_data.eotd_avail)
1923 {
1924 ncell_list_req->list_size = c_found;
1925 alr_data->nc_data.c_sync_req = c_found;
1926 if (c_found < MAX_NCELL_EOTD_L1)
1927 memset(&(ncell_list_req->ncell_list[c_found]),
1928 0,
1929 (MAX_NCELL_EOTD_L1 - c_found) * sizeof(T_ncell_list));
1930
1931 if(alr_data->nc_data.eotd_avail)
1932 /* add the 2 scell sync_ind */
1933 alr_data->nc_data.c_sync_req += 2;
1934
1935 nc_disable_conf(DONT_FREE_POS_IND);
1936 SET_STATE(STATE_NC_PROC, NC_CONFIRM);
1937 ma_nc_list_sync_req (ncell_list_req);
1938 TRACE_EVENT_P3("MPHC_NCELL_LIST_SYNC_REQ eotd=%d c_sync_req=%u SC=%u",
1939 alr_data->nc_data.eotd_avail,
1940 alr_data->nc_data.c_sync_req,
1941 alr_data->serving_cell);
1942 }
1943 else
1944 {
1945 PFREE(ncell_list_req);
1946 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
1947 nc_enable_conf();
1948 }
1949 }
1950
1951 /*
1952 +--------------------------------------------------------------------+
1953 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1954 | STATE : code ROUTINE : nc_store_eotd |
1955 +--------------------------------------------------------------------+
1956
1957 PURPOSE : copies the measurement results into the MPH_NCELL_POS_IND
1958
1959 */
1960 LOCAL void nc_store_eotd (T_eotd_sc_res * p_res,
1961 T_MPHC_NCELL_SYNC_IND * sync_ind,
1962 USHORT arfcn)
1963 {
1964 p_res->sb_flag = sync_ind->sb_flag;
1965 p_res->bsic = sync_ind->bsic;
1966 p_res->arfcn = arfcn;
1967 memcpy(&(p_res->eotd_crosscor),
1968 &(sync_ind->a_eotd_crosscor),
1969 sizeof(sync_ind->a_eotd_crosscor));
1970 p_res->d_eotd_nrj = sync_ind->d_eotd_nrj;
1971 p_res->time_tag = sync_ind->time_tag;
1972 }
1973
1974 /*
1975 +--------------------------------------------------------------------+
1976 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
1977 | STATE : code ROUTINE : nc_stop_ext_meas_ind |
1978 +--------------------------------------------------------------------+
1979
1980 PURPOSE : Notify RR about the end of the end of the Extended
1981 Measurement procedure.
1982
1983 */
1984 GLOBAL void nc_stop_ext_meas_ind (void)
1985 {
1986 PALLOC ( mph_sync_ind, MPH_SYNC_IND );
1987 mph_sync_ind->cs = CS_STOP_PLMN_SEARCH;
1988 mph_sync_ind->arfcn = NOT_PRESENT_16BIT;
1989 PSENDX ( RR, mph_sync_ind );
1990
1991 if( alr_data->cs_data.p_power_cnf NEQ NULL )
1992 {
1993 PFREE(alr_data->cs_data.p_power_cnf)
1994 alr_data->cs_data.p_power_cnf = NULL;
1995 }
1996 if( IS_EXT_MEAS_RUNNING )/*alr_data->cs_data.mph_ext_meas_req NEQ NULL */
1997 {
1998 PFREE ( alr_data->cs_data.mph_ext_meas_req );
1999 alr_data->cs_data.mph_ext_meas_req = NULL;
2000 }
2001 }
2002
2003 /*
2004 +--------------------------------------------------------------------+
2005 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
2006 | STATE : code ROUTINE : nc_stop_rr_activity |
2007 +--------------------------------------------------------------------+
2008
2009 PURPOSE : Stop BCCH reading or PLMN seach originated by RR.
2010
2011 */
2012 GLOBAL void nc_stop_rr_activity (UBYTE stop)
2013 {
2014 /*
2015 * RR signals stop BCCH reading or stop PLMN search
2016 */
2017 if( (IS_EXT_MEAS_RUNNING) AND
2018 (alr_data->nc_data.cell[LAST_BSIC_REQ].status EQ READ_FB_SB_PENDING) )
2019 {
2020 /*
2021 * Wait for MPHC_NCELL_SYNC_IND or MPHC_STOP_NCELL_SYNC_CON
2022 */
2023 alr_data->cs_data.ext_meas_state_pend = CS_ACTIVE_SYNC;
2024 }
2025 nc_clear_last_bsic();
2026
2027 /*
2028 * RR signals end of PLMN search
2029 */
2030 if (stop)
2031 {
2032 alr_data->plmn_search_running = FALSE;
2033 nc_enable_conf();
2034 }
2035
2036 if ( IS_EXT_MEAS_RUNNING AND (alr_data->cs_data.ext_meas_state_pend EQ CS_NULL) )
2037 {
2038 nc_stop_ext_meas_ind();
2039 }
2040 }
2041
2042 /*
2043 +--------------------------------------------------------------------+
2044 | PROJECT : GSM-PS (8403) MODULE : ALR_NC |
2045 | STATE : code ROUTINE : nc_bsic_req |
2046 +--------------------------------------------------------------------+
2047
2048 PURPOSE : Request of RR to search for frequency correction
2049 burst and synchron burst.
2050
2051 */
2052
2053 GLOBAL void nc_bsic_req (T_MPH_BSIC_REQ *mph_bsic_req)
2054 {
2055 USHORT i;
2056
2057 mph_bsic_req->arfcn &= ARFCN_MASK;
2058 ALR_TRACE_NC_BSIC_REQ (mph_bsic_req->arfcn);
2059
2060 ALR_EM_NEIGHBOURCELL_BSIC_REQUEST;
2061
2062 nc_clear_last_bsic();
2063
2064 /*
2065 * look if the requested channel number is also in the normal
2066 * BA list to stop it.
2067 */
2068 i = nc_get_index( mph_bsic_req->arfcn );
2069
2070 switch(i)
2071 {
2072 case NOT_PRESENT_16BIT:
2073 case LAST_BSIC_REQ:
2074 break;
2075 default:
2076 nc_stop_if_active(i);
2077 TRACE_ERROR("bsic_req for arfcn which is in BA list");
2078 break;
2079 }
2080
2081
2082 /*
2083 * fill in parameters for BSIC request
2084 */
2085 nc_set_status (LAST_BSIC_REQ, READ_FB_SB);
2086 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = mph_bsic_req->arfcn;
2087
2088 /*
2089 * forward synchronisation request to layer 1, if not full
2090 */
2091 if (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT)
2092 {
2093 /*
2094 * reset if we are in NC_CON_EST
2095 */
2096
2097 if(GET_STATE(STATE_NC) EQ NC_CON_EST
2098 #ifdef GPRS
2099 AND !alr_data->gprs_data.pbcch
2100 #endif
2101 )
2102 {
2103 SET_STATE(STATE_NC, NC_IDLE);
2104 }
2105 #ifdef GPRS
2106 else if(GET_STATE(STATE_NC) EQ NC_CON_EST AND
2107 alr_data->gprs_data.pbcch) /* AND */
2108 /* add later alr_data->gprs_data.pim) */
2109 {
2110 SET_STATE(STATE_NC, NC_PIM_PBCCH);
2111 }
2112 #endif
2113
2114 nc_process_status ();
2115 }
2116
2117 }
2118
2119
2120 /*
2121 +--------------------------------------------------------------------+
2122 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
2123 | STATE : code ROUTINE : nc_bcch_ind |
2124 +--------------------------------------------------------------------+
2125
2126 PURPOSE : Reception of a system information message for a neighbourcell.
2127
2128 */
2129
2130 GLOBAL void nc_bcch_ind (T_MPHC_NCELL_BCCH_IND *data_ind)
2131 {
2132 USHORT index;
2133 UBYTE msg_t = data_ind->l2_frame.content[SI_CONTENTS_MSG_T];
2134
2135 if (alr_data->nc_data.cell[LAST_BSIC_REQ].status EQ READ_BCCH_PENDING AND
2136 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn EQ ARFCN_TO_G23(data_ind->radio_freq))
2137 {
2138 /*
2139 * Cell selection or PLMN available search triggered by RR.
2140 */
2141 if (data_ind->error_flag NEQ VALID_BLOCK)
2142 {
2143 /*
2144 * Reception of an invalid block
2145 */
2146 ALR_TRACE_NC ("invalid PLMN BCCH");
2147
2148 /*
2149 * indicate BCCH read error to RR, too many errors are controlled by RR
2150 */
2151 ma_error_ind (CS_BCCH_READ_ERROR, ARFCN_TO_G23(data_ind->radio_freq));
2152 }
2153 else
2154 {
2155 UBYTE mt = data_ind->l2_frame.content[2];
2156
2157 ALR_TRACE_NC ("valid PLMN BCCH");
2158
2159 /*
2160 * forward message to RR
2161 */
2162 ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind);
2163
2164 switch (mt)
2165 {
2166 case D_SYS_INFO_3:
2167 case D_SYS_INFO_4:
2168 alr_data->nc_data.cell[LAST_BSIC_REQ].blocks_required = 0;
2169 break;
2170
2171 default:
2172 /*
2173 * Reception of any other message. Shall not happen after
2174 * GSM 5.02 chapter 6.3.1.3 Mapping of BCCH data, but
2175 * is possible for future extensions.
2176 * Read this tc again plus all which are not read until now.
2177 */
2178 break;
2179 }
2180 }
2181
2182 /*
2183 * all frames received, then decrement pending BCCH request
2184 */
2185 if (alr_data->nc_data.cell[LAST_BSIC_REQ].blocks_required EQ 0)
2186 {
2187
2188 nc_set_status (LAST_BSIC_REQ, IDLE);
2189 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
2190
2191 /*
2192 * L3 may avoid sending a stop message to terminate a NCELL_BCCH process
2193 * if there no more pending request in L1
2194 */
2195 if (alr_data->nc_data.c_bcch_req > 0)
2196 {
2197 /*
2198 * stop any ongoing request in layer 1
2199 */
2200 ma_nc_stop_ncell_bcch_req(ARFCN_TO_G23(data_ind->radio_freq));
2201
2202 /*
2203 * decrement the number of pending requests in layer 1.
2204 */
2205 alr_data->nc_data.c_bcch_req--;
2206 }
2207 }
2208 else
2209 {
2210 /*
2211 * stop pending request and start again.
2212 */
2213 nc_restart_bcch (LAST_BSIC_REQ);
2214 }
2215 return ;
2216 }
2217
2218 /*
2219 * Normal Ncell Handling, get position in neighbourcell list
2220 */
2221 index = nc_get_index (ARFCN_TO_G23(data_ind->radio_freq));
2222
2223 if (index NEQ NOT_PRESENT_16BIT AND
2224 index NEQ LAST_BSIC_REQ AND
2225 (alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING OR
2226 alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED))
2227 {
2228 /*
2229 * normal member of the neighbourcell list and an answer is expected.
2230 */
2231 if (data_ind->error_flag EQ VALID_BLOCK)
2232 {
2233 switch (msg_t)
2234 {
2235 case D_SYS_INFO_3:
2236 /*
2237 * Sys Info 3 contains the needed information in any case
2238 */
2239 #if defined(TRACING)
2240 TRACE_EVENT_P3("NC%u[%d] BCCH ok %s",
2241 index,
2242 alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ?
2243 -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si3");
2244 #endif /* TRACING */
2245 if (alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED)
2246 {
2247 /*
2248 * store data if RR is not informed yet about
2249 * synchronisation
2250 */
2251 nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,0);
2252 nc_set_status (index, FB_SB_SYNC_RR_NOT_INFORMED);
2253 }
2254 else
2255 {
2256 /*
2257 * forward information to RR
2258 */
2259 ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind);
2260 nc_set_fb_sb_sync_initial (index);
2261
2262 }
2263 break;
2264
2265 case D_SYS_INFO_4:
2266 if ((data_ind->l2_frame.content[SI_CONTENTS_CS2] & ONLY_ACS) EQ 0)
2267 {
2268 #if defined(TRACING)
2269 TRACE_EVENT_P3("NC%u[%d] BCCH ok %s",
2270 index,
2271 alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ?
2272 -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si4");
2273 #endif /* TRACING */
2274 /*
2275 * additional cell selection info from sys info 7 or 8 is not necessary
2276 */
2277 if (alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED)
2278 {
2279 /*
2280 * store data if RR is not informed yet about synchronisation
2281 */
2282 nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,0);
2283 nc_set_status (index, FB_SB_SYNC_RR_NOT_INFORMED);
2284 }
2285 else
2286 {
2287 /*
2288 * forward information to RR
2289 */
2290 ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind);
2291 nc_set_fb_sb_sync_initial (index);
2292
2293 }
2294 }
2295 else
2296 {
2297 #if defined(TRACING)
2298 TRACE_EVENT_P3("NC%u[%d] BCCH ok %s",
2299 index,
2300 alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ?
2301 -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si4_n78");
2302 #endif /* TRACING */
2303 /*
2304 * additional information from system info 7 or 8
2305 * is needed for cell reselection purposes
2306 */
2307 if(alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED)
2308 {
2309 /*
2310 * store data if RR is not informed yet about synchronisation
2311 */
2312 nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,0);
2313 }
2314 else
2315 {
2316 /*
2317 * forward information to RR
2318 */
2319 ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind);
2320 }
2321
2322 /*
2323 * system info 3, 7 or 8 required
2324 * -> tc = 2,6 for normal BCCH or 3,7 for extended BCCH
2325 */
2326 alr_data->nc_data.cell[index].blocks_required = NCELL_BCCH_SI_3_7_8;
2327 }
2328 break;
2329
2330 case D_SYS_INFO_7:
2331 case D_SYS_INFO_8:
2332 if (nc_sys_info_78_required (index))
2333 {
2334 #if defined(TRACING)
2335 TRACE_EVENT_P3("NC%u[%d] BCCH ok %s",
2336 index,
2337 alr_data->nc_data.cell[index].ba_arfcn EQ NOT_PRESENT_16BIT ?
2338 -1 : alr_data->nc_data.cell[index].ba_arfcn&ARFCN_MASK, "si78");
2339 #endif /* TRACING */
2340 if(alr_data->nc_data.cell[index].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED)
2341 {
2342 /*
2343 * store data if RR is not informed yet about synchronisation
2344 */
2345 nc_store_bcch((T_MPHC_DATA_IND *) data_ind, index,1);
2346 nc_set_status (index, FB_SB_SYNC_RR_NOT_INFORMED);
2347 }
2348 else
2349 {
2350 /*
2351 * forward information to RR
2352 */
2353 ma_send_unitdata ((T_MPHC_DATA_IND *)data_ind);
2354 nc_set_fb_sb_sync_initial (index);
2355
2356 }
2357 }
2358 else
2359 /*
2360 * increment error counter and request tc again.
2361 */
2362 alr_data->nc_data.cell[index].c_error++;
2363
2364 break;
2365
2366 default:
2367 /*
2368 * increment error counter and request tc again.
2369 */
2370 alr_data->nc_data.cell[index].c_error++;
2371 break;
2372 }
2373 }
2374 else
2375 {
2376 /*
2377 * BCCH reading failed
2378 *
2379 * error counter is incremented and tc shall be read again.
2380 */
2381 alr_data->nc_data.cell[index].c_error++;
2382 }
2383
2384 /*
2385 * restart next attempt
2386 */
2387 if (alr_data->nc_data.cell[index].blocks_required EQ 0)
2388 {
2389 if (alr_data->nc_data.c_bcch_req > 0)
2390 {
2391 /*
2392 * decrement number of pending BCCH requests in layer 1.
2393 */
2394 alr_data->nc_data.c_bcch_req--;
2395
2396 /*
2397 * Stop the pending reading, if not all tc-s read
2398 */
2399 ma_nc_stop_ncell_bcch_req (alr_data->nc_data.cell[index].ba_arfcn);
2400 }
2401 alr_data->nc_data.cell[index].c_attempt = 0;
2402
2403 /*
2404 * start next request to layer 1 if necessary
2405 */
2406 nc_process_status ();
2407 }
2408 else
2409 {
2410 if (alr_data->nc_data.cell[index].c_error >= 4)
2411 {
2412 /*
2413 * set status to failed or excluded depending on the failed
2414 * attempt counter and/or restart for this channel.
2415 */
2416 nc_sync_failed_attempt (index);
2417
2418 /*
2419 * L3 may avoid sending a stop message to terminate a NCELL_BCCH process
2420 * if there no more pending request in L1
2421 */
2422 if (alr_data->nc_data.c_bcch_req > 0)
2423 {
2424 /*
2425 * decrement number of pending BCCH requests in layer 1.
2426 */
2427 alr_data->nc_data.c_bcch_req--;
2428
2429 /*
2430 * Stop the pending reading, if not all tc-s read
2431 */
2432 ma_nc_stop_ncell_bcch_req (alr_data->nc_data.cell[index].ba_arfcn);
2433 }
2434
2435 /*
2436 * start next request to layer 1 if necessary
2437 */
2438 nc_process_status ();
2439 }
2440 else
2441 {
2442 /*
2443 * restart the BCCH reading for this TC again.
2444 */
2445 nc_restart_bcch (index);
2446 }
2447 }
2448 }
2449 }
2450
2451 /*
2452 +--------------------------------------------------------------------+
2453 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
2454 | STATE : code ROUTINE : nc_restart_bcch |
2455 +--------------------------------------------------------------------+
2456
2457 PURPOSE : Stop old request and start new request to layer 1.
2458
2459 */
2460
2461 LOCAL void nc_restart_bcch (USHORT index)
2462 {
2463 PALLOC (ncell_bcch, MPHC_NCELL_BCCH_REQ);
2464
2465 if (alr_data->nc_data.c_bcch_req > 0)
2466 {
2467 /*
2468 * if necessary stop previous request to avoid on the fly change
2469 */
2470 ma_nc_stop_ncell_bcch_req(alr_data->nc_data.cell[index].ba_arfcn);
2471 }
2472
2473 ncell_bcch->radio_freq = ARFCN_TO_L1(alr_data->nc_data.cell[index].ba_arfcn);
2474 ncell_bcch->fn_offset = alr_data->nc_data.cell[index].frame_offset;
2475 ncell_bcch->time_alignment = alr_data->nc_data.cell[index].time_align;
2476 ncell_bcch->tsc = (UBYTE)(alr_data->nc_data.cell[index].bsic & ONLY_BCC);
2477 ncell_bcch->bcch_blocks_required = alr_data->nc_data.cell[index].blocks_required;
2478 #ifdef GPRS
2479 /*if the mobile is in PTM the GPRS_PRIORITY must be set to TOP*/
2480 if(ma_is_ptm())
2481 {
2482 ncell_bcch->gprs_prio = GPRS_PRIO_TOP;
2483 }
2484 else
2485 #endif
2486 ncell_bcch->gprs_prio = GPRS_PRIO_NORM;
2487
2488 /*
2489 * and start next request
2490 */
2491 ma_nc_bcch_req (ncell_bcch);
2492 }
2493 /*
2494 +--------------------------------------------------------------------+
2495 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
2496 | STATE : code ROUTINE : nc_store_sync_ind |
2497 +--------------------------------------------------------------------+
2498
2499 PURPOSE : stores the data of an MPHC_NCELL_SYNC_IND end enters
2500 a new state of ncell.
2501
2502 */
2503
2504 LOCAL void nc_store_sync_ind (USHORT index,
2505 T_MPHC_NCELL_SYNC_IND *sync_ind,
2506 UBYTE new_status)
2507 {
2508 T_NC* pcell = &alr_data->nc_data.cell[index];
2509 pcell->bsic = (UBYTE)(sync_ind->bsic & ONLY_BSIC);
2510 pcell->frame_offset = sync_ind->fn_offset;
2511 pcell->time_align = sync_ind->time_alignment;
2512 pcell->tim_valid = TV_VALID_TIMING_INFO;
2513 nc_set_status (index, new_status);
2514 }
2515
2516 /*
2517 +--------------------------------------------------------------------+
2518 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
2519 | STATE : code ROUTINE : nc_sync_ind |
2520 +--------------------------------------------------------------------+
2521
2522 PURPOSE : Confirmation for a synchronisation request to layer 1.
2523
2524 */
2525
2526 GLOBAL void nc_sync_ind (T_MPHC_NCELL_SYNC_IND *sync_ind)
2527 {
2528 USHORT index;
2529 UBYTE bsic = (UBYTE)(sync_ind->bsic & ONLY_BSIC);
2530 USHORT arfcn = ARFCN_TO_G23(sync_ind->radio_freq)&ARFCN_MASK;
2531 index = nc_get_index (arfcn);
2532
2533 switch (GET_STATE (STATE_NC))
2534 {
2535 case NC_IDLE:
2536 case NC_DEDICATED:
2537 #ifdef GPRS
2538 case NC_PIM_PBCCH:
2539 case NC_PTM_PBCCH: /*XXX*/
2540 #endif
2541 TRACE_EVENT_P5("nc_sync_ind[%d] sb_flag=%d fn_offset=%ld time_alignment=%ld bsic=%d",
2542 arfcn, sync_ind->sb_flag, sync_ind->fn_offset,
2543 sync_ind->time_alignment, sync_ind->bsic);
2544 if (alr_data->nc_data.c_sync_req > 0)
2545 alr_data->nc_data.c_sync_req--;
2546
2547 if (alr_data->nc_data.cell[LAST_BSIC_REQ].status EQ READ_FB_SB_PENDING AND
2548 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn EQ arfcn AND
2549 #ifdef GPRS
2550 (GET_STATE(STATE_NC) EQ NC_IDLE OR GET_STATE(STATE_NC) EQ NC_PIM_PBCCH)
2551 )
2552 #else
2553 GET_STATE(STATE_NC) EQ NC_IDLE
2554 )
2555 #endif
2556 {
2557 nc_sync_ind_last_bsic_req(sync_ind,index,arfcn,bsic);
2558 }
2559 else
2560 {
2561 if (index NEQ NOT_PRESENT_16BIT AND
2562 index NEQ LAST_BSIC_REQ)
2563 {
2564 nc_sync_ind_ncell(sync_ind,index,arfcn,bsic);
2565 } /* valid index check */
2566 else if (alr_data->nc_data.eotd_avail AND
2567 alr_data->nc_data.ppos_ind NEQ NULL)
2568 nc_check_sync_ind_eotd(sync_ind, arfcn);
2569 /* LAST_BSIC_REQ check */
2570 else if ( (index EQ NOT_PRESENT_16BIT) AND (IS_EXT_MEAS_RUNNING) AND
2571 (GET_STATE(STATE_NC) EQ NC_IDLE))
2572 {
2573 if ( alr_data->cs_data.ext_meas_state_pend NEQ CS_NULL )
2574 {
2575 nc_stop_ext_meas_ind();
2576 alr_data->cs_data.ext_meas_state_pend = CS_NULL;
2577 return;
2578 }
2579 }
2580 }
2581
2582 if( alr_data->nc_data.c_sync_intrupted EQ TRUE AND alr_data->nc_data.c_sync_req EQ 0)
2583 {
2584 nc_enable_conf();
2585 alr_data->nc_data.c_sync_intrupted = FALSE;
2586 }
2587
2588 if(GET_STATE(STATE_NC_PROC) EQ NC_ACQUIRE)
2589 {
2590 nc_process_status();
2591 }
2592
2593 break;
2594 default:
2595 break;
2596 } /* STATE_NC */
2597 }
2598
2599 /*
2600 +--------------------------------------------------------------------+
2601 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
2602 | STATE : code ROUTINE : nc_sync_ind_last_bsic_req |
2603 +--------------------------------------------------------------------+
2604
2605 PURPOSE : Confirmation of the LAST_BSIC_REQ synchronisation request
2606
2607 */
2608
2609 LOCAL void nc_sync_ind_last_bsic_req(T_MPHC_NCELL_SYNC_IND* sync_ind,
2610 USHORT index,
2611 USHORT arfcn,
2612 UBYTE bsic)
2613 {
2614
2615 /*
2616 * decoding of FB / SB of hplmn cell is in progress
2617 * send confirmation to RR.
2618 */
2619 PALLOC (mph_bsic_cnf, MPH_BSIC_CNF);
2620
2621 mph_bsic_cnf->arfcn = arfcn;
2622 mph_bsic_cnf->bsic = bsic;
2623
2624 if (sync_ind->sb_flag EQ SB_FOUND)
2625 {
2626 ALR_TRACE_NC_BSIC_CNF(sync_ind->radio_freq);
2627
2628 /*
2629 * FCB and SCB found, set result code
2630 */
2631 mph_bsic_cnf->cs = CS_NO_ERROR;
2632
2633 if ( IS_EXT_MEAS_RUNNING )
2634 {
2635 nc_set_status (LAST_BSIC_REQ, IDLE);
2636 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
2637
2638 if ( alr_data->cs_data.ext_meas_state_pend NEQ CS_NULL )
2639 {
2640 PFREE ( mph_bsic_cnf );
2641 nc_stop_ext_meas_ind();
2642 }
2643 else
2644 {
2645 ma_bsic_cnf (mph_bsic_cnf);
2646 }
2647 return;
2648 }
2649
2650 ALR_EM_NEIGHBOURCELL_BCCH(EM_AVAIL);
2651
2652 /* save data for next cell reselection */
2653 {
2654 T_NC *pcr_cell = &alr_data->nc_data.cr_cell;
2655 pcr_cell->ba_arfcn = arfcn;
2656 pcr_cell->bsic = bsic;
2657 pcr_cell->frame_offset = sync_ind->fn_offset;
2658 pcr_cell->time_align = sync_ind->time_alignment;
2659 }
2660
2661 ma_bsic_cnf (mph_bsic_cnf);
2662
2663 nc_store_sync_ind (LAST_BSIC_REQ, sync_ind, READ_BCCH);
2664 #ifdef GPRS
2665 /* don't do the next checks for PBCCH just return
2666 * maybe later TODO(opt)
2667 */
2668 if (GET_STATE (STATE_NC) EQ NC_PIM_PBCCH OR
2669 GET_STATE (STATE_NC) EQ NC_PTM_PBCCH)
2670 {
2671 return;
2672 }
2673 #endif
2674
2675 index = nc_get_index (arfcn);
2676
2677 if(index NEQ LAST_BSIC_REQ AND
2678 index NEQ NOT_PRESENT_16BIT)
2679 {
2680 /*
2681 * check BSIC of the incoming BCCH message
2682 */
2683 switch (nc_check_bsic (index, bsic))
2684 {
2685 case NC_CHECK_OK:
2686 /*
2687 * channel has passed NCC permitted check.
2688 */
2689 switch (alr_data->nc_data.cell[index].status)
2690 {
2691
2692 case IDLE:
2693 /* This patch helps during parallel search in Limited service.
2694 * Cell synchronised in the last BSIC_REQ fromm RR during parallel
2695 * search is also a part of BA list. In such a case, we store the
2696 * synchrinisation information, so that its can be used later by
2697 * nc_start_reselect.
2698 */
2699 if(alr_data->nc_data.cell[index].one_of_twelve)
2700 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2701 else
2702 nc_store_sync_ind (index, sync_ind, IDLE_SYNC);
2703 break;
2704
2705 case READ_FB_SB:
2706 /*
2707 * the channel shall start synchronisation of FB/SB
2708 * so reading of BCCH shall be started.
2709 */
2710 if(alr_data->nc_data.cell[index].one_of_six AND
2711 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
2712 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2713 else if(alr_data->nc_data.cell[index].one_of_twelve)
2714 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2715 break;
2716
2717 case READ_SB:
2718 /*
2719 * the channel shall start synchronisation of SB
2720 * so this is done.
2721 */
2722 if(alr_data->nc_data.cell[index].one_of_twelve)
2723 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2724 break;
2725
2726 case FB_SB_FAILED:
2727 /*
2728 * A channel synchronisation has failed in the past.
2729 * Now it is synchronized again. Start BCCH reading
2730 * and send this information to RR after indicating
2731 * the synchronisation with next measurement report.
2732 */
2733 if(alr_data->nc_data.cell[index].one_of_six AND
2734 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
2735 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2736 else if(alr_data->nc_data.cell[index].one_of_twelve)
2737 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2738 break;
2739
2740
2741 case READ_SB_BCCH:
2742 /*
2743 * the channel shall start synchronisation of SB
2744 * followed by BCCH reading. SB synchronisation
2745 * is done.
2746 */
2747 if(alr_data->nc_data.cell[index].one_of_six)
2748 nc_store_sync_ind (index, sync_ind, READ_BCCH);
2749 break;
2750
2751 case READ_FB_SB_PENDING:
2752 case READ_SB_PENDING:
2753 case READ_SB_BCCH_PENDING:
2754 case READ_BCCH_PENDING:
2755 case READ_BCCH_PENDING_RR_NOT_INFORMED:
2756 /*
2757 * REMARK: this shall not happen, because this
2758 * attempt shall be killed if RR requests
2759 * procedure for the channel.
2760 */
2761 ALR_TRACE_NC ("Abnormal situation sync ind");
2762 break;
2763
2764 default:
2765 break;
2766 }
2767 break;
2768
2769 case NC_CHECK_BSIC_CHANGED:
2770 /*
2771 * BSIC of the channel has changed.
2772 */
2773 switch (alr_data->nc_data.cell[index].status)
2774 {
2775 case READ_SB:
2776 /*
2777 * the channel shall start synchronisation of SB
2778 * so this is done, but a changed BSIC is stored.
2779 * Read BCCH of the channel and forward to RR.
2780 */
2781 if(alr_data->nc_data.cell[index].one_of_six AND
2782 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
2783 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2784 else if(alr_data->nc_data.cell[index].one_of_twelve)
2785 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2786 break;
2787
2788 case FB_SB_FAILED:
2789 /*
2790 * A channel synchronisation has failed in the past.
2791 * Now it is synchronized again. Start BCCH reading
2792 * and send this information to RR after indicating
2793 * the synchronisation with next measurement report.
2794 */
2795 if(alr_data->nc_data.cell[index].one_of_six AND
2796 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
2797 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2798 else if(alr_data->nc_data.cell[index].one_of_twelve)
2799 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2800 break;
2801
2802 case READ_SB_BCCH:
2803 /*
2804 * the channel shall start synchronisation of SB
2805 * followed by BCCH reading. SB synchronisation
2806 * is done. Read BCCH of the channel and forward to RR.
2807 */
2808 if(alr_data->nc_data.cell[index].one_of_six)
2809 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2810 break;
2811
2812 case READ_FB_SB:
2813 case READ_FB_SB_PENDING:
2814 case READ_SB_PENDING:
2815 case READ_SB_BCCH_PENDING:
2816 case READ_BCCH_PENDING:
2817 case READ_BCCH_PENDING_RR_NOT_INFORMED:
2818 /*
2819 * REMARK: this shall not happen, because this
2820 * attempt shall be killed if RR requests
2821 * procedure for the channel.
2822 */
2823 ALR_TRACE_NC ("Abnormal situation sync ind (changed BSIC)");
2824 break;
2825
2826 default:
2827 break;
2828 }
2829 break;
2830
2831 case NC_CHECK_NCC_FAILED:
2832 /*
2833 * ncc permitted check failed
2834 */
2835 nc_set_status (index, EXCLUDED);
2836 break;
2837
2838 default:
2839 break;
2840 }
2841 }
2842
2843 ALR_EM_NEIGHBOURCELL_BSIC_CONFIRM(EM_AVAIL);
2844
2845 }
2846 else
2847 {
2848 /*
2849 * FCB and SCB not found, set result code,
2850 * mark cell[LAST_BSIC_REQ] and cr_cell as invalid
2851 * and send negative answer to RR
2852 */
2853 mph_bsic_cnf->cs = CS_NO_BCCH_AVAIL;
2854 nc_set_status (LAST_BSIC_REQ, IDLE);
2855 alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn = NOT_PRESENT_16BIT;
2856 alr_data->nc_data.cr_cell.ba_arfcn = NOT_PRESENT_16BIT;
2857
2858 ma_bsic_cnf (mph_bsic_cnf);
2859
2860 ALR_EM_NEIGHBOURCELL_BSIC_CONFIRM(EM_NOT_AVAIL);
2861
2862 }
2863 }
2864
2865 /*
2866 +--------------------------------------------------------------------+
2867 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
2868 | STATE : code ROUTINE : nc_sync_ind_ncell |
2869 +--------------------------------------------------------------------+
2870
2871 PURPOSE : Confirmation of a ncell synchronisation request
2872
2873 */
2874
2875 LOCAL void nc_sync_ind_ncell(T_MPHC_NCELL_SYNC_IND* sync_ind,
2876 USHORT index,
2877 USHORT arfcn,
2878 UBYTE bsic)
2879 {
2880 #ifdef GPRS
2881 BOOL bsic_chg = FALSE;
2882 #endif
2883
2884 if (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM)
2885 {
2886 /* eotd confirmation is active */
2887 if(alr_data->nc_data.eotd_avail)
2888 nc_check_sync_ind_eotd(sync_ind, arfcn);
2889
2890 TRACE_EVENT_P2("sync_ind[%u] c_sync_req=%u", arfcn, alr_data->nc_data.c_sync_req);
2891 /*
2892 * check if the end of the CONFIRM procedure (LIST_REQ) is
2893 * reached
2894 * this is done here because it is independent from EOTD
2895 */
2896 if(alr_data->nc_data.c_sync_req EQ 0)
2897 {
2898 nc_enable_conf();
2899 }
2900 /*
2901 * skip the rest of this function for scell
2902 * because the status for the scell is always FB_SB_SYNC
2903 */
2904 if(alr_data->nc_data.eotd_avail AND
2905 arfcn EQ alr_data->serving_cell)
2906 return;
2907 }
2908
2909 if (sync_ind->sb_flag EQ SB_FOUND)
2910 {
2911 /*
2912 * Synchronization successful for a normal member of the BA list.
2913 */
2914 ALR_TRACE_NC_SB_IND_PASSED(arfcn);
2915
2916 ALR_EM_NEIGHBOURCELL_SB(EM_AVAIL);
2917
2918 switch (GET_STATE (STATE_NC))
2919 {
2920 case NC_IDLE:
2921 case NC_DEDICATED:
2922 /*
2923 * check neighbourcell
2924 */
2925 switch (nc_check_bsic (index, bsic))
2926 {
2927 case NC_CHECK_OK:
2928 /*
2929 * channel has passed NCC permitted check.
2930 */
2931 switch (alr_data->nc_data.cell[index].status)
2932 {
2933 case READ_FB_SB_PENDING:
2934 /*
2935 * initial synchronization to FB and SB
2936 * if the cell is a 1o6 we read the BCCH
2937 * otherwise we just set it to synchronized
2938 */
2939
2940 if(alr_data->nc_data.cell[index].one_of_six AND
2941 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
2942 {
2943 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
2944 }
2945 else if(alr_data->nc_data.cell[index].one_of_twelve)
2946 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2947 else
2948 {
2949 TRACE_EVENT_P1("sync ind for not 1o12 cell %d", arfcn);
2950 }
2951 break;
2952
2953 case READ_SB_PENDING:
2954 /*
2955 * confirmation of SB
2956 */
2957 alr_data->nc_data.cell[index].c_attempt = 0;
2958 if(alr_data->nc_data.cell[index].one_of_twelve)
2959 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2960 else
2961 nc_store_sync_ind (index, sync_ind, IDLE_SYNC);
2962 break;
2963
2964 case READ_SB_BCCH_PENDING:
2965 /*
2966 * confirmation of SB before reading
2967 * neighbour cell BCCH all five minutes.
2968 */
2969 if(alr_data->nc_data.cell[index].one_of_six AND
2970 GET_STATE(STATE_NC) EQ NC_IDLE)
2971 {
2972 nc_store_sync_ind (index, sync_ind, READ_BCCH);
2973 }
2974 else
2975 {
2976 alr_data->nc_data.cell[index].c_attempt = 0;
2977 if(alr_data->nc_data.cell[index].one_of_twelve)
2978 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2979 else
2980 nc_store_sync_ind (index, sync_ind, IDLE_SYNC);
2981 }
2982 break;
2983 case READ_BCCH_RR_NOT_INFORMED: /*TODO(opt)*/
2984 case READ_BCCH_PENDING_RR_NOT_INFORMED:/*TODO(opt)*/
2985 case READ_BCCH:/*TODO(opt)*/
2986 case READ_BCCH_PENDING:/*TODO(opt)*/
2987 TRACE_ERROR("sync_ind for ncell in READ_BCCH*");
2988 if(alr_data->nc_data.cell[index].one_of_six AND
2989 GET_STATE(STATE_NC) EQ NC_IDLE)
2990 {
2991 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
2992 }
2993 break;
2994 default:
2995 break;
2996 } /*switch(status)*/
2997 break;
2998 case NC_CHECK_BSIC_CHANGED:
2999 /*
3000 * channel has passed NCC permitted check,
3001 * but a changed BSIC has been detected.
3002 */
3003 switch (alr_data->nc_data.cell[index].status)
3004 {
3005 case READ_SB_PENDING:
3006 case READ_SB_BCCH_PENDING:
3007 /*
3008 * confirmation of SB indicates new BSIC
3009 */
3010 if(alr_data->nc_data.cell[index].one_of_six AND
3011 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
3012 {
3013 nc_store_sync_ind (index, sync_ind, READ_BCCH_RR_NOT_INFORMED);
3014 }
3015 else if(alr_data->nc_data.cell[index].one_of_twelve)
3016 {
3017 alr_data->nc_data.cell[index].c_attempt = 0;
3018 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
3019 }
3020 else
3021 {
3022 TRACE_EVENT_P1("sync ind for not 1o12 cell %d", arfcn);
3023 nc_store_sync_ind (index, sync_ind, IDLE_SYNC);
3024 }
3025 break;
3026
3027 default:
3028 break;
3029 } /*switch(status)*/
3030 break;
3031
3032 case NC_CHECK_NCC_FAILED:
3033 /*
3034 * ncc permitted check failed. Attempt again.
3035 * BSIC of a cell may always change. So do not
3036 * exclude this cell in IDLE mode meaurements
3037 */
3038 if(GET_STATE(STATE_NC) EQ NC_IDLE)
3039 {
3040 alr_data->nc_data.cell[index].c_attempt = 0;
3041 nc_set_fb_sb_failed (index, TEN_SECONDS);
3042 }
3043 else if(GET_STATE(STATE_NC) EQ NC_DEDICATED)
3044 {
3045 alr_data->nc_data.cell[index].c_attempt = 0;
3046 nc_set_fb_sb_failed (index, THIRTY_SECONDS);
3047 }
3048 else
3049 {
3050 nc_set_status (index, EXCLUDED);
3051 }
3052 break;
3053 }
3054 break;
3055 #ifdef GPRS
3056 case NC_PIM_PBCCH:
3057 case NC_PTM_PBCCH: /*XXX*/
3058 TRACE_EVENT("sync_ind PBCCH");
3059 switch (alr_data->nc_data.cell[index].status)
3060 {
3061 case READ_FB_SB_PENDING:
3062 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
3063 nc_inform_grr_of_ncell(index, GRR_SB_FOUND);
3064 break;
3065 case READ_SB_PENDING:
3066 if(bsic NEQ alr_data->nc_data.cell[index].bsic)
3067 bsic_chg = TRUE;
3068 else
3069 bsic_chg = FALSE;
3070
3071 if(alr_data->nc_data.cell[index].one_of_twelve)
3072 nc_store_sync_ind (index, sync_ind, FB_SB_SYNC);
3073 else
3074 nc_store_sync_ind (index, sync_ind, IDLE_SYNC);
3075
3076 if(bsic_chg)
3077 nc_inform_grr_of_ncell(index, GRR_SB_FOUND);
3078 break;
3079 default:
3080 break;
3081 }
3082 break;
3083 default:
3084 break;
3085 #endif
3086 } /* NC_STATE */
3087 }
3088 else /* sb_flag EQ FALSE */
3089 {
3090 /*
3091 * Synchronization failed
3092 */
3093 ALR_TRACE_NC_SB_FAILED (sync_ind->radio_freq);
3094 if (alr_data->nc_data.cell[index].ba_status EQ IN_BA)
3095 {
3096 switch (alr_data->nc_data.cell[index].status)
3097 {
3098 case READ_FB_SB_PENDING:
3099 case READ_SB_PENDING:
3100 case READ_SB_BCCH_PENDING:
3101
3102 ALR_EM_NEIGHBOURCELL_SB(EM_NOT_AVAIL);
3103
3104 if(GET_STATE(STATE_NC) EQ NC_IDLE)
3105 nc_sync_failed_attempt(index);
3106 else if(GET_STATE(STATE_NC) EQ NC_DEDICATED)
3107 nc_sync_failed_attempt_dedicated(index);
3108 #ifdef GPRS /*XXX*/
3109 else
3110 nc_sync_failed_gprs(index);
3111 #endif
3112 break;
3113 default:
3114 break;
3115 }
3116 }
3117 else
3118 { /*
3119 * the cell currently or perhaps for a longer time doesn't
3120 * belong to the BA list, no more attempts to synchronize now
3121 */
3122 switch (alr_data->nc_data.cell[index].status)
3123 {
3124 case READ_FB_SB_PENDING:
3125 nc_set_status (index, IDLE);
3126 break;
3127 case READ_SB_PENDING:
3128 alr_data->nc_data.cell[index].c_attempt++;
3129 alr_data->nc_data.cell[index].tim_valid = TV_APPROX_TIMING_INFO;
3130 nc_set_status (index, READ_SB);
3131 break;
3132 case READ_SB_BCCH_PENDING:
3133 alr_data->nc_data.cell[index].c_attempt++;
3134 alr_data->nc_data.cell[index].tim_valid = TV_APPROX_TIMING_INFO;
3135 nc_set_status (index, READ_SB_BCCH);
3136 break;
3137 default:
3138 break;
3139 }
3140 }
3141 } /* error_flag check */
3142 }
3143
3144 /*
3145 +--------------------------------------------------------------------+
3146 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3147 | STATE : code ROUTINE : nc_check_sync_ind_eotd |
3148 +--------------------------------------------------------------------+
3149
3150 PURPOSE : copies the measurement results to the MPH_NCELL_POS_IND
3151 while EOTD is active
3152
3153 */
3154 LOCAL void nc_check_sync_ind_eotd (T_MPHC_NCELL_SYNC_IND* sync_ind, USHORT arfcn)
3155 {
3156 T_MPH_NCELL_POS_IND* ppos_ind;
3157
3158 if ((ppos_ind = alr_data->nc_data.ppos_ind) EQ NULL)
3159 {
3160 TRACE_ERROR("nc_check_sync_ind_eotd() while alr_data->nc_data.ppos_ind==0");
3161 return;
3162 }
3163
3164 if (arfcn EQ alr_data->serving_cell)
3165 {
3166 if (ppos_ind->eotd_res EQ 0) /*0 doesn't mean EOTD_SUCC here
3167 - it indicates that no SC results are present*/
3168 {
3169 nc_store_eotd(&(ppos_ind->eotd_sc_res), sync_ind, arfcn);
3170 ppos_ind->fn = sync_ind->fn_in_sb;
3171 ppos_ind->eotd_res++;
3172 }
3173 else /*first EOTD results for SC are already present
3174 - now continue with second SC results*/
3175 {
3176 nc_store_eotd((T_eotd_sc_res*)(&(ppos_ind->eotd_sc_res1)), sync_ind,
3177 arfcn);
3178 ppos_ind->eotd_res = EOTD_SUCC;
3179 ppos_ind->ta = GET_STATE(STATE_NC) EQ NC_DEDICATED ?
3180 alr_data->nc_data.tav : NOT_PRESENT_8BIT;
3181 PSENDX (RR, ppos_ind);
3182 alr_data->nc_data.ppos_ind = NULL;
3183
3184 if (alr_data->nc_data.ppos_req NEQ NULL)
3185 {
3186 PFREE(alr_data->nc_data.ppos_req);
3187 alr_data->nc_data.ppos_req = NULL;
3188 }
3189 }
3190 }
3191 else
3192 {
3193 if (ppos_ind->c_eotd_nc_res < MAX_NCELL_EOTD_RES)
3194 {
3195 nc_store_eotd((T_eotd_sc_res*)(
3196 &(ppos_ind->eotd_nc_res[ppos_ind->c_eotd_nc_res])) , sync_ind, arfcn);
3197 (ppos_ind->c_eotd_nc_res)++;
3198 }
3199 else
3200 TRACE_ERROR("more than MAX_NCELL_EOTD_RES ncell sync indications");
3201 }
3202 }
3203
3204 /*
3205 +--------------------------------------------------------------------+
3206 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3207 | STATE : code ROUTINE : nc_sync_failed_attempt |
3208 +--------------------------------------------------------------------+
3209
3210 PURPOSE : A synchronisation attempt has failed during idle mode.
3211
3212 */
3213 LOCAL void nc_sync_failed_attempt (USHORT index)
3214 {
3215 switch (alr_data->nc_data.cell[index].c_attempt)
3216 {
3217 case 0:
3218 case 1:
3219 case 2:
3220 case 3:
3221 /*
3222 * for attempts 1 to 4 try it again
3223 * after ten seconds
3224 */
3225 nc_set_fb_sb_failed (index, TEN_SECONDS);
3226
3227 break;
3228 default:
3229 /*
3230 * if there are more attempts, exclude
3231 * the cell from further attempts
3232 * Store last fieldstrength value
3233 */
3234 nc_set_status (index, EXCLUDED);
3235 break;
3236 }
3237 }
3238
3239 /*
3240 +--------------------------------------------------------------------+
3241 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3242 | STATE : code ROUTINE : nc_sync_failed_attempt_dedicated |
3243 +--------------------------------------------------------------------+
3244
3245 PURPOSE : A synchronisation attempt has failed during dedicated mode.
3246
3247 */
3248 LOCAL void nc_sync_failed_attempt_dedicated (USHORT index)
3249 {
3250 /*
3251 * Store last fieldstrength value
3252 */
3253 switch (alr_data->nc_data.cell[index].c_attempt)
3254 {
3255 case 0:
3256 case 1:
3257 case 2:
3258 /*
3259 * for attempts 1 to 3 try it again immediately
3260 */
3261 alr_data->nc_data.cell[index].c_attempt++;
3262 if (alr_data->nc_data.cell[index].status EQ READ_FB_SB_PENDING)
3263 alr_data->nc_data.cell[index].tim_valid = TV_INVALID_TIMING_INFO;
3264 else
3265 alr_data->nc_data.cell[index].tim_valid = TV_APPROX_TIMING_INFO;
3266 nc_set_status (index, READ_FB_SB);
3267 break;
3268 default:
3269 /*
3270 * if there are more attempts, exclude
3271 * the cell from further attempts
3272 */
3273 nc_set_status (index, EXCLUDED);
3274 break;
3275 }
3276 }
3277
3278 /*
3279 +--------------------------------------------------------------------+
3280 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3281 | STATE : code ROUTINE : nc_start_dedicated |
3282 +--------------------------------------------------------------------+
3283
3284 PURPOSE : Process signal nc_start_dedicated from SDL process
3285 Main_Control.
3286
3287 */
3288
3289 GLOBAL void nc_start_dedicated (UBYTE pwrc, UBYTE dtx)
3290 {
3291 USHORT i;
3292
3293 switch(GET_STATE(STATE_NC))
3294 {
3295 case NC_CON_EST:
3296 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
3297 {
3298 switch (alr_data->nc_data.cell[i].status)
3299 {
3300 case READ_BCCH_RR_NOT_INFORMED:
3301 case FB_SB_SYNC_RR_NOT_INFORMED:
3302 case READ_BCCH:
3303 /*
3304 * BCCH reading is not needed during dedicated mode,
3305 * but SB synchronisation is already done.
3306 * clear a stored BCCH if needed.
3307 */
3308 nc_set_status (i, FB_SB_SYNC);
3309 break;
3310
3311 case READ_SB_BCCH:
3312 nc_set_status (i, READ_SB);
3313 break;
3314
3315 case READ_FB_SB_PENDING:
3316 case READ_SB_PENDING:
3317 case READ_SB_BCCH_PENDING:
3318 case READ_BCCH_PENDING_RR_NOT_INFORMED:
3319 case READ_BCCH_PENDING:
3320 TRACE_ERROR("Abnormal situation nc_start_dedi");
3321 nc_set_status (i, IDLE);
3322 break;
3323 case FB_SB_FAILED:
3324 nc_set_status (i, IDLE);
3325 break;
3326 case IDLE_SYNC:
3327 if (alr_data->nc_data.cell[i].c_sync > 0)
3328 alr_data->nc_data.cell[i].c_sync = TEN_SECONDS;
3329 break;
3330 default:
3331 break;
3332 }
3333 }
3334
3335 nc_clear_last_bsic();
3336
3337 alr_data->nc_data.pwrc = pwrc;
3338 alr_data->nc_data.dtx = dtx;
3339
3340 SET_STATE (STATE_NC, NC_DEDICATED);
3341 nc_enable_conf();
3342 break;
3343 default:
3344 TRACE_ERROR("nc_start_dedicated in wrong state");
3345 break;
3346 }
3347
3348 }
3349
3350 /*
3351 +--------------------------------------------------------------------+
3352 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3353 | STATE : code ROUTINE : nc_suspend |
3354 +--------------------------------------------------------------------+
3355
3356 PURPOSE : This stops all active processes like FB/SB and BCCH reading
3357 if
3358 - the mobile start connection establishment
3359 - RR requests power measurements parallel to idle mode
3360 - leave dedicated mode.
3361
3362 */
3363
3364 GLOBAL void nc_suspend (void)
3365 {
3366 ALR_TRACE_NC( "nc_suspend");
3367
3368 switch (GET_STATE(STATE_NC))
3369 {
3370 case NC_IDLE:
3371 case NC_DEDICATED:
3372 nc_clear_last_bsic();
3373 nc_stop_all();
3374 nc_disable_conf(FREE_POS_IND);
3375
3376 SET_STATE(STATE_NC, NC_CON_EST);
3377 break;
3378 case NC_CON_EST:
3379 break;
3380 #ifdef GPRS
3381 case NC_PIM_PBCCH:
3382 if(alr_data->nc_data.cell[LAST_BSIC_REQ].status NEQ IDLE)
3383 nc_clear_last_bsic();
3384 /*lint -fallthrough*/
3385 case NC_PTM_PBCCH:
3386 nc_stop_all();
3387 nc_disable_conf(FREE_POS_IND);
3388 SET_STATE(STATE_NC, NC_CON_EST);
3389 break;
3390 #endif
3391 default:
3392 break;
3393 }
3394 }
3395
3396 GLOBAL void nc_suspend_handover (void)
3397 {
3398 ALR_TRACE_NC( "nc_suspend_handover");
3399
3400 switch (GET_STATE(STATE_NC))
3401 {
3402 case NC_DEDICATED:
3403 nc_stop_all();
3404 nc_disable_conf(FREE_POS_IND);
3405 break;
3406 }
3407 }
3408 /*
3409 +--------------------------------------------------------------------+
3410 | PROJECT : GSM-PS (6103) MODULE : alr_nc |
3411 | STATE : code ROUTINE : nc_resume |
3412 +--------------------------------------------------------------------+
3413
3414 PURPOSE : Only needed for alr_gprs.c
3415
3416 */
3417
3418 GLOBAL void nc_resume (void)
3419 {
3420 SET_STATE (STATE_NC, NC_IDLE);
3421 nc_enable_conf();
3422 }
3423
3424 /*
3425 +--------------------------------------------------------------------+
3426 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3427 | STATE : code ROUTINE : nc_update_dedicated |
3428 +--------------------------------------------------------------------+
3429
3430 PURPOSE : Process signal nc_update_dedicated from SDL process
3431 Dedi_Control.
3432
3433 */
3434
3435 GLOBAL void nc_update_dedicated (UBYTE dtx, UBYTE pwrc)
3436 {
3437 UBYTE i, j;
3438 UBYTE c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
3439
3440 switch(GET_STATE (STATE_NC))
3441 {
3442 case NC_DEDICATED:
3443 {
3444 PALLOC (upd_dedi, MPHC_UPDATE_BA_LIST);
3445
3446 /*
3447 * updated values of pwrc or dtx can be configure
3448 * only by sending a new neighbourcell list to layer 1
3449 */
3450 alr_data->nc_data.pwrc = pwrc;
3451 alr_data->nc_data.dtx = dtx;
3452
3453 for (i = 0, j = 0; i < c_ba_arfcn; i++)
3454 {
3455 if (alr_data->nc_data.cell[i].ba_status EQ IN_BA)
3456 upd_dedi->chan_list.radio_freq[j++] =
3457 ARFCN_TO_L1(alr_data->nc_data.cell[i].ba_arfcn);
3458 }
3459
3460 upd_dedi->num_of_chans = j;
3461 alr_data->nc_data.ba_id = ALR_ALLOCATE_NEW_BA ( alr_data->nc_data.ba_id );
3462 upd_dedi->ba_id = alr_data->nc_data.ba_id;
3463 upd_dedi->pwrc = alr_data->nc_data.pwrc;
3464 upd_dedi->dtx_allowed = alr_data->nc_data.dtx;
3465
3466 alr_data->nc_data.update = TRUE;
3467 ma_nc_update_ba_list (upd_dedi);
3468 }
3469 break;
3470 default:
3471 TRACE_ERROR("nc_update_dedicated in wrong state");
3472 break;
3473 }
3474 }
3475
3476 GLOBAL void nc_resume_dedicated(void)
3477 {
3478 nc_enable_conf();
3479 }
3480 /*
3481 +--------------------------------------------------------------------+
3482 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3483 | STATE : code ROUTINE : nc_get_fn_time |
3484 +--------------------------------------------------------------------+
3485
3486 PURPOSE : Export Procedure to request frame offset and time
3487 alignment of neighbour cells.
3488
3489 Returns FALSE if timing information not found.
3490
3491 */
3492
3493 GLOBAL BOOL nc_get_fn_time (USHORT channel,
3494 ULONG *fn,
3495 ULONG *time)
3496 {
3497 USHORT index;
3498 if( channel EQ alr_data->serving_cell)
3499 {
3500 *fn = 0;
3501 *time = 0;
3502 return TRUE;
3503 }
3504
3505 /* Check if we have read SYNC on this channel */
3506 index = nc_get_index (channel);
3507 if (index NEQ NOT_PRESENT_16BIT)
3508 {
3509 *fn = alr_data->nc_data.cell[index].frame_offset;
3510 *time = alr_data->nc_data.cell[index].time_align;
3511
3512 if( (*fn EQ NOT_PRESENT_32BIT) OR (*time EQ NOT_PRESENT_32BIT))
3513 {
3514 return FALSE;
3515 }
3516 else
3517 {
3518 return TRUE;
3519 }
3520 }
3521 else
3522 {
3523 *fn = NOT_PRESENT_32BIT;
3524 *time = NOT_PRESENT_32BIT;
3525 return FALSE;
3526 }
3527 }
3528
3529
3530 /*
3531 +--------------------------------------------------------------------+
3532 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3533 | STATE : code ROUTINE : nc_start_reselect |
3534 +--------------------------------------------------------------------+
3535
3536 PURPOSE : Process signal nc_start_reselect from SDL process
3537 Main_Control.
3538
3539 */
3540
3541 GLOBAL void nc_start_reselect (USHORT arfcn)
3542 {
3543 USHORT index;
3544 T_NC *pcell;
3545
3546 ALR_TRACE_NC_RESELECT(arfcn);
3547
3548 index = nc_get_index (arfcn);
3549 if (index EQ NOT_PRESENT_16BIT)
3550 {
3551 if (arfcn NEQ alr_data->nc_data.cr_cell.ba_arfcn)
3552 {
3553 ma_error_ind (CS_BCCH_READ_ERROR, arfcn);
3554 return;
3555 }
3556 else
3557 {
3558 pcell = &alr_data->nc_data.cr_cell;
3559 }
3560 }
3561 else
3562 {
3563 pcell = &alr_data->nc_data.cell[index];
3564
3565 /* Cannot to reselect to a cell for which the synchronization information
3566 * is not available
3567 */
3568 if (pcell->bsic EQ NOT_PRESENT_8BIT)
3569 {
3570 ma_error_ind (CS_NC_SYNC_FAILED, arfcn);
3571 return;
3572 }
3573 }
3574
3575
3576 {
3577 PALLOC(reselect, MPHC_NEW_SCELL_REQ);
3578
3579 reselect->radio_freq = ARFCN_TO_L1(arfcn);
3580 reselect->fn_offset = (ULONG)pcell->frame_offset;
3581 reselect->time_alignment = (ULONG)pcell->time_align;
3582 reselect->tsc = pcell->bsic;
3583 alr_data->nc_data.channel = arfcn;
3584
3585 ALR_TRACE_NC_FN_TA(index, reselect->fn_offset, reselect->time_alignment);
3586
3587 ALR_EM_CONFIGURE_CELL_RESELECTION;
3588
3589 ma_new_scell_req(reselect);
3590 }
3591 }
3592
3593 /*
3594 +--------------------------------------------------------------------+
3595 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3596 | STATE : code ROUTINE : nc_report |
3597 +--------------------------------------------------------------------+
3598
3599 PURPOSE : Process signal nc_report from SDL process
3600 Main_Control.
3601
3602 */
3603
3604 GLOBAL void nc_report (T_MPHC_RXLEV_PERIODIC_IND *rxlev_periodic_ind)
3605 {
3606 ALR_TRACE_NC("nc_report");
3607
3608
3609 switch(GET_STATE(STATE_NC))
3610 {
3611 case NC_IDLE:
3612 case NC_CON_EST:
3613 nc_store_rxlev (rxlev_periodic_ind);
3614
3615 #ifdef GPRS
3616 nc_rxlev_sc_req (rxlev_periodic_ind->s_rxlev);
3617 #endif
3618 nc_check_activity();
3619 break;
3620 default:
3621 TRACE_ERROR("nc_report in invalid state");
3622 break;
3623 }
3624 }
3625
3626 /*
3627 +--------------------------------------------------------------------+
3628 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3629 | STATE : code ROUTINE : nc_report_dedicated |
3630 +--------------------------------------------------------------------+
3631
3632 PURPOSE : Process signal nc_report_dedicated from SDL process
3633 Main_Control.
3634
3635 */
3636
3637 GLOBAL void nc_report_dedicated (T_MPHC_MEAS_REPORT *meas_report)
3638 {
3639 switch(GET_STATE(STATE_NC))
3640 {
3641 case NC_DEDICATED:
3642 nc_store_dedicated (meas_report);
3643 nc_check_activity ();
3644 break;
3645 default:
3646 TRACE_ERROR("nc_report_dedicated in wrong state");
3647 break;
3648 }
3649 }
3650
3651 /*
3652 +--------------------------------------------------------------------+
3653 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3654 | STATE : code ROUTINE : nc_update_list |
3655 +--------------------------------------------------------------------+
3656
3657 PURPOSE : Procedure to update frame offset and time alignment after
3658 cell change. All values are relative to the actual serving
3659 cell.
3660
3661 */
3662
3663 #define TDMA_FRAMES_PER_HYPERFRAME 2715648
3664
3665 GLOBAL void nc_update_list (USHORT channel)
3666 {
3667 USHORT index;
3668 USHORT i;
3669
3670 switch(GET_STATE(STATE_NC))
3671 {
3672 case NC_CON_EST:
3673 case NC_DEDICATED:
3674 case NC_IDLE:
3675 index = nc_get_index (channel);
3676 if (index NEQ NOT_PRESENT_16BIT)
3677 {
3678 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
3679 {
3680 if (i NEQ index)
3681 {
3682 ULONG new_frame_offset;
3683 ULONG new_time_align;
3684
3685 new_frame_offset = (alr_data->nc_data.cell[i].frame_offset -
3686 alr_data->nc_data.cell[index].frame_offset +
3687 TDMA_FRAMES_PER_HYPERFRAME) %
3688 TDMA_FRAMES_PER_HYPERFRAME;
3689 if (alr_data->nc_data.cell[i].time_align >= alr_data->nc_data.cell[index].time_align)
3690 {
3691 new_time_align = alr_data->nc_data.cell[i].time_align -
3692 alr_data->nc_data.cell[index].time_align;
3693 }
3694 else
3695 {
3696 new_time_align = 5000 + alr_data->nc_data.cell[i].time_align -
3697 alr_data->nc_data.cell[index].time_align;
3698 new_frame_offset = (new_frame_offset + 1) %
3699 TDMA_FRAMES_PER_HYPERFRAME;
3700 } /* time_align */
3701 alr_data->nc_data.cell[i].frame_offset = new_frame_offset;
3702 alr_data->nc_data.cell[i].time_align = new_time_align;
3703 } /* i NEQ index */
3704 } /* for(all ncells) */
3705
3706 ALR_TRACE_NC("set chan to 0");
3707
3708 alr_data->nc_data.cell[index].frame_offset = 0;
3709 alr_data->nc_data.cell[index].time_align = 0;
3710 } /* NOT_PRESENT */
3711 break;
3712 default:
3713 TRACE_ERROR("nc_update_list in invalid state");
3714 break;
3715 }
3716 }
3717
3718 /*
3719 +--------------------------------------------------------------------+
3720 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3721 | STATE : code ROUTINE : nc_add_offset |
3722 +--------------------------------------------------------------------+
3723
3724 PURPOSE : If the mobile comes back from dedicated mode all synchronized
3725 neighbourcells make a status transition to READ_BCCH_RR_NOT_INFORMED.
3726 This triggers reading of the neighbourcell BCCH.
3727
3728 */
3729
3730 GLOBAL void nc_add_offset (void)
3731 {
3732 USHORT i;
3733 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
3734
3735 for (i = 0; i < c_ba_arfcn; i++)
3736 {
3737 if (alr_data->nc_data.cell[i].ba_arfcn NEQ alr_data->serving_cell)
3738 {
3739 /*XXX c_sync should be the same in idle and dedic also for pbcchc
3740 so no action here */
3741 switch (alr_data->nc_data.cell[i].status)
3742 {
3743 case FB_SB_SYNC:
3744 case READ_SB:
3745 nc_set_status (i, READ_BCCH_RR_NOT_INFORMED);
3746 break;
3747 default:
3748 break;
3749
3750 }
3751 }
3752 else
3753 nc_set_status (i, FB_SB_SYNC);
3754 }
3755 }
3756
3757 /*
3758 +--------------------------------------------------------------------+
3759 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3760 | STATE : code ROUTINE : nc_fill_report_sc_dedi |
3761 +--------------------------------------------------------------------+
3762
3763 PURPOSE : Fills the serving cell values for a measurement report.
3764
3765 */
3766
3767 GLOBAL void nc_fill_report_sc_dedi (T_MPH_MEASUREMENT_IND *rr_report,
3768 UBYTE ncells)
3769 {
3770 rr_report->valid = TRUE;
3771 rr_report->ncells.no_of_ncells = ncells;
3772 rr_report->arfcn = alr_data->serving_cell;
3773 rr_report->fn_offset = 103; /* average of SDCCH/FACCH */
3774 rr_report->dtx = alr_data->nc_data.act_dtx;
3775 rr_report->rx_lev_full = (UBYTE)alr_data->nc_data.rxlev_full;
3776 if (rr_report->rx_lev_full > 63)
3777 rr_report->rx_lev_full = 63;
3778 rr_report->rx_lev_sub = (UBYTE)alr_data->nc_data.rxlev_sub;
3779 if (rr_report->rx_lev_sub > 63)
3780 rr_report->rx_lev_sub = 63;
3781 rr_report->rx_qual_full = alr_data->nc_data.rxqual_full;
3782 rr_report->rx_qual_sub = alr_data->nc_data.rxqual_sub;
3783 rr_report->otd = alr_data->nc_data.tav;
3784
3785 if(ncells EQ 0)
3786 {
3787 /*
3788 * rxlev of SC BCCH channel is not avail
3789 * use approx value (rxlev_sub)
3790 */
3791 rr_report->bcch_rxlev_of_sc = rr_report->rx_lev_sub;
3792 }
3793 else
3794 {
3795 USHORT index = nc_get_index(alr_data->serving_cell);
3796 if(index EQ NOT_PRESENT_16BIT)
3797 {
3798 TRACE_EVENT("Error SC not present in BA list");
3799 rr_report->bcch_rxlev_of_sc = rr_report->rx_lev_sub;
3800 }
3801 else
3802 {
3803 if((UBYTE) alr_data->nc_data.cell[index].rxlev_average > 63)
3804 rr_report->bcch_rxlev_of_sc = 63;
3805 else
3806 rr_report->bcch_rxlev_of_sc = (UBYTE)alr_data->nc_data.cell[index].rxlev_average;
3807 }
3808 }
3809 }
3810
3811 /*
3812 +--------------------------------------------------------------------+
3813 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3814 | STATE : code ROUTINE : inform GRR |
3815 +--------------------------------------------------------------------+
3816
3817 PURPOSE : inform GRR
3818
3819 */
3820
3821 #ifdef GPRS
3822 LOCAL void nc_inform_grr_of_ncell (USHORT index, UBYTE type)
3823 {
3824 PALLOC(rr_rep, MPH_MEASUREMENT_IND);
3825 rr_rep->ncells.no_of_ncells = 1;
3826 rr_rep->ncells.arfcn[0] = alr_data->nc_data.cell[index].ba_arfcn;
3827 if(type EQ GRR_SB_FOUND)
3828 rr_rep->ncells.bsic[0] = alr_data->nc_data.cell[index].bsic;
3829 else
3830 rr_rep->ncells.bsic[0] = type;
3831 rr_rep->gprs_sync = SYNC_RESULTS;
3832 PSENDX(RR,rr_rep);
3833 }
3834
3835 LOCAL void remove_ncell_and_inform_grr (USHORT index)
3836 {
3837 nc_inform_grr_of_ncell (index, GRR_SB_UNKNOWN);
3838 nc_remove_channel_from_ba_list(index);
3839 }
3840 #endif
3841
3842
3843 /*
3844 +--------------------------------------------------------------------+
3845 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3846 | STATE : code ROUTINE : nc_build_rr_report |
3847 +--------------------------------------------------------------------+
3848
3849 PURPOSE : Fills a measurement report to RR with neighbour cell
3850 information.
3851
3852 */
3853
3854 LOCAL void nc_build_rr_report (T_MPH_MEASUREMENT_IND *rr_report)
3855 {
3856 UBYTE c_report;
3857 UBYTE c_ba_list;
3858 T_NC * pcell = alr_data->nc_data.cell;
3859
3860 c_report = 0;
3861 rr_report->valid = TRUE;
3862
3863 for (c_ba_list = 0; c_ba_list < alr_data->nc_data.c_ba_arfcn AND
3864 c_report < MAX_RR_NCELL_CNT; c_ba_list++, pcell++)
3865 {
3866 if(pcell->one_of_six AND pcell->ba_status EQ IN_BA)
3867 {
3868 switch (pcell->status)
3869 {
3870 case FB_SB_SYNC_RR_NOT_INFORMED:
3871 /*
3872 * the cell is synchronized but RR has no prior
3873 * knowledge of the cell, but we may have already
3874 * read data from the ncell BCCH. This check is performed
3875 * after sending the measurement report
3876 */
3877 case FB_SB_SYNC:
3878 case READ_BCCH:
3879 case READ_SB:
3880 case READ_SB_BCCH:
3881 /*
3882 * we may be currently reading this SB/FB or BCCH of the cell
3883 * pass up this cell also
3884 * if READ_FB_SB_PENDING this may be the first time that the
3885 * cell is read so check if the bsic of this cell has been
3886 * read already
3887 */
3888 case READ_SB_PENDING:
3889 case READ_SB_BCCH_PENDING:
3890 case READ_BCCH_PENDING:
3891 case READ_FB_SB_PENDING:
3892 if (pcell->ba_arfcn NEQ alr_data->serving_cell AND
3893 pcell->bsic NEQ NOT_PRESENT_8BIT)
3894 {
3895 rr_report->ncells.arfcn[c_report] = pcell->ba_arfcn;
3896 rr_report->ncells.rx_lev[c_report] = (UBYTE)pcell->rxlev_average;
3897 #if defined(_SIMULATION_)
3898 TRACE_EVENT_P3 ("rx_lev%u[%u]=%d",
3899 c_report, rr_report->ncells.arfcn[c_report],
3900 rr_report->ncells.rx_lev[c_report]);
3901 #endif /* _SIMULATION_ */
3902 rr_report->ncells.bsic[c_report] = pcell->bsic;
3903 rr_report->ncells.time_alignmt[c_report] = pcell->time_align;
3904 rr_report->ncells.frame_offset[c_report++] = pcell->frame_offset;
3905 }
3906 break;
3907 case READ_BCCH_RR_NOT_INFORMED:
3908 case READ_BCCH_PENDING_RR_NOT_INFORMED:
3909 case READ_FB_SB:
3910 /* do nothing */
3911 default:
3912 break;
3913 }
3914 }/* not one_of_six*/
3915 }
3916 rr_report->ncells.no_of_ncells = c_report;
3917 }
3918
3919
3920
3921 /*
3922 +--------------------------------------------------------------------+
3923 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
3924 | STATE : code ROUTINE : nc_build_nwctrl_rr_report |
3925 +--------------------------------------------------------------------+
3926
3927 PURPOSE : Fills a measurement report to RR with neighbour cell
3928 information.
3929
3930 */
3931
3932
3933 #ifdef GPRS
3934 GLOBAL void nc_build_nwctrl_rr_report (T_MPH_MEAS_REP_CNF *rr_report)
3935 {
3936 UBYTE c_report;
3937 UBYTE c_ba_list;
3938 USHORT index;
3939 T_NC * pcell;
3940
3941 /*
3942 * Store the rxlev average for the serving cell
3943 */
3944 index = nc_get_index(alr_data->serving_cell);
3945 if ( index NEQ NOT_PRESENT_16BIT )
3946 {
3947 pcell = &alr_data->nc_data.cell[index];
3948 rr_report->meas_rep[0].arfcn = alr_data->serving_cell;
3949 rr_report->meas_rep[0].bsic = pcell->bsic;
3950
3951 if(pcell->c_nc_rxlev)
3952 {
3953 rr_report->meas_rep[0].rx_lev = pcell->nc_rxlev/pcell->c_nc_rxlev;
3954 }
3955 #if defined(_SIMULATION_)
3956 TRACE_EVENT_P3 ("nw_sc__rxlev[%u]=acc : %d, count:%d",rr_report->meas_rep[0].arfcn,pcell->nc_rxlev,pcell->c_nc_rxlev);
3957 #endif /* _SIMULATION_ */
3958 }
3959
3960 c_report = 0;
3961 pcell = alr_data->nc_data.cell;
3962
3963 for (c_ba_list = 0; c_ba_list < alr_data->nc_data.c_ba_arfcn AND
3964 c_report < MAX_RR_NCELL_CNT; c_ba_list++, pcell++)
3965 {
3966 if(pcell->one_of_six AND pcell->ba_status EQ IN_BA)
3967 {
3968 switch (pcell->status)
3969 {
3970 case FB_SB_SYNC_RR_NOT_INFORMED:
3971 /*
3972 * the cell is synchronized but RR has no prior
3973 * knowledge of the cell, but we may have already
3974 * read data from the ncell BCCH. This check is performed
3975 * after sending the measurement report
3976 */
3977 case FB_SB_SYNC:
3978 case READ_BCCH:
3979 case READ_SB:
3980 case READ_SB_BCCH:
3981 /*
3982 * we may be currently reading this SB/FB or BCCH of the cell
3983 * pass up this cell also
3984 * if READ_FB_SB_PENDING this may be the first time that the
3985 * cell is read so check if the bsic of this cell has been
3986 * read already
3987 */
3988 case READ_SB_PENDING:
3989 case READ_SB_BCCH_PENDING:
3990 case READ_BCCH_PENDING:
3991 case READ_FB_SB_PENDING:
3992 if (pcell->ba_arfcn NEQ alr_data->serving_cell AND
3993 pcell->bsic NEQ NOT_PRESENT_8BIT)
3994 {
3995 rr_report->meas_rep[c_report+1].arfcn = pcell->ba_arfcn;
3996 rr_report->meas_rep[c_report+1].bsic = pcell->bsic;
3997 if(pcell->c_nc_rxlev)
3998 {
3999 rr_report->meas_rep[c_report+1].rx_lev = pcell->nc_rxlev/pcell->c_nc_rxlev;
4000 }
4001
4002 #if defined(_SIMULATION_)
4003 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);
4004 #endif /* _SIMULATION_ */
4005 c_report++;
4006 }
4007 break;
4008 case READ_BCCH_RR_NOT_INFORMED:
4009 case READ_BCCH_PENDING_RR_NOT_INFORMED:
4010 case READ_FB_SB:
4011 /* do nothing */
4012 default:
4013 break;
4014 }
4015 }/* not one_of_six*/
4016 }
4017
4018 if( (c_report + 1 ) < RR_ALR_MEAS_REPORT_SIZE )
4019 {
4020 rr_report->meas_rep[c_report+1].arfcn = NOT_PRESENT_16BIT ;
4021 rr_report->meas_rep[c_report+1].rx_lev = NOT_PRESENT_8BIT ;
4022 rr_report->meas_rep[c_report+1].bsic = NOT_PRESENT_8BIT ;
4023 }
4024 }
4025 #endif /* ifdef GPRS */
4026
4027 /*
4028 +--------------------------------------------------------------------+
4029 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4030 | STATE : code ROUTINE : nc_store_tav |
4031 +--------------------------------------------------------------------+
4032
4033 PURPOSE : Stores timing advance receveived with dedicated mode SI's
4034 */
4035 GLOBAL void nc_store_tav(USHORT tav)
4036 {
4037 alr_data->nc_data.tav = tav;
4038 }
4039
4040
4041 /*
4042 *========================================================================
4043 * Helper Functions
4044 *========================================================================
4045 */
4046
4047
4048 /*
4049 +--------------------------------------------------------------------+
4050 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4051 | STATE : code ROUTINE : nc_check_status |
4052 +--------------------------------------------------------------------+
4053
4054 PURPOSE : Checks the status of the neighbour cells.
4055 */
4056
4057 LOCAL void nc_check_status (UBYTE start_list)
4058 {
4059 USHORT i;
4060 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
4061 T_NC * pcell = alr_data->nc_data.cell;
4062
4063 for (i = 0; i < c_ba_arfcn; i++, pcell++)
4064 {
4065 if (pcell->ba_arfcn NEQ alr_data->serving_cell)
4066 {
4067 switch (GET_STATE(STATE_NC))
4068 {
4069 case NC_DEDICATED:
4070 switch (pcell->status)
4071 {
4072 case INACTIVE:
4073 break;
4074 case IDLE:
4075 if (pcell->one_of_twelve)
4076 nc_set_status (i, READ_FB_SB);
4077 if (start_list EQ CHECK_FOR_CONFIRM)
4078 {
4079 if (pcell->tim_valid EQ TV_VALID_TIMING_INFO)
4080 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4081 else if (pcell->tim_valid EQ TV_APPROX_TIMING_INFO)
4082 pcell->tim_valid = TV_INVALID_TIMING_INFO;
4083 }
4084 break;
4085 case READ_FB_SB:
4086 if (pcell->one_of_twelve EQ FALSE)
4087 {
4088 nc_set_status (i, IDLE);
4089 if (start_list EQ CHECK_FOR_CONFIRM AND pcell->tim_valid EQ TV_APPROX_TIMING_INFO)
4090 pcell->tim_valid = TV_INVALID_TIMING_INFO;
4091 }
4092 break;
4093 case FB_SB_SYNC:
4094 if (pcell->one_of_twelve EQ FALSE)
4095 {
4096 nc_set_status (i, IDLE_SYNC);
4097 }
4098 else
4099 {
4100 if ( (start_list) AND (alr_data->nc_data.c_sync_intrupted EQ FALSE))
4101 nc_set_status (i, READ_SB);
4102 }
4103 break;
4104 case IDLE_SYNC:
4105 if (pcell->one_of_twelve)
4106 {
4107 if (pcell->c_sync EQ 0)
4108 nc_set_status (i, READ_FB_SB);
4109 else
4110 nc_set_status (i, FB_SB_SYNC);
4111 }
4112 else
4113 {
4114 if (pcell->c_sync EQ 0)
4115 {
4116 nc_set_status (i, IDLE);
4117 }
4118 }
4119 break;
4120 case READ_SB:
4121 if (pcell->one_of_twelve EQ FALSE)
4122 {
4123 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4124 nc_set_status (i, IDLE);
4125 }
4126 break;
4127 case READ_BCCH_RR_NOT_INFORMED:
4128 case READ_BCCH:
4129 case READ_SB_BCCH:
4130 TRACE_EVENT("unexpected STATE_NC during NC_DEDICATED");
4131 if (pcell->one_of_twelve)
4132 nc_set_status (i, READ_FB_SB);
4133 else
4134 {
4135 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4136 nc_set_status (i, IDLE);
4137 }
4138 break;
4139
4140 case FB_SB_FAILED:
4141 if (pcell->one_of_twelve EQ FALSE)
4142 nc_set_status (i, IDLE);
4143 else if (pcell->c_sync EQ 0)
4144 nc_set_status (i, READ_FB_SB);
4145 break;
4146
4147 default:
4148 break;
4149 }
4150 break;
4151 case NC_IDLE:
4152 switch (pcell->status)
4153 {
4154 case INACTIVE:
4155 break;
4156 case IDLE:
4157 if (pcell->one_of_twelve)
4158 nc_set_status (i, READ_FB_SB);
4159 if (start_list EQ CHECK_FOR_CONFIRM)
4160 {
4161 if (pcell->tim_valid EQ TV_VALID_TIMING_INFO)
4162 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4163 else if (pcell->tim_valid EQ TV_APPROX_TIMING_INFO)
4164 pcell->tim_valid = TV_INVALID_TIMING_INFO;
4165 }
4166 break;
4167 case READ_FB_SB:
4168 if (pcell->one_of_twelve EQ FALSE)
4169 {
4170 nc_set_status (i, IDLE);
4171 if (start_list EQ CHECK_FOR_CONFIRM AND pcell->tim_valid EQ TV_APPROX_TIMING_INFO)
4172 pcell->tim_valid = TV_INVALID_TIMING_INFO;
4173 }
4174 break;
4175 case FB_SB_SYNC:
4176 if (pcell->one_of_twelve EQ FALSE)
4177 {
4178 nc_set_status (i, IDLE_SYNC);
4179 }
4180 else
4181 {
4182 if (start_list)
4183 nc_set_status (i, READ_SB);
4184 if (pcell->one_of_six AND
4185 pcell->c_bcch EQ 0)
4186 nc_set_status (i, READ_SB_BCCH);
4187 }
4188 break;
4189 case FB_SB_SYNC_RR_NOT_INFORMED:
4190 if (pcell->one_of_six EQ FALSE)
4191 {
4192 if (pcell->one_of_twelve EQ FALSE)
4193 {
4194 nc_set_status (i, IDLE_SYNC);
4195 }
4196 else
4197 {
4198 nc_set_status (i, FB_SB_SYNC);
4199 }
4200 }
4201 break;
4202 case FB_SB_FAILED:
4203 if (pcell->one_of_twelve EQ FALSE)
4204 nc_set_status (i, IDLE);
4205 else if (pcell->c_sync EQ 0)
4206 nc_set_status (i, READ_FB_SB);
4207 break;
4208 case IDLE_SYNC:
4209 if (pcell->one_of_twelve)
4210 {
4211 if(pcell->one_of_six)
4212 {
4213 if (pcell->c_sync EQ 0)
4214 nc_set_status (i, READ_FB_SB);
4215 else
4216 nc_set_status (i, READ_BCCH_RR_NOT_INFORMED);
4217 }
4218 else
4219 {
4220 if (pcell->c_sync EQ 0)
4221 nc_set_status (i, READ_FB_SB);
4222 else
4223 nc_set_status (i, FB_SB_SYNC);
4224 }
4225 }
4226 else
4227 {
4228 if (pcell->c_sync EQ 0)
4229 {
4230 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4231 nc_set_status (i, IDLE);
4232 }
4233 }
4234 break;
4235 case READ_SB:
4236 if (pcell->one_of_twelve EQ FALSE)
4237 {
4238 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4239 nc_set_status (i, IDLE);
4240 }
4241 else
4242 {
4243 if (pcell->c_bcch EQ 0)
4244 nc_set_status (i, READ_SB_BCCH);
4245 }
4246 break;
4247 case READ_BCCH:
4248 if (pcell->one_of_six EQ FALSE)
4249 {
4250 if (pcell->one_of_twelve EQ FALSE)
4251 {
4252 nc_set_status (i, IDLE_SYNC);
4253 }
4254 else
4255 {
4256 nc_set_status (i, FB_SB_SYNC);
4257 }
4258 }
4259 break;
4260 case READ_BCCH_RR_NOT_INFORMED:
4261 if (pcell->one_of_six EQ FALSE)
4262 {
4263 if (pcell->one_of_twelve EQ FALSE)
4264 {
4265 nc_set_status (i, IDLE_SYNC);
4266 }
4267 else
4268 {
4269 nc_set_status (i, FB_SB_SYNC);
4270 }
4271 }
4272 break;
4273
4274 case READ_SB_BCCH:
4275 if (pcell->one_of_six EQ FALSE)
4276 {
4277 if (pcell->one_of_twelve)
4278 nc_set_status(i, READ_SB);
4279 else
4280 {
4281 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4282 nc_set_status (i, IDLE);
4283 }
4284 }
4285 break;
4286
4287 default:
4288 break;
4289 }
4290 break;
4291 #ifdef GPRS
4292 case NC_PIM_PBCCH:
4293 case NC_PTM_PBCCH: /*XXX*/
4294 case NC_CON_EST: /*in case of an updated list in CON_EST */
4295 switch (pcell->status)
4296 {
4297 case IDLE:
4298 if(pcell->one_of_twelve)
4299 nc_set_status (i, READ_FB_SB);
4300 if (start_list EQ CHECK_FOR_CONFIRM)
4301 {
4302 if (pcell->tim_valid EQ TV_VALID_TIMING_INFO)
4303 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4304 else if (pcell->tim_valid EQ TV_APPROX_TIMING_INFO)
4305 pcell->tim_valid = TV_INVALID_TIMING_INFO;
4306 }
4307 break;
4308 case FB_SB_SYNC:
4309 if(pcell->one_of_twelve EQ FALSE)
4310 nc_set_status (i, IDLE_SYNC);
4311 else
4312 {
4313 if (start_list)
4314 nc_set_status (i, READ_SB);
4315 }
4316 break;
4317 case FB_SB_FAILED:
4318 if(pcell->one_of_twelve EQ FALSE)
4319 remove_ncell_and_inform_grr(i);
4320 else
4321 if(pcell->c_sync EQ 0)
4322 nc_set_status (i, READ_FB_SB);
4323 break;
4324 case READ_FB_SB:
4325 break;
4326 case READ_SB:
4327 if (pcell->one_of_twelve EQ FALSE)
4328 {
4329 pcell->tim_valid = TV_APPROX_TIMING_INFO;
4330 nc_set_status (i, IDLE);
4331 }
4332 break;
4333 case IDLE_SYNC:
4334 if(pcell->c_sync EQ 0)
4335 remove_ncell_and_inform_grr(i);
4336 else
4337 {
4338 if(pcell->one_of_twelve)
4339 nc_set_status (i, FB_SB_SYNC);
4340 }
4341 break;
4342 case READ_BCCH_RR_NOT_INFORMED:
4343 case READ_BCCH:
4344 case FB_SB_SYNC_RR_NOT_INFORMED:
4345 if (pcell->one_of_twelve EQ FALSE)
4346 {
4347 nc_set_status (i, IDLE_SYNC);
4348 }
4349 break;
4350 default:
4351 TRACE_EVENT_P4("wrong state in check_st: i%d a%d 1o6%d st%d", i,
4352 pcell->ba_arfcn,
4353 pcell->one_of_six,
4354 pcell->status);
4355 break;
4356 }
4357 #endif
4358 break;
4359 default:
4360 break;
4361 }/*switch state*/
4362 } /*if*/
4363 } /*for*/
4364 }
4365
4366 /*
4367 +--------------------------------------------------------------------+
4368 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4369 | STATE : code ROUTINE : nc_build_rr_report_dedi |
4370 +--------------------------------------------------------------------+
4371
4372 PURPOSE : Fills a measurement report to RR with neighbour cell
4373 information in dedicated mode.
4374 In dedicated mode the serving cell may be included.
4375
4376 */
4377 LOCAL void nc_build_rr_report_dedi (T_MPH_MEASUREMENT_IND *rr_report)
4378 {
4379 UBYTE c_report = 0;
4380 UBYTE c_ba_list;
4381 UBYTE found = TRUE;
4382 UBYTE index;
4383 UBYTE i;
4384 UBYTE in_report[34];
4385 T_NC * pcell1;
4386
4387 memset (in_report, 0, 34);
4388
4389 for ( i = 0; i < 6 AND found EQ TRUE; i++)
4390 {
4391 found = FALSE;
4392 index = NOT_PRESENT_8BIT;
4393 pcell1 = alr_data->nc_data.cell;
4394
4395 for (c_ba_list = 0; c_ba_list < alr_data->nc_data.c_ba_arfcn; c_ba_list++, pcell1++)
4396 {
4397 if (in_report[c_ba_list] EQ FALSE AND pcell1->ba_status EQ IN_BA)
4398 {
4399 switch (pcell1->status)
4400 {
4401 case FB_SB_SYNC:
4402 case READ_SB:
4403 case READ_SB_PENDING:
4404 if (nc_ncell_in_plmn_permitted(pcell1->bsic))
4405 {
4406 if ((pcell1->ba_arfcn NEQ alr_data->serving_cell AND
4407 pcell1->one_of_six) OR
4408 (pcell1->ba_arfcn EQ alr_data->serving_cell AND
4409 alr_data->nc_data.sc_included))
4410 {
4411 if (index EQ NOT_PRESENT_8BIT)
4412 index = c_ba_list;
4413 else
4414 {
4415 if (pcell1->rxlev_average >
4416 alr_data->nc_data.cell[index].rxlev_average)
4417 index = c_ba_list;
4418 }
4419 }
4420 }
4421 break;
4422 }
4423 }
4424 }
4425
4426 if (index NEQ NOT_PRESENT_8BIT)
4427 {
4428 T_NC* pcell = &alr_data->nc_data.cell[index];
4429 found = TRUE;
4430 in_report[index] = TRUE;
4431
4432 rr_report->ncells.arfcn[c_report] = pcell->ba_arfcn;
4433
4434 if ((UBYTE)pcell->rxlev_average > 63)
4435 rr_report->ncells.rx_lev[c_report] = 63;
4436 else
4437 rr_report->ncells.rx_lev[c_report] = (UBYTE)pcell->rxlev_average;
4438
4439 rr_report->ncells.bsic[c_report] = pcell->bsic;
4440 rr_report->ncells.time_alignmt[c_report] = pcell->time_align;
4441 rr_report->ncells.frame_offset[c_report++] = pcell->frame_offset;
4442 }
4443
4444 } /*for (up to 6 ncells)*/
4445 /*
4446 * insert serving cell values
4447 */
4448 nc_fill_report_sc_dedi (rr_report, c_report);
4449 }
4450
4451 /*
4452 +--------------------------------------------------------------------+
4453 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4454 | STATE : code ROUTINE : nc_rank_ncells |
4455 +--------------------------------------------------------------------+
4456
4457 PURPOSE : Searches for the six and additionally the twelve strongest neighbourcells.
4458
4459 */
4460 LOCAL void nc_rank_ncells (void)
4461 {
4462 USHORT c_found, i;
4463 USHORT last = (sizeof alr_data->nc_data.cell /
4464 sizeof alr_data->nc_data.cell[0]);
4465 UBYTE old_1of6[ sizeof alr_data->nc_data.cell /
4466 sizeof alr_data->nc_data.cell[0] ];
4467 UBYTE num_1of6, hyst_rxlev, nc_conf_active = FALSE;
4468
4469 num_1of6 = 0;
4470 hyst_rxlev = 63;
4471 alr_data->nc_data.new_strong_cell_detect = FALSE;
4472
4473 for ( i = 0; i < last; i++ )
4474 {
4475 old_1of6[i] = alr_data->nc_data.cell[i].one_of_six;
4476 alr_data->nc_data.cell[i].new_strong_cell = FALSE;
4477
4478 if(old_1of6[i])
4479 {
4480 num_1of6++;
4481
4482 if(alr_data->nc_data.cell[i].rxlev_average < hyst_rxlev)
4483 hyst_rxlev = alr_data->nc_data.cell[i].rxlev_average;
4484 }
4485
4486 alr_data->nc_data.cell[i].one_of_six = FALSE;
4487
4488 }
4489
4490 if(num_1of6 < MAX_RR_NCELL_CNT)
4491 hyst_rxlev = 0;
4492
4493 if((GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) AND
4494 (GET_STATE(STATE_NC) EQ NC_DEDICATED) AND
4495 (!alr_data->nc_data.eotd_avail))
4496 nc_conf_active = TRUE;
4497
4498 c_found = 0;
4499
4500 if ((std EQ STD_DUAL) OR (std EQ STD_DUAL_EGSM) OR (std EQ STD_DUAL_US))
4501 {
4502 switch (alr_data->nc_data.multiband)
4503 {
4504 case MULTI_BAND_0:
4505 /* Find 6 cells from any band */
4506 nc_find_cells (&c_found, MAX_RR_NCELL_CNT, NO_BAND_LIMITATION, ALR_RXLEV_AVERAGE_MIN);
4507 break;
4508 case MULTI_BAND_1:
4509 /* Find 1 cell from bands other than Serving cell band */
4510 nc_find_cells (&c_found, 1, EXCLUDE_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR);
4511
4512 /* Find 5 cells from the Serving cell band */
4513 nc_find_cells (&c_found, MAX_RR_NCELL_CNT-1, ONLY_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR);
4514
4515 /* If number of found cells are less than six, find the remaining from any band.
4516 * Also relax the Rxlev criteria
4517 */
4518 nc_find_cells (&c_found, (USHORT)(MAX_RR_NCELL_CNT - c_found), NO_BAND_LIMITATION,
4519 ALR_RXLEV_AVERAGE_MIN);
4520 break;
4521 case MULTI_BAND_2:
4522 /* Find 2 cell from bands other than Serving cell band */
4523 nc_find_cells (&c_found, 2, EXCLUDE_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR);
4524
4525 /* Find 4 cells from the Serving cell band */
4526 nc_find_cells (&c_found, MAX_RR_NCELL_CNT-2, ONLY_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR);
4527
4528 /* If number of found cells are less than six, find the remaining from any band.
4529 * Also relax the Rxlev criteria
4530 */
4531 nc_find_cells (&c_found, (USHORT)(MAX_RR_NCELL_CNT - c_found), NO_BAND_LIMITATION,
4532 ALR_RXLEV_AVERAGE_MIN);
4533 break;
4534 case MULTI_BAND_3:
4535 /* Find 3 cell from bands other than Serving cell band */
4536 nc_find_cells (&c_found, 3, EXCLUDE_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR);
4537
4538 /* Find 3 cells from the Serving cell band */
4539 nc_find_cells (&c_found, MAX_RR_NCELL_CNT-3, ONLY_SC_BAND, ALR_RXLEV_AVERAGE_LWR_THR);
4540
4541 /* If number of found cells are less than six, find the remaining from any band.
4542 * Also relax the Rxlev criteria
4543 */
4544 nc_find_cells (&c_found, (USHORT)(MAX_RR_NCELL_CNT - c_found), NO_BAND_LIMITATION,
4545 ALR_RXLEV_AVERAGE_MIN);
4546 break;
4547 }
4548 }
4549 else
4550 nc_find_cells (&c_found, MAX_RR_NCELL_CNT, NO_BAND_LIMITATION, ALR_RXLEV_AVERAGE_MIN);
4551
4552 for ( i = 0; i < last; i++ )
4553 {
4554 if (alr_data->nc_data.cell[i].one_of_six AND !old_1of6[i] AND
4555 GET_STATE(STATE_NC) NEQ NC_DEDICATED)
4556 { /* the cell becomes one of six */
4557 switch (alr_data->nc_data.cell[i].status)
4558 {
4559 case FB_SB_SYNC:
4560 /* the cell is treaded as synchronized, perform BCCH reading ASAP */
4561 nc_set_status(i, READ_BCCH_RR_NOT_INFORMED);
4562 break;
4563 case READ_SB:
4564 case IDLE_SYNC:
4565 case FB_SB_FAILED:
4566 /* the cell shall be synchronized ASAP, then BCCH info is to send to RR */
4567 nc_set_status(i, READ_FB_SB);
4568 break;
4569 case READ_SB_PENDING:
4570 /* after receipt of sync ind the BCCH is to read and to send to RR */
4571 nc_set_status(i, READ_FB_SB_PENDING);
4572 break;
4573 default:
4574 break;
4575 }
4576 }
4577 if (old_1of6[i] AND
4578 !alr_data->nc_data.cell[i].one_of_six AND
4579 alr_data->nc_data.cell[i].status EQ FB_SB_SYNC)
4580 alr_data->nc_data.cell[i].c_attempt = 0;
4581
4582 /* Check the new strong cell criteria when confirmation is active */
4583 if(nc_conf_active)
4584 {
4585 nc_check_new_strong_cell(i, old_1of6[i], hyst_rxlev);
4586
4587 }
4588 }
4589
4590 nc_find_list_cells();
4591
4592 TRACE_EVENT_P1("New strong cell detect:%d",
4593 alr_data->nc_data.new_strong_cell_detect);
4594 }
4595
4596 /*
4597 +--------------------------------------------------------------------+
4598 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4599 | STATE : code ROUTINE : nc_find_cells |
4600 +--------------------------------------------------------------------+
4601
4602 PURPOSE : Searches for the six strongest neighbourcells,
4603 using multiband parameter if needed.
4604 Called only in case of the value of 'std' is set to
4605 STD_DUAL, STD_DUAL_EGSM or STD_DUAL_US.
4606 (And therefore only for the combination of
4607 GSM900/E-GSM/DCS1800 or GSM850/PCS1900.)
4608
4609 */
4610 LOCAL void nc_find_cells (USHORT *c_found, USHORT max, UBYTE limitation,
4611 UBYTE min_rxlev)
4612 {
4613 int i, j;
4614 BOOL limit;
4615 int index;
4616
4617
4618 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
4619 T_NC* pcell;
4620 UBYTE band_nc;
4621 UBYTE band_sc = get_band (alr_data->serving_cell);
4622
4623 if (*c_found >= MAX_RR_NCELL_CNT)
4624 return;
4625
4626 if (band_sc EQ BAND_E_GSM)
4627 band_sc = BAND_GSM_900; /* equal treatment of E-GSM and GSM900 */
4628
4629 for (j = 0, index = 0; (j < max) AND (index NEQ NOT_PRESENT_16BIT); j++)
4630 {
4631 index = NOT_PRESENT_16BIT;
4632
4633 for (i = 0; i < c_ba_arfcn; i++)
4634 {
4635 pcell = &alr_data->nc_data.cell[i];
4636 /*
4637 * The six strongest neighbour cells do not include cells
4638 * currently not belonging to BA list
4639 */
4640 if (pcell->ba_status NEQ IN_BA)
4641 continue;
4642
4643 switch (pcell->status)
4644 {
4645 case INACTIVE:
4646 case EXCLUDED:
4647 /*
4648 * The six strongest neighbour cells do not include failed ncells.
4649 */
4650 break;
4651 default:
4652 if (pcell->ba_arfcn NEQ alr_data->serving_cell AND
4653 pcell->one_of_six EQ FALSE AND
4654 pcell->rxlev_average > min_rxlev) /* > -106 dBm */
4655 {
4656 band_nc = get_band (pcell->ba_arfcn);
4657 if (band_nc EQ BAND_E_GSM)
4658 band_nc = BAND_GSM_900; /* equal treatment of E-GSM and GSM900 */
4659
4660 switch (limitation)
4661 {
4662 default:
4663 case NO_BAND_LIMITATION:
4664 limit = FALSE;
4665 break;
4666 case EXCLUDE_SC_BAND:
4667 limit = (band_sc EQ band_nc);
4668 break;
4669 case ONLY_SC_BAND:
4670 limit = (band_sc NEQ band_nc);
4671 break;
4672 }
4673
4674 if (!limit)
4675 {
4676 if (index EQ NOT_PRESENT_16BIT)
4677 {
4678 index = i;
4679 }
4680 else
4681 {
4682 if (pcell->rxlev_average >
4683 alr_data->nc_data.cell[index].rxlev_average)
4684 {
4685 index = i;
4686 }
4687 }
4688 }
4689 }
4690 break;
4691 } /*ncell status*/
4692 }
4693
4694 if (index NEQ NOT_PRESENT_16BIT)
4695 {
4696 alr_data->nc_data.cell[index].one_of_six = TRUE;
4697 (*c_found)++;
4698 }
4699 }
4700 }
4701
4702
4703 /*
4704 +--------------------------------------------------------------------+
4705 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4706 | STATE : code ROUTINE : nc_find_list_cells |
4707 +--------------------------------------------------------------------+
4708
4709 PURPOSE : Searches for the 6 or 12 strongest neighbourcells
4710
4711 */
4712 LOCAL void nc_find_list_cells (void)
4713 {
4714 USHORT i, j;
4715 UBYTE found, c_found = 0;
4716 USHORT index;
4717 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
4718 T_NC* pcell;
4719
4720 for (i = 0, pcell = &alr_data->nc_data.cell[0]; i < c_ba_arfcn; i++, pcell++ )
4721 {
4722 if ((pcell->one_of_twelve = pcell->one_of_six) EQ TRUE)
4723 c_found++;
4724 }
4725 /*
4726 * The flag one_of_six controls the property to include a neighbour cell
4727 * into the measurement report,
4728 * the flag one_of_twelve controls whether the ncell is included into the
4729 * synchronisation confirmation process. In case of EOTD up to 12 cell are
4730 * included, in case of non-EOTD 6 cells are sufficient.
4731 */
4732 if (!alr_data->nc_data.eotd_avail)
4733 return;
4734
4735 for (j = c_found, found = TRUE; (j < MAX_L1_SYNC_CNT) AND (found EQ TRUE); j++)
4736 {
4737 index = NOT_PRESENT_16BIT;
4738 found = FALSE;
4739
4740 for (i = 0; i < c_ba_arfcn; i++)
4741 {
4742 pcell = &alr_data->nc_data.cell[i];
4743 /*
4744 * The 12 strongest neighbour cells do not include ncells currently not belonging to BA list.
4745 */
4746 if (pcell->ba_status NEQ IN_BA)
4747 continue;
4748
4749 switch (pcell->status)
4750 {
4751 case INACTIVE:
4752 case EXCLUDED:
4753 /*
4754 * The 12 strongest neighbour cells do not include failed ncells.
4755 */
4756 break;
4757 default:
4758 if (pcell->ba_arfcn NEQ alr_data->serving_cell AND
4759 pcell->one_of_twelve EQ FALSE AND
4760 pcell->rxlev_average > ALR_RXLEV_AVERAGE_MIN) /* > -110 dBm */
4761 {
4762 if (index EQ NOT_PRESENT_16BIT)
4763 {
4764 index = i;
4765 found = TRUE;
4766 }
4767 else
4768 {
4769 if (pcell->rxlev_average >
4770 alr_data->nc_data.cell[index].rxlev_average)
4771 {
4772 index = i;
4773 found = TRUE;
4774 }
4775 }
4776 }
4777 break;
4778 } /*ncell status*/
4779 }
4780
4781 if (found AND (index NEQ NOT_PRESENT_16BIT))
4782 alr_data->nc_data.cell[index].one_of_twelve = TRUE;
4783 }
4784 }
4785
4786 /*
4787 +--------------------------------------------------------------------+
4788 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4789 | STATE : code ROUTINE : nc_store_rxlev |
4790 +--------------------------------------------------------------------+
4791
4792 PURPOSE : Stores the fieldstrength values of the neighbour cells.
4793 Calculates the average of the fieldstrength after five
4794 samples.
4795
4796 */
4797
4798
4799 LOCAL void nc_store_rxlev (T_MPHC_RXLEV_PERIODIC_IND *report)
4800 {
4801 USHORT i;
4802 USHORT index;
4803 UBYTE diff;
4804 int max_attempt;
4805 T_NC* pcell;
4806
4807 ALR_TRACE_NC("store rxlev");
4808 /*
4809 * Patch for 20.5
4810 * The fieldstrength average for a new channel
4811 * increases too slow if more then eight channels
4812 * are in the neighbourcell list, because layer 1
4813 * sends not raw data every paging period.
4814 */
4815 if (test_house AND
4816 alr_data->nc_data.c_ba_arfcn > 8)
4817 max_attempt = 3;
4818 else
4819 max_attempt = 5;
4820
4821 if (alr_data->nc_data.tim_state NEQ NC_TIM_STOPPED)
4822 {
4823 /* Decrement the 10sec timer counter variable by BS_PA_MFRMS */
4824 alr_data->nc_data.c_ncsync_tim = (UBYTE)(alr_data->nc_data.c_ncsync_tim - alr_data->bs_pa_mfrms - 2);
4825
4826 if ((signed char)(alr_data->nc_data.c_ncsync_tim) < 0)
4827 alr_data->nc_data.c_ncsync_tim = 0;
4828
4829 if( alr_data->nc_data.c_ncsync_tim EQ 0 )
4830 nc_ncsync_tim_expiry(); /* 10 sec have elapsed. Perform all requisite tasks */
4831 }
4832
4833 /* serving cell rxlev storage */
4834 index = nc_get_index (alr_data->serving_cell);
4835 pcell = &alr_data->nc_data.cell[index];
4836
4837 if ( (signed char)report->s_rxlev < 0)
4838 report->s_rxlev = 0;
4839
4840 if (pcell->c_rxlev EQ NOT_PRESENT_8BIT)
4841 {
4842 pcell->c_rxlev = 0;
4843 memset (pcell->rxlev, report->s_rxlev, 5);
4844 }
4845 else
4846 {
4847 pcell->rxlev[pcell->c_rxlev++] = report->s_rxlev;
4848 }
4849 pcell->c_rxlev %= 5;
4850
4851 /*
4852 * store the results seperately for averaging when NC=1 or NC=2
4853 */
4854 #ifdef GPRS
4855 if(alr_data->nwctrl_meas_active)
4856 {
4857 pcell->nc_rxlev += report->s_rxlev;
4858 pcell->c_nc_rxlev++;
4859 }
4860 #endif
4861
4862 /*
4863 * ncell rxlev storage
4864 */
4865 for (i = 0; i < report->nbr_of_carriers; i++)
4866 {
4867 /*
4868 * The RX level from TI is signed in the SAP
4869 * we define it as unsigned
4870 */
4871 if ((signed char) (report->result[i].rxlev) < 0)
4872 {
4873 report->result[i].rxlev = 0;
4874 }
4875
4876 index = nc_get_index (ARFCN_TO_G23(report->result[i].radio_freq));
4877 if (index NEQ NOT_PRESENT_16BIT AND
4878 index NEQ LAST_BSIC_REQ AND
4879 ARFCN_TO_G23(report->result[i].radio_freq) NEQ alr_data->serving_cell)
4880 {
4881 int temp;
4882 UBYTE rxlev = report->result[i].rxlev;
4883 pcell = &alr_data->nc_data.cell[index];
4884
4885 if (pcell->c_rxlev EQ NOT_PRESENT_8BIT)
4886 {
4887 /*
4888 * if it is a new cell, build an average from the first value
4889 * to speed up fb sb read
4890 */
4891 pcell->rxlev[0] = rxlev;
4892 pcell->rxlev[1] = rxlev;
4893 pcell->rxlev[2] = rxlev;
4894 pcell->rxlev[3] = rxlev;
4895 pcell->rxlev[4] = rxlev;
4896 pcell->c_rxlev = 0;
4897 }
4898 else
4899 {
4900 pcell->rxlev[pcell->c_rxlev++] = rxlev;
4901 if (pcell->c_rxlev >= (UBYTE)max_attempt)
4902 pcell->c_rxlev = 0;
4903 }
4904 temp = pcell->rxlev[0] +
4905 pcell->rxlev[1] +
4906 pcell->rxlev[2];
4907
4908 if (max_attempt EQ 5)
4909 {
4910 temp += pcell->rxlev[3] +
4911 pcell->rxlev[4];
4912 }
4913
4914 pcell->rxlev_average = (UBYTE)(temp / max_attempt);
4915 /*
4916 * store the results seperately for averaging when NC=1 or NC=2
4917 */
4918 #ifdef GPRS
4919 if(alr_data->nwctrl_meas_active)
4920 {
4921 pcell->nc_rxlev += rxlev;
4922 pcell->c_nc_rxlev++;
4923 }
4924 #endif
4925
4926
4927 #if defined(TRACING)
4928 TRACE_EVENT_P4("NC%u[%d] rx=%d av=%d",
4929 index,
4930 pcell->ba_arfcn EQ NOT_PRESENT_16BIT ? -1 : pcell->ba_arfcn&ARFCN_MASK,
4931 report->result[i].rxlev, pcell->rxlev_average);
4932 #endif /* TRACING */
4933
4934 switch (pcell->status)
4935 {
4936 case INACTIVE:
4937 nc_set_status (index, IDLE);
4938 break;
4939 case EXCLUDED:
4940 diff = (UBYTE)(pcell->rxlev_average - pcell->last_rxlev);
4941 if (diff < 128 AND diff >= 6)
4942 {
4943 /*
4944 * result is positive and more than 6 dBm
4945 */
4946 nc_set_status (index, IDLE);
4947 }
4948 break;
4949 default:
4950 break;
4951 }
4952 }
4953 }
4954 }
4955
4956 /*
4957 +--------------------------------------------------------------------+
4958 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
4959 | STATE : code ROUTINE : nc_find_serving_cell_entry |
4960 +--------------------------------------------------------------------+
4961
4962 PURPOSE : Finds an entry for serving cell
4963 in the BCCH allocation list.
4964
4965 */
4966 LOCAL T_NC* nc_find_serving_cell_entry (USHORT serving_cell)
4967 {
4968 T_NC* pcell;
4969 USHORT i;
4970 UBYTE last_alr = alr_data->nc_data.c_ba_arfcn;
4971
4972 if (last_alr < LAST_BSIC_REQ)
4973 {
4974 pcell = &alr_data->nc_data.cell[last_alr];
4975 #if defined(TRACING)
4976 TRACE_EVENT_P2 ("NC%u[%u] add", last_alr, serving_cell);
4977 #endif /* TRACING */
4978 alr_data->nc_data.c_ba_arfcn = last_alr+1; /* store new last index */
4979 i = last_alr;
4980 ALR_TRACE_ALL_NC ();
4981 }
4982 else
4983 { /* ALR list is full, search for an entry not in state IN_BA */
4984 for (i = 0, pcell = alr_data->nc_data.cell; i < LAST_BSIC_REQ; i++, pcell++)
4985 {
4986 if (pcell->ba_status NEQ IN_BA)
4987 break;
4988 } /* for (i...) */
4989 if (i >= LAST_BSIC_REQ)
4990 { /*
4991 * no entry found
4992 * reuse the last entry to make sure there is a place for serving cell
4993 */
4994 i = LAST_BSIC_REQ-1;
4995 pcell = &alr_data->nc_data.cell[i];
4996 }
4997
4998 nc_stop_if_active(i);
4999 #if defined(TRACING)
5000 TRACE_EVENT_P2 ("NC%u[%u] replace", i, serving_cell);
5001 #endif /* TRACING */
5002 }
5003 nc_set_status (i, FB_SB_SYNC);
5004 pcell->ba_status = IN_BA; /* even if not in the BA but other functions need it */
5005 pcell->ba_arfcn = serving_cell;
5006 return pcell;
5007 }
5008
5009 /*
5010 +--------------------------------------------------------------------+
5011 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5012 | STATE : code ROUTINE : nc_add_serving_cell_ba_list|
5013 +--------------------------------------------------------------------+
5014
5015 PURPOSE : Adds serving cell to neighbourcell list.
5016 This function is called just before nc_start_reselect
5017 and not after the MPHC_NEW_SCELL_CNF.
5018
5019 */
5020 LOCAL void nc_add_serving_cell_ba_list (USHORT serving_cell)
5021 {
5022 USHORT index = nc_get_index (serving_cell);
5023 T_NC* pcell;
5024
5025 /*
5026 * Add serving cell if not included
5027 */
5028 switch (index)
5029 {
5030 case NOT_PRESENT_16BIT:
5031 case LAST_BSIC_REQ:
5032 /* serving cell isn´t inside the BA list */
5033 pcell = nc_find_serving_cell_entry(serving_cell);
5034 pcell->bsic = alr_data->nc_data.cr_cell.bsic;
5035 pcell->frame_offset = alr_data->nc_data.cr_cell.frame_offset;
5036 pcell->time_align = alr_data->nc_data.cr_cell.time_align;
5037 break;
5038
5039 default:
5040 if (index < ELEMENTS(alr_data->nc_data.cell))
5041 {
5042 /* serving cell is already included in ba list */
5043 /* For GPRS the scell may not be in FB_SB_SYNC so put it there */
5044 pcell = &alr_data->nc_data.cell[index];
5045
5046 /* Check whether the cell has valid sync info */
5047 if (pcell->bsic NEQ NOT_PRESENT_8BIT)
5048 {
5049 nc_set_status(index, FB_SB_SYNC);
5050 alr_data->nc_data.cell[index].one_of_six = FALSE;
5051 alr_data->nc_data.cell[index].ba_status = IN_BA; /* even if not in the BA but other functions need it */
5052 }
5053 }
5054 break;
5055 }
5056 }
5057
5058 /*
5059 +--------------------------------------------------------------------+
5060 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5061 | STATE : code ROUTINE : nc_update_ba_list |
5062 +--------------------------------------------------------------------+
5063
5064 PURPOSE : Updates the BCCH allocation list.
5065
5066 */
5067
5068 LOCAL void nc_update_ba_list (USHORT serving_cell, T_MPH_NEIGHBOURCELL_REQ *ncell_list)
5069 {
5070 USHORT n_rr; /* index of RR neighbor cell list */
5071 USHORT n_alr; /* index of ALR neighbor cell list */
5072 UBYTE last_alr; /* last index of ALR neighbor cell list */
5073 USHORT arfcn;
5074 T_NC* pcell;
5075
5076 alr_data->nc_data.multiband = ncell_list->multi_band;
5077
5078 /*
5079 * remove or mark all channels which are not longer member of the
5080 * neighbour cell list.
5081 */
5082 last_alr = alr_data->nc_data.c_ba_arfcn; /* current last index */
5083 for (n_alr = 0; n_alr < last_alr; n_alr++)
5084 {
5085 pcell = &alr_data->nc_data.cell[n_alr];
5086 arfcn = pcell->ba_arfcn;
5087 if (!nc_is_in_ncell_list (arfcn, ncell_list) AND
5088 (arfcn NEQ serving_cell))
5089 {
5090 if (GET_STATE(STATE_NC) EQ NC_IDLE)
5091 { /* the RR neighbor cell list is complete */
5092 last_alr = nc_remove_channel_from_ba_list (n_alr);
5093 #if defined(TRACING)
5094 TRACE_EVENT_P2 ("NC%u[%u] remove", n_alr, arfcn);
5095 #endif /* TRACING */
5096 n_alr--;
5097 ALR_TRACE_ALL_NC ();
5098 }
5099 else
5100 { /* the RR neighbor cell list may be incomplete so mark only the entry */
5101 if (pcell->ba_status EQ IN_BA)
5102 {
5103 pcell->ba_status = NOT_IN_BA_SHORT;
5104
5105 #if defined(TRACING)
5106 TRACE_EVENT_P2 ("NC%u[%u] -> NOT_IN_BA_SHORT", n_alr, arfcn);
5107 #endif /* TRACING */
5108 }
5109 }
5110 }
5111 }
5112
5113 /*
5114 * add all new channels.
5115 */
5116 for (n_rr = 0; n_rr < MAX_NEIGHBOURCELLS; n_rr++)
5117 {
5118 arfcn = ncell_list->arfcn[n_rr];
5119 if (arfcn EQ NOT_PRESENT_16BIT)
5120 break; /* no more entries in the RR ncell_list */
5121
5122 n_alr = nc_get_index (arfcn);
5123
5124 if (arfcn NEQ serving_cell)
5125 {
5126 if (n_alr EQ NOT_PRESENT_16BIT OR n_alr EQ LAST_BSIC_REQ)
5127 {
5128 if (last_alr < BA_LIST_SIZE)
5129 {
5130 pcell = &alr_data->nc_data.cell[last_alr];
5131
5132 #if defined(TRACING)
5133 TRACE_EVENT_P2 ("NC%u[%u] add", last_alr, arfcn);
5134 #endif /* TRACING */
5135 pcell->ba_arfcn = arfcn;
5136 nc_set_status (last_alr, INACTIVE);
5137 pcell->ba_status = IN_BA;
5138 last_alr++; /* increment last index */
5139 }
5140 else
5141 { /* ALR list is full, search for an entry not in state IN_BA */
5142 USHORT i;
5143 for (i = 0, pcell = alr_data->nc_data.cell; i < BA_LIST_SIZE; i++, pcell++)
5144 {
5145 if (pcell->ba_status NEQ IN_BA AND pcell->ba_arfcn NEQ serving_cell)
5146 {
5147 nc_stop_if_active(i);
5148 #if defined(TRACING)
5149 TRACE_EVENT_P2 ("NC%u[%u] replace", i, arfcn);
5150 #endif /* TRACING */
5151 pcell->ba_arfcn = arfcn;
5152 nc_set_status (i, INACTIVE);
5153 pcell->ba_status = IN_BA;
5154 break;
5155 }
5156 } /* for (i...) */
5157 }
5158 }
5159 else
5160 {
5161 #if defined(TRACING)
5162 if (alr_data->nc_data.cell[n_alr].ba_status NEQ IN_BA)
5163 TRACE_EVENT_P2 ("NC%u[%u] -> IN_BA", n_alr, arfcn);
5164 #endif
5165 alr_data->nc_data.cell[n_alr].ba_status = IN_BA;
5166 }
5167 } /* if (arfcn NEQ serving_cell) */
5168 }
5169
5170 /*
5171 * store whether SC was included into the BA list by the net
5172 */
5173 if (nc_is_in_ncell_list (serving_cell, ncell_list))
5174 {
5175 alr_data->nc_data.sc_included = TRUE;
5176 }
5177 else
5178 {
5179 alr_data->nc_data.sc_included = FALSE;
5180 }
5181 alr_data->nc_data.c_ba_arfcn = last_alr; /* store new last index */
5182
5183 /*
5184 * Add serving cell if not included
5185 */
5186 n_alr = nc_get_index (serving_cell);
5187 switch (n_alr)
5188 {
5189 case NOT_PRESENT_16BIT:
5190 case LAST_BSIC_REQ:
5191 pcell = nc_find_serving_cell_entry(serving_cell);
5192
5193 pcell->bsic = alr_data->bsic;
5194 pcell->frame_offset = 0;
5195 pcell->time_align = 0;
5196 break;
5197
5198 default:
5199 /* serving cell is already included */
5200 pcell = &alr_data->nc_data.cell[n_alr];
5201 pcell->bsic = alr_data->bsic;
5202 pcell->frame_offset = 0;
5203 pcell->time_align = 0;
5204 pcell->ba_status = IN_BA; /* even if not in the BA but other functions need it */
5205 nc_set_status (n_alr, FB_SB_SYNC); /* make sure the SC is reported in measurement reports if included into BA list */
5206 break;
5207 }
5208
5209 /*
5210 * reset status of neighbour cells with failed
5211 * synchronisation attempts.
5212 */
5213 for (n_alr = 0; n_alr < last_alr; n_alr++)
5214 {
5215 switch (alr_data->nc_data.cell[n_alr].status)
5216 {
5217 case FB_SB_FAILED:
5218 case EXCLUDED:
5219 alr_data->nc_data.cell[n_alr].tim_valid = TV_INVALID_TIMING_INFO;
5220 nc_set_status (n_alr, IDLE);
5221 break;
5222 }
5223 }
5224
5225 /*
5226 * Reorder the entries. The goal is that the propably strongest neigbour cells
5227 * are measured in the first measurement period of a subsequent
5228 * MPHC_RXLEV_PERIODIC_REQ/IND. The appropriate arfcn's are the first ones in
5229 * ncell_list->arfcn
5230 */
5231 if (last_alr > 8)
5232 {
5233 T_NC temp, *prr, *palr;
5234
5235 for (n_rr = 0; n_rr < 8 && ncell_list->arfcn[n_rr] NEQ NOT_PRESENT_16BIT; n_rr++)
5236 {
5237 n_alr = nc_get_index (ncell_list->arfcn[n_rr]);
5238 if (n_rr NEQ n_alr)
5239 {
5240 palr = &(alr_data->nc_data.cell[n_alr]);
5241 prr = &(alr_data->nc_data.cell[n_rr]);
5242 memcpy(&temp, palr, sizeof(T_NC));
5243 memcpy(palr, prr, sizeof(T_NC));
5244 memcpy(prr, &temp, sizeof(T_NC));
5245 /*TRACE_EVENT_P4("reordered NC%u[%u] and NC%u[%u]",
5246 n_rr,
5247 ncell_list->arfcn[n_rr],
5248 n_alr, ncell_list->arfcn[n_alr]);*/
5249 }
5250 }
5251 }
5252
5253 ALR_TRACE_ALL_NC ();
5254 }
5255
5256 /*
5257 +--------------------------------------------------------------------+
5258 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5259 | STATE : code ROUTINE : nc_new_serving_cell |
5260 +--------------------------------------------------------------------+
5261
5262 PURPOSE : Store old, set new serving cell, and add to neighbourcell list.
5263
5264 */
5265 GLOBAL void nc_new_serving_cell (USHORT serving_cell)
5266 {
5267 alr_data->old_serving_cell = alr_data->serving_cell;
5268 alr_data->serving_cell = serving_cell;
5269 alr_data->sc_band = get_band (alr_data->serving_cell);
5270 nc_add_serving_cell_ba_list(serving_cell);
5271 }
5272
5273 /*
5274 +--------------------------------------------------------------------+
5275 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5276 | STATE : code ROUTINE : nc_is_in_ncell_list |
5277 +--------------------------------------------------------------------+
5278
5279 PURPOSE : Checks whether a channel is in the ncell_list of RR.
5280
5281 */
5282 LOCAL UBYTE nc_is_in_ncell_list (USHORT channel, T_MPH_NEIGHBOURCELL_REQ *ncell_list)
5283 {
5284 USHORT i;
5285
5286 for (i = 0; i < MAX_NEIGHBOURCELLS AND ncell_list->arfcn[i] NEQ NOT_PRESENT_16BIT; i++)
5287 {
5288 if (channel EQ ncell_list->arfcn[i])
5289 return TRUE;
5290 }
5291
5292 return FALSE;
5293 }
5294
5295 /*
5296 +--------------------------------------------------------------------+
5297 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5298 | STATE : code ROUTINE : nc_remove_channel_from_ba_list |
5299 +--------------------------------------------------------------------+
5300
5301 PURPOSE : Removes one channel from the BCCH allocation.
5302
5303 */
5304
5305 LOCAL UBYTE nc_remove_channel_from_ba_list (USHORT index)
5306 {
5307 USHORT i;
5308 UBYTE c_ba_arfcn;
5309
5310 switch(alr_data->nc_data.cell[index].status)
5311 {
5312 case READ_SB_PENDING:
5313 case READ_SB_BCCH_PENDING:
5314 if ( alr_data->nc_data.eotd_avail AND
5315 ( GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM) )
5316 {
5317 /* we cannot stop this
5318 * because we are using a list_req
5319 */
5320 nc_set_status(index, INACTIVE);
5321 break;
5322 }
5323 /*lint -fallthrough*/
5324 case READ_FB_SB_PENDING:
5325 /*
5326 * sync request is ongoing in layer 1.
5327 */
5328 nc_stop_sync (index, INACTIVE);
5329 break;
5330 case READ_BCCH_PENDING:
5331 case READ_BCCH_PENDING_RR_NOT_INFORMED:
5332 /*
5333 * stop pending BCCH request
5334 */
5335 nc_stop_bcch (index, INACTIVE);
5336 break;
5337 default:
5338 nc_set_status (index, INACTIVE);
5339 break;
5340 }
5341
5342 c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
5343 for (i = index + 1; i < c_ba_arfcn; i++)
5344 {
5345 memcpy (&alr_data->nc_data.cell[i - 1],&alr_data->nc_data.cell[i],sizeof(T_NC)); /*shift NC*/
5346 }
5347 memset (&alr_data->nc_data.cell[i - 1],0,sizeof (T_NC));/*delete old content of obsolete ba_list entry*/
5348
5349 alr_data->nc_data.c_ba_arfcn--;
5350 return (alr_data->nc_data.c_ba_arfcn);
5351 }
5352
5353
5354 /*
5355 +--------------------------------------------------------------------+
5356 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5357 | STATE : code ROUTINE : nc_get_index |
5358 +--------------------------------------------------------------------+
5359
5360 PURPOSE : Calculates the index in the BCCH allocation.
5361
5362 */
5363
5364 GLOBAL USHORT nc_get_index (USHORT arfcn)
5365 {
5366 USHORT i;
5367 T_NC *pcell; /* use pointer to increase processing speed */
5368 USHORT last_alr; /* last index of ALR neighbor cell list */
5369
5370 last_alr = alr_data->nc_data.c_ba_arfcn;
5371 pcell = &alr_data->nc_data.cell[0]; /* pointer to first cell */
5372 for (i = 0; i < last_alr; i++, pcell++)
5373 {
5374 if (arfcn EQ pcell->ba_arfcn)
5375 return i;
5376 }
5377
5378 if (arfcn EQ alr_data->nc_data.cell[LAST_BSIC_REQ].ba_arfcn)
5379 return LAST_BSIC_REQ;
5380
5381 return NOT_PRESENT_16BIT;
5382 }
5383 /*
5384 +--------------------------------------------------------------------+
5385 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5386 | STATE : code ROUTINE : nc_build_sync_req |
5387 +--------------------------------------------------------------------+
5388
5389 PURPOSE : Builds an MPHC_NCELL_SYNC_REQ and sends it to L1.
5390
5391 */
5392 LOCAL void nc_build_sync_req (USHORT index)
5393 {
5394 T_NC * p_ncell = &alr_data->nc_data.cell[index];
5395 PALLOC (sync_req, MPHC_NCELL_SYNC_REQ);
5396
5397 sync_req->radio_freq = ARFCN_TO_L1(p_ncell->ba_arfcn);
5398 if (p_ncell->tim_valid EQ TV_INVALID_TIMING_INFO)
5399 {
5400 sync_req->fn_offset = 0;
5401 sync_req->time_alignment = 0;
5402 }
5403 else
5404 {
5405 sync_req->fn_offset = p_ncell->frame_offset;
5406 sync_req->time_alignment = p_ncell->time_align;
5407 }
5408 sync_req->timing_validity = p_ncell->tim_valid;
5409 TRACE_EVENT_P4("nc_build_sync_req[%d] timing_validity=%d fn_offset=%ld, time_alignment=%ld",
5410 p_ncell->ba_arfcn,
5411 sync_req->timing_validity,
5412 sync_req->fn_offset,
5413 sync_req->time_alignment);
5414 ma_nc_sync_req (sync_req);
5415
5416 ALR_EM_READ_NEIGHBOURCELL_SB;
5417
5418 nc_set_status (index, READ_FB_SB_PENDING);
5419 alr_data->nc_data.c_sync_req++;
5420 }
5421
5422
5423 /*
5424 +--------------------------------------------------------------------+
5425 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5426 | STATE : code ROUTINE : nc_process_status |
5427 +--------------------------------------------------------------------+
5428
5429 PURPOSE : Starts a specific procedure for neighbour cells like
5430 synchronisation to frequency correction burst and
5431 synchron burst, confirmation of synchron burst or
5432 reading of BCCH. With the new ALR interface it's possible
5433 to send up to 12 SYNC_REQ's and BCCH_REQ's.
5434
5435 */
5436
5437 LOCAL void nc_process_status (void)
5438 {
5439 UBYTE st = GET_STATE(STATE_NC);
5440
5441 /* Sync requests for New cells are allowed only in dedicated state
5442 * when eotd is not enabled. Fix for
5443 */
5444 if(((alr_data->nc_data.eotd_avail) OR ( st NEQ NC_DEDICATED)) AND
5445 (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM))
5446 return;
5447
5448 #ifdef GPRS
5449 if((st EQ NC_IDLE AND !ma_is_ptm()) OR
5450 st EQ NC_PIM_PBCCH )
5451 nc_process_status_last_bsic();
5452 #else
5453 nc_process_status_last_bsic();
5454 #endif
5455
5456
5457 if(alr_data->plmn_search_running)
5458 return;
5459
5460 #ifdef GPRS
5461 if(st EQ NC_PIM_PBCCH OR
5462 st EQ NC_PTM_PBCCH )
5463 nc_process_status_sync_gprs();
5464 else
5465 #endif
5466 nc_process_status_sync();
5467
5468 if(st EQ NC_IDLE)
5469 nc_process_status_bcch();
5470 }
5471
5472 /*
5473 +--------------------------------------------------------------------+
5474 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5475 | STATE : code ROUTINE : nc_process_status_last_bsic|
5476 +--------------------------------------------------------------------+
5477
5478 PURPOSE : When doing idle mode cell selection we use
5479 LAST_BSIC_REQ for storing the information of the cell.
5480 This has priority over normal neighbour cell monitoring.
5481
5482 */
5483
5484
5485 LOCAL void nc_process_status_last_bsic(void)
5486 {
5487 T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ];
5488
5489
5490 switch (pbsic->status)
5491 {
5492 case READ_FB_SB:
5493 if (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT)
5494 {
5495 pbsic->tim_valid = TV_INVALID_TIMING_INFO;
5496 nc_build_sync_req (LAST_BSIC_REQ);
5497 ALR_TRACE_NC ("ncell_sync_req HPLMN");
5498
5499 /* If the Mobile is in page mode REORG the NC search cannot be
5500 * performed because L1 is too busy listening to the PCH. Therefore
5501 * the page mode is changed from REORG to REORG_NC_SYNC (NORMAL).
5502 */
5503 if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR
5504 alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS)
5505 {
5506 page_mode_before_hplmn_search = alr_data->pch_data.pl_idle.page_mode;
5507 alr_data->pch_data.pl_idle.page_mode = PGM_REORG_NC_SYNC;
5508 pch_start_ccch_req ();
5509 ALR_TRACE_NC ("HPLMN search cannot be performed with REORG - possible loss of pagings");
5510 }
5511
5512 }
5513 return ;
5514
5515 case READ_BCCH:
5516 if (alr_data->nc_data.c_bcch_req < MAX_L1_BCCH_CNT)
5517 {
5518 PALLOC (ncell_bcch, MPHC_NCELL_BCCH_REQ);
5519
5520 ncell_bcch->radio_freq = ARFCN_TO_L1(pbsic->ba_arfcn);
5521 ncell_bcch->fn_offset = pbsic->frame_offset;
5522 ncell_bcch->time_alignment = pbsic->time_align;
5523 /*
5524 * The training sequence code on broadcast and common control channels
5525 * has to be equal to the base station color code see GSM 5.02
5526 */
5527 ncell_bcch->tsc = (UBYTE)(pbsic->bsic & ONLY_BCC);
5528 /*
5529 * Read SI 3/4 to get the MNC/MCC
5530 */
5531 pbsic->blocks_required =
5532 ncell_bcch->bcch_blocks_required = NCELL_BCCH_SI_3_4;
5533 ncell_bcch->gprs_prio = GPRS_PRIO_NORM;
5534
5535 ma_nc_bcch_req (ncell_bcch);
5536 alr_data->nc_data.c_bcch_req++;
5537 nc_set_status (LAST_BSIC_REQ, READ_BCCH_PENDING);
5538 }
5539 return;
5540 case READ_FB_SB_PENDING:
5541 case READ_BCCH_PENDING:
5542 return;
5543 default:
5544 break;
5545 }
5546 }
5547
5548
5549 /*
5550 +--------------------------------------------------------------------+
5551 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5552 | STATE : code ROUTINE : nc_process_status_sync |
5553 +--------------------------------------------------------------------+
5554
5555 PURPOSE : Processes cell synchronisation.
5556
5557 */
5558
5559
5560
5561 LOCAL void nc_process_status_sync(void)
5562 {
5563 USHORT i;
5564 USHORT index;
5565 T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ];
5566
5567 /* Sync requests for New cells are allowed only in dedicated state
5568 * when eotd is not enabled. Patch for
5569 */
5570 if((!alr_data->nc_data.eotd_avail) AND
5571 ( GET_STATE(STATE_NC) EQ NC_DEDICATED) AND
5572 (GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM))
5573 {
5574 if(alr_data->nc_data.new_strong_cell_detect)
5575 nc_handle_new_strong_cells();
5576
5577 alr_data->nc_data.new_strong_cell_detect = FALSE;
5578 return;
5579 }
5580
5581 while (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT)
5582 {
5583 /*
5584 * It is possible to send more sync requests to layer 1
5585 */
5586 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
5587 index = NOT_PRESENT_16BIT;
5588
5589 for (i = 0; i < c_ba_arfcn; i++)
5590 {
5591 /*
5592 * search for the candidate with the highest fieldstrength
5593 */
5594 T_NC* pcell = &alr_data->nc_data.cell[i];
5595
5596 if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND
5597 (pcell->ba_arfcn NEQ alr_data->serving_cell))
5598 {
5599 switch (pcell->status)
5600 {
5601 case READ_FB_SB:
5602 if (index EQ NOT_PRESENT_16BIT)
5603 index = i;
5604 else
5605 {
5606 if (pcell->rxlev_average >
5607 alr_data->nc_data.cell[index].rxlev_average)
5608 index = i;
5609 }
5610 break;
5611 default:
5612 break;
5613 }
5614 }
5615 }
5616
5617 if (index NEQ NOT_PRESENT_16BIT)
5618 {
5619 /*
5620 * Request synchronisation for this cell
5621 */
5622 nc_build_sync_req(index);
5623 ALR_TRACE_NC ("ncell_sync_req");
5624 }
5625 else
5626 break; /*while loop */
5627 } /* while( c_sync_req < MAX_L1_SYNC_CNT) */
5628 }
5629
5630 /*
5631 +--------------------------------------------------------------------+
5632 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5633 | STATE : code ROUTINE : nc_process_status_sync_gprs|
5634 +--------------------------------------------------------------------+
5635
5636 PURPOSE : Processes GPRS cell synchronisation.
5637
5638 */
5639
5640
5641 #ifdef GPRS /*XXX*/
5642 LOCAL void nc_process_status_sync_gprs(void)
5643 {
5644 USHORT i;
5645 T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ];
5646 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
5647
5648
5649 for (i = 0; i < c_ba_arfcn AND alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT; i++)
5650 {
5651 /*
5652 * search for the candidate with the highest fieldstrength
5653 */
5654 T_NC* pcell = &alr_data->nc_data.cell[i];
5655
5656 if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND
5657 (pcell->ba_arfcn NEQ alr_data->serving_cell) AND
5658 (pcell->status EQ READ_FB_SB))
5659 {
5660 /*
5661 * Request synchronisation for this cell
5662 */
5663 nc_build_sync_req(i);
5664 ALR_TRACE_NC ("ncell_sync_req");
5665 }
5666 }
5667 }
5668
5669 /*
5670 +--------------------------------------------------------------------+
5671 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5672 | STATE : code ROUTINE : nc_sync_failed_gprs |
5673 +--------------------------------------------------------------------+
5674
5675 PURPOSE : Handles synchronisation failed situation
5676
5677 */
5678
5679
5680 LOCAL void nc_sync_failed_gprs(USHORT index)
5681 {
5682 alr_data->nc_data.cell[index].c_sync = 1; /*XXX*/
5683 nc_set_status (index, FB_SB_FAILED);
5684 nc_inform_grr_of_ncell(index, GRR_SB_NOT_FOUND);
5685 }
5686 #endif
5687
5688
5689 /*
5690 +--------------------------------------------------------------------+
5691 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5692 | STATE : code ROUTINE : nc_process_status_bcch |
5693 +--------------------------------------------------------------------+
5694
5695 PURPOSE : Processes CB status
5696
5697 */
5698
5699
5700 LOCAL void nc_process_status_bcch(void)
5701 {
5702 USHORT i;
5703 USHORT index;
5704 T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ];
5705
5706 while (alr_data->nc_data.c_bcch_req < MAX_L1_BCCH_CNT)
5707 {
5708 /*
5709 * It is possible to send more BCCH request to layer 1
5710 */
5711 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
5712 index = NOT_PRESENT_16BIT;
5713
5714 for (i = 0; i < c_ba_arfcn; i++)
5715 {
5716 /*
5717 * search for the candidate with the highest fieldstrength
5718 */
5719 T_NC* pcell = &alr_data->nc_data.cell[i];
5720
5721 if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND
5722 (pcell->ba_arfcn NEQ alr_data->serving_cell))
5723 {
5724 switch (pcell->status)
5725 {
5726 case READ_BCCH:
5727 case READ_BCCH_RR_NOT_INFORMED:
5728 if (index EQ NOT_PRESENT_16BIT)
5729 index = i;
5730 else
5731 {
5732 if (pcell->rxlev_average >
5733 alr_data->nc_data.cell[index].rxlev_average)
5734 index = i;
5735 }
5736 break;
5737 default:
5738 break;
5739 }
5740 }
5741 }
5742
5743 if (index NEQ NOT_PRESENT_16BIT)
5744 {
5745 /*
5746 * Request BCCH reading for this cell
5747 */
5748 T_NC* pcell = &alr_data->nc_data.cell[index];
5749 PALLOC (ncell_bcch, MPHC_NCELL_BCCH_REQ);
5750
5751 ncell_bcch->radio_freq = ARFCN_TO_L1(pcell->ba_arfcn);
5752 ncell_bcch->fn_offset = pcell->frame_offset;
5753 ncell_bcch->time_alignment = pcell->time_align;
5754 /*
5755 * The training sequence code on broadcast and common control channels
5756 * has to be equal to the Base Station Colour Code (BCC),
5757 * see 3GPP TS 5.02, section 5.2.3 and
5758 * 3GPP TS 03.03, section 4.3.2 Base Station Identify Code (BSIC)
5759 */
5760 ncell_bcch->tsc = (UBYTE)(pcell->bsic & ONLY_BCC);
5761 pcell->blocks_required =
5762 ncell_bcch->bcch_blocks_required = NCELL_BCCH_SI_3_4;
5763 #ifdef GPRS
5764 /*if the mobile is in PTM the GPRS_PRIORITY must be set to TOP*/
5765 if(ma_is_ptm())
5766 {
5767 ncell_bcch->gprs_prio = GPRS_PRIO_TOP;
5768 }
5769 else
5770 #endif
5771 ncell_bcch->gprs_prio = GPRS_PRIO_NORM;
5772
5773
5774 ma_nc_bcch_req (ncell_bcch);
5775
5776 ALR_TRACE_NC("ncell_bcch_read");
5777
5778 alr_data->nc_data.c_bcch_req++;
5779 /*
5780 * read a maximum of four blocks
5781 *
5782 * sys info 3 normal BCCH TC 2 or 6
5783 * sys info 4 normal BCCH TC 3 or 7
5784 */
5785 if(pcell->status EQ READ_BCCH)
5786 nc_set_status (index, READ_BCCH_PENDING);
5787 else
5788 nc_set_status (index, READ_BCCH_PENDING_RR_NOT_INFORMED);
5789 }
5790 else
5791 break; /*while loop */
5792 } /* while(c_bcch_req < MAX_L1_BCCH_CNT)*/
5793 }
5794
5795 /*
5796 +--------------------------------------------------------------------+
5797 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5798 | STATE : code ROUTINE : nc_ncell_in_plmn_permitted |
5799 +--------------------------------------------------------------------+
5800
5801 PURPOSE : checks whether the national colour code (ncc) is member
5802 of the ncc permitted field.
5803
5804 */
5805 static const UBYTE ncc_bit_mask[8] =
5806 {
5807 BIT_0, BIT_1, BIT_2, BIT_3,
5808 BIT_4, BIT_5, BIT_6, BIT_7
5809 };
5810
5811 LOCAL BOOL nc_ncell_in_plmn_permitted (UBYTE bsic)
5812 {
5813 return ((BOOL) ((UBYTE) (alr_data->ncc_permitted &
5814 ncc_bit_mask[(bsic >> 3) & BIT_012])) NEQ 0);
5815 }
5816
5817
5818 /*
5819 +--------------------------------------------------------------------+
5820 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5821 | STATE : code ROUTINE : nc_store_dedicated |
5822 +--------------------------------------------------------------------+
5823
5824 PURPOSE : Stores the values of the neighbour cells
5825 and the serving cell.
5826
5827 */
5828 LOCAL void nc_store_dedicated (T_MPHC_MEAS_REPORT *report)
5829 {
5830 USHORT i;
5831 USHORT index;
5832 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
5833
5834 if (alr_data->nc_data.tim_state NEQ NC_TIM_STOPPED)
5835 {
5836 /* Decrement the 10sec timer counter variable by 2 */
5837 alr_data->nc_data.c_ncsync_tim = alr_data->nc_data.c_ncsync_tim-2;
5838
5839 if ((signed char)( alr_data->nc_data.c_ncsync_tim) < 0)
5840 alr_data->nc_data.c_ncsync_tim = 0;
5841
5842 if( alr_data->nc_data.c_ncsync_tim EQ 0 ) /* 10 sec have elapsed. Perform all requisite tasks */
5843 nc_ncsync_tim_expiry();
5844 }
5845
5846 for (i = 0; i < report->no_of_ncells_meas; i++)
5847 {
5848 T_NC* pcell;
5849 T_res_list* plist = &report->ncell_meas.res_list[i];
5850
5851 index = nc_get_index (ARFCN_TO_G23(plist->bcch_freq));
5852 if ((index EQ NOT_PRESENT_16BIT) OR (index EQ LAST_BSIC_REQ))
5853 continue;
5854 pcell = &alr_data->nc_data.cell[index];
5855
5856 if (plist->rxlev_nbr_meas EQ 0)
5857 pcell->rxlev_average = 0;
5858 else
5859 {
5860 if ((signed short)(plist->rxlev_acc) < 0)
5861 plist->rxlev_acc = 0;
5862
5863 /* why this casting? - a "real" expression is of type int */
5864 pcell->rxlev_average = (UBYTE)(plist->rxlev_acc/plist->rxlev_nbr_meas);
5865 }
5866 if (pcell->status EQ INACTIVE)
5867 nc_set_status (index, IDLE);
5868
5869 if (pcell->status EQ EXCLUDED)
5870 {
5871 int diff;
5872
5873 diff = pcell->rxlev_average - pcell->last_rxlev;
5874
5875 if (diff >= 6)
5876 {
5877 /*
5878 * result is positive and more than 6 dBm
5879 */
5880 nc_set_status (index, IDLE);
5881 }
5882 }
5883 }
5884
5885
5886 alr_data->nc_data.act_dtx = report->dtx_used;
5887
5888 if (report->rxlev_full_nbr_meas EQ 0)
5889 alr_data->nc_data.rxlev_full = 0;
5890 else
5891 {
5892 if ((signed short)(report->rxlev_full_acc) < 0)
5893 report->rxlev_full_acc = 0;
5894
5895 alr_data->nc_data.rxlev_full =
5896 (UBYTE)(report->rxlev_full_acc / report->rxlev_full_nbr_meas);
5897 }
5898
5899 if (report->rxlev_sub_nbr_meas EQ 0)
5900 alr_data->nc_data.rxlev_sub = 0;
5901 else
5902 {
5903 if ((signed short)(report->rxlev_sub_acc) < 0)
5904 report->rxlev_sub_acc = 0;
5905 alr_data->nc_data.rxlev_sub = (UBYTE)(report->rxlev_sub_acc / report->rxlev_sub_nbr_meas);
5906 }
5907
5908 alr_data->nc_data.rxqual_full =
5909 nc_convert_quality (report->rxqual_full_acc_errors,
5910 report->rxqual_full_nbr_bits);
5911
5912 alr_data->nc_data.rxqual_sub =
5913 nc_convert_quality (report->rxqual_sub_acc_errors,
5914 report->rxqual_sub_nbr_bits);
5915 }
5916
5917
5918
5919 /*
5920 +--------------------------------------------------------------------+
5921 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5922 | STATE : code ROUTINE : nc_convert_quality |
5923 +--------------------------------------------------------------------+
5924
5925 PURPOSE : Calculates the quality Value.
5926
5927 */
5928
5929 LOCAL UBYTE nc_convert_quality (USHORT errors, USHORT total)
5930 {
5931 USHORT quality;
5932
5933 if (total EQ 0)
5934 quality = 0;
5935 else
5936 quality = (USHORT)((errors * 500) / total);
5937
5938 if (quality EQ 0)
5939 return 0; /* RX_QUAL_0 */
5940
5941 if (quality EQ 1)
5942 return 1; /* RX_QUAL_1 */
5943
5944 if (quality < 4)
5945 return 2; /* RX_QUAL_2 */
5946
5947 if (quality < 8)
5948 return 3; /* RX_QUAL_3 */
5949
5950 if (quality < 16)
5951 return 4; /* RX_QUAL_4 */
5952
5953 if (quality < 32)
5954 return 5; /* RX_QUAL_5 */
5955
5956 if (quality < 64)
5957 return 6; /* RX_QUAL_6 */
5958
5959 return 7; /* RX_QUAL_7 */
5960
5961 }
5962
5963 /*
5964 +--------------------------------------------------------------------+
5965 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
5966 | STATE : code ROUTINE : nc_release_bcch |
5967 +--------------------------------------------------------------------+
5968
5969 PURPOSE : Check if we have read the BCCH of a ncell but RR has
5970 not yet received the data because this cell has not
5971 been reported to RR before.
5972 */
5973
5974 LOCAL void nc_release_bcch (void)
5975 {
5976 USHORT i;
5977 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
5978 /*
5979 * for every ncell
5980 */
5981 for (i = 0; i < c_ba_arfcn; i++)
5982 {
5983 T_NC* pcell = &alr_data->nc_data.cell[i];
5984
5985 switch (pcell->status)
5986 {
5987 case FB_SB_SYNC_RR_NOT_INFORMED:
5988 /*
5989 * Reading of the BCCH of the neighbourcell is performed,
5990 * but RR has been just informed with a measurement report
5991 * about synchronisation.
5992 */
5993 if(pcell->mph_unitdata_ind NEQ NULL)
5994 {
5995 ALR_TRACE_NC ("send 34");
5996
5997 /*
5998 * a system info type 3 or 4 message is stored.
5999 * Send the message to RR and clear the internal variable.
6000 */
6001 PSENDX(RR, pcell->mph_unitdata_ind);
6002 pcell->mph_unitdata_ind = NULL;
6003 }
6004
6005 if(pcell->mph_unitdata_ind78 NEQ NULL)
6006 {
6007 ALR_TRACE_NC ("send 78");
6008
6009 /*
6010 * a system info type 7 or 8 message is stored.
6011 * Send the message to RR and clear the internal variable.
6012 */
6013 PSENDX(RR, pcell->mph_unitdata_ind78);
6014 pcell->mph_unitdata_ind78 = NULL;
6015 }
6016
6017 /*
6018 * set status to FB_SB_SYNC, that means RR is completely informed.
6019 */
6020 nc_set_fb_sb_sync_initial (i);
6021 break;
6022
6023 default:
6024 break;
6025 }
6026 }
6027 }
6028
6029 /*
6030 +--------------------------------------------------------------------+
6031 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6032 | STATE : code ROUTINE : nc_store_bcch |
6033 +--------------------------------------------------------------------+
6034
6035 PURPOSE : Temporarily store BCCH data for ncell.
6036
6037 */
6038
6039 LOCAL void nc_store_bcch (T_MPHC_DATA_IND* data_ind, USHORT index, UBYTE sys_info_78)
6040 {
6041 #define SYS_INFO_LEN 24
6042
6043 USHORT len_in_bits = SYS_INFO_LEN * BITS_PER_BYTE;
6044 T_NC* pcell = &alr_data->nc_data.cell[index];
6045 /*
6046 * Allocate a SDU for sending later to RR
6047 */
6048 PALLOC_SDU (data_out, MPH_UNITDATA_IND, len_in_bits);
6049
6050 /*
6051 * set length and offset, but cut IE and Pseudo Length
6052 */
6053 data_out->sdu.l_buf = (SYS_INFO_LEN - 2) * BITS_PER_BYTE;
6054 data_out->sdu.o_buf = 1 * BITS_PER_BYTE;
6055
6056 /*
6057 * copy content of the message
6058 */
6059 memcpy (data_out->sdu.buf, &data_ind->l2_frame, SYS_INFO_LEN - 1);/*lint !e419 (Warning -- Apparent data overrun)*/
6060
6061 /*
6062 * set BCCH frequency of the message
6063 */
6064 data_out->arfcn = ARFCN_TO_G23(data_ind->radio_freq)&ARFCN_MASK;
6065 data_out->fn = data_ind->fn;
6066
6067 if (sys_info_78)
6068 {
6069 ALR_TRACE_NC ("store 78");
6070
6071 /*
6072 * if it is a system info 7 or 8 message, free the previous
6073 * stored message, if something is stored and store the new
6074 * one.
6075 */
6076 if (pcell->mph_unitdata_ind78 NEQ NULL)
6077 {
6078 ALR_TRACE_NC ("store,free old 78");
6079
6080 PFREE(pcell->mph_unitdata_ind78);
6081 }
6082
6083 pcell->mph_unitdata_ind78 = data_out;
6084
6085 }
6086 else
6087 {
6088 ALR_TRACE_NC ("store 34");
6089
6090 /*
6091 * if it is a system info 3 or 4 message, free the previous
6092 * stored message, if something is stored and store the new
6093 * one.
6094 */
6095 if (pcell->mph_unitdata_ind NEQ NULL)
6096 {
6097 ALR_TRACE_NC( "store,free old 34");
6098
6099 PFREE(pcell->mph_unitdata_ind);
6100 }
6101
6102 pcell->mph_unitdata_ind = data_out;
6103
6104 }
6105 }
6106
6107
6108 /*
6109 +--------------------------------------------------------------------+
6110 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6111 | STATE : code ROUTINE : nc_sys_info_78_required |
6112 +--------------------------------------------------------------------+
6113
6114 PURPOSE : The function checks whether sys info 7 or 8 are expected
6115 and required.
6116
6117 */
6118
6119 LOCAL UBYTE nc_sys_info_78_required (USHORT index)
6120 {
6121 if (alr_data->nc_data.cell[index].mph_unitdata_ind NEQ 0)
6122 {
6123 T_sdu * sdu = &alr_data->nc_data.cell[index].mph_unitdata_ind->sdu;
6124 /*lint -e415 (Warning -- creation of out-of-bounds pointer)*/
6125 /*lint -e416 (Warning -- access of out-of-bounds pointer)*/
6126 if ((sdu->buf[SI_CONTENTS_CS2] & ONLY_ACS) NEQ 0)
6127 return TRUE;
6128 /*lint +e415 (Warning -- creation of out-of-bounds pointer)*/
6129 /*lint +e416 (Warning -- access of out-of-bounds pointer)*/
6130 }
6131 return FALSE;
6132 }
6133
6134 /*
6135 +--------------------------------------------------------------------+
6136 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6137 | STATE : code ROUTINE : nc_stop_bcch |
6138 +--------------------------------------------------------------------+
6139
6140 PURPOSE : Stop a pending BCCH.
6141
6142 */
6143
6144 LOCAL void nc_stop_bcch (USHORT index, UBYTE new_status)
6145 {
6146 /*
6147 * L3 may avoid sending a stop message to terminate a NCELL_BCCH process
6148 * if there no more pending request in L1
6149 */
6150
6151 if (alr_data->nc_data.c_bcch_req > 0)
6152 {
6153 /*
6154 * stop BCCH request in layer 1.
6155 */
6156 ma_nc_stop_ncell_bcch_req(alr_data->nc_data.cell[index].ba_arfcn);
6157
6158 /*
6159 * decrement counter of pending requests
6160 */
6161 alr_data->nc_data.c_bcch_req--;
6162 }
6163
6164 /*
6165 * set new status
6166 */
6167 nc_set_status (index, new_status);
6168 }
6169
6170
6171 /*
6172 +--------------------------------------------------------------------+
6173 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6174 | STATE : code ROUTINE : nc_stop_sync |
6175 +--------------------------------------------------------------------+
6176
6177 PURPOSE : Stop a pending Sync request.
6178
6179 */
6180
6181 LOCAL void nc_stop_sync (USHORT index, UBYTE new_status)
6182 {
6183 /*
6184 * L3 may avoid sending a stop message to terminate a NCELL_SYNC process
6185 * if there no more pending request in L1
6186 */
6187
6188 if (alr_data->nc_data.c_sync_req > 0)
6189 {
6190 /*
6191 * stop sync request in layer 1.
6192 */
6193 ma_nc_stop_ncell_sync_req (alr_data->nc_data.cell[index].ba_arfcn);
6194
6195 /*
6196 * decrement counter of pending requests
6197 */
6198 alr_data->nc_data.c_sync_req--;
6199 /*
6200 * check whether the confirmation procedure is finished indirectly
6201 */
6202 if (alr_data->nc_data.c_sync_req EQ 0 AND
6203 alr_data->nc_data.eotd_avail EQ FALSE AND
6204 GET_STATE(STATE_NC_PROC) EQ NC_CONFIRM)
6205 {
6206 nc_enable_conf();
6207 }
6208 }
6209
6210 /*
6211 * set new status
6212 */
6213 nc_set_status (index, new_status);
6214 }
6215
6216 /*
6217 +--------------------------------------------------------------------+
6218 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6219 | STATE : code ROUTINE : nc_clean_store_bcch |
6220 +--------------------------------------------------------------------+
6221
6222 PURPOSE : Clean a stored BCCH.
6223
6224 */
6225
6226 LOCAL void nc_clean_store_bcch (USHORT index)
6227 {
6228 T_NC* pcell = &alr_data->nc_data.cell[index];
6229 if (pcell->mph_unitdata_ind NEQ NULL)
6230 {
6231 ALR_TRACE_NC ("free 34");
6232
6233 /*
6234 * a system info type 3 or 4 message is stored
6235 * then free the message and clean the pointer.
6236 */
6237
6238 PFREE(pcell->mph_unitdata_ind);
6239 pcell->mph_unitdata_ind = NULL;
6240
6241 }
6242
6243 if(pcell->mph_unitdata_ind78 NEQ NULL)
6244 {
6245 ALR_TRACE_NC ("free 78");
6246
6247 /*
6248 * a system info type 7 or 8 message is stored
6249 * then free the message and clean the pointer.
6250 */
6251
6252 PFREE(pcell->mph_unitdata_ind78);
6253 pcell->mph_unitdata_ind78 = NULL;
6254 }
6255 }
6256
6257 /*
6258 +--------------------------------------------------------------------+
6259 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6260 | STATE : code ROUTINE : nc_check_bsic |
6261 +--------------------------------------------------------------------+
6262
6263 PURPOSE : Check a base station identification code of a neighbourcell
6264 The following return values are possible:
6265
6266 NC_CHECK_OK : BSIC has not changed and is permitted.
6267 NC_CHECK_NCC_FAILED : NCC permitted check has failed
6268 NC_CHECK_BSIC_CHANGED : a BSIC change has occured
6269
6270
6271 */
6272
6273 LOCAL UBYTE nc_check_bsic (USHORT index, UBYTE bsic)
6274 {
6275 /*
6276 * check only the lowest 6 bits (= NCC + BCC)
6277 */
6278 bsic = (UBYTE)(bsic & ONLY_BSIC);
6279
6280 /*
6281 * first check whether ncc is member of the ncc permitted field
6282 */
6283 if (!nc_ncell_in_plmn_permitted (bsic))
6284 return NC_CHECK_NCC_FAILED;
6285
6286 /*
6287 * no bsic stored until now.
6288 */
6289 if (alr_data->nc_data.cell[index].bsic EQ NOT_PRESENT_8BIT)
6290 return NC_CHECK_OK;
6291
6292 /*
6293 * check against BSIC changes
6294 */
6295 if (alr_data->nc_data.cell[index].bsic NEQ bsic)
6296 return NC_CHECK_BSIC_CHANGED;
6297
6298 /*
6299 * all checks passed
6300 */
6301 return NC_CHECK_OK;
6302 }
6303
6304
6305 /*
6306 +--------------------------------------------------------------------+
6307 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6308 | STATE : code ROUTINE : nc_check_new_ncc_permitted |
6309 +--------------------------------------------------------------------+
6310
6311 PURPOSE : Checks whether status transitions are needed after reception
6312 of a changed NCC permitted field.
6313
6314 */
6315
6316 GLOBAL void nc_check_new_ncc_permitted (UBYTE new_ncc_permitted)
6317 {
6318 USHORT i;
6319 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
6320 if (new_ncc_permitted NEQ alr_data->ncc_permitted)
6321 {
6322 /*
6323 * a change has occured, so store new value and check all cells
6324 */
6325 alr_data->ncc_permitted = new_ncc_permitted;
6326
6327 for (i = 0; i < c_ba_arfcn; i++)
6328 {
6329 switch (alr_data->nc_data.cell[i].status)
6330 {
6331 case FB_SB_SYNC:
6332 case FB_SB_SYNC_RR_NOT_INFORMED:
6333 case READ_SB:
6334 case READ_BCCH:
6335 case IDLE_SYNC:
6336 case READ_SB_BCCH:
6337 case READ_BCCH_RR_NOT_INFORMED:
6338 if (nc_ncell_in_plmn_permitted(alr_data->nc_data.cell[i].bsic) EQ FALSE)
6339 nc_set_status (i, EXCLUDED);
6340 break;
6341
6342 case READ_BCCH_PENDING:
6343 case READ_BCCH_PENDING_RR_NOT_INFORMED:
6344 if (nc_ncell_in_plmn_permitted(alr_data->nc_data.cell[i].bsic) EQ FALSE)
6345 nc_set_status (i, EXCLUDED);
6346 break;
6347
6348 case EXCLUDED:
6349 /*
6350 * give channel a new chance
6351 */
6352 nc_set_status (i, IDLE);
6353 break;
6354 }
6355 }
6356 }
6357 }
6358
6359 #if !defined(DEFINE_OLD_NC_STATUS)
6360 LOCAL UBYTE nc_get_nc_status(UBYTE status)
6361 {
6362 UBYTE st;
6363
6364 switch (status)
6365 {
6366 case INACTIVE:st=0;break;
6367 case IDLE:st=1;break;
6368 case READ_BCCH:st=2;break;
6369 case FB_SB_SYNC:st=3;break;
6370 case FB_SB_FAILED:st=4;break;
6371 case READ_FB_SB:st=5;break;
6372 case READ_SB:st=6;break;
6373 case IDLE_SYNC:st=7;break;
6374 case EXCLUDED:st=8;break;
6375 case FB_SB_SYNC_RR_NOT_INFORMED:st=9;break;
6376 case READ_SB_BCCH:st=10;break;
6377 case READ_BCCH_PENDING:st=11;break;
6378 case READ_FB_SB_PENDING:st=12;break;
6379 case READ_SB_PENDING:st=13;break;
6380 case READ_SB_BCCH_PENDING:st=14;break;
6381 case READ_BCCH_RR_NOT_INFORMED:st=15;break;
6382 case READ_BCCH_PENDING_RR_NOT_INFORMED:st=16;break;
6383 default:st=17;break;
6384 }
6385
6386 return st;
6387 }
6388 #else /* DEFINE_OLD_NC_STATUS */
6389 #define nc_get_nc_status(st) (((int)(st) >= 18) ? 18 : (st))
6390 #endif /* DEFINE_OLD_NC_STATUS */
6391
6392 #if !defined(NTRACE) && defined(TRACING)
6393 LOCAL const char * nc_get_nc_state_str(UBYTE status)
6394 {
6395 return alr_nc_state_trc[nc_get_nc_status(status)];
6396 }
6397 #endif /* !NTRACE && TRACING */
6398 #if 0 /* not needed currently */
6399 #if defined(TRACING)
6400 /*
6401 +--------------------------------------------------------------------+
6402 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6403 | STATE : code ROUTINE : nc_get_status |
6404 +--------------------------------------------------------------------+
6405
6406 PURPOSE : The function returns the status for a channel.
6407
6408 */
6409
6410 LOCAL UBYTE nc_get_status (USHORT index)
6411 {
6412 /* use pointer to save time and ROM */
6413 T_NC* pcell = &alr_data->nc_data.cell[index];
6414
6415 TRACE_USER_CLASS_P3 (TC_USER1, "NC%u[%d] %s",
6416 index,
6417 pcell->ba_arfcn EQ NOT_PRESENT_16BIT ? -1 : pcell->ba_arfcn&ARFCN_MASK,
6418 nc_get_nc_state_str(pcell->status));
6419
6420 return pcell->status;
6421 }
6422 #endif /* TRACING */
6423 #endif /* 0|1 */
6424 /*
6425 +--------------------------------------------------------------------+
6426 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6427 | STATE : code ROUTINE : nc_set_status |
6428 +--------------------------------------------------------------------+
6429
6430 PURPOSE : The function sets a new status for a channel. Depending on
6431 the new status several variables which are not valid in
6432 the new status are initialised to their default values.
6433
6434
6435 */
6436
6437 GLOBAL void nc_set_status (USHORT index, UBYTE new_status)
6438 {
6439 /* use pointer to save time and ROM */
6440 T_NC* pcell = &alr_data->nc_data.cell[index];
6441
6442 #if defined(TRACING)
6443 TRACE_EVENT_P4 ("NC%u[%d] %s -> %s",
6444 index,
6445 pcell->ba_arfcn EQ NOT_PRESENT_16BIT ? -1 : pcell->ba_arfcn&ARFCN_MASK,
6446 nc_get_nc_state_str(pcell->status),
6447 nc_get_nc_state_str(new_status));
6448 #endif /* TRACING */
6449
6450 switch (new_status)
6451 {
6452 case INACTIVE:
6453 pcell->bsic = NOT_PRESENT_8BIT;
6454 pcell->frame_offset = NOT_PRESENT_32BIT;
6455 pcell->time_align = NOT_PRESENT_32BIT;
6456 pcell->last_rxlev = 0;
6457 pcell->c_rxlev = NOT_PRESENT_8BIT;
6458 pcell->rxlev_average = 0;
6459 memset (pcell->rxlev, 0, 5);
6460 pcell->one_of_six = FALSE;
6461 pcell->one_of_twelve = FALSE;
6462 pcell->c_attempt = 0;
6463 pcell->c_bcch = C_INVALID_BCCH;
6464 pcell->c_sync = C_INVALID_SYNC;
6465 pcell->tim_valid = TV_INVALID_TIMING_INFO;
6466 pcell->blocks_required = 0;
6467 pcell->c_error = 0;
6468 nc_clean_store_bcch (index);
6469 break;
6470
6471 case IDLE:
6472 pcell->bsic = NOT_PRESENT_8BIT;
6473 /* pcell->frame_offset = 0;
6474 pcell->time_align = 0;
6475 pcell->last_rxlev = 0; */
6476 pcell->one_of_six = FALSE;
6477 pcell->one_of_twelve = FALSE;
6478 /*pcell->c_attempt = 0;*/
6479 pcell->c_bcch = C_INVALID_BCCH;
6480 pcell->c_sync = C_INVALID_SYNC;
6481 pcell->blocks_required = 0;
6482 pcell->c_error = 0;
6483 nc_clean_store_bcch (index);
6484 break;
6485
6486 case READ_FB_SB:
6487 case READ_FB_SB_PENDING:
6488 pcell->bsic = NOT_PRESENT_8BIT;
6489 /* pcell->frame_offset = 0;
6490 pcell->time_align = 0; */
6491 pcell->last_rxlev = 0;
6492 pcell->c_bcch = C_INVALID_BCCH;
6493 pcell->c_sync = C_INVALID_SYNC;
6494 pcell->blocks_required = 0;
6495 pcell->c_error = 0;
6496 nc_clean_store_bcch (index);
6497 break;
6498
6499 case READ_BCCH:
6500 pcell->last_rxlev = 0;
6501 /*pcell->c_attempt = 0;*/
6502 pcell->c_bcch = C_INVALID_BCCH;
6503 pcell->c_sync = C_INVALID_SYNC;
6504 pcell->c_error = 0;
6505 pcell->blocks_required = 0;
6506 nc_clean_store_bcch (index);
6507 break;
6508 case READ_BCCH_RR_NOT_INFORMED:
6509 pcell->last_rxlev = 0;
6510 pcell->c_bcch = C_INVALID_BCCH;
6511 pcell->c_sync = C_INVALID_SYNC;
6512 pcell->c_error = 0;
6513 pcell->blocks_required = 0;
6514 nc_clean_store_bcch (index);
6515 break;
6516
6517 case FB_SB_SYNC_RR_NOT_INFORMED:
6518 pcell->last_rxlev = 0;
6519 pcell->c_bcch = C_INVALID_BCCH;
6520 pcell->c_sync = C_INVALID_SYNC;
6521 pcell->blocks_required = 0;
6522 pcell->c_attempt = 0;
6523 pcell->c_error = 0;
6524 break;
6525
6526 case FB_SB_SYNC:
6527 pcell->last_rxlev = 0;
6528 pcell->blocks_required = 0;
6529 if (!pcell->one_of_six)
6530 pcell->c_attempt = 0;
6531 pcell->c_error = 0;
6532 pcell->c_sync = C_INVALID_SYNC;
6533 nc_clean_store_bcch (index);
6534 break;
6535
6536 case READ_SB:
6537 case READ_SB_PENDING:
6538 pcell->last_rxlev = 0;
6539 pcell->c_sync = C_INVALID_SYNC;
6540 pcell->blocks_required = 0;
6541 /*pcell->c_attempt = 0;*/
6542 pcell->c_error = 0;
6543 nc_clean_store_bcch (index);
6544 break;
6545
6546 case READ_SB_BCCH:
6547 case READ_SB_BCCH_PENDING:
6548 pcell->last_rxlev = 0;
6549 pcell->c_bcch = C_INVALID_BCCH;
6550 pcell->c_sync = C_INVALID_SYNC;
6551 pcell->blocks_required = 0;
6552 pcell->c_error = 0;
6553 /*pcell->c_attempt = 0;*/
6554 nc_clean_store_bcch (index);
6555 break;
6556
6557
6558 case IDLE_SYNC:
6559 pcell->last_rxlev = 0;
6560 pcell->c_bcch = C_INVALID_BCCH;
6561 pcell->one_of_six = FALSE;
6562 pcell->one_of_twelve = FALSE;
6563 pcell->c_attempt = 0;
6564 pcell->blocks_required = 0;
6565 pcell->c_error = 0;
6566 pcell->c_sync = alr_data->nc_data.c_nc_timer; /*TODO maybe move this to a function*/
6567 nc_clean_store_bcch (index);
6568 break;
6569
6570 case FB_SB_FAILED:
6571 pcell->bsic = NOT_PRESENT_8BIT;
6572 if (pcell->status EQ READ_FB_SB_PENDING)
6573 {
6574 pcell->frame_offset = NOT_PRESENT_32BIT;
6575 pcell->time_align = NOT_PRESENT_32BIT;
6576 pcell->tim_valid = TV_INVALID_TIMING_INFO;
6577 }
6578 else
6579 pcell->tim_valid = TV_APPROX_TIMING_INFO;
6580 pcell->last_rxlev = 0;
6581 pcell->c_bcch = C_INVALID_BCCH;
6582 pcell->blocks_required = 0;
6583 pcell->c_error = 0;
6584 nc_clean_store_bcch (index);
6585 break;
6586
6587 case EXCLUDED:
6588 pcell->bsic = NOT_PRESENT_8BIT;
6589 pcell->frame_offset = NOT_PRESENT_32BIT;
6590 pcell->time_align = NOT_PRESENT_32BIT;
6591 pcell->one_of_six = FALSE;
6592 pcell->one_of_twelve = FALSE;
6593 pcell->last_rxlev = pcell->rxlev_average; /* TODO maybe move this to a function */
6594 pcell->c_attempt = 0;
6595 pcell->c_bcch = C_INVALID_BCCH;
6596 pcell->c_sync = C_INVALID_SYNC;
6597 pcell->tim_valid = TV_INVALID_TIMING_INFO;
6598 pcell->blocks_required = 0;
6599 pcell->c_error = 0;
6600 nc_clean_store_bcch (index);
6601 break;
6602
6603 case READ_BCCH_PENDING:
6604 case READ_BCCH_PENDING_RR_NOT_INFORMED:
6605 pcell->last_rxlev = 0;
6606 /*pcell->c_attempt = 0;*/
6607 pcell->c_bcch = C_INVALID_BCCH;
6608 pcell->c_sync = C_INVALID_SYNC;
6609 nc_clean_store_bcch (index);
6610 break;
6611 }
6612
6613 /*
6614 * set new status
6615 */
6616 pcell->status = new_status;
6617 }
6618
6619 GLOBAL void nc_check_activity (void)
6620 {
6621 int i;
6622 switch(GET_STATE(STATE_NC))
6623 {
6624 case NC_IDLE:
6625 /* count number of reports */
6626 alr_data->nc_data.c_reports++;
6627
6628 nc_rank_ncells ();
6629 nc_check_status (CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL);
6630 nc_process_status();
6631
6632 if (first_period AND !first_l1_meas)
6633 {
6634 if (alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports OR
6635 alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports - 1)
6636 {
6637 UBYTE all_sync = TRUE;
6638 /*
6639 * for every ncell
6640 */
6641 for (i = 0; i < alr_data->nc_data.c_ba_arfcn; i++)
6642 {
6643 if (alr_data->nc_data.cell[i].status EQ READ_BCCH_PENDING OR
6644 alr_data->nc_data.cell[i].status EQ READ_BCCH_PENDING_RR_NOT_INFORMED)
6645 {
6646 /* not all needed SI are read yet */
6647 all_sync = FALSE;
6648 break;
6649 }
6650 }
6651 if (!all_sync AND
6652 alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports)
6653 {
6654 /* spend an additional reporting period to give FTA 20.7 a better chance to pass */
6655 alr_data->nc_data.c_reports--;
6656 first_period = FALSE;
6657 ALR_TRACE_NC ("one additional period");
6658 }
6659 else if (all_sync AND
6660 alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports - 1)
6661 {
6662 /* skip an additional reporting period to give FTA 20.19 a better chance to pass */
6663 alr_data->nc_data.c_reports++;
6664 first_period = FALSE;
6665 ALR_TRACE_NC ("one period skipped");
6666 }
6667 }
6668 }
6669 first_l1_meas = FALSE;
6670
6671 #if defined(_SIMULATION_)
6672 TRACE_EVENT_P2 ("c_reports=%u/%u",
6673 alr_data->nc_data.c_reports, alr_data->nc_data.max_reports);
6674 #endif /* WIN32 */
6675
6676 /* check if 5sec have passed, we then have to inform RR */
6677 if (alr_data->nc_data.c_reports EQ alr_data->nc_data.max_reports)
6678 {
6679 USHORT index, average;
6680 T_NC* pcell;
6681 PALLOC (report, MPH_MEASUREMENT_IND);
6682 memset (report, 0, sizeof (T_MPH_MEASUREMENT_IND));
6683
6684 first_period = FALSE;
6685 #ifdef GPRS
6686 report->gprs_sync = NORMAL_MEAS_REP;
6687 #endif
6688
6689 report->arfcn = alr_data->serving_cell;
6690
6691 average = 0;
6692 index = nc_get_index(alr_data->serving_cell);
6693 if ( index NEQ NOT_PRESENT_16BIT )
6694 {
6695 pcell = &alr_data->nc_data.cell[index];
6696 pcell->rxlev_average = 0; /* Is this really needed? */
6697 for (i = 0; i < 5; i++)
6698 average += pcell->rxlev[i];
6699 }
6700
6701 report->rx_lev_full = (UBYTE) (average / 5);
6702 report->fn_offset = alr_data->nc_data.fn_offset;
6703
6704 alr_data->nc_data.c_reports = 0;
6705
6706 nc_build_rr_report (report);
6707 ma_nc_report_res (report);
6708 nc_release_bcch ();
6709 }
6710 break;
6711 case NC_DEDICATED:
6712 nc_rank_ncells ();
6713 nc_check_status (CHECK_FOR_ACQUIRE_AND_BCCH_AND_FAIL);
6714 nc_process_status();
6715 {
6716 PALLOC(mph_measurement_ind, MPH_MEASUREMENT_IND);
6717 #ifdef GPRS
6718 mph_measurement_ind->gprs_sync = NORMAL_MEAS_REP;
6719 #endif
6720 nc_build_rr_report_dedi (mph_measurement_ind);
6721 ma_nc_report_res (mph_measurement_ind);
6722 }
6723 break;
6724 default:
6725 break;
6726 }
6727 }
6728
6729 /*
6730 +--------------------------------------------------------------------+
6731 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6732 | STATE : code ROUTINE : nc_set_fb_sb_sync_initial |
6733 +--------------------------------------------------------------------+
6734
6735 PURPOSE : Inital setting of status FB_SB_SYNC. Counter for SB
6736 confirmation and BCCH re-reading are initialized.
6737
6738 */
6739
6740 LOCAL void nc_set_fb_sb_sync_initial (USHORT index)
6741 {
6742 alr_data->nc_data.cell[index].c_bcch = FIVE_MINUTES;
6743
6744 if(!alr_data->nc_data.eotd_avail)
6745 {
6746 /*round to next confirmation boundary */
6747 if(alr_data->nc_data.c_nc_timer NEQ THIRTY_SECONDS)
6748 alr_data->nc_data.cell[index].c_bcch += alr_data->nc_data.c_nc_timer;
6749 }
6750
6751 nc_set_status (index, FB_SB_SYNC);
6752 }
6753
6754 /*
6755 +--------------------------------------------------------------------+
6756 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6757 | STATE : code ROUTINE : nc_set_fb_sb_failed |
6758 +--------------------------------------------------------------------+
6759
6760 PURPOSE : Set the status to FB_SB_FAILED, update the attempt counter
6761 and set time until next attempt is started.
6762
6763 */
6764
6765 LOCAL void nc_set_fb_sb_failed (USHORT index,
6766 UBYTE c_sync)
6767 {
6768 alr_data->nc_data.cell[index].c_attempt++;
6769 alr_data->nc_data.cell[index].c_sync = c_sync;
6770 nc_set_status (index, FB_SB_FAILED);
6771 }
6772
6773 /*
6774 +--------------------------------------------------------------------+
6775 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6776 | STATE : code ROUTINE : nc_rxlev_sc_req |
6777 +--------------------------------------------------------------------+
6778
6779 PURPOSE : A new RXLEV value of the serving cell has been measured.
6780 Inform GPL in case it is necessary.
6781
6782 */
6783 #ifdef GPRS
6784
6785 LOCAL void nc_rxlev_sc_req (UBYTE rxlev)
6786 {
6787 if(GET_STATE (STATE_NC) EQ NC_IDLE)
6788 {
6789 PALLOC (rxlev_sc_req, TB_RXLEV_SC_REQ);
6790
6791 rxlev_sc_req->sc_rxlev = rxlev;
6792
6793 ma_nc_rxlev_sc_req (rxlev_sc_req);
6794 }
6795 }
6796
6797 #endif /* #ifdef GPRS */
6798
6799 #if defined(_SIMULATION_)
6800 LOCAL void trace_nc(void)
6801 {
6802 char buf[80];
6803 int i, o;
6804 T_NC* pcell;
6805 o = sprintf (buf, "NC: ");
6806
6807 for (i=0,pcell = &alr_data->nc_data.cell[0]; i < alr_data->nc_data.c_ba_arfcn; i++,pcell++)
6808 {
6809 if(pcell->ba_arfcn EQ alr_data->serving_cell)
6810 {
6811 o += sprintf (buf+o, "%u[SC=%u]%u, ", i, pcell->ba_arfcn, pcell->ba_status);
6812 }
6813 else
6814 {
6815 o += sprintf (buf+o, "%u[%u]%u, ", i, pcell->ba_arfcn, pcell->ba_status);
6816 }
6817 if (o > 60)
6818 {
6819 TRACE_EVENT (buf);
6820 o = sprintf (buf, "NC: ");
6821 }
6822 }
6823 if (o>4)
6824 {
6825 buf[o-2]=0;
6826 TRACE_EVENT (buf);
6827 }
6828 }
6829 #endif /* _SIMULATION_ */
6830
6831 /*
6832 +--------------------------------------------------------------------+
6833 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6834 | STATE : code ROUTINE : nc_check_new_strong_cell |
6835 +--------------------------------------------------------------------+
6836
6837 PURPOSE : Checks the New strong cell criteria
6838
6839 */
6840
6841 LOCAL void nc_check_new_strong_cell(USHORT index, UBYTE o_1of6,
6842 UBYTE rxlev)
6843 {
6844 T_NC* pcell = &alr_data->nc_data.cell[index];
6845
6846 if((pcell->one_of_six ) AND (!o_1of6))
6847 {
6848 /* NCELL confirmation active. New 1of6 cell found */
6849 if((pcell->rxlev_average > rxlev) AND
6850 ((pcell->rxlev_average - rxlev ) >= 5))
6851 pcell->new_strong_cell = TRUE;
6852 }
6853 else if ((pcell->one_of_six ) AND (o_1of6) AND
6854 (pcell->status EQ READ_FB_SB) AND
6855 (pcell->c_attempt EQ 0 ))
6856 {
6857 /* NCELL confirmation interrupted the sync of last 1of6 cell
6858 * This has to be synchronized again
6859 */
6860 pcell->new_strong_cell = TRUE;
6861 }
6862
6863 if(pcell->new_strong_cell)
6864 {
6865 alr_data->nc_data.new_strong_cell_detect = TRUE;
6866 TRACE_EVENT_P1("[%d]New strong cell",pcell->ba_arfcn);
6867 }
6868
6869 }
6870
6871 /*
6872 +--------------------------------------------------------------------+
6873 | PROJECT : GSM-PS (6103) MODULE : ALR_NC |
6874 | STATE : code ROUTINE : nc_handle_new_strong_cells |
6875 +--------------------------------------------------------------------+
6876
6877 PURPOSE : Processes cell synchronisation.
6878
6879 */
6880
6881 LOCAL void nc_handle_new_strong_cells(void)
6882 {
6883 USHORT i;
6884 USHORT index;
6885 UBYTE first_sync_req = TRUE;
6886 T_NC* pbsic = &alr_data->nc_data.cell[LAST_BSIC_REQ];
6887
6888 alr_data->nc_data.c_sync_intrupted = FALSE;
6889
6890 while (alr_data->nc_data.c_sync_req < MAX_L1_SYNC_CNT)
6891 {
6892 /*
6893 * It is possible to send more sync requests to layer 1
6894 */
6895 USHORT c_ba_arfcn = alr_data->nc_data.c_ba_arfcn;
6896 index = NOT_PRESENT_16BIT;
6897
6898 for (i = 0; i < c_ba_arfcn; i++)
6899 {
6900 /*
6901 * search for "New strong cell" with the highest fieldstrength
6902 */
6903 T_NC* pcell = &alr_data->nc_data.cell[i];
6904
6905 if ((pcell->ba_arfcn NEQ pbsic->ba_arfcn) AND
6906 (pcell->ba_arfcn NEQ alr_data->serving_cell) AND
6907 (pcell->new_strong_cell))
6908 {
6909 switch (pcell->status)
6910 {
6911 case READ_FB_SB:
6912 if (index EQ NOT_PRESENT_16BIT)
6913 index = i;
6914 else
6915 {
6916 if (pcell->rxlev_average >
6917 alr_data->nc_data.cell[index].rxlev_average)
6918 index = i;
6919 }
6920 break;
6921 default:
6922 break;
6923 }
6924 }
6925 }
6926
6927 if (index NEQ NOT_PRESENT_16BIT)
6928 {
6929
6930 if(first_sync_req EQ TRUE)
6931 {
6932 first_sync_req = FALSE;
6933
6934 if(alr_data->nc_data.c_sync_req > 0)
6935 {
6936
6937 TRACE_EVENT("RE-SYNC interrupted");
6938 alr_data->nc_data.c_sync_intrupted = TRUE;
6939
6940 nc_stop_all();
6941
6942 if(!alr_data->nc_data.c_sync_req)
6943 {
6944 alr_data->nc_data.tim_state = NC_CONF_PENDING;
6945 SET_STATE(STATE_NC_PROC, NC_ACQUIRE);
6946 }
6947 }
6948 } /* first_sync_req */
6949
6950 /*
6951 * Request synchronisation for this cell
6952 */
6953 nc_build_sync_req(index);
6954 alr_data->nc_data.cell[index].new_strong_cell = FALSE;
6955 TRACE_EVENT_P1("[%d]N_S_C sync req",alr_data->nc_data.cell[index].ba_arfcn);
6956 }
6957 else
6958 break; /*while loop */
6959 } /* while( c_sync_req < MAX_L1_SYNC_CNT) */
6960 }
6961 #endif