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

/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch.c
* \brief Top-level routines for transmission of the PUSCH TS 38.211 v 15.4.0
* \author Khalid Ahmed
* \date 2019
* \version 0.1
* \company Fraunhofer IIS
* \email: khalid.ahmed@iis.fraunhofer.de
* \note
* \warning
*/
#include <stdint.h>
33
#include "PHY/NR_REFSIG/dmrs_nr.h"
adk's avatar
adk committed
34
#include "PHY/NR_REFSIG/ptrs_nr.h"
35
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
36 37
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/MODULATION/nr_modulation.h"
38
#include "PHY/MODULATION/modulation_common.h"
Khalid Ahmed's avatar
Khalid Ahmed committed
39
#include "common/utils/assertions.h"
40
#include "common/utils/LOG/vcd_signal_dumper.h"
Khalid Ahmed's avatar
Khalid Ahmed committed
41
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
42
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
Khalid Ahmed's avatar
Khalid Ahmed committed
43
#include "PHY/defs_nr_common.h"
44
#include "PHY/TOOLS/tools_defs.h"
45
#include "executables/nr-softmodem.h"
46
#include "executables/softmodem-common.h"
matzakos's avatar
matzakos committed
47
#include "LAYER2/NR_MAC_UE/mac_proto.h"
48 49

//#define DEBUG_SCFDMA
50
//#define DEBUG_PUSCH_MAPPING
51
//#define DEBUG_MAC_PDU
52

53
//extern int32_t uplink_counter;
54

Khalid Ahmed's avatar
Khalid Ahmed committed
55
void nr_pusch_codeword_scrambling(uint8_t *in,
56
                         uint32_t size,
Khalid Ahmed's avatar
Khalid Ahmed committed
57 58 59 60 61
                         uint32_t Nid,
                         uint32_t n_RNTI,
                         uint32_t* out) {

  uint8_t reset, b_idx;
Khalid Ahmed's avatar
Khalid Ahmed committed
62
  uint32_t x1, x2, s=0, temp_out;
Khalid Ahmed's avatar
Khalid Ahmed committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76

  reset = 1;
  x2 = (n_RNTI<<15) + Nid;

  for (int i=0; i<size; i++) {
    b_idx = i&0x1f;
    if (b_idx==0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
      if (i)
        out++;
    }
    if (in[i]==NR_PUSCH_x)
      *out ^= 1<<b_idx;
Khalid Ahmed's avatar
Khalid Ahmed committed
77 78 79 80 81 82 83 84 85 86
    else if (in[i]==NR_PUSCH_y){
      if (b_idx!=0)
        *out ^= (*out & (1<<(b_idx-1)))<<1;
      else{

        temp_out = *(out-1);
        *out ^= temp_out>>31;

      }
    }
Khalid Ahmed's avatar
Khalid Ahmed committed
87 88 89 90 91
    else
      *out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
    //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
  }

92
}
93

94
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
95
                               unsigned char harq_pid,
96
                               uint8_t frame,
97 98
                               uint8_t slot,
                               uint8_t thread_id,
99
                               int gNB_id) {
100

101
  uint32_t available_bits;
102
  uint8_t mod_order, cwd_index, num_of_codewords, l;
103 104 105 106 107
  uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5];
  uint32_t ***pusch_dmrs;
  int16_t **tx_layers;
  int32_t **txdataF;
  uint16_t start_sc, start_rb;
108
  int8_t Wf[2], Wt[2], l_prime[2], delta;
adk's avatar
adk committed
109
  uint16_t n_dmrs, code_rate, number_dmrs_symbols, k;
110
  uint8_t dmrs_type;
111 112 113
  int ap, start_symbol, Nid_cell, i;
  int sample_offsetF, N_RE_prime, N_PRB_oh;
  uint16_t n_rnti;
114
  uint8_t data_existing =0;
adk's avatar
adk committed
115 116
  uint8_t L_ptrs, K_ptrs; // PTRS parameters
  uint16_t beta_ptrs; // PTRS parameter related to power control
117 118 119 120

  NR_UE_ULSCH_t *ulsch_ue;
  NR_UL_UE_HARQ_t *harq_process_ul_ue;
  NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
121
  NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][gNB_id];
122
  uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES];
adk's avatar
adk committed
123
  ptrs_UplinkConfig_t *ptrs_Uplink_Config = &UE->pusch_config.dmrs_UplinkConfig.ptrs_UplinkConfig;
124 125

  num_of_codewords = 1; // tmp assumption
126 127 128
  n_rnti = 0x1234;
  Nid_cell = 0;
  N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
129
  number_dmrs_symbols = 0;
130
  uint8_t mapping_type = UE->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType;
131

132 133
  for (cwd_index = 0;cwd_index < num_of_codewords; cwd_index++) {

134
    ulsch_ue = UE->ulsch[thread_id][gNB_id][cwd_index];
135 136
    harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid];

137 138 139
    start_symbol = harq_process_ul_ue->start_symbol;

    for (i = start_symbol; i < start_symbol + harq_process_ul_ue->number_of_symbols; i++)
140
      number_dmrs_symbols += is_dmrs_symbol((mapping_type)?i-start_symbol:i,
141 142 143 144 145 146
                                            0,
                                            0,
                                            0,
                                            0,
                                            0,
                                            harq_process_ul_ue->number_of_symbols,
147
                                            UE->pusch_config.dmrs_UplinkConfig.pusch_dmrs_type,
148 149
                                            frame_parms->ofdm_symbol_size);

150 151
    ulsch_ue->length_dmrs = number_dmrs_symbols; // pusch.MaxLenght is redundant here as number_dmrs_symbols
                                                 // contains all dmrs symbols even for double symbol dmrs
152 153
    ulsch_ue->rnti        = n_rnti;
    ulsch_ue->Nid_cell    = Nid_cell;
154
    ulsch_ue->nb_re_dmrs  = ((UE->pusch_config.dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4);
155

156
    N_RE_prime = NR_NB_SC_PER_RB*harq_process_ul_ue->number_of_symbols - ulsch_ue->nb_re_dmrs*number_dmrs_symbols - N_PRB_oh;
157 158 159

    harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*harq_process_ul_ue->nb_rb*num_of_codewords;

160 161 162 163 164 165 166 167 168
    mod_order      = nr_get_Qm_ul(harq_process_ul_ue->mcs, 0);
    code_rate      = nr_get_code_rate_ul(harq_process_ul_ue->mcs, 0);

    harq_process_ul_ue->TBS = nr_compute_tbs(mod_order, 
                                             code_rate,
                                             harq_process_ul_ue->nb_rb,
                                             harq_process_ul_ue->number_of_symbols,
                                             ulsch_ue->nb_re_dmrs*ulsch_ue->length_dmrs,
                                             0,
169
                                             harq_process_ul_ue->Nl);
170

171 172
    uint8_t access_mode = SCHEDULED_ACCESS;

173 174
    //-----------------------------------------------------//
    // to be removed later when MAC is ready
175

176
    if (harq_process_ul_ue != NULL){
177
      data_existing = 0;
178 179 180 181

    	if (IS_SOFTMODEM_NOS1){
    		data_existing = nr_ue_get_sdu(UE->Mod_id, UE->CC_id, frame,
    				slot, 0, ulsch_input_buffer, harq_process_ul_ue->TBS/8, &access_mode);
182
    		//IP traffic to be transmitted
183 184 185
    		if(data_existing){
    			//harq_process_ul_ue->a = (unsigned char*)calloc(harq_process_ul_ue->TBS/8, sizeof(unsigned char));
    			memcpy(harq_process_ul_ue->a, ulsch_input_buffer, harq_process_ul_ue->TBS/8);
186 187

    			#ifdef DEBUG_MAC_PDU
188
    				LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", harq_process_ul_ue->TBS/8);
189 190 191 192 193 194
    				for (i = 0; i < harq_process_ul_ue->TBS / 8; i++) {
    					printf("0x%02x",harq_process_ul_ue->a[i]);
    				}
    				printf("\n");
				#endif
    		}
195 196
      }
      //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
197
      if (!IS_SOFTMODEM_NOS1 || !data_existing) {
198 199 200 201 202 203 204 205 206 207 208
        //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
        //and block this traffic from being forwarded to the upper layers at the gNB
        uint16_t payload_offset = 5;
        LOG_D(PHY, "Random data to be tranmsitted: \n");
        //Give the header bytes some dummy value in order to block the random packet at the MAC layer of the receiver
        for (i = 0; i<payload_offset; i++)
          harq_process_ul_ue->a[i] = 0;

        for (i = payload_offset; i < harq_process_ul_ue->TBS / 8; i++) {
          harq_process_ul_ue->a[i] = (unsigned char) rand();
          //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
209
        }
210
      }
211 212 213 214 215 216
    } else {
      LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n");
      return;
    }

    //-----------------------------------------------------//
217

218 219 220
    /////////////////////////ULSCH coding/////////////////////////
    ///////////

221

222 223 224 225 226 227 228 229
    nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid);

    ///////////
    ////////////////////////////////////////////////////////////////////

    /////////////////////////ULSCH scrambling/////////////////////////
    ///////////

230
    mod_order      = nr_get_Qm_ul(harq_process_ul_ue->mcs, 0);
231 232

    available_bits = nr_get_G(harq_process_ul_ue->nb_rb,
Ahmed Hussein's avatar
Ahmed Hussein committed
233
                              harq_process_ul_ue->number_of_symbols,
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
                              ulsch_ue->nb_re_dmrs,
                              ulsch_ue->length_dmrs,
                              mod_order,
                              1);

    memset(scrambled_output[cwd_index], 0, ((available_bits>>5)+1)*sizeof(uint32_t));

    nr_pusch_codeword_scrambling(ulsch_ue->g,
                                 available_bits,
                                 ulsch_ue->Nid_cell,
                                 ulsch_ue->rnti,
                                 scrambled_output[cwd_index]); // assume one codeword for the moment


    /////////////
    //////////////////////////////////////////////////////////////////////////

    /////////////////////////ULSCH modulation/////////////////////////
    ///////////

    nr_modulation(scrambled_output[cwd_index], // assume one codeword for the moment
                  available_bits,
                  mod_order,
                  (int16_t *)ulsch_ue->d_mod);

259

260
    // pusch_transform_precoding(ulsch_ue, frame_parms, harq_pid);
261 262 263 264 265

    ///////////
    ////////////////////////////////////////////////////////////////////////


266
  //}
267 268 269 270 271
  }

  /////////////////////////DMRS Modulation/////////////////////////
  ///////////
  pusch_dmrs = UE->nr_gold_pusch_dmrs[slot];
272
  n_dmrs = (harq_process_ul_ue->nb_rb*ulsch_ue->nb_re_dmrs*ulsch_ue->length_dmrs);
273
  int16_t mod_dmrs[n_dmrs<<1];
274
  dmrs_type = UE->pusch_config.dmrs_UplinkConfig.pusch_dmrs_type;
275 276 277
  ///////////
  ////////////////////////////////////////////////////////////////////////

adk's avatar
adk committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297

  /////////////////////////PTRS parameters' initialization/////////////////////////
  ///////////

  int16_t mod_ptrs[(harq_process_ul_ue->nb_rb/2)*(NR_SYMBOLS_PER_SLOT-1)*2]; // assume maximum number of PTRS per pusch allocation
  K_ptrs = 0; // just to avoid a warning

  if (UE->ptrs_configured == 1) {

    K_ptrs = get_K_ptrs(ptrs_Uplink_Config, harq_process_ul_ue->nb_rb);

    L_ptrs = get_L_ptrs(ptrs_Uplink_Config, harq_process_ul_ue->mcs);

    beta_ptrs = 1; // temp value until power control is implemented

    ulsch_ue->ptrs_symbols = 0;

    set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols,
                      harq_process_ul_ue->number_of_symbols,
                      start_symbol,
298
                      dmrs_type,
adk's avatar
adk committed
299
                      L_ptrs,
300
                      ulsch_ue->length_dmrs,
adk's avatar
adk committed
301 302 303 304 305 306
                      frame_parms->ofdm_symbol_size);
  }

  ///////////
  ////////////////////////////////////////////////////////////////////////////////

307 308 309 310 311
  /////////////////////////ULSCH layer mapping/////////////////////////
  ///////////

  tx_layers = (int16_t **)pusch_ue->txdataF_layers;

312
  nr_ue_layer_mapping(UE->ulsch[thread_id][gNB_id],
313 314 315 316
                   harq_process_ul_ue->Nl,
                   available_bits/mod_order,
                   tx_layers);

317 318 319 320 321 322 323 324 325 326 327 328 329
  ///////////
  ////////////////////////////////////////////////////////////////////////


  //////////////////////// ULSCH transform precoding ////////////////////////
  ///////////

  l_prime[0] = 0; // single symbol ap 0

#ifdef NR_SC_FDMA
  uint32_t nb_re_pusch, nb_re_dmrs_per_rb;
  uint32_t y_offset = 0;

Ahmed Hussein's avatar
Ahmed Hussein committed
330
  for (l = start_symbol; l < start_symbol + harq_process_ul_ue->number_of_symbols; l++) {
331

332
    is_dmrs = is_dmrs_symbol((mapping_type)?l-start_symbol:l,
333 334 335 336 337 338
                             0,
                             0,
                             0,
                             0,
                             0,
                             harq_process_ul_ue->number_of_symbols,
339
                             dmrs_type,
340 341 342 343
                             frame_parms->ofdm_symbol_size);

    if (is_dmrs == 1)
      nb_re_dmrs_per_rb = ulsch_ue->nb_re_dmrs;
344 345 346 347 348 349 350 351 352 353 354 355
    else
      nb_re_dmrs_per_rb = 0;
    
    nb_re_pusch = harq_process_ul_ue->nb_rb * (NR_NB_SC_PER_RB - nb_re_dmrs_per_rb);

    nr_dft(&ulsch_ue->y[y_offset], &((int32_t*)tx_layers[0])[y_offset], nb_re_pusch);

    y_offset = y_offset + nb_re_pusch;
  }
#else
  memcpy(ulsch_ue->y, tx_layers[0], (available_bits/mod_order)*sizeof(int32_t));
#endif
356 357 358 359

  ///////////
  ////////////////////////////////////////////////////////////////////////

360 361


362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
  /////////////////////////ULSCH RE mapping/////////////////////////
  ///////////

  txdataF = UE->common_vars.txdataF;

  start_rb = harq_process_ul_ue->first_rb;
  start_sc = frame_parms->first_carrier_offset + start_rb*NR_NB_SC_PER_RB;

  if (start_sc >= frame_parms->ofdm_symbol_size)
    start_sc -= frame_parms->ofdm_symbol_size;

  for (ap=0; ap<harq_process_ul_ue->Nl; ap++) {

    // DMRS params for this ap
    get_Wt(Wt, ap, dmrs_type);
    get_Wf(Wf, ap, dmrs_type);
    delta = get_delta(ap, dmrs_type);
379
    
380

381
    uint8_t k_prime=0;
adk's avatar
adk committed
382
    uint8_t is_dmrs, is_ptrs;
383
    uint8_t l_ref;
adk's avatar
adk committed
384
    uint16_t m=0, n=0, dmrs_idx=0, ptrs_idx = 0;
385

Ahmed Hussein's avatar
Ahmed Hussein committed
386
    for (l=start_symbol; l<start_symbol+harq_process_ul_ue->number_of_symbols; l++) {
387 388

      k = start_sc;
Khalid Ahmed's avatar
Khalid Ahmed committed
389
      n = 0;
390
      dmrs_idx = 0;
391
      l_ref = (mapping_type) ? l-start_symbol : l;
392 393 394 395 396

      for (i=0; i<harq_process_ul_ue->nb_rb*NR_NB_SC_PER_RB; i++) {

        sample_offsetF = l*frame_parms->ofdm_symbol_size + k;

Khalid Ahmed's avatar
Khalid Ahmed committed
397
        is_dmrs = 0;
adk's avatar
adk committed
398
        is_ptrs = 0;
Khalid Ahmed's avatar
Khalid Ahmed committed
399

400
        is_dmrs = is_dmrs_symbol(l_ref,
Khalid Ahmed's avatar
Khalid Ahmed committed
401 402 403 404 405 406
                                 k,
                                 start_sc,
                                 k_prime,
                                 n,
                                 delta,
                                 harq_process_ul_ue->number_of_symbols,
407
                                 dmrs_type,
Khalid Ahmed's avatar
Khalid Ahmed committed
408 409
                                 frame_parms->ofdm_symbol_size);

adk's avatar
adk committed
410 411 412 413 414 415 416 417 418 419 420 421
        if (UE->ptrs_configured == 1){
          is_ptrs = is_ptrs_symbol(l,
                                   k,
                                   ulsch_ue->rnti,
                                   harq_process_ul_ue->nb_rb,
                                   harq_process_ul_ue->number_of_symbols,
                                   ap,
                                   K_ptrs,
                                   ulsch_ue->ptrs_symbols,
                                   start_sc,
                                   frame_parms->ofdm_symbol_size,
                                   UE->pusch_config.dmrs_UplinkConfig.pusch_dmrs_type,
422
                                   ptrs_Uplink_Config->resourceElementOffset);
adk's avatar
adk committed
423 424
        }

Khalid Ahmed's avatar
Khalid Ahmed committed
425
        if (is_dmrs == 1) {
426

adk's avatar
adk committed
427 428 429
          if (k == start_sc){
            nr_modulation(pusch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
          }
430 431 432 433 434

          ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx<<1]) >> 15;
          ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;

          #ifdef DEBUG_PUSCH_MAPPING
435
            printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
436 437 438 439
            dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1],
            ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1]);
          #endif

440

441 442 443 444 445
          dmrs_idx++;
          k_prime++;
          k_prime&=1;
          n+=(k_prime)?0:1;

adk's avatar
adk committed
446 447 448 449 450 451 452 453 454 455 456 457
        }  else if (is_ptrs == 1) {

          if (k == start_sc){
            nr_modulation(pusch_dmrs[l][0], harq_process_ul_ue->nb_rb/2, DMRS_MOD_ORDER, mod_ptrs);
          }

          ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (beta_ptrs*AMP*mod_ptrs[ptrs_idx<<1]) >> 15;
          ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (beta_ptrs*AMP*mod_ptrs[(ptrs_idx<<1) + 1]) >> 15;

          ptrs_idx++;

          } else {
458

459 460
          ((int16_t*)txdataF[ap])[(sample_offsetF)<<1]       = ((int16_t *) ulsch_ue->y)[m<<1];
          ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = ((int16_t *) ulsch_ue->y)[(m<<1) + 1];
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475

          #ifdef DEBUG_PUSCH_MAPPING
            printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
            m, l, k, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1],
            ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1]);
          #endif

          m++;
        }

        if (++k >= frame_parms->ofdm_symbol_size)
          k -= frame_parms->ofdm_symbol_size;
      }
    }
  }
476

477 478
  //}

479 480 481
  ///////////
  ////////////////////////////////////////////////////////////////////////

482
  LOG_D(PHY, "Is data existing ?: %d \n", data_existing);
483 484 485 486
}


uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
487
                                      uint8_t harq_pid,
488
                                      uint8_t slot,
489 490
                                      uint8_t thread_id,
                                      uint8_t gNB_id,
491 492 493 494 495
                                      NR_DL_FRAME_PARMS *frame_parms) {

  int tx_offset, ap;
  int32_t **txdata;
  int32_t **txdataF;
496
  int timing_advance;
497
  uint8_t Nl = UE->ulsch[thread_id][gNB_id][0]->harq_processes[harq_pid]->Nl; // cw 0
498 499 500 501

  /////////////////////////IFFT///////////////////////
  ///////////

502 503 504 505 506 507
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)  || defined(OAI_ADRV9371_ZC706)
  timing_advance = UE->timing_advance;
#else
  timing_advance = 0;
#endif

508
  tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0) - timing_advance;
509 510 511 512

  if (tx_offset < 0)
    tx_offset += frame_parms->samples_per_frame;

513 514 515 516 517 518 519
  // clear the transmit data array for the current subframe
  /*for (int aa=0; aa<UE->frame_parms.nb_antennas_tx; aa++) {
	  memset(&UE->common_vars.txdata[aa][tx_offset],0,UE->frame_parms.samples_per_slot*sizeof(int32_t));
	  //memset(&UE->common_vars.txdataF[aa][tx_offset],0,UE->frame_parms.samples_per_slot*sizeof(int32_t));
  }*/


520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
  txdata = UE->common_vars.txdata;
  txdataF = UE->common_vars.txdataF;

  for (ap = 0; ap < Nl; ap++) {
      if (frame_parms->Ncp == 1) { // extended cyclic prefix
  PHY_ofdm_mod(txdataF[ap],
         &txdata[ap][tx_offset],
         frame_parms->ofdm_symbol_size,
         12,
         frame_parms->nb_prefix_samples,
         CYCLIC_PREFIX);
      } else { // normal cyclic prefix
  nr_normal_prefix_mod(txdataF[ap],
           &txdata[ap][tx_offset],
           14,
           frame_parms);
      }
    }
538

539 540 541 542
  ///////////
  ////////////////////////////////////////////////////
  return 0;
}