nr-ue.c 36.8 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 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include "executables/nr-uesoftmodem.h"

#include "LAYER2/NR_MAC_UE/mac.h"
//#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"
#include "LAYER2/NR_MAC_UE/mac_proto.h"
#include "RRC/NR_UE/rrc_proto.h"

//#ifndef NO_RAT_NR
#include "SCHED_NR/phy_frame_config_nr.h"
//#endif
#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
46
#include "common/utils/system.h"
laurent's avatar
laurent committed
47
#include "common/utils/LOG/vcd_signal_dumper.h"
48
#include "executables/nr-softmodem.h"
laurent's avatar
laurent committed
49 50 51 52 53 54 55 56 57

#include "T.h"

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

  extern char do_forms;
#endif

58 59 60
// Missing stuff?
int next_ra_frame = 0;
module_id_t next_Mod_id = 0;
laurent's avatar
laurent committed
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 137 138

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;


139 140 141 142
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
143
{
144

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

laurent's avatar
laurent committed
150 151 152 153 154 155 156 157 158 159 160 161
  // initialize all signal buffers
  init_nr_ue_signal(ue,1,abstraction_flag);
  // intialize transport
  init_nr_ue_transport(ue,abstraction_flag);
}

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

typedef struct syncData_s {
162
  UE_nr_rxtx_proc_t proc;
laurent's avatar
laurent committed
163 164 165 166 167 168 169 170 171 172 173 174 175
  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) {
176 177
    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
178 179 180
           oai_exit, openair0_cfg[0].rx_num_channels);

    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
181 182
      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
183 184
      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;

185
      if (UE->frame_parms.frame_type == FDD) 
laurent's avatar
laurent committed
186
        openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
187
      else 
laurent's avatar
laurent committed
188 189 190 191 192
        openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
    }

    sync_mode = pbch;
  } else {
193 194
    LOG_E(PHY,"Fixme!\n");
    /*
laurent's avatar
laurent committed
195 196 197 198 199 200 201 202 203
    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;
    }
204
    */
laurent's avatar
laurent committed
205 206 207 208 209
  }

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

  switch (sync_mode) {
210
    /*
laurent's avatar
laurent committed
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
    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;
239
    */
laurent's avatar
laurent committed
240 241 242
    case pbch:
      LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);

243
      if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) {
laurent's avatar
laurent committed
244
        freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
245
        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
246
                         round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0);
247
        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
248 249 250
              hw_slot_offset,
              freq_offset,
              UE->rx_total_gain_dB,
251 252
              UE->frame_parms.dl_CarrierFreq+freq_offset,
              UE->frame_parms.ul_CarrierFreq+freq_offset,
laurent's avatar
laurent committed
253 254 255 256 257 258 259 260 261 262 263 264
              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] =
265 266
            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
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
        }

        // 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;
298 299 300 301 302 303

          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
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        }

        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;
331
          LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %lu, UL %lu)\n",
laurent's avatar
laurent committed
332 333
                freq_offset,
                UE->rx_total_gain_dB,
334 335
                UE->frame_parms.dl_CarrierFreq+freq_offset,
                UE->frame_parms.ul_CarrierFreq+freq_offset );
laurent's avatar
laurent committed
336 337

          for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
338 339
            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
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
            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
359
void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
360 361 362
  uint32_t nb_rb, start_rb;
  uint8_t nb_symb_sch, start_symbol, mcs, precod_nbr_layers, harq_pid, rvidx;
  uint16_t n_rnti;
363

Florian Kaltenberger's avatar
Florian Kaltenberger committed
364 365 366 367
  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;

  // program PUSCH. this should actually be done by the MAC upon reception of an UL DCI
368
  if (proc->nr_tti_tx == 8 || UE->frame_parms.frame_type == FDD){
Florian Kaltenberger's avatar
Florian Kaltenberger committed
369

370 371 372 373 374 375
    dcireq.module_id = UE->Mod_id;
    dcireq.gNB_index = 0;
    dcireq.cc_id     = 0;
    dcireq.frame     = proc->frame_rx;
    dcireq.slot      = proc->nr_tti_rx;

Florian Kaltenberger's avatar
Florian Kaltenberger committed
376
    scheduled_response.dl_config = NULL;
377
    scheduled_response.ul_config = &dcireq.ul_config_req;
378 379 380 381 382
    scheduled_response.tx_request = NULL;
    scheduled_response.module_id = UE->Mod_id;
    scheduled_response.CC_id     = 0;
    scheduled_response.frame = proc->frame_rx;
    scheduled_response.slot  = proc->nr_tti_rx;
383 384 385
    //--------------------------Temporary configuration-----------------------------//
    n_rnti = 0x1234;
    nb_rb = 50;
386
    start_rb = 0;
387 388 389 390 391 392
    nb_symb_sch = 12;
    start_symbol = 2;
    precod_nbr_layers = 1;
    mcs = 9;
    harq_pid = 0;
    rvidx = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
393
    //------------------------------------------------------------------------------//
394

395
    scheduled_response.ul_config->slot = 8;
396
    scheduled_response.ul_config->number_pdus = 1;
397
    scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
398 399 400 401 402 403 404 405 406 407
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.rnti = n_rnti;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.number_rbs = nb_rb;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.start_rb = start_rb;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.number_symbols = nb_symb_sch;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.start_symbol = start_symbol;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.mcs = mcs;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.ndi = 0;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.rv = rvidx;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.n_layers = precod_nbr_layers;
    scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.harq_process_nbr = harq_pid;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421

    nr_ue_scheduled_response(&scheduled_response);
    
    if (UE->mode != loop_through_memory) {
      uint8_t thread_id = PHY_vars_UE_g[UE->Mod_id][0]->current_thread_id[proc->nr_tti_tx];
      phy_procedures_nrUE_TX(UE,proc,0,thread_id);
    }
  }
}

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

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
422
  uint8_t  ssb_period = UE->nrUE_config.ssb_table.ssb_period; 
Florian Kaltenberger's avatar
Florian Kaltenberger committed
423 424 425

  //program DCI for slot 1
  //TODO: all of this has to be moved to the MAC!!!
Florian Kaltenberger's avatar
Florian Kaltenberger committed
426
  if (proc->nr_tti_rx == NR_DOWNLINK_SLOT || UE->frame_parms.frame_type == FDD){
Florian Kaltenberger's avatar
Florian Kaltenberger committed
427 428 429 430 431 432 433 434 435 436 437 438 439
    dcireq.module_id = UE->Mod_id;
    dcireq.gNB_index = 0;
    dcireq.cc_id     = 0;
    dcireq.frame     = proc->frame_rx;
    dcireq.slot      = proc->nr_tti_rx;
    nr_ue_dcireq(&dcireq); //to be replaced with function pointer later

    // we should have received a DL DCI here, so configure DL accordingly
    scheduled_response.dl_config = &dcireq.dl_config_req;
    scheduled_response.ul_config = NULL;
    scheduled_response.tx_request = NULL;
    scheduled_response.module_id = UE->Mod_id;
    scheduled_response.CC_id     = 0;
440 441 442 443 444 445 446
    if (!((proc->frame_rx)%(1<<(ssb_period-1)))) {
      if(proc->frame_rx > dcireq.dl_config_req.sfn)
        UE->frame_gap = proc->frame_rx - dcireq.dl_config_req.sfn;
      if(proc->frame_rx < dcireq.dl_config_req.sfn)
        UE->frame_gap = dcireq.dl_config_req.sfn - proc->frame_rx;
      proc->frame_rx = dcireq.dl_config_req.sfn;
    }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
447
    scheduled_response.frame = proc->frame_rx;
cig's avatar
cig committed
448
    scheduled_response.slot = proc->nr_tti_rx;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
449

450
    nr_ue_scheduled_response(&scheduled_response);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
451
  }
452

Florian Kaltenberger's avatar
Florian Kaltenberger committed
453 454
  // Process Rx data for one sub-frame
  if ( proc->nr_tti_rx >=0 && proc->nr_tti_rx <= 1 ) {
laurent's avatar
laurent committed
455 456 457
#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
458
    uint64_t a=rdtsc();
459
    phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode);
460
    LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500);
461
    //printf(">>> nr_ue_pdcch_procedures ended\n");
laurent's avatar
laurent committed
462
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
463 464 465 466 467 468 469 470 471
    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);
      pdcp_fifo_flush_sdus(&ctxt);
    }
laurent's avatar
laurent committed
472 473
  }

474 475 476
  
  // no UL for now
  /*
laurent's avatar
laurent committed
477 478 479 480 481 482 483 484 485 486 487 488
  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);
    }
  }
489
  */
laurent's avatar
laurent committed
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
}

/*!
 * \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) {
  processingData_t *rxtxD=(processingData_t *) arg;
  UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
  PHY_VARS_NR_UE    *UE   = rxtxD->UE;

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
  uint8_t gNB_id = 0;

  // 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) {

    if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot){
      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;
      //}
    }
  }
534

Florian Kaltenberger's avatar
Florian Kaltenberger committed
535
  processSlotRX(UE, proc);
laurent's avatar
laurent committed
536

Florian Kaltenberger's avatar
Florian Kaltenberger committed
537
  processSlotTX(UE, proc);
laurent's avatar
laurent committed
538 539 540

}

541
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
laurent's avatar
laurent committed
542 543 544
  void *dummy_tx[UE->frame_parms.nb_antennas_tx];

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

547 548 549 550 551 552 553
  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
554 555 556 557 558

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

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

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
  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]);
586
    }
laurent's avatar
laurent committed
587 588 589 590 591
  }

}

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

laurent's avatar
laurent committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
    LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
    void *dummy_tx[UE->frame_parms.nb_antennas_tx];

    for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
      dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);

    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 ;
      AssertFatal(unitTransfer ==
                  UE->rfdevice.trx_read_func(&UE->rfdevice,
                                             timestamp,
                                             (void **)UE->common_vars.rxdata,
                                             unitTransfer,
                                             UE->frame_parms.nb_antennas_rx),"");
    }

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

laurent's avatar
laurent committed
612 613 614
}

int computeSamplesShift(PHY_VARS_NR_UE *UE) {
615
  if (IS_SOFTMODEM_RFSIM) {
laurent's avatar
laurent committed
616 617 618 619 620 621
    LOG_E(PHY,"SET rx_offset %d \n",UE->rx_offset);
    //UE->rx_offset_diff=0;
    return 0;
  }

  // compute TO compensation that should be applied for this frame
622 623 624
  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
625
    return -1 ;
626
  }
laurent's avatar
laurent committed
627

628 629 630
  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
631
    return 1;
632
  }
laurent's avatar
laurent committed
633

laurent's avatar
laurent committed
634 635 636
  return 0;
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
  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;
}

inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
  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
653
void *UE_thread(void *arg) {
laurent's avatar
laurent committed
654
  //this thread should be over the processing thread to keep in real time
laurent's avatar
laurent committed
655 656 657 658 659 660 661 662 663 664 665 666
  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;
667 668
  notifiedFIFO_t freeBlocks;
  initNotifiedFIFO_nothreadSafe(&freeBlocks);
669 670
  NR_UE_MAC_INST_t *mac = get_mac_inst(0);

laurent's avatar
laurent committed
671

672 673 674
  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
675

laurent's avatar
fixes  
laurent committed
676
  bool syncRunning=false;
677
  const int nb_slot_frame = UE->frame_parms.slots_per_frame;
678
  int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
laurent's avatar
laurent committed
679 680

  while (!oai_exit) {
681 682 683 684 685 686 687
    if (syncRunning) {
      notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool);

      if (res) {
        syncRunning=false;
        syncData_t *tmp=(syncData_t *)NotifiedFifoData(res);
        // shift the frame index with all the frames we trashed meanwhile we perform the synch search
688 689
        decoded_frame_rx=((((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx) +
                         (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER;
690
        delNotifiedFIFO_elt(res);
laurent's avatar
laurent committed
691
      } else {
692
        readFrame(UE, &timestamp, true);
693
        trashed_frames+=2;
694
        continue;
laurent's avatar
laurent committed
695
      }
696
    }
laurent's avatar
laurent committed
697

698
    AssertFatal( !syncRunning, "At this point synchronization can't be running\n");
699 700

    if (!UE->is_synchronized) {
701
      readFrame(UE, &timestamp, false);
702 703 704 705 706 707 708
      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
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
      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
724 725
      // we have the decoded frame index in the return of the synch process
      // and we shifted above to the first slot of next frame
726
      decoded_frame_rx++;
727
      // we do ++ first in the regular processing, so it will be begin of frame;
728
      absolute_slot=decoded_frame_rx*nb_slot_frame -1;
laurent's avatar
laurent committed
729 730 731
      continue;
    }

732

laurent's avatar
laurent committed
733
    absolute_slot++;
734 735 736 737
    // 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
738
    thread_idx = absolute_slot % RX_NB_TH;
laurent's avatar
fixes  
laurent committed
739
    int slot_nr = absolute_slot % nb_slot_frame;
740 741 742 743
    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
744
    // update thread index for received subframe
745
    curMsg->UE->current_thread_id[slot_nr] = thread_idx;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
746 747
    curMsg->proc.CC_id = 0;
    curMsg->proc.nr_tti_rx= slot_nr;
748
    curMsg->proc.subframe_rx=slot_nr/(nb_slot_frame/10);
749 750
    curMsg->proc.nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
    curMsg->proc.subframe_tx=curMsg->proc.nr_tti_rx;
751 752
    curMsg->proc.frame_rx = ((absolute_slot/nb_slot_frame)+UE->frame_gap) % MAX_FRAME_NUMBER;
    curMsg->proc.frame_tx = (((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame)+UE->frame_gap) % MAX_FRAME_NUMBER;
753
    curMsg->proc.decoded_frame_rx=-1;
Hongzhi Wang's avatar
Hongzhi Wang committed
754 755 756
    //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
757
    /*uint32_t total_gain_dB_prev = 0;
Hongzhi Wang's avatar
Hongzhi Wang committed
758 759
    if (total_gain_dB_prev != UE->rx_total_gain_dB) {
		total_gain_dB_prev = UE->rx_total_gain_dB;
Hongzhi Wang's avatar
Hongzhi Wang committed
760
        openair0_cfg[0].rx_gain[0] = UE->rx_total_gain_dB;
Hongzhi Wang's avatar
Hongzhi Wang committed
761
        UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&openair0_cfg[0]);
Hongzhi Wang's avatar
Hongzhi Wang committed
762
    }*/
Hongzhi Wang's avatar
Hongzhi Wang committed
763
#endif
laurent's avatar
laurent committed
764

Sakthivel Velumani's avatar
Sakthivel Velumani committed
765
    int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
laurent's avatar
laurent committed
766
    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
Sakthivel Velumani's avatar
Sakthivel Velumani committed
767
      rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
768
               get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
laurent's avatar
laurent committed
769 770

    for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
771 772
      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
773 774 775 776

    int readBlockSize, writeBlockSize;

    if (slot_nr<(nb_slot_frame - 1)) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
777
      readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
778
      writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms);
laurent's avatar
laurent committed
779 780
    } else {
      UE->rx_offset_diff = computeSamplesShift(UE);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
781
      readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
laurent's avatar
laurent committed
782
                    UE->rx_offset_diff;
783
      writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms) -
laurent's avatar
laurent committed
784 785 786 787 788 789 790 791 792
                     UE->rx_offset_diff;
    }

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

laurent's avatar
laurent committed
794 795 796
    AssertFatal( writeBlockSize ==
                 UE->rfdevice.trx_write_func(&UE->rfdevice,
                     timestamp+
797
                     UE->frame_parms.get_samples_slot_timestamp(slot_nr,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
798
                     &UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp -
laurent's avatar
laurent committed
799 800 801 802
                     openair0_cfg[0].tx_sample_advance,
                     txp,
                     writeBlockSize,
                     UE->frame_parms.nb_antennas_tx,
803
                     1),"");
laurent's avatar
laurent committed
804 805 806

    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
807
      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
808 809 810 811 812 813 814 815 816 817 818 819

      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);
    }

820
    curMsg->proc.timestamp_tx = timestamp+
821
                                UE->frame_parms.get_samples_slot_timestamp(slot_nr,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
822 823
                                &UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp;

laurent's avatar
fixes  
laurent committed
824
    notifiedFIFO_elt_t *res;
laurent's avatar
laurent committed
825

826
    while (nbSlotProcessing >= RX_NB_TH) {
827
      if ( (res=tryPullTpool(&nf, Tpool)) != NULL ) {
laurent's avatar
laurent committed
828 829
        nbSlotProcessing--;
        processingData_t *tmp=(processingData_t *)res->msgData;
laurent's avatar
fixes  
laurent committed
830

laurent's avatar
laurent committed
831 832
        if (tmp->proc.decoded_frame_rx != -1)
          decoded_frame_rx=tmp->proc.decoded_frame_rx;
laurent's avatar
fixes  
laurent committed
833

834
        pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
835
      }
laurent's avatar
laurent committed
836

laurent's avatar
laurent committed
837 838 839
      usleep(200);
    }

840 841
    if (  decoded_frame_rx != curMsg->proc.frame_rx &&
          ((decoded_frame_rx+1) % MAX_FRAME_NUMBER) != curMsg->proc.frame_rx )
842
      LOG_D(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
843
            decoded_frame_rx, curMsg->proc.frame_rx  );
laurent's avatar
laurent committed
844

845
    nbSlotProcessing++;
846 847
    msgToPush->key=slot_nr;
    pushTpool(Tpool, msgToPush);
laurent's avatar
laurent committed
848

849
    if (IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) {  //getenv("RFSIMULATOR")
laurent's avatar
laurent committed
850 851 852 853
      // 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
854
      nbSlotProcessing--;
laurent's avatar
fixes  
laurent committed
855 856 857 858 859
      processingData_t *tmp=(processingData_t *)res->msgData;

      if (tmp->proc.decoded_frame_rx != -1)
        decoded_frame_rx=tmp->proc.decoded_frame_rx;

860
      pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
laurent's avatar
laurent committed
861 862 863 864 865 866
    }
  } // while !oai_exit

  return NULL;
}

867
void init_NR_UE(int nb_inst, char* rrc_config_path) {
laurent's avatar
laurent committed
868 869
  int inst;
  NR_UE_MAC_INST_t *mac_inst;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
870 871
  NR_UE_RRC_INST_t* rrc_inst;
  
laurent's avatar
laurent committed
872
  for (inst=0; inst < nb_inst; inst++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
873 874 875
    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");
876 877 878 879 880 881 882 883 884 885 886
  }
}

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
887
    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
888
    threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
889 890

#ifdef UE_DLSCH_PARALLELISATION
891
    pthread_t dlsch0_threads;
892 893 894
    threadCreate(&dlsch0_threads, dlsch_thread, (void *)UE, "DLthread", -1, OAI_PRIORITY_RT_MAX-1);
#endif

laurent's avatar
laurent committed
895 896 897
  }
}

898 899 900 901 902 903 904 905 906 907 908
/* 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();
}

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