rrc_common.c 17.4 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2
3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


nikaeinn's avatar
nikaeinn committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16
17
18
19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20

nikaeinn's avatar
nikaeinn committed
21
22
23
24
  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

nikaeinn's avatar
nikaeinn committed
28
*******************************************************************************/
29
30

/*! \file rrc_common.c
31
 * \brief rrc common procedures for eNB and UE
nikaeinn's avatar
nikaeinn committed
32
33
 * \author Navid Nikaein and Raymond Knopp
 * \date 2011 - 2014
34
35
 * \version 1.0
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
36
 * \email:  navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
37
 */
38
39
40
41
42

#include "defs.h"
#include "extern.h"
#include "LAYER2/MAC/extern.h"
#include "COMMON/openair_defs.h"
gauthier's avatar
gauthier committed
43
#include "COMMON/platform_types.h"
44
45
46
47
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "LAYER2/RLC/rlc.h"
#include "COMMON/mac_rrc_primitives.h"
#include "UTIL/LOG/log.h"
48
#include "asn1_msg.h"
49
#include "pdcp.h"
50

51
52
53
54
#define DEBUG_RRC 1
extern eNB_MAC_INST *eNB_mac_inst;
extern UE_MAC_INST *UE_mac_inst;

55
56
extern mui_t rrc_eNB_mui;

57
//configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
58
void openair_rrc_on(module_id_t Mod_id, const eNB_flag_t eNB_flag) {
59
60
  unsigned short i;

61
62
63
64
65
66
67
68
69
70
71
72
73
  if (eNB_flag == 1) {
    LOG_I(RRC, "[eNB %d] OPENAIR RRC IN....\n", Mod_id);

    rrc_config_buffer (&eNB_rrc_inst[Mod_id].SI, BCCH, 1);
    eNB_rrc_inst[Mod_id].SI.Active = 1;
    rrc_config_buffer (&eNB_rrc_inst[Mod_id].Srb0, CCCH, 1);
    eNB_rrc_inst[Mod_id].Srb0.Active = 1;

  }
  else {
    LOG_I(RRC, "[UE %d] OPENAIR RRC IN....\n", Mod_id);
    for (i = 0; i < NB_eNB_INST; i++) {
      LOG_D(RRC, "[RRC][UE %d] Activating CCCH (eNB %d)\n", Mod_id, i);
74
      UE_rrc_inst[Mod_id].Srb0[i].Srb_id = CCCH;
75
76
77
78
      memcpy (&UE_rrc_inst[Mod_id].Srb0[i].Lchan_desc[0], &CCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
      memcpy (&UE_rrc_inst[Mod_id].Srb0[i].Lchan_desc[1], &CCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
      rrc_config_buffer (&UE_rrc_inst[Mod_id].Srb0[i], CCCH, 1);
      UE_rrc_inst[Mod_id].Srb0[i].Active = 1;
79
80
81
82
    }
  }
}

83
int rrc_init_global_param(void) {
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

  //#ifdef USER_MODE
  //  Rrc_xface = (RRC_XFACE*)malloc16(sizeof(RRC_XFACE));
  //#endif //USRE_MODE

  //  Rrc_xface->openair_rrc_top_init = openair_rrc_top_init;
  //  Rrc_xface->openair_rrc_eNB_init = openair_rrc_eNB_init;
  //  Rrc_xface->openair_rrc_UE_init  = openair_rrc_ue_init;
  //  Rrc_xface->mac_rrc_data_ind     = mac_rrc_data_ind;
  //Rrc_xface->mac_rrc_data_req     = mac_rrc_data_req;
  // Rrc_xface->rrc_data_indP        = (void *)rlcrrc_data_ind;
  //  Rrc_xface->rrc_rx_tx            = rrc_rx_tx;
  //  Rrc_xface->mac_rrc_meas_ind     = mac_rrc_meas_ind;
  //  Rrc_xface->get_rrc_status       = get_rrc_status;

  //Rrc_xface->rrc_get_status = ...

  //  Mac_rlc_xface->mac_out_of_sync_ind=mac_out_of_sync_ind;

#ifndef NO_RRM
  //  Rrc_xface->fn_rrc=fn_rrc;
#endif
  //  LOG_D(RRC, "[RRC]INIT_GLOBAL_PARAM: Mac_rlc_xface %p, rrc_rlc_register %p,rlcrrc_data_ind%p\n",Mac_rlc_xface,Mac_rlc_xface->rrc_rlc_register_rrc,rlcrrc_data_ind);
  /*
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
   if((Mac_rlc_xface==NULL) || (Mac_rlc_xface->rrc_rlc_register_rrc==NULL) ||
   (rlcrrc_data_ind==NULL)) {
   LOG_E(RRC,"Data structured is not initialized \n");
   return -1;
   }
   */
  rrc_rlc_register_rrc (rlcrrc_data_ind, NULL); //register with rlc

  DCCH_LCHAN_DESC.transport_block_size = 4;
  DCCH_LCHAN_DESC.max_transport_blocks = 16;
  DCCH_LCHAN_DESC.Delay_class = 1;
  DTCH_DL_LCHAN_DESC.transport_block_size = 52;
  DTCH_DL_LCHAN_DESC.max_transport_blocks = 20;
  DTCH_DL_LCHAN_DESC.Delay_class = 1;
  DTCH_UL_LCHAN_DESC.transport_block_size = 52;
  DTCH_UL_LCHAN_DESC.max_transport_blocks = 20;
  DTCH_UL_LCHAN_DESC.Delay_class = 1;

gauthier's avatar
gauthier committed
126
  Rlc_info_um.rlc_mode = RLC_MODE_UM;
127
128
129
  Rlc_info_um.rlc.rlc_um_info.timer_reordering = 5;
  Rlc_info_um.rlc.rlc_um_info.sn_field_length = 10;
  Rlc_info_um.rlc.rlc_um_info.is_mXch = 0;
130
131
  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;

gauthier's avatar
gauthier committed
132
  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
133
  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
134
135
136
137
138
  Rlc_info_am_config.rlc.rlc_am_info.poll_pdu = 8;
  Rlc_info_am_config.rlc.rlc_am_info.poll_byte = 1000;
  Rlc_info_am_config.rlc.rlc_am_info.t_poll_retransmit = 15;
  Rlc_info_am_config.rlc.rlc_am_info.t_reordering = 50;
  Rlc_info_am_config.rlc.rlc_am_info.t_status_prohibit = 10;
139
#ifndef NO_RRM
140
141
  if (L3_xface_init ())
    return (-1);
142
143
144
145
146
147
148
#endif

  return 0;
}

#ifndef NO_RRM
/*------------------------------------------------------------------------------*/
149
150
int L3_xface_init(void) {
  /*------------------------------------------------------------------------------*/
151
152
153
154
155

  int ret = 0;

#ifdef USER_MODE

156
  int sock;
157
158
  LOG_D(RRC, "[L3_XFACE] init de l'interface \n");

159
  if (open_socket (&S_rrc, RRC_RRM_SOCK_PATH, RRM_RRC_SOCK_PATH, 0) == -1)
160
161
    return (-1);

162
163
164
  if (S_rrc.s == -1) {
    return (-1);
  }
165

166
167
168
  socket_setnonblocking (S_rrc.s);
  msg ("Interface Connected... RRM-RRC\n");
  return 0;
169
170
171
172
173
174
175
176
177
178

#else

  ret=rtf_create(RRC2RRM_FIFO,32768);

  if (ret < 0) {
    msg("[openair][MAC][INIT] Cannot create RRC2RRM fifo %d (ERROR %d)\n",RRC2RRM_FIFO,ret);

    return(-1);
  }
179
  else {
180
181
182
183
184
185
186
187
188
189
190
    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRC2RRM_FIFO);
    rtf_reset(RRC2RRM_FIFO);
  }

  ret=rtf_create(RRM2RRC_FIFO,32768);

  if (ret < 0) {
    msg("[openair][MAC][INIT] Cannot create RRM2RRC fifo %d (ERROR %d)\n",RRM2RRC_FIFO,ret);

    return(-1);
  }
191
  else {
192
193
194
195
196
197
198
199
200
201
    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRM2RRC_FIFO);
    rtf_reset(RRM2RRC_FIFO);
  }

  return(0);

#endif
}
#endif

gauthier's avatar
gauthier committed
202
void rrc_config_buffer(SRB_INFO *Srb_info, uint8_t Lchan_type, uint8_t Role) {
203
204
205
206
207
208

  Srb_info->Rx_buffer.payload_size = 0;
  Srb_info->Tx_buffer.payload_size = 0;
}

/*------------------------------------------------------------------------------*/
knopp's avatar
   
knopp committed
209
void openair_rrc_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active,uint8_t HO_active){
210
211
  /*-----------------------------------------------------------------------------*/

gauthier's avatar
gauthier committed
212
213
  module_id_t         module_id;
  OAI_UECapability_t *UECap     = NULL;
214
215
  //  uint8_t dummy_buffer[100];

216
217
218
219
220
221
  LOG_D(RRC, "[OPENAIR][INIT] Init function start: NB_UE_INST=%d, NB_eNB_INST=%d\n", NB_UE_INST, NB_eNB_INST);

  if (NB_UE_INST > 0) {
    UE_rrc_inst = (UE_RRC_INST*) malloc16(NB_UE_INST*sizeof(UE_RRC_INST));
    memset (UE_rrc_inst, 0, NB_UE_INST * sizeof(UE_RRC_INST));
    LOG_D(RRC, "ALLOCATE %d Bytes for UE_RRC_INST @ %p\n", (unsigned int)(NB_UE_INST*sizeof(UE_RRC_INST)), UE_rrc_inst);
222
223

    // fill UE capability
knopp's avatar
   
knopp committed
224
    UECap = fill_ue_capability (uecap_xer);
knopp's avatar
   
knopp committed
225
226
    UE_rrc_inst[module_id].UECap = UECap;

gauthier's avatar
gauthier committed
227
228
229
    for (module_id = 0; module_id < NB_UE_INST; module_id++) {
      UE_rrc_inst[module_id].UECapability = UECap->sdu;
      UE_rrc_inst[module_id].UECapability_size = UECap->sdu_size;
230
    }
231
232
#ifdef Rel10
    LOG_I(RRC,"[UE] eMBMS active state is %d \n", eMBMS_active);
gauthier's avatar
gauthier committed
233
234
    for (module_id=0;module_id<NB_UE_INST;module_id++) {
      UE_rrc_inst[module_id].MBMS_flag = (uint8_t)eMBMS_active;
235
236
    }
#endif 
237
238
239
  }
  else
    UE_rrc_inst = NULL;
240

241
242
243
  if (NB_eNB_INST > 0) {
    eNB_rrc_inst = (eNB_RRC_INST*) malloc16(NB_eNB_INST*sizeof(eNB_RRC_INST));
    memset (eNB_rrc_inst, 0, NB_eNB_INST * sizeof(eNB_RRC_INST));
244
    LOG_I(RRC,"[eNB] handover active state is %d \n", HO_active);
gauthier's avatar
gauthier committed
245
246
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {
      eNB_rrc_inst[module_id].HO_flag   = (uint8_t)HO_active;
247
    }
248
#ifdef Rel10
249
    LOG_I(RRC,"[eNB] eMBMS active state is %d \n", eMBMS_active);
gauthier's avatar
gauthier committed
250
251
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {
      eNB_rrc_inst[module_id].MBMS_flag = (uint8_t)eMBMS_active;
252
    }
253
254
#endif 
#ifdef CBA
gauthier's avatar
gauthier committed
255
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {
256
      eNB_rrc_inst[module_id].num_active_cba_groups = cba_group_active;
257
    }
258
259
260
261
262
263
264
265
266
267
268
#endif
#ifdef LOCALIZATION
    /* later set this from xml or enb.config file*/
    struct timeval ts; // time struct
    gettimeofday(&ts, NULL); // get the current epoch timestamp
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {  
        eNB_rrc_inst[module_id].reference_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;  
        initialize(&eNB_rrc_inst[module_id].loc_list);
        eNB_rrc_inst[module_id].loc_type=0;      
        eNB_rrc_inst[module_id].aggregation_period_ms = 5000;
    }
269
#endif
270
271
272
273
274
    LOG_D(RRC,
          "ALLOCATE %d Bytes for eNB_RRC_INST @ %p\n", (unsigned int)(NB_eNB_INST*sizeof(eNB_RRC_INST)), eNB_rrc_inst);
  }
  else
    eNB_rrc_inst = NULL;
275
276
277
278
279
280
281
282
283
284
#ifndef NO_RRM
#ifndef USER_MODE

  Header_buf=(char*)malloc16(sizeof(msg_head_t));
  Data=(char*)malloc16(2400);
  Header_read_idx=0;
  Data_read_idx=0;
  Header_size=sizeof(msg_head_t);

#endif //NO_RRM
285
  Data_to_read = 0;
286
287
288
#endif //USER_MODE
}

289
void rrc_top_cleanup(void) {
290

291
292
293
294
  if (NB_UE_INST > 0)
    free (UE_rrc_inst);
  if (NB_eNB_INST > 0)
    free (eNB_rrc_inst);
295
296
297

}

298

299
void rrc_t310_expiration(const frame_t frameP, uint8_t Mod_id, uint8_t eNB_index) {
300

301
302
303
304
305
306
307
  protocol_ctxt_t ctxt;

  ctxt.enb_module_id = eNB_index;
  ctxt.ue_module_id  = Mod_id;
  ctxt.frame         = frameP;
  ctxt.enb_flag      = ENB_FLAG_NO;

308
309
310
311
312
313
314
315
316
317
318
319
320
321
  if (UE_rrc_inst[Mod_id].Info[eNB_index].State != RRC_CONNECTED) {
    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE\n");
    UE_rrc_inst[Mod_id].Info[eNB_index].State = RRC_IDLE;
    UE_rrc_inst[Mod_id].Info[eNB_index].UE_index = 0xffff;

    UE_rrc_inst[Mod_id].Srb0[eNB_index].Rx_buffer.payload_size = 0;
    UE_rrc_inst[Mod_id].Srb0[eNB_index].Tx_buffer.payload_size = 0;

    UE_rrc_inst[Mod_id].Srb1[eNB_index].Srb_info.Rx_buffer.payload_size = 0;
    UE_rrc_inst[Mod_id].Srb1[eNB_index].Srb_info.Tx_buffer.payload_size = 0;

    if (UE_rrc_inst[Mod_id].Srb2[eNB_index].Active == 1) {
      msg ("[RRC Inst %d] eNB_index %d, Remove RB %d\n ", Mod_id, eNB_index,
           UE_rrc_inst[Mod_id].Srb2[eNB_index].Srb_info.Srb_id);
322
323
324
325
326
327
328
329
330
331
332
      rrc_pdcp_config_req (&ctxt,
                           SRB_FLAG_YES,
                           CONFIG_ACTION_REMOVE,
                           UE_rrc_inst[Mod_id].Srb2[eNB_index].Srb_info.Srb_id,
                           0);
      rrc_rlc_config_req (&ctxt,
                          SRB_FLAG_YES,
                          MBMS_FLAG_NO,
                          CONFIG_ACTION_REMOVE,
                          UE_rrc_inst[Mod_id].Srb2[eNB_index].Srb_info.Srb_id,
                          Rlc_info_um);
333
334
335
      UE_rrc_inst[Mod_id].Srb2[eNB_index].Active = 0;
      UE_rrc_inst[Mod_id].Srb2[eNB_index].Status = IDLE;
      UE_rrc_inst[Mod_id].Srb2[eNB_index].Next_check_frame = 0;
336
337
    }
  }
338
339
  else { // Restablishment procedure
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
340
341
  }
}
Cedric Roux's avatar
Cedric Roux committed
342

343
RRC_status_t rrc_rx_tx(uint8_t Mod_id, const frame_t frameP, const eNB_flag_t eNB_flagP,uint8_t index,int CC_id){
344
  
345
346
347
348
  uint8_t UE_id;
  int32_t current_timestamp_ms, ref_timestamp_ms;
  struct timeval ts;
          
gauthier's avatar
gauthier committed
349
  if(eNB_flagP == 0) {
350
    // check timers
351
352

    if (UE_rrc_inst[Mod_id].Info[index].T300_active == 1) {
353
      if ((UE_rrc_inst[Mod_id].Info[index].T300_cnt % 10) == 0)
354
        LOG_D(RRC,
355
              "[UE %d][RAPROC] Frame %d T300 Count %d ms\n", Mod_id, frameP, UE_rrc_inst[Mod_id].Info[index].T300_cnt);
356
357
358
359
360
      if (UE_rrc_inst[Mod_id].Info[index].T300_cnt
          == T300[UE_rrc_inst[Mod_id].sib2[index]->ue_TimersAndConstants.t300]) {
        UE_rrc_inst[Mod_id].Info[index].T300_active = 0;
        // ALLOW CCCH to be used
        UE_rrc_inst[Mod_id].Srb0[index].Tx_buffer.payload_size = 0;
361
        rrc_ue_generate_RRCConnectionRequest (Mod_id, frameP, index);
362
        return (RRC_ConnSetup_failed);
363
364
365
366
      }
      UE_rrc_inst[Mod_id].Info[index].T300_cnt++;
    }
    if (UE_rrc_inst[Mod_id].sib2[index]) {
367
368
369
      if (UE_rrc_inst[Mod_id].Info[index].N310_cnt
          == N310[UE_rrc_inst[Mod_id].sib2[index]->ue_TimersAndConstants.n310]) {
        UE_rrc_inst[Mod_id].Info[index].T310_active = 1;
370
371
372
      }
    }
    else { // in case we have not received SIB2 yet
373
374
375
      if (UE_rrc_inst[Mod_id].Info[index].N310_cnt == 100) {
        UE_rrc_inst[Mod_id].Info[index].N310_cnt = 0;
        return RRC_PHY_RESYNCH;
376
377
      }
    }
378
379
380
381
382
    if (UE_rrc_inst[Mod_id].Info[index].T310_active == 1) {
      if (UE_rrc_inst[Mod_id].Info[index].N311_cnt
          == N311[UE_rrc_inst[Mod_id].sib2[index]->ue_TimersAndConstants.n311]) {
        UE_rrc_inst[Mod_id].Info[index].T310_active = 0;
        UE_rrc_inst[Mod_id].Info[index].N311_cnt = 0;
383
384
      }
      if ((UE_rrc_inst[Mod_id].Info[index].T310_cnt % 10) == 0)
385
        LOG_D(RRC, "[UE %d] Frame %d T310 Count %d ms\n", Mod_id, frameP, UE_rrc_inst[Mod_id].Info[index].T310_cnt);
386
      if (UE_rrc_inst[Mod_id].Info[index].T310_cnt    == T310[UE_rrc_inst[Mod_id].sib2[index]->ue_TimersAndConstants.t310]) {
387
        UE_rrc_inst[Mod_id].Info[index].T310_active = 0;
388
        rrc_t310_expiration (frameP, Mod_id, index);
389
        return (RRC_PHY_RESYNCH);
390
391
392
      }
      UE_rrc_inst[Mod_id].Info[index].T310_cnt++;
    }
393
394
395
396
    
    
    if (UE_rrc_inst[Mod_id].Info[index].T304_active==1) {
      if ((UE_rrc_inst[Mod_id].Info[index].T304_cnt % 10) == 0)
397
	LOG_D(RRC,"[UE %d][RAPROC] Frame %d T304 Count %d ms\n",Mod_id,frameP,
398
399
400
401
402
403
404
405
406
407
408
409
	      UE_rrc_inst[Mod_id].Info[index].T304_cnt);
      if (UE_rrc_inst[Mod_id].Info[index].T304_cnt == 0) {
	UE_rrc_inst[Mod_id].Info[index].T304_active = 0;
	UE_rrc_inst[Mod_id].HandoverInfoUe.measFlag = 1;
	LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n");
	//Implement 36.331, section 5.3.5.6 here
	return(RRC_Handover_failed);
      }
      UE_rrc_inst[Mod_id].Info[index].T304_cnt--;
    }
    // Layer 3 filtering of RRC measurements
    if (UE_rrc_inst[Mod_id].QuantityConfig[0] != NULL) {
410
      ue_meas_filtering(Mod_id,frameP,index);
411
    }
412
    ue_measurement_report_triggering(Mod_id,frameP,index);
413
    if (UE_rrc_inst[Mod_id].Info[0].handoverTarget > 0)       
414
      LOG_I(RRC,"[UE %d] Frame %d : RRC handover initiated\n", Mod_id, frameP);
415
416
417
418
419
    if((UE_rrc_inst[Mod_id].Info[index].State == RRC_HO_EXECUTION)   && 
       (UE_rrc_inst[Mod_id].HandoverInfoUe.targetCellId != 0xFF)) {
      UE_rrc_inst[Mod_id].Info[index].State= RRC_IDLE;
      return(RRC_HO_STARTED);
    }
420

421
  }
422
  else { // eNB
423
    check_handovers(Mod_id,frameP);
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    // counetr, and get the value and aggregate
#ifdef LOCALIZATION
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
    
    ref_timestamp_ms = eNB_rrc_inst[Mod_id].reference_timestamp_ms;
    
    
    for  (UE_id=0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {

        if ((current_timestamp_ms - ref_timestamp_ms > eNB_rrc_inst[Mod_id].aggregation_period_ms) &&
                rrc_get_estimated_ue_distance(Mod_id,frameP,UE_id, CC_id,eNB_rrc_inst[Mod_id].loc_type) != -1) {
            LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n", 
                    UE_id, 
                    Mod_id, 
                    current_timestamp_ms,
                    frameP,
                    rrc_get_estimated_ue_distance(Mod_id,frameP,UE_id, CC_id,eNB_rrc_inst[Mod_id].loc_type));
            LOG_D(LOCALIZE, " RRC status %d\n", eNB_rrc_inst[Mod_id].Info.UE[UE_id].Status);
            push_front(&eNB_rrc_inst[Mod_id].loc_list,
                       rrc_get_estimated_ue_distance(Mod_id,frameP,UE_id, CC_id,eNB_rrc_inst[Mod_id].loc_type));
            eNB_rrc_inst[Mod_id].reference_timestamp_ms = current_timestamp_ms;
        }
    }
#endif
450
451
  }
  
452
453
  return (RRC_OK);
}
454
455

long binary_search_int(int elements[], long numElem, int value) {
winckel's avatar
winckel committed
456
  long first, last, middle, search = -1;
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
  if(value < elements[0])
    return first;
  if(value > elements[last])
    return last;
  
  while (first <= last) {
    if (elements[middle] < value)
      first = middle+1;
    else if (elements[middle] == value) {
      search = middle+1;
      break;
    }
    else
      last = middle -1;
    
    middle = (first+last)/2;
  }
  if (first > last)
    LOG_E(RRC,"Error in binary search!");
  return search;
}

/* This is a binary search routine which operates on an array of floating
   point numbers and returns the index of the range the value lies in
   Used for RSRP and RSRQ measurement mapping. Can potentially be used for other things
*/
long binary_search_float(float elements[], long numElem, float value) {
winckel's avatar
winckel committed
487
  long first, last, middle;
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
  if(value <= elements[0])
    return first;
  if(value >= elements[last])
    return last;
  
  while (last - first > 1) {
    if (elements[middle] > value)
      last = middle;
    else
      first = middle;
    
    middle = (first+last)/2;
  }
  if (first < 0 || first >= numElem)
    LOG_E(RRC,"\n Error in binary search float!");
  return first;
}