nr-ue.c 35.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
/*
 * 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.0  (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
 */
21
#include "executables/thread-common.h"
laurent's avatar
laurent committed
22 23
#include "executables/nr-uesoftmodem.h"

24
#include "NR_MAC_UE/mac.h"
laurent's avatar
laurent committed
25 26 27 28 29 30 31 32 33 34
//#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface_extern.h"

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "fapi_nr_ue_l1.h"
#include "PHY/phy_extern_nr_ue.h"
#include "PHY/INIT/phy_init.h"
#include "PHY/MODULATION/modulation_UE.h"
35
#include "NR_MAC_UE/mac_proto.h"
laurent's avatar
laurent committed
36 37
#include "RRC/NR_UE/rrc_proto.h"

cig's avatar
cig committed
38
#include "SCHED_NR_UE/phy_frame_config_nr.h"
laurent's avatar
laurent committed
39 40 41 42 43
#include "SCHED_NR_UE/defs.h"

#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"

#include "common/utils/LOG/log.h"
laurent's avatar
laurent committed
44
#include "common/utils/system.h"
laurent's avatar
laurent committed
45
#include "common/utils/LOG/vcd_signal_dumper.h"
46
#include "executables/nr-softmodem.h"
laurent's avatar
laurent committed
47 48 49 50 51 52 53 54 55

#include "T.h"

#ifdef XFORMS
  #include "PHY/TOOLS/nr_phy_scope.h"

  extern char do_forms;
#endif

56 57 58
// Missing stuff?
int next_ra_frame = 0;
module_id_t next_Mod_id = 0;
laurent's avatar
laurent committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 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 123 124 125 126 127 128 129 130 131 132 133 134 135 136

extern double cpuf;
//static  nfapi_nr_config_request_t config_t;
//static  nfapi_nr_config_request_t* config =&config_t;

/*
 *  NR SLOT PROCESSING SEQUENCE
 *
 *  Processing occurs with following steps for connected mode:
 *
 *  - Rx samples for a slot are received,
 *  - PDCCH processing (including DCI extraction for downlink and uplink),
 *  - PDSCH processing (including transport blocks decoding),
 *  - PUCCH/PUSCH (transmission of acknowledgements, CSI, ... or data).
 *
 *  Time between reception of the slot and related transmission depends on UE processing performance.
 *  It is defined by the value NR_UE_CAPABILITY_SLOT_RX_TO_TX.
 *
 *  In NR, network gives the duration between Rx slot and Tx slot in the DCI:
 *  - for reception of a PDSCH and its associated acknowledgment slot (with a PUCCH or a PUSCH),
 *  - for reception of an uplink grant and its associated PUSCH slot.
 *
 *  So duration between reception and it associated transmission depends on its transmission slot given in the DCI.
 *  NR_UE_CAPABILITY_SLOT_RX_TO_TX means the minimum duration but higher duration can be given by the network because UE can support it.
 *
 *                                                                                                    Slot k
 *                                                                                  -------+------------+--------
 *                Frame                                                                    | Tx samples |
 *                Subframe                                                                 |   buffer   |
 *                Slot n                                                            -------+------------+--------
 *       ------ +------------+--------                                                     |
 *              | Rx samples |                                                             |
 *              |   buffer   |                                                             |
 *       -------+------------+--------                                                     |
 *                           |                                                             |
 *                           V                                                             |
 *                           +------------+                                                |
 *                           |   PDCCH    |                                                |
 *                           | processing |                                                |
 *                           +------------+                                                |
 *                           |            |                                                |
 *                           |            v                                                |
 *                           |            +------------+                                   |
 *                           |            |   PDSCH    |                                   |
 *                           |            | processing | decoding result                   |
 *                           |            +------------+    -> ACK/NACK of PDSCH           |
 *                           |                         |                                   |
 *                           |                         v                                   |
 *                           |                         +-------------+------------+        |
 *                           |                         | PUCCH/PUSCH | Tx samples |        |
 *                           |                         |  processing | transfer   |        |
 *                           |                         +-------------+------------+        |
 *                           |                                                             |
 *                           |/___________________________________________________________\|
 *                            \  duration between reception and associated transmission   /
 *
 * Remark: processing is done slot by slot, it can be distribute on different threads which are executed in parallel.
 * This is an architecture optimization in order to cope with real time constraints.
 * By example, for LTE, subframe processing is spread over 4 different threads.
 *
 */

#ifndef NO_RAT_NR
  #define DURATION_RX_TO_TX           (NR_UE_CAPABILITY_SLOT_RX_TO_TX)  /* for NR this will certainly depends to such UE capability which is not yet defined */
#else
  #define DURATION_RX_TO_TX           (4)   /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */
#endif

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

typedef enum {
  pss=0,
  pbch=1,
  si=2
} sync_mode_t;


137 138 139 140
void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
                     NR_DL_FRAME_PARMS *frame_parms,
                     uint8_t UE_id,
                     uint8_t abstraction_flag)
laurent's avatar
laurent committed
141
{
142

143 144
  int nb_connected_gNB = 1, gNB_id;

laurent's avatar
fixes  
laurent committed
145
  memcpy(&(ue->frame_parms), frame_parms, sizeof(NR_DL_FRAME_PARMS));
146

laurent's avatar
laurent committed
147 148
  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
149

150 151 152 153 154 155
  // Setting UE mode to NOT_SYNCHED by default
  for (gNB_id = 0; gNB_id < nb_connected_gNB; gNB_id++){
    ue->UE_mode[gNB_id] = NOT_SYNCHED;
    ue->prach_resources[gNB_id] = (NR_PRACH_RESOURCES_t *)malloc16_clear(sizeof(NR_PRACH_RESOURCES_t));
  }

laurent's avatar
laurent committed
156
  // initialize all signal buffers
157
  init_nr_ue_signal(ue, nb_connected_gNB, abstraction_flag);
158

laurent's avatar
laurent committed
159
  // intialize transport
160
  init_nr_ue_transport(ue, abstraction_flag);
laurent's avatar
laurent committed
161 162 163 164 165 166 167 168
}

/*!
 * It performs band scanning and synchonization.
 * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
 */

typedef struct syncData_s {
169
  UE_nr_rxtx_proc_t proc;
laurent's avatar
laurent committed
170 171 172 173 174 175 176 177 178 179 180 181 182
  PHY_VARS_NR_UE *UE;
} syncData_t;

static void UE_synch(void *arg) {
  syncData_t *syncD=(syncData_t *) arg;
  int i, hw_slot_offset;
  PHY_VARS_NR_UE *UE = syncD->UE;
  sync_mode_t sync_mode = pbch;
  int CC_id = UE->CC_id;
  int freq_offset=0;
  UE->is_synchronized = 0;

  if (UE->UE_scan == 0) {
183 184 185 186 187 188

    // Overwrite DL frequency (for FR2 testing)
    if (downlink_frequency[0][0]!=0){
       UE->frame_parms.dl_CarrierFreq = downlink_frequency[0][0];
       UE->frame_parms.ul_CarrierFreq = downlink_frequency[0][0];
    }
Rakesh's avatar
Rakesh committed
189

190 191
    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu64", UL %"PRIu64" (oai_exit %d, rx_num_channels %d)\n",
           UE->frame_parms.dl_CarrierFreq, UE->frame_parms.ul_CarrierFreq,
laurent's avatar
laurent committed
192 193 194
           oai_exit, openair0_cfg[0].rx_num_channels);

    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
195 196
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq;
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq;
laurent's avatar
laurent committed
197 198
      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;

199
      if (UE->frame_parms.frame_type == FDD) 
laurent's avatar
laurent committed
200
        openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
201
      else 
laurent's avatar
laurent committed
202 203 204 205 206
        openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
    }

    sync_mode = pbch;
  } else {
207 208
    LOG_E(PHY,"Fixme!\n");
    /*
laurent's avatar
laurent committed
209 210 211 212 213 214 215 216 217
    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
      downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min;
      uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] =
        bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min;
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
        downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
    }
218
    */
laurent's avatar
laurent committed
219 220 221 222 223
  }

  LOG_W(PHY, "Starting sync detection\n");

  switch (sync_mode) {
224
    /*
laurent's avatar
laurent committed
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
    case pss:
      LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
      //lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
      current_offset += 20000000; // increase by 20 MHz

      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
        current_band++;
        current_offset=0;
      }

      if (current_band==bands_to_scan.nbands) {
        current_band=0;
        oai_exit=1;
      }

      for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
        downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
        uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
        openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
        openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
        openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;

        if (UE->UE_scan_carrier) {
          openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
        }
      }

      break;
253
    */
laurent's avatar
laurent committed
254 255 256
    case pbch:
      LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);

257
      if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) {
laurent's avatar
laurent committed
258
        freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
259
        hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) +
Sakthivel Velumani's avatar
Sakthivel Velumani committed
260
                         round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0);
261
        LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %lu, UL %lu), UE_scan_carrier %d\n",
laurent's avatar
laurent committed
262 263 264
              hw_slot_offset,
              freq_offset,
              UE->rx_total_gain_dB,
265 266
              UE->frame_parms.dl_CarrierFreq+freq_offset,
              UE->frame_parms.ul_CarrierFreq+freq_offset,
laurent's avatar
laurent committed
267 268 269 270 271 272 273 274 275 276 277 278
              UE->UE_scan_carrier );

        // rerun with new cell parameters and frequency-offset
        for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
          openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;

          if (freq_offset >= 0)
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset);
          else
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset);

          openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
279 280
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+(UE->frame_parms.ul_CarrierFreq-UE->frame_parms.dl_CarrierFreq);
          UE->frame_parms.dl_CarrierFreq = openair0_cfg[CC_id].rx_freq[i];
laurent's avatar
laurent committed
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
        }

        // reconfigure for potentially different bandwidth
        switch(UE->frame_parms.N_RB_DL) {
          case 6:
            openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
            openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
            openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
            //            openair0_cfg[0].rx_gain[0] -= 12;
            break;

          case 25:
            openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
            openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
            openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
            //            openair0_cfg[0].rx_gain[0] -= 6;
            break;

          case 50:
            openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
            openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
            openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
            //            openair0_cfg[0].rx_gain[0] -= 3;
            break;

          case 100:
            openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
            openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
            openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
            //            openair0_cfg[0].rx_gain[0] -= 0;
            break;
312 313 314 315 316 317

          case 66:
            openair0_cfg[UE->rf_map.card].sample_rate=122.88e6;
            openair0_cfg[UE->rf_map.card].rx_bw=100.e6;
            openair0_cfg[UE->rf_map.card].tx_bw=100.e6;
            break;
laurent's avatar
laurent committed
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
        }

        if (UE->mode != loop_through_memory) {
          UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
          //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
          //UE->rfdevice.trx_stop_func(&UE->rfdevice);
          // sleep(1);
          //nr_init_frame_parms_ue(&UE->frame_parms);
          /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
            LOG_E(HW,"Could not start the device\n");
            oai_exit=1;
            }*/
        }

        if (UE->UE_scan_carrier == 1) {
          UE->UE_scan_carrier = 0;
        } else {
          UE->is_synchronized = 1;
        }
      } else {
        // initial sync failed
        // calculate new offset and try again
        if (UE->UE_scan_carrier == 1) {
          if (freq_offset >= 0)
            freq_offset += 100;

          freq_offset *= -1;
345
          LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %lu, UL %lu)\n",
laurent's avatar
laurent committed
346 347
                freq_offset,
                UE->rx_total_gain_dB,
348 349
                UE->frame_parms.dl_CarrierFreq+freq_offset,
                UE->frame_parms.ul_CarrierFreq+freq_offset );
laurent's avatar
laurent committed
350 351

          for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
352 353
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq+freq_offset;
            openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq+freq_offset;
laurent's avatar
laurent committed
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
            openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;

            if (UE->UE_scan_carrier==1)
              openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
          }

          if (UE->mode != loop_through_memory)
            UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
        }// initial_sync=0

        break;

      case si:
      default:
        break;
      }
  }
}

Florian Kaltenberger's avatar
Florian Kaltenberger committed
373
void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
374

Florian Kaltenberger's avatar
Florian Kaltenberger committed
375

376 377
  fapi_nr_config_request_t *cfg = &UE->nrUE_config;
  int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_tti_tx);
378
  uint8_t gNB_id = 0;
379 380

  if (tx_slot_type == NR_UPLINK_SLOT || tx_slot_type == NR_MIXED_SLOT){
Florian Kaltenberger's avatar
Florian Kaltenberger committed
381

382 383 384 385 386 387 388 389 390 391 392 393 394
    // trigger L2 to run ue_scheduler thru IF module
    // [TODO] mapping right after NR initial sync
    if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
      nr_uplink_indication_t ul_indication;
      memset((void*)&ul_indication, 0, sizeof(ul_indication));

      ul_indication.module_id = UE->Mod_id;
      ul_indication.gNB_index = gNB_id;
      ul_indication.cc_id     = UE->CC_id;
      ul_indication.frame_rx  = proc->frame_rx;
      ul_indication.slot_rx   = proc->nr_tti_rx;
      ul_indication.frame_tx  = proc->frame_tx;
      ul_indication.slot_tx   = proc->nr_tti_tx;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
395

396 397
      UE->if_inst->ul_indication(&ul_indication);
    }
398

Florian Kaltenberger's avatar
Florian Kaltenberger committed
399
    if (UE->mode != loop_through_memory) {
400
      uint8_t thread_id = PHY_vars_UE_g[UE->Mod_id][0]->current_thread_id[proc->nr_tti_rx];
Florian Kaltenberger's avatar
Florian Kaltenberger committed
401 402 403 404 405 406 407
      phy_procedures_nrUE_TX(UE,proc,0,thread_id);
    }
  }
}

void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {

408 409
  fapi_nr_config_request_t *cfg = &UE->nrUE_config;
  int rx_slot_type = nr_ue_slot_select(cfg, proc->frame_rx, proc->nr_tti_rx);
cig's avatar
cig committed
410 411
  uint8_t gNB_id = 0;

412
  if (rx_slot_type == NR_DOWNLINK_SLOT || rx_slot_type == NR_MIXED_SLOT){
Florian Kaltenberger's avatar
Florian Kaltenberger committed
413

cig's avatar
cig committed
414
    if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
415 416 417
      nr_downlink_indication_t dl_indication;
      memset((void*)&dl_indication, 0, sizeof(dl_indication));

cig's avatar
cig committed
418 419 420 421 422
      dl_indication.module_id = UE->Mod_id;
      dl_indication.gNB_index = gNB_id;
      dl_indication.cc_id     = UE->CC_id;
      dl_indication.frame     = proc->frame_rx;
      dl_indication.slot      = proc->nr_tti_rx;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
423

424 425
      UE->if_inst->dl_indication(&dl_indication, NULL);
    }
426

Florian Kaltenberger's avatar
Florian Kaltenberger committed
427
  // Process Rx data for one sub-frame
laurent's avatar
laurent committed
428 429 430
#ifdef UE_SLOT_PARALLELISATION
    phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
laurent's avatar
laurent committed
431
    uint64_t a=rdtsc();
432
    phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode);
433
    LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500);
434
    //printf(">>> nr_ue_pdcch_procedures ended\n");
laurent's avatar
laurent committed
435
#endif
Raymond Knopp's avatar
Raymond Knopp committed
436

Florian Kaltenberger's avatar
Florian Kaltenberger committed
437 438 439 440 441 442 443 444
    if(IS_SOFTMODEM_NOS1){ //&& proc->nr_tti_rx==1
      //Hardcoded rnti value
      protocol_ctxt_t ctxt;
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO,
				     0x1234, proc->frame_rx,
				     proc->nr_tti_rx, 0);
      pdcp_run(&ctxt);
    }
laurent's avatar
laurent committed
445 446
  }

447 448
  // no UL for now
  /*
laurent's avatar
laurent committed
449 450 451 452 453 454 455 456 457 458 459 460
  if (UE->mac_enabled==1) {
    //  trigger L2 to run ue_scheduler thru IF module
    //  [TODO] mapping right after NR initial sync
    if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
      UE->ul_indication.module_id = 0;
      UE->ul_indication.gNB_index = 0;
      UE->ul_indication.cc_id = 0;
      UE->ul_indication.frame = proc->frame_rx;
      UE->ul_indication.slot = proc->nr_tti_rx;
      UE->if_inst->ul_indication(&UE->ul_indication);
    }
  }
461
  */
462

laurent's avatar
laurent committed
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
}

/*!
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
 * This thread performs the phy_procedures_UE_RX() on every received slot.
 * then, if TX is enabled it performs TX for n+4.
 * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */

typedef struct processingData_s {
  UE_nr_rxtx_proc_t proc;
  PHY_VARS_NR_UE    *UE;
}  processingData_t;

void UE_processing(void *arg) {
479
  processingData_t *rxtxD = (processingData_t *) arg;
laurent's avatar
laurent committed
480 481 482
  UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
  PHY_VARS_NR_UE    *UE   = rxtxD->UE;

483
  uint8_t gNB_id = 0;
484 485 486 487 488 489 490 491 492 493 494 495 496

  // params for UL time alignment procedure
  NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id];
  uint8_t numerology = UE->frame_parms.numerology_index;
  uint16_t bwp_ul_NB_RB = UE->frame_parms.N_RB_UL;
  int slot_tx = proc->nr_tti_tx;
  int frame_tx = proc->frame_tx;

  /* UL time alignment
  // If the current tx frame and slot match the TA configuration in ul_time_alignment
  // then timing advance is processed and set to be applied in the next UL transmission */
  if (UE->mac_enabled == 1) {

laurent's avatar
laurent committed
497
    if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) {
498 499 500 501 502 503 504 505 506
      LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx);

      //if (nfapi_mode!=3){
      nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB);
      ul_time_alignment->ta_frame = -1;
      ul_time_alignment->ta_slot = -1;
      //}
    }
  }
507

Florian Kaltenberger's avatar
Florian Kaltenberger committed
508 509
  processSlotRX(UE, proc);
  processSlotTX(UE, proc);
laurent's avatar
laurent committed
510 511
}

512
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
laurent's avatar
laurent committed
513 514 515
  void *dummy_tx[UE->frame_parms.nb_antennas_tx];

  for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
516
    dummy_tx[i]=malloc16_clear(writeBlockSize*4);
laurent's avatar
laurent committed
517

518 519 520 521 522 523 524
  AssertFatal( writeBlockSize ==
               UE->rfdevice.trx_write_func(&UE->rfdevice,
               timestamp,
               dummy_tx,
               writeBlockSize,
               UE->frame_parms.nb_antennas_tx,
               4),"");
laurent's avatar
laurent committed
525 526 527 528 529

  for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
    free(dummy_tx[i]);
}

530
void readFrame(PHY_VARS_NR_UE *UE,  openair0_timestamp *timestamp, bool toTrash) {
laurent's avatar
laurent committed
531

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
  void *rxp[NB_ANTENNAS_RX];

  for(int x=0; x<20; x++) {  // two frames for initial sync
    for (int slot=0; slot<UE->frame_parms.slots_per_subframe; slot ++ ) {
      for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) {
        if (toTrash)
          rxp[i]=malloc16(UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms)*4);
        else
          rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) +
                   4*((x*UE->frame_parms.samples_per_subframe)+
                   UE->frame_parms.get_samples_slot_timestamp(slot,&UE->frame_parms,0));
      }
        
      AssertFatal( UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms) ==
                   UE->rfdevice.trx_read_func(&UE->rfdevice,
                   timestamp,
                   rxp,
                   UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms),
                   UE->frame_parms.nb_antennas_rx), "");

      if (IS_SOFTMODEM_RFSIM)
        dummyWrite(UE,*timestamp, UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms));
      if (toTrash)
        for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
          free(rxp[i]);
557
    }
laurent's avatar
laurent committed
558 559 560 561 562
  }

}

void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
563

laurent's avatar
laurent committed
564 565
    LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);

Sakthivel Velumani's avatar
Sakthivel Velumani committed
566
    *timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
laurent's avatar
laurent committed
567 568
    for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
      int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
569 570 571
      // we write before read becasue gNB waits for UE to write and both executions halt
      // this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
      if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
laurent's avatar
laurent committed
572 573 574 575 576 577
      AssertFatal(unitTransfer ==
                  UE->rfdevice.trx_read_func(&UE->rfdevice,
                                             timestamp,
                                             (void **)UE->common_vars.rxdata,
                                             unitTransfer,
                                             UE->frame_parms.nb_antennas_rx),"");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
578
      *timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
laurent's avatar
laurent committed
579 580 581 582 583 584 585
    }

}

int computeSamplesShift(PHY_VARS_NR_UE *UE) {

  // compute TO compensation that should be applied for this frame
586 587 588
  if ( UE->rx_offset < UE->frame_parms.samples_per_frame/2  &&
       UE->rx_offset > 0 ) {
    //LOG_I(PHY,"!!!adjusting -1 samples!!!\n");
laurent's avatar
laurent committed
589
    return -1 ;
590
  }
laurent's avatar
laurent committed
591

592 593 594
  if ( UE->rx_offset > UE->frame_parms.samples_per_frame/2 &&
       UE->rx_offset < UE->frame_parms.samples_per_frame ) {
    //LOG_I(PHY,"!!!adjusting +1 samples!!!\n");
laurent's avatar
laurent committed
595
    return 1;
596
  }
laurent's avatar
laurent committed
597

laurent's avatar
laurent committed
598 599 600
  return 0;
}

601
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
602 603 604 605 606 607 608
  if (fp->numerology_index == 0)
    return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
  int num_samples = (slot%(fp->slots_per_subframe/2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
  num_samples += fp->ofdm_symbol_size;
  return num_samples;
}

609
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
610 611 612 613 614 615 616
  int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
  int next_slot_first_symbol = 0;
  if (slot < (fp->slots_per_frame-1))
    next_slot_first_symbol = get_firstSymSamp(slot+1, fp);
  return rem_samples + next_slot_first_symbol;
}

laurent's avatar
laurent committed
617
void *UE_thread(void *arg) {
laurent's avatar
laurent committed
618
  //this thread should be over the processing thread to keep in real time
laurent's avatar
laurent committed
619 620 621 622 623 624 625 626 627 628 629 630
  PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
  //  int tx_enabled = 0;
  openair0_timestamp timestamp;
  void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
  int start_rx_stream = 0;
  AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
  UE->rfdevice.host_type = RAU_HOST;
  AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
  notifiedFIFO_t nf;
  initNotifiedFIFO(&nf);
  int nbSlotProcessing=0;
  int thread_idx=0;
631 632
  notifiedFIFO_t freeBlocks;
  initNotifiedFIFO_nothreadSafe(&freeBlocks);
633
  NR_UE_MAC_INST_t *mac = get_mac_inst(0);
laurent's avatar
laurent committed
634

635 636 637
  for (int i=0; i<RX_NB_TH+1; i++)  // RX_NB_TH working + 1 we are making to be pushed
    pushNotifiedFIFO_nothreadSafe(&freeBlocks,
                                  newNotifiedFIFO_elt(sizeof(processingData_t), 0,&nf,UE_processing));
laurent's avatar
laurent committed
638

laurent's avatar
fixes  
laurent committed
639
  bool syncRunning=false;
640
  const int nb_slot_frame = UE->frame_parms.slots_per_frame;
641
  int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
laurent's avatar
laurent committed
642 643

  while (!oai_exit) {
644 645 646 647 648 649
    if (syncRunning) {
      notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool);

      if (res) {
        syncRunning=false;
        syncData_t *tmp=(syncData_t *)NotifiedFifoData(res);
650 651 652 653 654
        if (UE->is_synchronized) {
          decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
          // shift the frame index with all the frames we trashed meanwhile we perform the synch search
          decoded_frame_rx=(decoded_frame_rx + (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER;
        }
655
        delNotifiedFIFO_elt(res);
laurent's avatar
laurent committed
656
      } else {
657
        readFrame(UE, &timestamp, true);
658
        trashed_frames+=2;
659
        continue;
laurent's avatar
laurent committed
660
      }
661
    }
laurent's avatar
laurent committed
662

663
    AssertFatal( !syncRunning, "At this point synchronization can't be running\n");
664 665

    if (!UE->is_synchronized) {
666
      readFrame(UE, &timestamp, false);
667 668 669 670 671 672 673
      notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(syncData_t),0,&nf,UE_synch);
      syncData_t *syncMsg=(syncData_t *)NotifiedFifoData(Msg);
      syncMsg->UE=UE;
      memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
      pushTpool(Tpool, Msg);
      trashed_frames=0;
      syncRunning=true;
laurent's avatar
laurent committed
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
      continue;
    }

    if (start_rx_stream==0) {
      start_rx_stream=1;
      syncInFrame(UE, &timestamp);
      UE->rx_offset=0;
      UE->time_sync_cell=0;
      // read in first symbol
      AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
                   UE->rfdevice.trx_read_func(&UE->rfdevice,
                                              &timestamp,
                                              (void **)UE->common_vars.rxdata,
                                              UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
                                              UE->frame_parms.nb_antennas_rx),"");
laurent's avatar
fixes  
laurent committed
689 690
      // we have the decoded frame index in the return of the synch process
      // and we shifted above to the first slot of next frame
691
      decoded_frame_rx++;
692
      // we do ++ first in the regular processing, so it will be begin of frame;
693
      absolute_slot=decoded_frame_rx*nb_slot_frame -1;
laurent's avatar
laurent committed
694 695 696
      continue;
    }

697

laurent's avatar
laurent committed
698
    absolute_slot++;
699

700 701 702 703
    // whatever means thread_idx
    // Fix me: will be wrong when slot 1 is slow, as slot 2 finishes
    // Slot 3 will overlap if RX_NB_TH is 2
    // this is general failure in UE !!!
laurent's avatar
laurent committed
704
    thread_idx = absolute_slot % RX_NB_TH;
laurent's avatar
fixes  
laurent committed
705
    int slot_nr = absolute_slot % nb_slot_frame;
706 707 708 709
    notifiedFIFO_elt_t *msgToPush;
    AssertFatal((msgToPush=pullNotifiedFIFO_nothreadSafe(&freeBlocks)) != NULL,"chained list failure");
    processingData_t *curMsg=(processingData_t *)NotifiedFifoData(msgToPush);
    curMsg->UE=UE;
laurent's avatar
laurent committed
710
    // update thread index for received subframe
711
    curMsg->UE->current_thread_id[slot_nr] = thread_idx;
712
    curMsg->proc.CC_id = UE->CC_id;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
713
    curMsg->proc.nr_tti_rx= slot_nr;
714
    curMsg->proc.subframe_rx=slot_nr/(nb_slot_frame/10);
715 716
    curMsg->proc.nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
    curMsg->proc.subframe_tx=curMsg->proc.nr_tti_rx;
717 718
    curMsg->proc.frame_rx = (absolute_slot/nb_slot_frame) % MAX_FRAME_NUMBER;
    curMsg->proc.frame_tx = ((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame) % MAX_FRAME_NUMBER;
719
    curMsg->proc.decoded_frame_rx=-1;
Hongzhi Wang's avatar
Hongzhi Wang committed
720 721 722
    //LOG_I(PHY,"Process slot %d thread Idx %d total gain %d\n", slot_nr, thread_idx, UE->rx_total_gain_dB);

#ifdef OAI_ADRV9371_ZC706
Hongzhi Wang's avatar
Hongzhi Wang committed
723
    /*uint32_t total_gain_dB_prev = 0;
Hongzhi Wang's avatar
Hongzhi Wang committed
724
    if (total_gain_dB_prev != UE->rx_total_gain_dB) {
725
        total_gain_dB_prev = UE->rx_total_gain_dB;
Hongzhi Wang's avatar
Hongzhi Wang committed
726
        openair0_cfg[0].rx_gain[0] = UE->rx_total_gain_dB;
Hongzhi Wang's avatar
Hongzhi Wang committed
727
        UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&openair0_cfg[0]);
Hongzhi Wang's avatar
Hongzhi Wang committed
728
    }*/
Hongzhi Wang's avatar
Hongzhi Wang committed
729
#endif
laurent's avatar
laurent committed
730

Sakthivel Velumani's avatar
Sakthivel Velumani committed
731
    int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
laurent's avatar
laurent committed
732
    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
Sakthivel Velumani's avatar
Sakthivel Velumani committed
733
      rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
734
               UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
laurent's avatar
laurent committed
735 736

    for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
737 738
      txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp(
               ((curMsg->proc.nr_tti_rx + DURATION_RX_TO_TX)%nb_slot_frame),&UE->frame_parms,0)];
laurent's avatar
laurent committed
739 740 741 742

    int readBlockSize, writeBlockSize;

    if (slot_nr<(nb_slot_frame - 1)) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
743
      readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
744
      writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms);
laurent's avatar
laurent committed
745 746
    } else {
      UE->rx_offset_diff = computeSamplesShift(UE);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
747
      readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
laurent's avatar
laurent committed
748
                    UE->rx_offset_diff;
749
      writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms) -
laurent's avatar
laurent committed
750 751 752 753 754 755 756 757 758
                     UE->rx_offset_diff;
    }

    AssertFatal(readBlockSize ==
                UE->rfdevice.trx_read_func(&UE->rfdevice,
                                           &timestamp,
                                           rxp,
                                           readBlockSize,
                                           UE->frame_parms.nb_antennas_rx),"");
759

laurent's avatar
laurent committed
760 761 762
    AssertFatal( writeBlockSize ==
                 UE->rfdevice.trx_write_func(&UE->rfdevice,
                     timestamp+
763
                     UE->frame_parms.get_samples_slot_timestamp(slot_nr,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
764
                     &UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp -
laurent's avatar
laurent committed
765 766 767 768
                     openair0_cfg[0].tx_sample_advance,
                     txp,
                     writeBlockSize,
                     UE->frame_parms.nb_antennas_tx,
769
                     1),"");
laurent's avatar
laurent committed
770 771 772

    if( slot_nr==(nb_slot_frame-1)) {
      // read in first symbol of next frame and adjust for timing drift
Sakthivel Velumani's avatar
Sakthivel Velumani committed
773
      int first_symbols=UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0; // first symbol of every frames
laurent's avatar
laurent committed
774 775 776 777 778 779 780 781 782 783 784 785

      if ( first_symbols > 0 )
        AssertFatal(first_symbols ==
                    UE->rfdevice.trx_read_func(&UE->rfdevice,
                                               &timestamp,
                                               (void **)UE->common_vars.rxdata,
                                               first_symbols,
                                               UE->frame_parms.nb_antennas_rx),"");
      else
        LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
    }

786
    curMsg->proc.timestamp_tx = timestamp+
787
                                UE->frame_parms.get_samples_slot_timestamp(slot_nr,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
788 789
                                &UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp;

laurent's avatar
fixes  
laurent committed
790
    notifiedFIFO_elt_t *res;
laurent's avatar
laurent committed
791

792
    while (nbSlotProcessing >= RX_NB_TH) {
793
      if ( (res=tryPullTpool(&nf, Tpool)) != NULL ) {
laurent's avatar
laurent committed
794 795
        nbSlotProcessing--;
        processingData_t *tmp=(processingData_t *)res->msgData;
laurent's avatar
fixes  
laurent committed
796

laurent's avatar
laurent committed
797
        if (tmp->proc.decoded_frame_rx != -1)
798 799
          decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
          //decoded_frame_rx=tmp->proc.decoded_frame_rx;
laurent's avatar
fixes  
laurent committed
800

801
        pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
802
      }
laurent's avatar
laurent committed
803

laurent's avatar
laurent committed
804 805 806
      usleep(200);
    }

807 808 809
    if (  (decoded_frame_rx != curMsg->proc.frame_rx) &&
          (((decoded_frame_rx+1) % MAX_FRAME_NUMBER) != curMsg->proc.frame_rx) &&
          (((decoded_frame_rx+2) % MAX_FRAME_NUMBER) != curMsg->proc.frame_rx))
laurent's avatar
laurent committed
810
      LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
811
            decoded_frame_rx, curMsg->proc.frame_rx  );
laurent's avatar
laurent committed
812

813
    nbSlotProcessing++;
814 815
    msgToPush->key=slot_nr;
    pushTpool(Tpool, msgToPush);
laurent's avatar
laurent committed
816

817
    if (IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) {  //getenv("RFSIMULATOR")
laurent's avatar
laurent committed
818 819 820 821
      // FixMe: Wait previous thread is done, because race conditions seems too bad
      // in case of actual RF board, the overlap between threads mitigate the issue
      // We must receive one message, that proves the slot processing is done
      res=pullTpool(&nf, Tpool);
laurent's avatar
laurent committed
822
      nbSlotProcessing--;
laurent's avatar
fixes  
laurent committed
823 824 825
      processingData_t *tmp=(processingData_t *)res->msgData;

      if (tmp->proc.decoded_frame_rx != -1)
826 827
        decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
        //decoded_frame_rx=tmp->proc.decoded_frame_rx;
laurent's avatar
fixes  
laurent committed
828

829
      pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
laurent's avatar
laurent committed
830 831 832 833 834 835
    }
  } // while !oai_exit

  return NULL;
}

836
void init_NR_UE(int nb_inst, char* rrc_config_path) {
laurent's avatar
laurent committed
837 838
  int inst;
  NR_UE_MAC_INST_t *mac_inst;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
839 840
  NR_UE_RRC_INST_t* rrc_inst;
  
laurent's avatar
laurent committed
841
  for (inst=0; inst < nb_inst; inst++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
842 843 844
    AssertFatal((rrc_inst = nr_l3_init_ue(rrc_config_path)) != NULL, "can not initialize RRC module\n");
    AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst)) != NULL, "can not initialize L2 module\n");
    AssertFatal((mac_inst->if_module = nr_ue_if_module_init(inst)) != NULL, "can not initialize IF module\n");
845 846 847 848 849 850 851 852 853 854 855
  }
}

void init_NR_UE_threads(int nb_inst) {
  int inst;

  pthread_t threads[nb_inst];

  for (inst=0; inst < nb_inst; inst++) {
    PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];

laurent's avatar
laurent committed
856
    LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
laurent's avatar
laurent committed
857
    threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
858 859

#ifdef UE_DLSCH_PARALLELISATION
860
    pthread_t dlsch0_threads;
861 862 863
    threadCreate(&dlsch0_threads, dlsch_thread, (void *)UE, "DLthread", -1, OAI_PRIORITY_RT_MAX-1);
#endif

laurent's avatar
laurent committed
864 865 866
  }
}

867 868 869 870 871 872 873 874 875 876 877
/* HACK: this function is needed to compile the UE
 * fix it somehow
 */
int8_t find_dlsch(uint16_t rnti,
                  PHY_VARS_eNB *eNB,
                  find_type_t type)
{
  printf("you cannot read this\n");
  abort();
}

878
void multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP) {}