nr-uesoftmodem.c 26.5 KB
Newer Older
laurent's avatar
laurent committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * 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
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * 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
 */


#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

#include "T.h"
#include "assertions.h"
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
Hongzhi Wang's avatar
Hongzhi Wang committed
30
#include "SCHED_NR_UE/defs.h"
laurent's avatar
laurent committed
31 32
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
33
//#include "common/utils/threadPool/thread-pool.h"
laurent's avatar
laurent committed
34 35 36 37 38 39 40
#include "common/utils/load_module_shlib.h"
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"

//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
41
#include "openair1/PHY/MODULATION/nr_modulation.h"
laurent's avatar
laurent committed
42 43 44 45 46 47 48 49 50
#include "PHY/phy_vars_nr_ue.h"
#include "PHY/LTE_TRANSPORT/transport_vars.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/MODULATION/modulation_vars.h"
//#include "../../SIMU/USER/init_lte.h"

#include "LAYER2/MAC/mac_vars.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
51
#include "openair1/SIMULATION/TOOLS/sim.h"
laurent's avatar
laurent committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"

#include "UTIL/OPT/opt.h"
#include "enb_config.h"
//#include "PHY/TOOLS/time_meas.h"

#ifndef OPENAIR2
  #include "UTIL/OTG/otg_vars.h"
#endif

#include "intertask_interface.h"

#include "PHY/INIT/phy_init.h"
#include "system.h"
#include <openair2/RRC/NR_UE/rrc_proto.h>
laurent's avatar
laurent committed
73 74
#include <openair2/LAYER2/NR_MAC_UE/mac_defs.h>
#include <openair2/LAYER2/NR_MAC_UE/mac_proto.h>
laurent's avatar
laurent committed
75 76 77
#include <openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h>
#include <openair1/SCHED_NR_UE/fapi_nr_ue_l1.h>

Laurent's avatar
Laurent committed
78
/* Callbacks, globals and object handlers */
79

laurent's avatar
laurent committed
80 81
//#include "stats.h"
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
82
#include "PHY/TOOLS/phy_scope_interface.h"
laurent's avatar
laurent committed
83
#include "PHY/TOOLS/nr_phy_scope.h"
laurent's avatar
laurent committed
84
#include <executables/nr-uesoftmodem.h>
85 86
#include "executables/softmodem-common.h"
#include "executables/thread-common.h"
laurent's avatar
laurent committed
87

88 89 90 91 92 93 94 95 96 97
// Raphael : missing
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
uint16_t sf_ahead=6; //??? value ???
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;

laurent's avatar
laurent committed
98 99 100 101 102 103
RAN_CONTEXT_t RC;
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
volatile int             oai_exit = 0;

int                      single_thread_flag=1;
104
static double            snr_dB=20;
laurent's avatar
laurent committed
105 106 107

int                      threequarter_fs=0;

108
uint64_t                 downlink_frequency[MAX_NUM_CCs][4];
laurent's avatar
laurent committed
109
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
110
//int32_t					 uplink_counter = 0;
laurent's avatar
laurent committed
111

112

laurent's avatar
laurent committed
113 114 115 116 117
extern int16_t nr_dlsch_demod_shift;

int UE_scan = 0;
int UE_scan_carrier = 0;
int UE_fo_compensation = 0;
118
int UE_no_timing_correction = 0;
laurent's avatar
laurent committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
runmode_t mode = normal_txrx;
openair0_config_t openair0_cfg[MAX_CARDS];

#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
#else
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
#endif

double rx_gain_off = 0.0;

double sample_rate=30.72e6;
double bw = 10.0e6;

static int  tx_max_power[MAX_NUM_CCs] = {0};


int chain_offset=0;
141

laurent's avatar
laurent committed
142 143 144 145 146 147 148 149 150 151

uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;

char ref[128] = "internal";
char channels[128] = "0";

152

153
int rx_input_level_dBm;
laurent's avatar
laurent committed
154

155
//static int online_log_messages=0;
laurent's avatar
laurent committed
156

157

158
int otg_enabled;
159
//int number_of_cards = 1;
laurent's avatar
laurent committed
160

161 162
static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
int16_t node_synch_ref[MAX_NUM_CCs];
laurent's avatar
laurent committed
163 164 165 166 167 168 169 170 171

uint32_t target_dl_mcs = 28; //maximum allowed mcs
uint32_t target_ul_mcs = 20;
uint32_t timing_advance = 0;
uint64_t num_missed_slots=0; // counter for the number of missed slots


int transmission_mode=1;
int numerology = 0;
172
int usrp_tx_thread = 0;
laurent's avatar
laurent committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186

/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */
//uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD;
/* struct for ethernet specific parameters given in eNB conf file */
//eth_params_t *eth_params;

double cpuf;

char uecap_xer[1024],uecap_xer_in=0;

int oaisim_flag=0;
int emulate_rf = 0;

tpool_t *Tpool;
Hongzhi Wang's avatar
Hongzhi Wang committed
187
#ifdef UE_DLSCH_PARALLELISATION
laurent's avatar
laurent committed
188
  tpool_t *Tpool_dl;
Hongzhi Wang's avatar
Hongzhi Wang committed
189 190
#endif

laurent's avatar
laurent committed
191 192 193

char *usrp_args=NULL;

194 195
char *rrc_config_path=NULL;

laurent's avatar
laurent committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
/* forward declarations */
void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);


/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;

/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end) {
  struct timespec temp;

  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }

  return temp;
}

void print_difftimes(void) {
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
}

void exit_function(const char *file, const char *function, const int line, const char *s) {
  int CC_id;

  if (s != NULL) {
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
  }

  oai_exit = 1;

  if (PHY_vars_UE_g && PHY_vars_UE_g[0]) {
    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      if (PHY_vars_UE_g[0][CC_id] && PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
        PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
    }
  }

  sleep(1); //allow lte-softmodem threads to exit first
245
  exit(1);
laurent's avatar
laurent committed
246 247 248
}


laurent's avatar
laurent committed
249
void reset_stats(long arg) {
laurent's avatar
laurent committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
  //int i,j,k;
  /*PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      for (k=0; k<8; k++) { //harq_processes
          for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
              phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
              phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
              phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
          }

          phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
          phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
          phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;

          for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) {
              phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
              phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
              phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
              phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
          }
      }

      phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
      phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
      phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
  }*/
}

void *l2l1_task(void *arg) {
  MessageDef *message_p = NULL;
  int         result;
  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);

  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);

    switch (ITTI_MSG_ID(message_p)) {
      case TERMINATE_MESSAGE:
        oai_exit=1;
        itti_exit_task ();
        break;

      case ACTIVATE_MESSAGE:
        start_UE = 1;
        break;

      case DEACTIVATE_MESSAGE:
        start_UE = 0;
        break;

      case MESSAGE_TEST:
        LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
        break;

      default:
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  } while(!oai_exit);

  return NULL;
}
318

laurent's avatar
laurent committed
319 320 321 322 323

int16_t dlsch_demod_shift;

static void get_options(void) {
  int CC_id;
324
  int tddflag=0, nonbiotflag, vcdflag=0;
325
  char *loopfile=NULL;
laurent's avatar
laurent committed
326
  int dumpframe=0;
327 328
  //uint32_t noS1;
  //uint32_t nokrnmod;
laurent's avatar
laurent committed
329
  //uint32_t nokrnmod;
330
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ;
laurent's avatar
laurent committed
331 332 333
  config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);


334 335
  paramdef_t cmdline_uemodeparams[] = CMDLINE_UEMODEPARAMS_DESC;
  paramdef_t cmdline_ueparams[] = CMDLINE_NRUEPARAMS_DESC;
laurent's avatar
laurent committed
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
  config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
  config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);

  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;

  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;

  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;

  if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr)
    if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;

  if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
    if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0)  mode = no_L2_connect;

  if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr)
    if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx;

  if (dumpframe  > 0)  mode = rx_dump_frame;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
  }

  UE_scan=0;

  if (tddflag > 0) {
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
      frame_parms[CC_id]->frame_type = TDD;
  }

367 368 369
  if (vcdflag > 0)
    ouput_vcd = 1;

laurent's avatar
laurent committed
370 371 372
  /*if (frame_parms[0]->N_RB_DL !=0) {
      if ( frame_parms[0]->N_RB_DL < 6 ) {
       frame_parms[0]->N_RB_DL = 6;
373
       printf ( "%i: Invalid number of resource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
laurent's avatar
laurent committed
374 375 376
      }
      if ( frame_parms[0]->N_RB_DL > 100 ) {
       frame_parms[0]->N_RB_DL = 100;
377
       printf ( "%i: Invalid number of resource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
laurent's avatar
laurent committed
378 379 380
      }
      if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
       frame_parms[0]->N_RB_DL = 50;
381
       printf ( "%i: Invalid number of resource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
laurent's avatar
laurent committed
382 383 384
      }
      if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
       frame_parms[0]->N_RB_DL = 25;
385
       printf ( "%i: Invalid number of resource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
laurent's avatar
laurent committed
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
      }
      UE_scan = 0;
      frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
      for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
        frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
        frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
      }
  }*/

  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
    tx_max_power[CC_id]=tx_max_power[0];
    rx_gain[0][CC_id] = rx_gain[0][0];
    tx_gain[0][CC_id] = tx_gain[0][0];
  }


  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT))  && (!(CONFIG_ISFLAGSET(CONFIG_NOOOPT))) ) {
    // Here the configuration file is the XER encoded UE capabilities
    // Read it in and store in asn1c data structures
    sprintf(uecap_xer,"%stargets/PROJECTS/GENERIC-LTE-EPC/CONF/UE_config.xml",getenv("OPENAIR_HOME"));
    printf("%s\n",uecap_xer);
    uecap_xer_in=1;
  } /* UE with config file  */
}


void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    /* Set some default values that may be overwritten while reading options */
    frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) calloc(sizeof(NR_DL_FRAME_PARMS),1);
418
    frame_parms[CC_id]->nr_band          = 78;
laurent's avatar
laurent committed
419 420 421 422 423 424 425 426 427
    frame_parms[CC_id]->frame_type          = FDD;
    frame_parms[CC_id]->tdd_config          = 3;
    //frame_parms[CC_id]->tdd_config_S        = 0;
    frame_parms[CC_id]->N_RB_DL             = 106;
    frame_parms[CC_id]->N_RB_UL             = 106;
    frame_parms[CC_id]->Ncp                 = NORMAL;
    //frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = 0;
    //frame_parms[CC_id]->num_MBSFN_config    = 0;
428
    frame_parms[CC_id]->nb_antenna_ports_gNB  = 1;
laurent's avatar
laurent committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;
    //frame_parms[CC_id]->nushift             = 0;
    // NR: Init to legacy LTE 20Mhz params
    frame_parms[CC_id]->numerology_index  = 0;
    frame_parms[CC_id]->ttis_per_subframe = 1;
    frame_parms[CC_id]->slots_per_tti   = 2;
  }
}

void init_openair0(void) {
  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {
    openair0_cfg[card].configFilename = NULL;
445
    openair0_cfg[card].threequarter_fs = frame_parms[0]->threequarter_fs;
446
    numerology = frame_parms[0]->numerology_index;
laurent's avatar
laurent committed
447

448 449 450 451 452 453 454 455
    if(frame_parms[0]->N_RB_DL == 66) {
      if (numerology==3) {
          openair0_cfg[card].sample_rate=122.88e6;
          openair0_cfg[card].samples_per_frame = 1228800;
        } else {
          LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
          exit(-1);
        }
456 457 458 459 460 461 462 463
    }else if(frame_parms[0]->N_RB_DL == 32) {
      if (numerology==3) {
          openair0_cfg[card].sample_rate=61.44e6;
          openair0_cfg[card].samples_per_frame = 614400;
        } else {
          LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
          exit(-1);
        }
464
    }else if(frame_parms[0]->N_RB_DL == 217) {
Rakesh's avatar
Rakesh committed
465 466 467 468 469 470 471 472
      if (numerology==1) {
        if (frame_parms[0]->threequarter_fs) {
          openair0_cfg[card].sample_rate=92.16e6;
          openair0_cfg[card].samples_per_frame = 921600;
        }
        else {
          openair0_cfg[card].sample_rate=122.88e6;
          openair0_cfg[card].samples_per_frame = 1228800;
laurent's avatar
laurent committed
473
        }
474 475 476 477
      } else {
        LOG_E(PHY,"Unsupported numerology!\n");
        exit(-1);
      }
laurent's avatar
laurent committed
478
    } else if(frame_parms[0]->N_RB_DL == 273) {
479 480 481 482 483 484 485
      if (numerology==1) {
        if (frame_parms[0]->threequarter_fs) {
          AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n");
        }
        else {
          openair0_cfg[card].sample_rate=122.88e6;
          openair0_cfg[card].samples_per_frame = 1228800;
laurent's avatar
laurent committed
486
        }
Rakesh's avatar
Rakesh committed
487 488 489 490
      } else {
        LOG_E(PHY,"Unsupported numerology!\n");
        exit(-1);
      }
laurent's avatar
laurent committed
491
    } else if(frame_parms[0]->N_RB_DL == 106) {
laurent's avatar
laurent committed
492 493 494 495 496 497 498 499
      if (numerology==0) {
        if (frame_parms[0]->threequarter_fs) {
          openair0_cfg[card].sample_rate=23.04e6;
          openair0_cfg[card].samples_per_frame = 230400;
        } else {
          openair0_cfg[card].sample_rate=30.72e6;
          openair0_cfg[card].samples_per_frame = 307200;
        }
laurent's avatar
laurent committed
500
      } else if (numerology==1) {
501
        if (frame_parms[0]->threequarter_fs) {
laurent's avatar
laurent committed
502 503
          openair0_cfg[card].sample_rate=46.08e6;
          openair0_cfg[card].samples_per_frame = 460800;
504 505
	}
	else {
laurent's avatar
laurent committed
506 507 508
          openair0_cfg[card].sample_rate=61.44e6;
          openair0_cfg[card].samples_per_frame = 614400;
        }
laurent's avatar
laurent committed
509 510
      } else if (numerology==2) {
        openair0_cfg[card].sample_rate=122.88e6;
511
        openair0_cfg[card].samples_per_frame = 1228800;
laurent's avatar
laurent committed
512 513 514 515 516 517 518 519 520 521 522 523 524 525
      } else {
        LOG_E(PHY,"Unsupported numerology!\n");
        exit(-1);
      }
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
    }
526 527 528 529
    else {
      LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms[0]->N_RB_DL);
      exit(-1);
    }
laurent's avatar
laurent committed
530 531 532 533 534 535

    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

536
    printf("HW: Configuring card %d, nb_antennas_tx/rx %hhu/%hhu\n",card,
laurent's avatar
laurent committed
537 538 539 540
           PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx,
           PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
    openair0_cfg[card].Mod_id = 0;
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
541 542
    openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
    openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
laurent's avatar
laurent committed
543 544 545 546 547
    openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx);
    openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);

    for (i=0; i<4; i++) {
      if (i<openair0_cfg[card].tx_num_channels)
548
        openair0_cfg[card].tx_freq[i] = frame_parms[0]->ul_CarrierFreq;
laurent's avatar
laurent committed
549 550 551 552
      else
        openair0_cfg[card].tx_freq[i]=0.0;

      if (i<openair0_cfg[card].rx_num_channels)
553
        openair0_cfg[card].rx_freq[i] = frame_parms[0]->dl_CarrierFreq;
laurent's avatar
laurent committed
554 555 556 557 558 559
      else
        openair0_cfg[card].rx_freq[i]=0.0;

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
      openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
560
      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
laurent's avatar
laurent committed
561 562 563 564 565 566 567 568 569 570 571 572
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
             openair0_cfg[card].rx_freq[i]);
    }

    if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;

  }
}

573 574 575 576 577 578 579 580 581 582
void init_pdcp(void) {
  uint32_t pdcp_initmask = (!IS_SOFTMODEM_NOS1) ? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);

  /*if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
  }*/

  if (IS_SOFTMODEM_NOKRNMOD)
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;

583
  /*if (rlc_module_init() != 0) {
laurent's avatar
laurent committed
584
    LOG_I(RLC, "Problem at RLC initiation \n");
585 586
  }
  pdcp_layer_init();
587
  nr_DRB_preconfiguration();*/
588 589 590 591 592 593
  pdcp_module_init(pdcp_initmask);
  pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
  pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
  LOG_I(PDCP, "Before getting out from init_pdcp() \n");
}

594
// Stupid function addition because UE itti messages queues definition is common with eNB
laurent's avatar
laurent committed
595
void *rrc_enb_process_msg(void *notUsed) {
laurent's avatar
laurent committed
596
  return NULL;
597 598
}

laurent's avatar
laurent committed
599 600 601 602 603 604

int main( int argc, char **argv ) {
  //uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
  PHY_VARS_NR_UE *UE[MAX_NUM_CCs];
  start_background_system();

605
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) {
laurent's avatar
laurent committed
606 607
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }
608
  set_softmodem_sighandler();
laurent's avatar
laurent committed
609 610 611 612 613 614 615 616 617
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
  set_default_frame_parms(frame_parms);
  mode = normal_txrx;
  memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS);
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
  // initialize logging
  logInit();
  // get options and fill parameters from configuration file
  get_options (); //Command-line options, enb_properties
618
  get_common_options(SOFTMODEM_5GUE_BIT );
laurent's avatar
laurent committed
619 620 621 622 623 624 625
#if T_TRACER
  T_Config_Init();
#endif
  //randominit (0);
  set_taus_seed (0);
  tpool_t pool;
  Tpool = &pool;
laurent's avatar
laurent committed
626
  char params[]="-1,-1";
laurent's avatar
laurent committed
627
  initTpool(params, Tpool, false);
Hongzhi Wang's avatar
Hongzhi Wang committed
628
#ifdef UE_DLSCH_PARALLELISATION
Hongzhi Wang's avatar
Hongzhi Wang committed
629 630
  tpool_t pool_dl;
  Tpool_dl = &pool_dl;
laurent's avatar
laurent committed
631
  char params_dl[]="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1";
Hongzhi Wang's avatar
Hongzhi Wang committed
632
  initTpool(params_dl, Tpool_dl, false);
Hongzhi Wang's avatar
Hongzhi Wang committed
633
#endif
laurent's avatar
laurent committed
634 635 636
  cpuf=get_cpu_freq_GHz();
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);

637
  init_opt() ;
638
  load_nrLDPClib();
laurent's avatar
laurent committed
639

640 641 642 643
  if (ouput_vcd) {
    vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
  }

644 645 646 647 648 649 650 651
  #ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);

  init_NR_UE(1,rrc_config_path);
  if(IS_SOFTMODEM_NOS1)
	  init_pdcp();
Raymond Knopp's avatar
Raymond Knopp committed
652
/*
laurent's avatar
laurent committed
653 654 655 656 657 658
#ifdef PDCP_USE_NETLINK
  netlink_init();
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
#endif
659
*/
laurent's avatar
laurent committed
660 661 662 663 664 665

  NB_UE_INST=1;
  NB_INST=1;
  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE **));
  PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE *)*MAX_NUM_CCs);

666 667 668
  if (get_softmodem_params()->do_ra)
    AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n");

laurent's avatar
laurent committed
669 670
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    printf("frame_parms %d\n",frame_parms[CC_id]->ofdm_symbol_size);
671 672 673 674 675 676 677
    frame_parms[CC_id]->nb_antennas_tx     = nb_antenna_tx;
    frame_parms[CC_id]->nb_antennas_rx     = nb_antenna_rx;
    frame_parms[CC_id]->nb_antenna_ports_gNB = 1; //initial value overwritten by initial sync later
    frame_parms[CC_id]->threequarter_fs = threequarter_fs;
    LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx);

    PHY_vars_UE_g[0][CC_id] = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE));
laurent's avatar
laurent committed
678 679

    UE[CC_id] = PHY_vars_UE_g[0][CC_id];
680 681 682 683 684 685 686 687
    memset(UE[CC_id],0,sizeof(PHY_VARS_NR_UE));

    NR_UE_MAC_INST_t *mac = get_mac_inst(0);
    if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL)
      mac->if_module->phy_config_request(&mac->phy_config);

    fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
    nr_init_frame_parms_ue(frame_parms[CC_id],nrUE_config,NORMAL);
688

689
    // Overwrite DL frequency (for FR2 testing)
690
    if (downlink_frequency[0][0]!=0) {
691
      frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
692 693
      frame_parms[CC_id]->ul_CarrierFreq = downlink_frequency[0][0];
    }
694
   
695
    init_symbol_rotation(frame_parms[CC_id],frame_parms[CC_id]->dl_CarrierFreq);
696
    init_nr_ue_vars(UE[CC_id],frame_parms[CC_id],0,abstraction_flag);
laurent's avatar
laurent committed
697

698
    UE[CC_id]->mac_enabled = 1;
699
    UE[CC_id]->if_inst = nr_ue_if_module_init(0);
laurent's avatar
laurent committed
700 701 702 703
    UE[CC_id]->UE_scan = UE_scan;
    UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
    UE[CC_id]->UE_fo_compensation = UE_fo_compensation;
    UE[CC_id]->mode    = mode;
704
    UE[CC_id]->no_timing_correction = UE_no_timing_correction;
laurent's avatar
laurent committed
705 706 707 708 709
    printf("UE[%d]->mode = %d\n",CC_id,mode);

    UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0] + rx_gain_off;
    UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];

710
    if (UE[CC_id]->frame_parms.frame_type == FDD) {
laurent's avatar
laurent committed
711 712
      UE[CC_id]->N_TA_offset = 0;
    } else {
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
      int N_RB = UE[CC_id]->frame_parms.N_RB_DL;
      int N_TA_offset = UE[CC_id]->frame_parms.ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples  for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
      double factor=1;
      switch (UE[CC_id]->frame_parms.numerology_index) {
        case 0: //15 kHz scs
          AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n");
          if (N_RB <= 25) factor = .25;      // 7.68 Ms/s
          else if (N_RB <=50) factor = .5;   // 15.36 Ms/s
          else if (N_RB <=75) factor = 1.0;  // 30.72 Ms/s
          else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s
          else AssertFatal(1==0,"Too many PRBS for mu=0\n");
          break;
        case 1: //30 kHz sc
          AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n");
          if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s
          else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s
          break;
        case 2: //60 kHz scs
          AssertFatal(1==0,"scs_common should not be 60 kHz\n");
          break;
        case 3: //120 kHz scs
          AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n");
          break;
        case 4: //240 kHz scs
          AssertFatal(1==0,"scs_common should not be 60 kHz\n");
          if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s
          else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s
          else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB);
          break;

        if (N_RB == 100)
          UE[CC_id]->N_TA_offset = 624;
        else if (N_RB == 50)
          UE[CC_id]->N_TA_offset = 624/2;
        else if (N_RB == 25)
          UE[CC_id]->N_TA_offset = 624/4;
      }
      if (UE[CC_id]->frame_parms.threequarter_fs == 1) factor = factor*.75;
      UE[CC_id]->N_TA_offset = (int)(N_TA_offset * factor);
cig's avatar
cig committed
752
      LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", UE[CC_id]->Mod_id, UE[CC_id]->N_TA_offset, factor, UE[CC_id]->frame_parms.ul_CarrierFreq, N_RB);
laurent's avatar
laurent committed
753 754 755 756 757 758 759 760
    }
  }

  //  printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power));
  init_openair0();
  // init UE_PF_PO and mutex lock
  pthread_mutex_init(&ue_pf_po_mutex, NULL);
  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
laurent's avatar
laurent committed
761
  configure_linux();
laurent's avatar
laurent committed
762
  mlockall(MCL_CURRENT | MCL_FUTURE);
763 764
 
  if(IS_SOFTMODEM_DOFORMS) { 
765
    load_softscope("nr",PHY_vars_UE_g[0][0]);
766
  }     
laurent's avatar
laurent committed
767 768 769 770 771
  number_of_cards = 1;

  for(int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
    PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
772
    PHY_vars_UE_g[0][CC_id]->timing_advance = timing_advance;
laurent's avatar
laurent committed
773 774
  }

Florian Kaltenberger's avatar
Florian Kaltenberger committed
775 776 777
  init_NR_UE_threads(1);
  printf("UE threads created by %ld\n", gettid());
  
laurent's avatar
laurent committed
778 779 780 781 782 783
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");

  while(true)
    sleep(3600);

784 785 786
  if (ouput_vcd)
    vcd_signal_dumper_close();

laurent's avatar
laurent committed
787 788
  return 0;
}