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
#ifdef LOCALIZATION 
#include <sys/time.h>
#endif

55
56
57
58
#define DEBUG_RRC 1
extern eNB_MAC_INST *eNB_mac_inst;
extern UE_MAC_INST *UE_mac_inst;

59
60
extern mui_t rrc_eNB_mui;

61
//configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
62
void openair_rrc_on(module_id_t Mod_id, const eNB_flag_t eNB_flag) {
63
64
  unsigned short i;

65
66
67
68
69
70
71
72
73
74
75
76
77
  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);
78
      UE_rrc_inst[Mod_id].Srb0[i].Srb_id = CCCH;
79
80
81
82
      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;
83
84
85
86
    }
  }
}

87
int rrc_init_global_param(void) {
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

  //#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);
  /*
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
   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
130
  Rlc_info_um.rlc_mode = RLC_MODE_UM;
131
132
133
  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;
134
135
  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;

gauthier's avatar
gauthier committed
136
  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
137
  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
138
139
140
141
142
  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;
143
#ifndef NO_RRM
144
145
  if (L3_xface_init ())
    return (-1);
146
147
148
149
150
151
152
#endif

  return 0;
}

#ifndef NO_RRM
/*------------------------------------------------------------------------------*/
153
154
int L3_xface_init(void) {
  /*------------------------------------------------------------------------------*/
155
156
157
158
159

  int ret = 0;

#ifdef USER_MODE

160
  int sock;
161
162
  LOG_D(RRC, "[L3_XFACE] init de l'interface \n");

163
  if (open_socket (&S_rrc, RRC_RRM_SOCK_PATH, RRM_RRC_SOCK_PATH, 0) == -1)
164
165
    return (-1);

166
167
168
  if (S_rrc.s == -1) {
    return (-1);
  }
169

170
171
172
  socket_setnonblocking (S_rrc.s);
  msg ("Interface Connected... RRM-RRC\n");
  return 0;
173
174
175
176
177
178
179
180
181
182

#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);
  }
183
  else {
184
185
186
187
188
189
190
191
192
193
194
    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);
  }
195
  else {
196
197
198
199
200
201
202
203
204
205
    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRM2RRC_FIFO);
    rtf_reset(RRM2RRC_FIFO);
  }

  return(0);

#endif
}
#endif

gauthier's avatar
gauthier committed
206
void rrc_config_buffer(SRB_INFO *Srb_info, uint8_t Lchan_type, uint8_t Role) {
207
208
209
210
211
212

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

/*------------------------------------------------------------------------------*/
knopp's avatar
   
knopp committed
213
void openair_rrc_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active,uint8_t HO_active){
214
215
  /*-----------------------------------------------------------------------------*/

gauthier's avatar
gauthier committed
216
217
  module_id_t         module_id;
  OAI_UECapability_t *UECap     = NULL;
218
219
  //  uint8_t dummy_buffer[100];

220
221
222
223
224
225
  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);
226
227

    // fill UE capability
knopp's avatar
   
knopp committed
228
    UECap = fill_ue_capability (uecap_xer);
knopp's avatar
   
knopp committed
229

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

245
246
247
  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));
248
    LOG_I(RRC,"[eNB] handover active state is %d \n", HO_active);
gauthier's avatar
gauthier committed
249
250
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {
      eNB_rrc_inst[module_id].HO_flag   = (uint8_t)HO_active;
251
    }
252
#ifdef Rel10
253
    LOG_I(RRC,"[eNB] eMBMS active state is %d \n", eMBMS_active);
gauthier's avatar
gauthier committed
254
255
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {
      eNB_rrc_inst[module_id].MBMS_flag = (uint8_t)eMBMS_active;
256
    }
257
258
#endif 
#ifdef CBA
gauthier's avatar
gauthier committed
259
    for (module_id=0;module_id<NB_eNB_INST;module_id++) {
260
      eNB_rrc_inst[module_id].num_active_cba_groups = cba_group_active;
261
    }
262
263
264
265
266
267
268
269
270
271
272
#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;
    }
273
#endif
274
275
276
277
278
    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;
279
280
281
282
283
284
285
286
287
288
#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
289
  Data_to_read = 0;
290
291
292
#endif //USER_MODE
}

293
void rrc_top_cleanup(void) {
294

295
296
297
298
  if (NB_UE_INST > 0)
    free (UE_rrc_inst);
  if (NB_eNB_INST > 0)
    free (eNB_rrc_inst);
299
300
301

}

302

303
void rrc_t310_expiration(const frame_t frameP, uint8_t Mod_id, uint8_t eNB_index) {
304

305
306
307
308
309
310
311
  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;

312
313
314
315
316
317
318
319
320
321
322
323
324
325
  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);
326
327
328
329
330
331
332
333
334
335
336
      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);
337
338
339
      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;
340
341
    }
  }
342
343
  else { // Restablishment procedure
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
344
345
  }
}
Cedric Roux's avatar
Cedric Roux committed
346

347
348
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)
{
349
  
gauthier's avatar
gauthier committed
350
  if(eNB_flagP == 0) {
351
    // check timers
352
353

    if (UE_rrc_inst[Mod_id].Info[index].T300_active == 1) {
354
      if ((UE_rrc_inst[Mod_id].Info[index].T300_cnt % 10) == 0)
355
        LOG_D(RRC,
356
              "[UE %d][RAPROC] Frame %d T300 Count %d ms\n", Mod_id, frameP, UE_rrc_inst[Mod_id].Info[index].T300_cnt);
357
358
359
360
361
      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;
362
        rrc_ue_generate_RRCConnectionRequest (Mod_id, frameP, index);
363
        return (RRC_ConnSetup_failed);
364
365
366
367
      }
      UE_rrc_inst[Mod_id].Info[index].T300_cnt++;
    }
    if (UE_rrc_inst[Mod_id].sib2[index]) {
368
369
370
      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;
371
372
373
      }
    }
    else { // in case we have not received SIB2 yet
374
375
376
      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;
377
378
      }
    }
379
380
381
382
383
    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;
384
385
      }
      if ((UE_rrc_inst[Mod_id].Info[index].T310_cnt % 10) == 0)
386
        LOG_D(RRC, "[UE %d] Frame %d T310 Count %d ms\n", Mod_id, frameP, UE_rrc_inst[Mod_id].Info[index].T310_cnt);
387
      if (UE_rrc_inst[Mod_id].Info[index].T310_cnt    == T310[UE_rrc_inst[Mod_id].sib2[index]->ue_TimersAndConstants.t310]) {
388
        UE_rrc_inst[Mod_id].Info[index].T310_active = 0;
389
        rrc_t310_expiration (frameP, Mod_id, index);
390
        return (RRC_PHY_RESYNCH);
391
392
393
      }
      UE_rrc_inst[Mod_id].Info[index].T310_cnt++;
    }
394
395
396
397
    
    
    if (UE_rrc_inst[Mod_id].Info[index].T304_active==1) {
      if ((UE_rrc_inst[Mod_id].Info[index].T304_cnt % 10) == 0)
398
	LOG_D(RRC,"[UE %d][RAPROC] Frame %d T304 Count %d ms\n",Mod_id,frameP,
399
400
401
402
403
404
405
406
407
408
409
410
	      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) {
411
      ue_meas_filtering(Mod_id,frameP,index);
412
    }
413
    ue_measurement_report_triggering(Mod_id,frameP,index);
414
    if (UE_rrc_inst[Mod_id].Info[0].handoverTarget > 0)       
415
      LOG_I(RRC,"[UE %d] Frame %d : RRC handover initiated\n", Mod_id, frameP);
416
417
418
419
420
    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);
    }
421

422
  }
423
  else { // eNB
424
    check_handovers(Mod_id,frameP);
425
426
    // counetr, and get the value and aggregate
#ifdef LOCALIZATION
427
428
429
    int32_t current_timestamp_ms, ref_timestamp_ms;
    struct timeval ts;

430
431
432
433
434
435
    /* 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;
    
436
    for  (uint8_t UE_id=0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

        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
453
454
  }
  
455
456
  return (RRC_OK);
}
457
458

long binary_search_int(int elements[], long numElem, int value) {
winckel's avatar
winckel committed
459
  long first, last, middle, search = -1;
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
487
488
489
  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
490
  long first, last, middle;
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  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;
}