phy_procedures_nr_gNB.c 24.4 KB
Newer Older
Guy De Souza's avatar
Guy De Souza committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

22 23
#include "PHY/phy_extern.h"
#include "PHY/defs_gNB.h"
Guy De Souza's avatar
Guy De Souza committed
24
#include "sched_nr.h"
25
#include "PHY/NR_REFSIG/dmrs_nr.h"
26
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
Guy De Souza's avatar
Guy De Souza committed
27
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
28
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
29
#include "PHY/NR_TRANSPORT/nr_dci.h"
30
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
Francesco Mani's avatar
Francesco Mani committed
31
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
32
#include "SCHED/sched_eNB.h"
33
#include "sched_nr.h"
34
#include "SCHED/sched_common_extern.h"
35 36 37
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
#include "fapi_nr_l1.h"
38 39
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
40
#include "PHY/INIT/phy_init.h"
41
#include "PHY/MODULATION/nr_modulation.h"
Guy De Souza's avatar
Guy De Souza committed
42
#include "T.h"
43
#include "executables/nr-softmodem.h"
44
#include "executables/softmodem-common.h"
Guy De Souza's avatar
Guy De Souza committed
45 46 47 48 49 50

#include "assertions.h"
#include "msc.h"

#include <time.h>

51
#include "intertask_interface.h"
Guy De Souza's avatar
Guy De Souza committed
52

53 54
//#define DEBUG_RXDATA

55 56
uint8_t SSB_Table[38]={0,2,4,6,8,10,12,14,254,254,16,18,20,22,24,26,28,30,254,254,32,34,36,38,40,42,44,46,254,254,48,50,52,54,56,58,60,62};

Guy De Souza's avatar
Guy De Souza committed
57
extern uint8_t nfapi_mode;
58

59
void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp) {
60 61 62 63 64 65 66

  uint8_t sco = 0;
  if (((fp->freq_range == nr_FR1) && (cfg->ssb_table.ssb_subcarrier_offset.value<24)) ||
      ((fp->freq_range == nr_FR2) && (cfg->ssb_table.ssb_subcarrier_offset.value<12)) )
    sco = cfg->ssb_table.ssb_subcarrier_offset.value;

  fp->ssb_start_subcarrier = (12 * cfg->ssb_table.ssb_offset_point_a.value + sco);
67
  LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->ssb_table.ssb_offset_point_a.value,sco);
68
}
Guy De Souza's avatar
Guy De Souza committed
69

70
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
71

Guy De Souza's avatar
Guy De Souza committed
72
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
73
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
74
  int **txdataF = gNB->common_vars.txdataF;
75
  uint8_t ssb_index, n_hf;
76
  uint16_t ssb_start_symbol, rel_slot;
77
  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
78 79
  uint16_t slots_per_hf = (fp->slots_per_frame)>>1;

80
  n_hf = fp->half_frame_bit;
81 82

  // if SSB periodicity is 5ms, they are transmitted in both half frames
83
  if ( cfg->ssb_table.ssb_period.value == 0) {
84
    if (slot<slots_per_hf)
85 86 87 88 89
      n_hf=0;
    else
      n_hf=1;
  }

90
  // to set a effective slot number in the half frame where the SSB is supposed to be
91
  rel_slot = (n_hf)? (slot-slots_per_hf) : slot; 
92

93
  LOG_D(PHY,"common_signal_procedures: frame %d, slot %d\n",frame,slot);
Guy De Souza's avatar
Guy De Souza committed
94

95
  if(rel_slot<38 && rel_slot>=0)  { // there is no SSB beyond slot 37
96

97
    for (int i=0; i<2; i++)  {  // max two SSB per frame
98
      
99 100
      ssb_index = i + SSB_Table[rel_slot]; // computing the ssb_index

101
      if ((ssb_index<64) && ((fp->L_ssb >> (63-ssb_index)) & 0x01))  { // generating the ssb only if the bit of L_ssb at current ssb index is 1
102 103 104 105 106
        fp->ssb_index = ssb_index;
        int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp); // computing the starting symbol for current ssb
	ssb_start_symbol = ssb_start_symbol_abs % fp->symbols_per_slot;  // start symbol wrt slot

	nr_set_ssb_first_subcarrier(cfg, fp);  // setting the first subcarrier
107
	
108 109 110
	LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol);
	nr_generate_pss(gNB->d_pss, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
	nr_generate_sss(gNB->d_sss, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
111
	
112 113 114 115
        if (cfg->carrier_config.num_tx_ant.value <= 4)
	  nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
        else
	  nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
116
	
117 118 119 120 121 122 123 124
	nr_generate_pbch(&gNB->pbch,
	                 &gNB->ssb_pdu,
	                 gNB->nr_pbch_interleaver,
			 &txdataF[0][txdataF_offset],
			 AMP,
			 ssb_start_symbol,
			 n_hf, frame, cfg, fp);

125 126
      }
    }
127
  }
Guy De Souza's avatar
Guy De Souza committed
128 129 130
}

void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
131
                           int frame,int slot,
132
                           int do_meas) {
Guy De Souza's avatar
Guy De Souza committed
133 134
  int aa;
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
135
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
136
  int offset = gNB->CC_id;
137
  uint8_t ssb_frame_periodicity = 1;  // every how many frames SSB are generated
138
  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
139

140 141 142
  
  
  if (cfg->ssb_table.ssb_period.value > 1) 
143
    ssb_frame_periodicity = 1 <<(cfg->ssb_table.ssb_period.value -1) ; 
Guy De Souza's avatar
Guy De Souza committed
144

Rakesh's avatar
Rakesh committed
145
  if ((cfg->cell_config.frame_duplex_type.value == TDD) &&
146
      (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return;
Guy De Souza's avatar
Guy De Souza committed
147

Rakesh's avatar
Rakesh committed
148
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1);
149

150
  if (do_meas==1) start_meas(&gNB->phy_proc_tx);
Guy De Souza's avatar
Guy De Souza committed
151 152

  // clear the transmit data array for the current subframe
Raymond Knopp's avatar
Raymond Knopp committed
153
  for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
154
    memset(&gNB->common_vars.txdataF[aa][txdataF_offset],0,fp->samples_per_slot_wCP*sizeof(int32_t));
Guy De Souza's avatar
Guy De Souza committed
155 156
  }

Rakesh's avatar
Rakesh committed
157
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1);
158
  if (nfapi_mode == 0 || nfapi_mode == 1) { 
159
    if ((!(frame%ssb_frame_periodicity)))  // generate SSB only for given frames according to SSB periodicity
160
      nr_common_signal_procedures(gNB,frame, slot);
161
  }
Rakesh's avatar
Rakesh committed
162
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0);
163

164 165
  int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST);
  int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST);
166

167 168 169 170 171
  LOG_D(PHY,"[gNB %d] Frame %d slot %d, pdcch_pdu_id %d, ul_pdcch_pdu_id %d\n",
	gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id);

  if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) {
    LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n",
172
	  gNB->Mod_id, frame, slot,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
173 174
	  gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci,
	  gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci);
175
  
Rakesh's avatar
Rakesh committed
176
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
177

178 179 180
    nr_generate_dci_top(gNB,
			pdcch_pdu_id>=0 ? &gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu : NULL,
			ul_pdcch_pdu_id>=0 ? &gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu : NULL,
181 182 183
			gNB->nr_gold_pdcch_dmrs[slot],
			&gNB->common_vars.txdataF[0][txdataF_offset],
			AMP, *fp);
184 185 186 187 188

    // free up entry in pdcch tables
    if (pdcch_pdu_id>=0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1;
    if (ul_pdcch_pdu_id>=0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1;

Rakesh's avatar
Rakesh committed
189
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
190 191
    if (pdcch_pdu_id >= 0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1;
    if (ul_pdcch_pdu_id >= 0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1;
192
  }
193
 
194
  for (int i=0; i<gNB->num_pdsch_rnti[slot]; i++) {
195
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
196
    LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot);
197
    nr_generate_pdsch(gNB->dlsch[i][0],
198 199 200 201 202 203 204 205 206 207 208 209 210
                      gNB->nr_gold_pdsch_dmrs[slot],
                      gNB->common_vars.txdataF,
                      AMP, frame, slot, fp, 0,
                      &gNB->dlsch_encoding_stats,
                      &gNB->dlsch_scrambling_stats,
                      &gNB->dlsch_modulation_stats,
                      &gNB->tinput,
                      &gNB->tprep,
                      &gNB->tparity,
                      &gNB->toutput,
                      &gNB->dlsch_rate_matching_stats,
                      &gNB->dlsch_interleaving_stats,
                      &gNB->dlsch_segmentation_stats);
211
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
212
  }
213

Rakesh's avatar
Rakesh committed
214
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
Guy De Souza's avatar
Guy De Souza committed
215
}
216 217


218

219
/*
220

221 222
  if ((cfg->subframe_config.duplex_mode.value == TDD) && 
      ((nr_slot_select(fp,frame,slot)&NR_DOWNLINK_SLOT)==SF_DL)) return;
223 224 225

  //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);

226 227
*/

Raymond Knopp's avatar
Raymond Knopp committed
228
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
229
{
230 231
  NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
  nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->ulsch_pdu;
232
  
233
  uint8_t ret;
234
  uint8_t l, number_dmrs_symbols = 0;
235
  uint32_t G;
236
  uint16_t start_symbol, number_symbols, nb_re_dmrs;
237

238 239
  start_symbol = pusch_pdu->start_symbol_index;
  number_symbols = pusch_pdu->nr_of_symbols;
240 241

  for (l = start_symbol; l < start_symbol + number_symbols; l++)
Francesco Mani's avatar
Francesco Mani committed
242
    number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01;
243

244 245
  if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1)
    nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data;
246
  else
247
    nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
248 249

  G = nr_get_G(pusch_pdu->rb_size,
250
               number_symbols,
251
               nb_re_dmrs,
252
               number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
253 254
               pusch_pdu->qam_mod_order,
               pusch_pdu->nrOfLayers);
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
  
  AssertFatal(G>0,"G is 0 : rb_size %d, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
	      pusch_pdu->rb_size,
	      number_symbols,
	      nb_re_dmrs,
	      number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
	      pusch_pdu->qam_mod_order,
	      pusch_pdu->nrOfLayers);
  LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
	pusch_pdu->rb_size,
	number_symbols,
	nb_re_dmrs,
	number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
	pusch_pdu->qam_mod_order,
	pusch_pdu->nrOfLayers);
270 271 272
  //----------------------------------------------------------
  //------------------- ULSCH unscrambling -------------------
  //----------------------------------------------------------
273
  start_meas(&gNB->ulsch_unscrambling_stats);
274 275 276 277 278
  nr_ulsch_unscrambling_optim(gNB->pusch_vars[ULSCH_id]->llr,
			      G,
			      0,
			      pusch_pdu->data_scrambling_id,
			      pusch_pdu->rnti);
279
  stop_meas(&gNB->ulsch_unscrambling_stats);
280 281 282 283
  //----------------------------------------------------------
  //--------------------- ULSCH decoding ---------------------
  //----------------------------------------------------------

284
  start_meas(&gNB->ulsch_decoding_stats);
285
  ret = nr_ulsch_decoding(gNB,
286 287 288 289 290 291 292 293
                          ULSCH_id,
                          gNB->pusch_vars[ULSCH_id]->llr,
                          frame_parms,
                          pusch_pdu,
                          frame_rx,
                          slot_rx,
                          harq_pid,
                          G);
294
  stop_meas(&gNB->ulsch_decoding_stats);
295

296
  if (ret > gNB->ulsch[ULSCH_id][0]->max_ldpc_iterations){
297
    LOG_I(PHY, "ULSCH %d in error\n",ULSCH_id);
298 299
    nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1);
  }
300
  else if(gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->b!=NULL){
301
    LOG_I(PHY, "ULSCH received ok \n");
302
    nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 0);
303
  }
304 305 306
}


307
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag) {
308

309
  pthread_mutex_lock(&gNB->UL_INFO_mutex);
310

311
  int timing_advance_update, cqi;
312
  int sync_pos;
cig's avatar
cig committed
313
  uint16_t mu = gNB->frame_parms.numerology_index;
314
  NR_gNB_ULSCH_t                       *ulsch                 = gNB->ulsch[ULSCH_id][0];
315 316
  NR_UL_gNB_HARQ_t                     *harq_process          = ulsch->harq_processes[harq_pid];

317
  nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
318 319

  //  pdu->data                              = gNB->ulsch[ULSCH_id+1][0]->harq_processes[harq_pid]->b;
cig's avatar
cig committed
320
  sync_pos                               = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC
321
  timing_advance_update                  = sync_pos * (1 << mu);                    // scale by the used scs numerology
322

323
  // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
324 325 326
  switch (gNB->frame_parms.N_RB_DL) {
    case 106: timing_advance_update /= 16; break;
    case 217: timing_advance_update /= 32; break;
327
    case 245: timing_advance_update /= 32; break;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
328
    case 273: timing_advance_update /= 32; break;
cig's avatar
cig committed
329
    case 66:  timing_advance_update /= 12; break;
330 331 332 333 334 335 336 337 338
    default: abort();
  }

  // put timing advance command in 0..63 range
  timing_advance_update += 31;

  if (timing_advance_update < 0)  timing_advance_update = 0;
  if (timing_advance_update > 63) timing_advance_update = 63;

339
  LOG_D(PHY, "Estimated timing advance PUSCH is  = %d, timing_advance_update is %d \n", sync_pos,timing_advance_update);
340

341
  // estimate UL_CQI for MAC (from antenna port 0 only)
342
  int SNRtimes10 = dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]) - (10*gNB->measurements.n0_power_dB[0]);
343

344
  LOG_D(PHY, "Estimated SNR for PUSCH is = %d dB\n", SNRtimes10/10);
345

346 347 348 349 350 351 352 353 354 355 356 357 358 359
  if      (SNRtimes10 < -640) cqi=0;
  else if (SNRtimes10 >  635) cqi=255;
  else                        cqi=(640+SNRtimes10)/5;

  // crc indication
  uint16_t num_crc = gNB->UL_INFO.crc_ind.number_crcs;
  gNB->UL_INFO.crc_ind.crc_list = &gNB->crc_pdu_list[0];
  gNB->UL_INFO.crc_ind.sfn = frame;
  gNB->UL_INFO.crc_ind.slot = slot_rx;

  gNB->crc_pdu_list[num_crc].handle = pusch_pdu->handle;
  gNB->crc_pdu_list[num_crc].rnti = pusch_pdu->rnti;
  gNB->crc_pdu_list[num_crc].harq_id = harq_pid;
  gNB->crc_pdu_list[num_crc].tb_crc_status = crc_flag;
360
  gNB->crc_pdu_list[num_crc].num_cb = pusch_pdu->pusch_data.num_cb;
361 362
  gNB->crc_pdu_list[num_crc].ul_cqi = cqi;
  gNB->crc_pdu_list[num_crc].timing_advance = timing_advance_update;
363
  // in terms of dBFS range -128 to 0 with 0.1 step
364
  gNB->crc_pdu_list[num_crc].rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]));
365 366 367 368 369 370 371 372 373 374 375 376 377

  gNB->UL_INFO.crc_ind.number_crcs++;

  // rx indication
  uint16_t num_rx = gNB->UL_INFO.rx_ind.number_of_pdus;
  gNB->UL_INFO.rx_ind.pdu_list = &gNB->rx_pdu_list[0];
  gNB->UL_INFO.rx_ind.sfn = frame;
  gNB->UL_INFO.rx_ind.slot = slot_rx;
  gNB->rx_pdu_list[num_rx].handle = pusch_pdu->handle;
  gNB->rx_pdu_list[num_rx].rnti = pusch_pdu->rnti;
  gNB->rx_pdu_list[num_rx].harq_id = harq_pid;
  gNB->rx_pdu_list[num_rx].ul_cqi = cqi;
  gNB->rx_pdu_list[num_rx].timing_advance = timing_advance_update;
378
  gNB->rx_pdu_list[num_rx].rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]));
379 380 381 382 383 384
  if (crc_flag)
    gNB->rx_pdu_list[num_rx].pdu_length = 0;
  else {
    gNB->rx_pdu_list[num_rx].pdu_length = harq_process->TBS;
    gNB->rx_pdu_list[num_rx].pdu = harq_process->b;
  }
385

386
  gNB->UL_INFO.rx_ind.number_of_pdus++;
387

388
  pthread_mutex_unlock(&gNB->UL_INFO_mutex);
389
}
390

391 392 393 394 395
// Function to fill UL RB mask to be used for N0 measurements
void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {

  int rb2, rb, nb_rb;
  for (int symbol=0;symbol<14;symbol++) {
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
    if (gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1){
      nb_rb = 0;
      for (int m=0;m<9;m++) gNB->rb_mask_ul[m] = 0;
      gNB->ulmask_symb = -1;

      for (int i=0;i<NUMBER_OF_NR_PUCCH_MAX;i++){
        NR_gNB_PUCCH_t *pucch = gNB->pucch[i];
        if (pucch) {
          if ((pucch->active == 1) &&
	      (pucch->frame == frame_rx) &&
	      (pucch->slot == slot_rx) ) {
            gNB->ulmask_symb = symbol;
            nfapi_nr_pucch_pdu_t  *pucch_pdu = &pucch[i].pucch_pdu;
            if ((symbol>=pucch_pdu->start_symbol_index) &&
                (symbol<(pucch_pdu->start_symbol_index + pucch_pdu->nr_of_symbols))){
              for (rb=0; rb<pucch_pdu->prb_size; rb++) {
                rb2 = rb+pucch_pdu->prb_start;
                gNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
              }
              nb_rb+=pucch_pdu->prb_size;
416 417 418 419
            }
          }
        }
      }
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
      for (int ULSCH_id=0;ULSCH_id<NUMBER_OF_NR_ULSCH_MAX;ULSCH_id++) {
        NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0];
        int harq_pid;
        NR_UL_gNB_HARQ_t *ulsch_harq;

        if ((ulsch) &&
            (ulsch->rnti > 0)) {
          for (harq_pid=0;harq_pid<NR_MAX_ULSCH_HARQ_PROCESSES;harq_pid++) {
            ulsch_harq = ulsch->harq_processes[harq_pid];
            AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid);
            if ((ulsch_harq->status == NR_ACTIVE) &&
                (ulsch_harq->frame == frame_rx) &&
                (ulsch_harq->slot == slot_rx) &&
                (ulsch_harq->handled == 0)){
              uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
              uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
              gNB->ulmask_symb = symbol;
              if ((symbol>=symbol_start) &&
                  (symbol<symbol_end)){
                for (rb=0; rb<ulsch_harq->ulsch_pdu.rb_size; rb++) {
                  rb2 = rb+ulsch_harq->ulsch_pdu.rb_start;
                  gNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
                }
                nb_rb+=ulsch_harq->ulsch_pdu.rb_size;
444 445 446 447 448
              }
            }
          }
        }
      //TODO Add check for PRACH as well?
449 450 451
      }
      if (nb_rb<gNB->frame_parms.N_RB_UL)
        return;
452 453 454 455
    }
  }
}

456
void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
457 458

  uint8_t symbol;
459
  unsigned char aa;
460 461

  for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) {
462
    // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
463

464 465 466 467 468
    for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
      nr_slot_fep_ul(&gNB->frame_parms,
                     gNB->common_vars.rxdata[aa],
                     gNB->common_vars.rxdataF[aa],
                     symbol,
469
                     slot_rx,
470 471 472
                     0,
                     0);
    }
473
  }
474 475 476

}

477
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
478

Rakesh's avatar
Rakesh committed
479
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1);
480
  LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx);
481

482 483 484
  fill_ul_rb_mask(gNB, frame_rx, slot_rx);
  gNB_I0_measurements(gNB);

Francesco Mani's avatar
Francesco Mani committed
485 486 487
  for (int i=0;i<NUMBER_OF_NR_PUCCH_MAX;i++){
    NR_gNB_PUCCH_t *pucch = gNB->pucch[i];
    if (pucch) {
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
      if ((pucch->active == 1) &&
	  (pucch->frame == frame_rx) &&
	  (pucch->slot == slot_rx) ) {

        nfapi_nr_pucch_pdu_t  *pucch_pdu = &pucch[i].pucch_pdu;
        uint16_t num_ucis;

        switch (pucch_pdu->format_type) {
        case 0:

          num_ucis = gNB->UL_INFO.uci_ind.num_ucis;
          gNB->UL_INFO.uci_ind.uci_list = &gNB->uci_pdu_list[0];
          gNB->UL_INFO.uci_ind.sfn = frame_rx;
          gNB->UL_INFO.uci_ind.slot = slot_rx;
          gNB->uci_pdu_list[num_ucis].pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE;
          gNB->uci_pdu_list[num_ucis].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t);
          nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &gNB->uci_pdu_list[num_ucis].pucch_pdu_format_0_1;

          nr_decode_pucch0(gNB,
	                   slot_rx,
                           uci_pdu_format0,
                           pucch_pdu);

          gNB->UL_INFO.uci_ind.num_ucis += 1;
          pucch->active = 0;
	  break;
        default:
	  AssertFatal(1==0,"Only PUCCH format 0 is currently supported\n");
        }
Francesco Mani's avatar
Francesco Mani committed
517 518 519 520
      }
    }
  }

521
  for (int ULSCH_id=0;ULSCH_id<NUMBER_OF_NR_ULSCH_MAX;ULSCH_id++) {
522 523
    NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0];
    int harq_pid;
524
    int no_sig;
525 526 527
    NR_UL_gNB_HARQ_t *ulsch_harq;

    if ((ulsch) &&
528
        (ulsch->rnti > 0)) {
529 530
      // for for an active HARQ process
      for (harq_pid=0;harq_pid<NR_MAX_ULSCH_HARQ_PROCESSES;harq_pid++) {
531
	ulsch_harq = ulsch->harq_processes[harq_pid];
532 533 534 535 536
    	AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid);
    	if ((ulsch_harq->status == NR_ACTIVE) &&
          (ulsch_harq->frame == frame_rx) &&
          (ulsch_harq->slot == slot_rx) &&
          (ulsch_harq->handled == 0)){
537

538
          LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n",
539 540
                frame_rx,slot_rx);

541
#ifdef DEBUG_RXDATA
542 543
          NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
          RU_t *ru = gNB->RU_list[0];
544 545
          int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx,frame_parms,0);
          slot_offset -= ru->N_TA_offset;
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[0]=(int16_t)ulsch->rnti;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[1]=(int16_t)ulsch_harq->ulsch_pdu.rb_size;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[2]=(int16_t)ulsch_harq->ulsch_pdu.rb_start;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[3]=(int16_t)ulsch_harq->ulsch_pdu.nr_of_symbols;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[4]=(int16_t)ulsch_harq->ulsch_pdu.start_symbol_index;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[5]=(int16_t)ulsch_harq->ulsch_pdu.mcs_index;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[6]=(int16_t)ulsch_harq->ulsch_pdu.pusch_data.rv_index;
          ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[7]=(int16_t)harq_pid;
          memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset+4],&ru->common.rxdata[0][slot_offset],frame_parms->get_samples_per_slot(slot_rx,frame_parms)*sizeof(int32_t));
          gNB->common_vars.debugBuff_sample_offset+=(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4);
          if(gNB->common_vars.debugBuff_sample_offset>((frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+2)*20)) {
            FILE *f;
            f = fopen("rxdata_buff.raw", "w"); if (f == NULL) exit(1);
            fwrite((int16_t*)gNB->common_vars.debugBuff,2,(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4)*20*2, f);
            fclose(f);
            exit(-1);
          }
563 564
#endif

565 566
          uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
          uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
Rakesh's avatar
Rakesh committed
567
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1);
568
	  start_meas(&gNB->rx_pusch_stats);
569 570
	  for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) {
	    no_sig = nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, symbol, harq_pid);
571
            if (no_sig) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
572
              LOG_I(PHY, "PUSCH not detected in symbol %d\n",symbol);
573
              nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
574
              return;
575
            }
576
	  }
577
	  stop_meas(&gNB->rx_pusch_stats);
Rakesh's avatar
Rakesh committed
578
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,0);
579 580
          //LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1);
          //LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1);
581
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,1);
582
          nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid);
583
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,0);
584 585
          break;
        }
Francesco Mani's avatar
Francesco Mani committed
586
      }
587 588
    }
  }
Rakesh's avatar
Rakesh committed
589
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0);
590
}