phy_procedures_nr_gNB.c 28.9 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, ssb_per_slot=0, 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 slot
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
	ssb_per_slot++;
103 104 105 106 107
        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
108
	
109 110 111
	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);
112
	
113 114 115 116
        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);
117 118 119 120 121 122 123 124 125

        if (T_ACTIVE(T_GNB_PHY_MIB)) {
          unsigned char bch[3];
          bch[0] = gNB->ssb_pdu.ssb_pdu_rel15.bchPayload & 0xff;
          bch[1] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 8) & 0xff;
          bch[2] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 16) & 0xff;
          T(T_GNB_PHY_MIB, T_INT(0) /* module ID */, T_INT(frame), T_INT(slot), T_BUFFER(bch, 3));
        }

126 127 128 129 130 131 132 133
	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);

Florian Kaltenberger's avatar
Florian Kaltenberger committed
134 135 136 137 138 139
	// SSB beamforming is handled at PHY
	// currently our PHY does not support switching more than once a slot. 
	if (ssb_per_slot>1) {
	  LOG_W(PHY,"beamforming currently not supported for more than one SSB per slot\n");
	}
	else if (ssb_per_slot==1) {
140
	  LOG_D(PHY,"slot %d, ssb_index %d, beam %d\n",slot,ssb_index,cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
141 142 143
	  for (int j=0;j<fp->symbols_per_slot;j++) 
	    gNB->common_vars.beam_id[0][slot*fp->symbols_per_slot+j] = cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value;
	}	
144
      }
145
    }
146
  }
Guy De Souza's avatar
Guy De Souza committed
147 148 149
}

void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
150
                           int frame,int slot,
151
                           int do_meas) {
Guy De Souza's avatar
Guy De Souza committed
152 153
  int aa;
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
154
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
155
  int offset = gNB->CC_id;
156
  uint8_t ssb_frame_periodicity = 1;  // every how many frames SSB are generated
157
  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
158 159
  
  if (cfg->ssb_table.ssb_period.value > 1) 
160
    ssb_frame_periodicity = 1 <<(cfg->ssb_table.ssb_period.value -1) ; 
Guy De Souza's avatar
Guy De Souza committed
161

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

Rakesh's avatar
Rakesh committed
165
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1);
166

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

169
  // clear the transmit data array and beam index for the current slot
Raymond Knopp's avatar
Raymond Knopp committed
170
  for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
171
    memset(&gNB->common_vars.txdataF[aa][txdataF_offset],0,fp->samples_per_slot_wCP*sizeof(int32_t));
172
    memset(&gNB->common_vars.beam_id[aa][slot*fp->symbols_per_slot],255,fp->symbols_per_slot*sizeof(uint8_t));
Guy De Souza's avatar
Guy De Souza committed
173 174
  }

Rakesh's avatar
Rakesh committed
175
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1);
176
  if (nfapi_mode == 0 || nfapi_mode == 1) { 
177
    if ((!(frame%ssb_frame_periodicity)))  // generate SSB only for given frames according to SSB periodicity
178
      nr_common_signal_procedures(gNB,frame, slot);
179
  }
Rakesh's avatar
Rakesh committed
180
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0);
181

182 183
  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);
184

185 186 187 188 189
  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",
190
	  gNB->Mod_id, frame, slot,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
191 192
	  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);
193
  
Rakesh's avatar
Rakesh committed
194
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
195

196 197 198
    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,
199 200 201
			gNB->nr_gold_pdcch_dmrs[slot],
			&gNB->common_vars.txdataF[0][txdataF_offset],
			AMP, *fp);
202 203 204 205 206

    // 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
207
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
208 209
    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;
210
  }
211
 
212
  for (int i=0; i<gNB->num_pdsch_rnti[slot]; i++) {
213
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
214
    LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot);
215 216
    nr_generate_pdsch(gNB,frame, slot);
    if ((frame&127) == 0) dump_pdsch_stats(gNB);
217
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
218
  }
219

220 221 222 223

  //apply the OFDM symbol rotation here
  apply_nr_rotation(fp,(int16_t*) &gNB->common_vars.txdataF[0][txdataF_offset],slot,0,fp->Ncp==EXTENDED?12:14,fp->ofdm_symbol_size);
  
Rakesh's avatar
Rakesh committed
224
  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
225
}
226 227


228

229
/*
230

231 232
  if ((cfg->subframe_config.duplex_mode.value == TDD) && 
      ((nr_slot_select(fp,frame,slot)&NR_DOWNLINK_SLOT)==SF_DL)) return;
233 234 235

  //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);

236 237
*/

Sakthivel Velumani's avatar
Sakthivel Velumani committed
238
void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
Sakthi's avatar
Sakthi committed
239 240 241 242
  ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
  NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
  NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
  int r = rdata->segment_r;
243

244
  bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
245 246 247
  ulsch_harq->processedSegments++;
  LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n",
	rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments);
Sakthi's avatar
Sakthi committed
248 249 250 251 252 253
  gNB->nbDecode--;
  LOG_D(PHY,"remain to decoded in subframe: %d\n", gNB->nbDecode);
  
  if (decodeSuccess) {
    memcpy(ulsch_harq->b+rdata->offset,
           ulsch_harq->c[r],
Cedric Roux's avatar
Cedric Roux committed
254
           rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
Sakthi's avatar
Sakthi committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

  } else {
    if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
      int nb=abortTpool(gNB->threadPool, req->key);
      nb+=abortNotifiedFIFO(gNB->respDecode, req->key);
      gNB->nbDecode-=nb;
      LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb);
      LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
      AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
		  ulsch_harq->processedSegments, nb, rdata->nbSegments);
      ulsch_harq->processedSegments=rdata->nbSegments;
    }
  }

  // if all segments are done 
  if (rdata->nbSegments == ulsch_harq->processedSegments) {
    if (decodeSuccess) {
272
      LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n",
Sakthi's avatar
Sakthi committed
273 274 275 276 277 278 279 280
            gNB->Mod_id,ulsch_harq->slot,ulsch_harq->TBS);
      ulsch_harq->status = SCH_IDLE;
      ulsch_harq->round  = 0;
      ulsch->harq_mask &= ~(1 << rdata->harq_pid);

      LOG_D(PHY, "ULSCH received ok \n");
      nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 0);
    } else {
Sakthivel Velumani's avatar
fixes  
Sakthivel Velumani committed
281
      LOG_D(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d) r %d\n",
Sakthi's avatar
Sakthi committed
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
            gNB->Mod_id, ulsch_harq->frame, ulsch_harq->slot,
            rdata->harq_pid,ulsch_harq->status, ulsch_harq->round,ulsch_harq->TBS,r);
      if (ulsch_harq->round >= ulsch->Mlimit) {
        ulsch_harq->status = SCH_IDLE;
        ulsch_harq->round  = 0;
        ulsch_harq->handled  = 0;
        ulsch->harq_mask &= ~(1 << rdata->harq_pid);
      }
      ulsch_harq->handled  = 1;

      LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
      nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 1);
    }
    ulsch->last_iteration_cnt = rdata->decodeIterations;
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
  }
}

300

Raymond Knopp's avatar
Raymond Knopp committed
301
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
302
{
303 304
  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;
305
  
306
  uint8_t l, number_dmrs_symbols = 0;
307
  uint32_t G;
308
  uint16_t start_symbol, number_symbols, nb_re_dmrs;
309

310 311
  start_symbol = pusch_pdu->start_symbol_index;
  number_symbols = pusch_pdu->nr_of_symbols;
312 313

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

316 317
  if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1)
    nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data;
318
  else
319
    nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
320 321

  G = nr_get_G(pusch_pdu->rb_size,
322
               number_symbols,
323
               nb_re_dmrs,
324
               number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
325 326
               pusch_pdu->qam_mod_order,
               pusch_pdu->nrOfLayers);
327
  
Raphael Defosseux's avatar
Raphael Defosseux committed
328
  AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
329 330 331 332 333 334 335 336 337 338 339 340 341
	      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);
342 343 344
  //----------------------------------------------------------
  //------------------- ULSCH unscrambling -------------------
  //----------------------------------------------------------
345
  start_meas(&gNB->ulsch_unscrambling_stats);
346 347 348 349 350
  nr_ulsch_unscrambling_optim(gNB->pusch_vars[ULSCH_id]->llr,
			      G,
			      0,
			      pusch_pdu->data_scrambling_id,
			      pusch_pdu->rnti);
351
  stop_meas(&gNB->ulsch_unscrambling_stats);
352 353 354 355
  //----------------------------------------------------------
  //--------------------- ULSCH decoding ---------------------
  //----------------------------------------------------------

356
  start_meas(&gNB->ulsch_decoding_stats);
357 358 359 360 361 362 363 364 365
  nr_ulsch_decoding(gNB,
                    ULSCH_id,
                    gNB->pusch_vars[ULSCH_id]->llr,
                    frame_parms,
                    pusch_pdu,
                    frame_rx,
                    slot_rx,
                    harq_pid,
                    G);
366

367 368
  while (gNB->nbDecode > 0) {
    notifiedFIFO_elt_t *req=pullTpool(gNB->respDecode, gNB->threadPool);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
369
    nr_postDecode(gNB, req);
370 371
    delNotifiedFIFO_elt(req);
  }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
372
  stop_meas(&gNB->ulsch_decoding_stats);
373 374 375
}


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

378
  pthread_mutex_lock(&gNB->UL_INFO_mutex);
379

380
  int timing_advance_update, cqi;
381
  int sync_pos;
cig's avatar
cig committed
382
  uint16_t mu = gNB->frame_parms.numerology_index;
383
  NR_gNB_ULSCH_t                       *ulsch                 = gNB->ulsch[ULSCH_id][0];
384 385
  NR_UL_gNB_HARQ_t                     *harq_process          = ulsch->harq_processes[harq_pid];

386
  nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
387 388

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

392
  // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
393 394 395
  switch (gNB->frame_parms.N_RB_DL) {
    case 106: timing_advance_update /= 16; break;
    case 217: timing_advance_update /= 32; break;
396
    case 245: timing_advance_update /= 32; break;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
397
    case 273: timing_advance_update /= 32; break;
cig's avatar
cig committed
398
    case 66:  timing_advance_update /= 12; break;
399 400
    case 32:  timing_advance_update /= 12; break;
    default: AssertFatal(0==1,"No case defined for PRB %d to calculate timing_advance_update\n",gNB->frame_parms.N_RB_DL);
401 402 403 404 405 406 407 408
  }

  // 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;

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

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

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

416 417 418 419 420 421 422 423 424 425 426 427 428 429
  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;
430
  gNB->crc_pdu_list[num_crc].num_cb = pusch_pdu->pusch_data.num_cb;
431 432
  gNB->crc_pdu_list[num_crc].ul_cqi = cqi;
  gNB->crc_pdu_list[num_crc].timing_advance = timing_advance_update;
433
  // in terms of dBFS range -128 to 0 with 0.1 step
434
  gNB->crc_pdu_list[num_crc].rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]));
435 436 437 438 439 440 441 442 443 444 445 446 447

  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;
448
  gNB->rx_pdu_list[num_rx].rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]));
449 450 451 452 453 454
  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;
  }
455

456
  gNB->UL_INFO.rx_ind.number_of_pdus++;
457

458
  pthread_mutex_unlock(&gNB->UL_INFO_mutex);
459
}
460

461 462 463 464 465
// 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++) {
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
    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;
486 487 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
      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;
514 515 516 517 518
              }
            }
          }
        }
      //TODO Add check for PRACH as well?
519 520 521
      }
      if (nb_rb<gNB->frame_parms.N_RB_UL)
        return;
522 523 524 525
    }
  }
}

526
void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
527 528

  uint8_t symbol;
529
  unsigned char aa;
530

531
  for(symbol = 0; symbol < (gNB->frame_parms.Ncp==EXTENDED?12:14); symbol++) {
532
    // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
533

534 535 536 537 538
    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,
539
                     slot_rx,
540 541 542
                     0,
                     0);
    }
543
  }
544

545 546 547 548 549 550 551 552 553
  for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
    apply_nr_rotation_ul(&gNB->frame_parms,
			 gNB->common_vars.rxdataF[aa],
			 slot_rx,
			 0,
			 gNB->frame_parms.Ncp==EXTENDED?12:14,
			 gNB->frame_parms.ofdm_symbol_size);
  }

554 555
}

556
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
557

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

cig's avatar
cig committed
561 562 563
  if (gNB->frame_parms.frame_type == TDD)
    fill_ul_rb_mask(gNB, frame_rx, slot_rx);

564 565
  gNB_I0_measurements(gNB);

Francesco Mani's avatar
Francesco Mani committed
566 567 568
  for (int i=0;i<NUMBER_OF_NR_PUCCH_MAX;i++){
    NR_gNB_PUCCH_t *pucch = gNB->pucch[i];
    if (pucch) {
569 570 571 572
      if ((pucch->active == 1) &&
	  (pucch->frame == frame_rx) &&
	  (pucch->slot == slot_rx) ) {

573
        nfapi_nr_pucch_pdu_t  *pucch_pdu = &pucch->pucch_pdu;
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
        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;
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
        case 2:
          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_2_3_4_PDU_TYPE;
          gNB->uci_pdu_list[num_ucis].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t);
          nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &gNB->uci_pdu_list[num_ucis].pucch_pdu_format_2_3_4;

          nr_decode_pucch2(gNB,
                           slot_rx,
                           uci_pdu_format2,
                           pucch_pdu);

          gNB->UL_INFO.uci_ind.num_ucis += 1;
          pucch->active = 0;
609
          break;
610
        default:
611
	  AssertFatal(1==0,"Only PUCCH formats 0 and 2 are currently supported\n");
612
        }
Francesco Mani's avatar
Francesco Mani committed
613 614 615 616
      }
    }
  }

617
  for (int ULSCH_id=0;ULSCH_id<NUMBER_OF_NR_ULSCH_MAX;ULSCH_id++) {
618 619
    NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0];
    int harq_pid;
620
    int no_sig;
621 622 623
    NR_UL_gNB_HARQ_t *ulsch_harq;

    if ((ulsch) &&
624
        (ulsch->rnti > 0)) {
625 626
      // for for an active HARQ process
      for (harq_pid=0;harq_pid<NR_MAX_ULSCH_HARQ_PROCESSES;harq_pid++) {
627
	ulsch_harq = ulsch->harq_processes[harq_pid];
628 629 630 631 632
    	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)){
633

634
          LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n",
635 636
                frame_rx,slot_rx);

637
#ifdef DEBUG_RXDATA
638 639
          NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
          RU_t *ru = gNB->RU_list[0];
640 641
          int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx,frame_parms,0);
          slot_offset -= ru->N_TA_offset;
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
          ((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);
          }
659 660
#endif

661 662
          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
663
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1);
664
	  start_meas(&gNB->rx_pusch_stats);
665 666
	  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);
667
            if (no_sig) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
668
              LOG_I(PHY, "PUSCH not detected in symbol %d\n",symbol);
669
              nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
670
              return;
671
            }
672
	  }
673
	  stop_meas(&gNB->rx_pusch_stats);
Rakesh's avatar
Rakesh committed
674
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,0);
675 676
          //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);
677
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,1);
678
          nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid);
679
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,0);
680 681
          break;
        }
Francesco Mani's avatar
Francesco Mani committed
682
      }
683 684
    }
  }
685 686
  // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS
  if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB);
Raymond Knopp's avatar
Raymond Knopp committed
687

Rakesh's avatar
Rakesh committed
688
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0);
689
}