rrc_common.c 18.3 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22
/*! \file rrc_common.c
23
 * \brief rrc common procedures for eNB and UE
24 25
 * \author Navid Nikaein and Raymond Knopp
 * \date 2011 - 2014
26 27
 * \version 1.0
 * \company Eurecom
28
 * \email:  navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
29
 */
30 31 32 33 34

#include "defs.h"
#include "extern.h"
#include "LAYER2/MAC/extern.h"
#include "COMMON/openair_defs.h"
35
#include "COMMON/platform_types.h"
36 37 38 39
#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"
40
#include "asn1_msg.h"
41
#include "pdcp.h"
42
#include "UTIL/LOG/vcd_signal_dumper.h"
43
#include "rrc_eNB_UE_context.h"
44
#include "common/ran_context.h"
45

46
#ifdef LOCALIZATION
47 48 49
#include <sys/time.h>
#endif

50
#define DEBUG_RRC 1
51
extern RAN_CONTEXT_t RC;
52 53
extern UE_MAC_INST *UE_mac_inst;

54 55
extern mui_t rrc_eNB_mui;

56
//configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
57 58 59 60 61 62
//-----------------------------------------------------------------------------
void
openair_rrc_on(
  const protocol_ctxt_t* const ctxt_pP
)
//-----------------------------------------------------------------------------
63
{
64
  unsigned short i;
65
  int            CC_id;
66

67 68 69
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
70
    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
71 72 73 74
      rrc_config_buffer (&RC.rrc[ctxt_pP->module_id]->carrier[CC_id].SI, BCCH, 1);
      RC.rrc[ctxt_pP->module_id]->carrier[CC_id].SI.Active = 1;
      rrc_config_buffer (&RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0, CCCH, 1);
      RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Active = 1;
75
    }
76
  } else {
77 78
    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
79

80
    for (i = 0; i < NB_eNB_INST; i++) {
81 82 83 84 85 86 87
      LOG_D(RRC, PROTOCOL_RRC_CTXT_FMT" Activating CCCH (eNB %d)\n",
            PROTOCOL_RRC_CTXT_ARGS(ctxt_pP), i);
      UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Srb_id = CCCH;
      memcpy (&UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Lchan_desc[0], &CCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
      memcpy (&UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Lchan_desc[1], &CCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
      rrc_config_buffer (&UE_rrc_inst[ctxt_pP->module_id].Srb0[i], CCCH, 1);
      UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Active = 1;
88 89 90 91
    }
  }
}

92 93 94 95 96 97
//-----------------------------------------------------------------------------
int
rrc_init_global_param(
  void
)
//-----------------------------------------------------------------------------
98
{
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

  //#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);
  /*
123 124 125 126 127 128
   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;
   }
   */
129
  rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc
130 131 132 133 134 135 136 137 138 139 140

  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;

Lionel Gauthier's avatar
Lionel Gauthier committed
141
  Rlc_info_um.rlc_mode = RLC_MODE_UM;
142 143 144
  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;
145 146
  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;

Lionel Gauthier's avatar
Lionel Gauthier committed
147
  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
148
  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
149 150 151 152 153
  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;
154

155
  return 0;
156 157
}

158 159 160 161 162 163 164 165
//-----------------------------------------------------------------------------
void
rrc_config_buffer(
  SRB_INFO* Srb_info,
  uint8_t Lchan_type,
  uint8_t Role
)
//-----------------------------------------------------------------------------
166
{
167 168 169 170 171

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

172

173 174 175 176 177 178 179
//-----------------------------------------------------------------------------
void
rrc_t310_expiration(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                 eNB_index
)
//-----------------------------------------------------------------------------
180
{
181

182
  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State != RRC_CONNECTED) {
183
    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE\n");
184 185 186 187 188 189 190 191 192 193 194
    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_IDLE;
    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].UE_index = 0xffff;
    UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Rx_buffer.payload_size = 0;
    UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size = 0;
    UE_rrc_inst[ctxt_pP->module_id].Srb1[eNB_index].Srb_info.Rx_buffer.payload_size = 0;
    UE_rrc_inst[ctxt_pP->module_id].Srb1[eNB_index].Srb_info.Tx_buffer.payload_size = 0;

    if (UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Active == 1) {
      msg ("[RRC Inst %d] eNB_index %d, Remove RB %d\n ", ctxt_pP->module_id, eNB_index,
           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id);
      rrc_pdcp_config_req (ctxt_pP,
195 196
                           SRB_FLAG_YES,
                           CONFIG_ACTION_REMOVE,
197
                           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
198
                           0);
199
      rrc_rlc_config_req (ctxt_pP,
200 201 202
                          SRB_FLAG_YES,
                          MBMS_FLAG_NO,
                          CONFIG_ACTION_REMOVE,
203
                          UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
204
                          Rlc_info_um);
205 206 207
      UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Active = 0;
      UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Status = IDLE;
      UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Next_check_frame = 0;
208
    }
209
  } else { // Restablishment procedure
210
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
211 212
  }
}
Cedric Roux's avatar
Cedric Roux committed
213

214 215 216
//-----------------------------------------------------------------------------
RRC_status_t
rrc_rx_tx(
217
  protocol_ctxt_t* const ctxt_pP,
218 219 220 221
  const uint8_t      enb_indexP,
  const int          CC_id
)
//-----------------------------------------------------------------------------
222
{
223
  //uint8_t        UE_id;
224 225
  int32_t        current_timestamp_ms, ref_timestamp_ms;
  struct timeval ts;
226 227
  struct rrc_eNB_ue_context_s   *ue_context_p = NULL,*ue_to_be_removed = NULL;

228 229 230 231
#ifdef LOCALIZATION
  double                         estimated_distance;
  protocol_ctxt_t                ctxt;
#endif
232
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
233

234
  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {
235
    // check timers
236

237 238
    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_active == 1) {
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt % 10) == 0)
239
        LOG_D(RRC,
240
              "[UE %d][RAPROC] Frame %d T300 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt);
241

242 243 244
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt
          == T300[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t300]) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_active = 0;
245
        // ALLOW CCCH to be used
246 247
        UE_rrc_inst[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
        rrc_ue_generate_RRCConnectionRequest (ctxt_pP, enb_indexP);
248
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
249
        return (RRC_ConnSetup_failed);
250
      }
251

252
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
253
    }
254

255
    if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
256 257
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt
          == N310[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n310]) {
258
	LOG_I(RRC,"Activating T310\n");
259
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
260
      }
261
    } else { // in case we have not received SIB2 yet
262
      /*      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
263
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;
264 265 266 267

	}*/
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
      return RRC_OK;
268
    }
269

270 271 272 273 274
    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active == 1) {
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N311_cnt
          == N311[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n311]) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N311_cnt = 0;
275
      }
276

277 278 279
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt % 10) == 0) {
        LOG_D(RRC, "[UE %d] Frame %d T310 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt);
      }
280

281 282 283
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt    == T310[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t310]) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
        rrc_t310_expiration (ctxt_pP, enb_indexP);
284
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
285
	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n");
286
        return RRC_PHY_RESYNCH;
287
      }
288

289
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
290
    }
291

292 293 294 295
    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_active==1) {
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt % 10) == 0)
        LOG_D(RRC,"[UE %d][RAPROC] Frame %d T304 Count %d ms\n",ctxt_pP->module_id,ctxt_pP->frame,
              UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt);
296

297 298 299
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt == 0) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_active = 0;
        UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
Cedric Roux's avatar
Cedric Roux committed
300 301
        LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n",
              ctxt_pP->module_id);
302
        //Implement 36.331, section 5.3.5.6 here
303
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
304
        return(RRC_Handover_failed);
305
      }
306

307
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
308
    }
309

310
    // Layer 3 filtering of RRC measurements
311 312
    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0] != NULL) {
      ue_meas_filtering(ctxt_pP,enb_indexP);
313
    }
314

315
    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
316

317 318 319
    if (UE_rrc_inst[ctxt_pP->module_id].Info[0].handoverTarget > 0) {
      LOG_I(RRC,"[UE %d] Frame %d : RRC handover initiated\n", ctxt_pP->module_id, ctxt_pP->frame);
    }
320

321 322 323
    if((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State == RRC_HO_EXECUTION)   &&
        (UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId != 0xFF)) {
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State= RRC_IDLE;
324
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
325 326
      return(RRC_HO_STARTED);
    }
327

328
  } else { // eNB
329
    check_handovers(ctxt_pP);
330
    // counetr, and get the value and aggregate
331

sharma's avatar
sharma committed
332

333
    // check for UL failure
334
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
335
      LOG_D(RRC,"SFN.SN %d.%d => release timer %d/%d\n",ctxt_pP->frame,ctxt_pP->subframe,
sharma's avatar
sharma committed
336
	    ue_context_p->ue_context.ue_release_timer,ue_context_p->ue_context.ue_release_timer_thres);
337 338 339 340 341 342 343 344 345 346 347 348 349
      if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) {
	if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n",
		ue_context_p->ue_context.rnti,
		ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
		ue_context_p->ue_context.ul_failure_timer);
	}
	else {
	  LOG_I(RRC,"UE rnti %x failure timer %d/20000\n",
		ue_context_p->ue_context.rnti,
		ue_context_p->ue_context.ul_failure_timer);
	}
      }
350 351 352 353
      if (ue_context_p->ue_context.ul_failure_timer>0) {
	ue_context_p->ue_context.ul_failure_timer++;
	if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
	  // remove UE after 20 seconds after MAC has indicated UL failure
sharma's avatar
sharma committed
354
	  LOG_I(RRC,"Removing UE %x instance (failure)\n",ue_context_p->ue_context.rnti);
355 356 357 358
	  ue_to_be_removed = ue_context_p;
	  break;
	}
      }
359 360
      if (ue_context_p->ue_context.ue_release_timer>0) {
	ue_context_p->ue_context.ue_release_timer++;
361
	if (ue_context_p->ue_context.ue_release_timer >=
362
	    ue_context_p->ue_context.ue_release_timer_thres) {
sharma's avatar
sharma committed
363
	  LOG_I(RRC,"Removing UE %x instance (release timer %d)\n",ue_context_p->ue_context.rnti,ue_context_p->ue_context.ue_release_timer);
364
	  ue_to_be_removed = ue_context_p;
sharma's avatar
sharma committed
365
	  exit(-1);
366 367 368
	  break;
	}
      }
369 370 371
    }
    if (ue_to_be_removed)
      rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed);
372

373
#ifdef RRC_LOCALIZATION
374

375 376 377
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
378 379
    ref_timestamp_ms = RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms;
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
380 381 382 383 384
      ctxt = *ctxt_pP;
      ctxt.rnti = ue_context_p->ue_context.rnti;
      estimated_distance = rrc_get_estimated_ue_distance(
                             &ctxt,
                             CC_id,
385
                             RC.rrc[ctxt_pP->module_id]->loc_type);
386

387
      if ((current_timestamp_ms - ref_timestamp_ms > RC.rrc[ctxt_pP->module_id]->aggregation_period_ms) &&
388
          estimated_distance != -1) {
389
        LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
390 391
              ctxt.rnti,
              ctxt_pP->module_id,
392
              current_timestamp_ms,
393 394 395
              ctxt_pP->frame,
              estimated_distance);
        LOG_D(LOCALIZE, " RRC status %d\n", ue_context_p->ue_context.Status);
396
        push_front(&RC.rrc[ctxt_pP->module_id]->loc_list,
397
                   estimated_distance);
398
        RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms = current_timestamp_ms;
399
      }
400
    }
401

402
#endif
403 404 405
    (void)ts; /* remove gcc warning "unused variable" */
    (void)ref_timestamp_ms; /* remove gcc warning "unused variable" */
    (void)current_timestamp_ms; /* remove gcc warning "unused variable" */
406
  }
407

408
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
409 410
  return (RRC_OK);
}
411

412 413 414 415 416 417 418 419
//-----------------------------------------------------------------------------
long
binary_search_int(
  int elements[],
  long numElem,
  int value
)
//-----------------------------------------------------------------------------
420
{
winckel's avatar
winckel committed
421
  long first, last, middle, search = -1;
422 423 424
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
425

426
  if(value < elements[0]) {
427
    return first;
428
  }
429

430
  if(value > elements[last]) {
431
    return last;
432
  }
433

434
  while (first <= last) {
435
    if (elements[middle] < value) {
436
      first = middle+1;
437
    } else if (elements[middle] == value) {
438 439
      search = middle+1;
      break;
440
    } else {
441
      last = middle -1;
442
    }
443

444 445
    middle = (first+last)/2;
  }
446

447
  if (first > last) {
448
    LOG_E(RRC,"Error in binary search!");
449
  }
450

451 452 453 454 455 456 457
  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
*/
458 459 460 461 462 463 464 465
//-----------------------------------------------------------------------------
long
binary_search_float(
  float elements[],
  long numElem,
  float value
)
//-----------------------------------------------------------------------------
466
{
winckel's avatar
winckel committed
467
  long first, last, middle;
468 469 470
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
471

472
  if(value <= elements[0]) {
473
    return first;
474
  }
475

476
  if(value >= elements[last]) {
477
    return last;
478
  }
479

480
  while (last - first > 1) {
481
    if (elements[middle] > value) {
482
      last = middle;
483
    } else {
484
      first = middle;
485
    }
486

487 488
    middle = (first+last)/2;
  }
489

490
  if (first < 0 || first >= numElem) {
491
    LOG_E(RRC,"\n Error in binary search float!");
492
  }
493

494 495
  return first;
}