phy_procedures_nr_gNB.c 14.7 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"
Guy De Souza's avatar
Guy De Souza committed
25
#include "PHY/NR_TRANSPORT/nr_transport.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_ESTIMATION/nr_ul_estimation.h"
30
#include "SCHED/sched_eNB.h"
31
#include "sched_nr.h"
32
#include "SCHED/sched_common_extern.h"
33 34 35
#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"
36 37
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
38
#include "PHY/INIT/phy_init.h"
39
#include "PHY/MODULATION/nr_modulation.h"
Guy De Souza's avatar
Guy De Souza committed
40 41 42 43 44 45 46 47
#include "T.h"

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

#include <time.h>

#if defined(ENABLE_ITTI)
48
  #include "intertask_interface.h"
Guy De Souza's avatar
Guy De Souza committed
49 50
#endif

Guy De Souza's avatar
Guy De Souza committed
51
extern uint8_t nfapi_mode;
52 53 54 55
/*
int return_ssb_type(nfapi_config_request_t *cfg)
{
  int mu = cfg->subframe_config.numerology_index_mu.value;
56
  nr_ssb_type_e ssb_type;
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

  switch(mu) {

  case NR_MU_0:
    ssb_type = nr_ssb_type_A;
    break;

  case NR_MU_1:
    ssb_type = nr_ssb_type_B;
    break;

  case NR_MU_3:
    ssb_type = nr_ssb_type_D;
    break;

  case NR_MU_4:
    ssb_type = nr_ssb_type_E;
    break;

  default:
    AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu);
  }

  LOG_D(PHY, "SSB type %d\n", ssb_type);
  return ssb_type;

}*/

85

86

87
void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp) {
88
  fp->ssb_start_subcarrier = (12 * cfg->ssb_table.ssb_offset_point_a.value + cfg->ssb_table.ssb_subcarrier_offset.value);
89
  LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->ssb_table.ssb_offset_point_a.value,cfg->ssb_table.ssb_subcarrier_offset.value);
90
}
Guy De Souza's avatar
Guy De Souza committed
91

92
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
Guy De Souza's avatar
Guy De Souza committed
93
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
94
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
95
  int **txdataF = gNB->common_vars.txdataF;
96
  uint8_t ssb_index, n_hf;
97
  int ssb_start_symbol, rel_slot;
98
  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
99
  uint16_t slots_per_hf = fp->slots_per_frame / 2;
Guy De Souza's avatar
Guy De Souza committed
100

101
  n_hf = fp->half_frame_bit;
102 103

  // if SSB periodicity is 5ms, they are transmitted in both half frames
104
  if ( cfg->ssb_table.ssb_period.value == 0) {
105
    if (slot<slots_per_hf)
106 107 108 109 110
      n_hf=0;
    else
      n_hf=1;
  }

111
  // to set a effective slot number between 0 to 9 in the half frame where the SSB is supposed to be
112
  rel_slot = (n_hf)? (slot-slots_per_hf) : slot; 
113

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

116
  if(rel_slot<10 && rel_slot>=0)  {
117 118 119 120
    for (int i=0; i<2; i++)  {  // max two SSB per frame
      
      ssb_index = i + 2*rel_slot; // computing the ssb_index
      if ((fp->L_ssb >> ssb_index) & 0x01)  { // generating the ssb only if the bit of L_ssb at current ssb index is 1
121
	
122 123
        gNB->ssb_pdu->ssb_pdu_rel15.SsbBlockIndex = ssb_index;
 
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp, ssb_index); // computing the starting symbol for current ssb
	ssb_start_symbol = ssb_start_symbol_abs % 14;  // start symbol wrt slot
	
	nr_set_ssb_first_subcarrier(cfg, fp);  // setting the first subcarrier
	
	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], AMP, ssb_start_symbol, cfg, fp);
	nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
	
	if (fp->Lmax == 4)
	  nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
	else
	  nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
	
	nr_generate_pbch(&gNB->pbch,
			 gNB->ssb_pdu,
			 gNB->nr_pbch_interleaver,
			 txdataF[0],
			 AMP,
			 ssb_start_symbol,
144
			 n_hf,fp->Lmax,
145 146 147
			 frame, cfg, fp);
      }
    }
148
  }
Guy De Souza's avatar
Guy De Souza committed
149 150 151
}

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

161 162 163 164
  
  
  if (cfg->ssb_table.ssb_period.value > 1) 
    ssb_frame_periodicity = 1 <<(cfg->ssb_table.ssb_period.value -1) ;  // 10ms is the frame length
Guy De Souza's avatar
Guy De Souza committed
165

166
  if ((cfg->cell_config.frame_duplex_type.value == TDD) && 
167
      ((nr_slot_select(fp,frame,slot)&NR_UPLINK_SLOT) > 0)) return;
Guy De Souza's avatar
Guy De Souza committed
168

169
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
170

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

  // clear the transmit data array for the current subframe
174
  for (aa=0; aa<fp->Lmax; aa++) {
175
    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
176 177
  }

WANG Tsu-Han's avatar
WANG Tsu-Han committed
178
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,1);
179
  if (nfapi_mode == 0 || nfapi_mode == 1) { 
180
    if ((!(frame%ssb_frame_periodicity)) && (gNB->ssb_pdu))  // generate SSB only for given frames according to SSB periodicity
181
      nr_common_signal_procedures(gNB,frame, slot);
182
  }
WANG Tsu-Han's avatar
WANG Tsu-Han committed
183
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,0);
184

185

186

187 188 189 190
  LOG_D(PHY, "[gNB %d] Frame %d slot %d \
    Calling nr_generate_dci_top (number of DCI %d)\n", gNB->Mod_id, frame, slot, gNB->pdcch_pdu->pdcch_pdu_rel15.numDlDci);
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
Guy De Souza's avatar
Guy De Souza committed
191

192 193 194 195 196 197
  if (gNB->pdcch_pdu || gNB->ul_dci_pdu) nr_generate_dci_top(gNB->pdcch_pdu,
							     gNB->ul_dci_pdu,
							     gNB->nr_gold_pdcch_dmrs[slot],
							     gNB->common_vars.txdataF[0],
							     AMP, *fp);

Raymond Knopp's avatar
Raymond Knopp committed
198
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
199 200 201
 
  LOG_D(PHY, "PDSCH generation started (%d)\n", gNB->num_pdsch_rnti);
  for (int i=0; i<gNB->num_pdsch_rnti; i++) {
202 203 204 205
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
    nr_generate_pdsch(gNB->dlsch[i][0],
		      gNB->nr_gold_pdsch_dmrs[slot],
		      gNB->common_vars.txdataF,
206
		      AMP, frame, slot, fp, 0,
207 208 209
		      &gNB->dlsch_encoding_stats,
		      &gNB->dlsch_scrambling_stats,
		      &gNB->dlsch_modulation_stats);
210
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
211
  }
212

213
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
Guy De Souza's avatar
Guy De Souza committed
214
}
215 216


217

218
/*
219

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

  //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);


  if (do_prach_rx(fp,frame,slot)) L1_nr_prach_procedures(gNB,frame,slot/fp->slots_per_subframe);
227 228
*/

Raymond Knopp's avatar
Raymond Knopp committed
229
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
230 231
{
  NR_DL_FRAME_PARMS                    *frame_parms           = &gNB->frame_parms;
232
  nfapi_nr_ul_config_ulsch_pdu         *rel15_ul              = &gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->ulsch_pdu;
233 234
  nfapi_nr_ul_config_ulsch_pdu_rel15_t *nfapi_ulsch_pdu_rel15 = &rel15_ul->ulsch_pdu_rel15;
  
235
  uint8_t ret;
236 237 238
  uint32_t G;
  int Nid_cell = 0; // [hna] shouldn't be a local variable (should be signaled)

239 240
  G = nr_get_G(nfapi_ulsch_pdu_rel15->number_rbs,
               nfapi_ulsch_pdu_rel15->number_symbols,
yilmazt's avatar
yilmazt committed
241 242 243 244
               nfapi_ulsch_pdu_rel15->nb_re_dmrs,
               nfapi_ulsch_pdu_rel15->length_dmrs,
               nfapi_ulsch_pdu_rel15->Qm,
               nfapi_ulsch_pdu_rel15->n_layers);
245 246 247 248 249

  //----------------------------------------------------------
  //------------------- ULSCH unscrambling -------------------
  //----------------------------------------------------------

Raymond Knopp's avatar
Raymond Knopp committed
250
  nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id]->llr,
yilmazt's avatar
yilmazt committed
251 252 253 254
                        G,
                        0,
                        Nid_cell,
                        rel15_ul->rnti);
255 256 257 258 259

  //----------------------------------------------------------
  //--------------------- ULSCH decoding ---------------------
  //----------------------------------------------------------

260
  ret = nr_ulsch_decoding(gNB,
Raymond Knopp's avatar
Raymond Knopp committed
261 262
                    ULSCH_id,
                    gNB->pusch_vars[ULSCH_id]->llr,
yilmazt's avatar
yilmazt committed
263
                    frame_parms,
264
                    frame_rx,
yilmazt's avatar
yilmazt committed
265
                    nfapi_ulsch_pdu_rel15->number_symbols,
266
                    slot_rx,
yilmazt's avatar
yilmazt committed
267 268
                    harq_pid,
                    0);
269
        
270
  if (ret > gNB->ulsch[ULSCH_id][0]->max_ldpc_iterations)
271 272 273
    LOG_I(PHY, "ULSCH in error\n");
  else
    LOG_I(PHY, "ULSCH received ok\n");
274 275 276 277

}


278
void nr_fill_rx_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid)
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
{
  // --------------------
  // [hna] TO BE CLEANED
  // --------------------

  // nfapi_rx_indication_pdu_t *pdu;

  int timing_advance_update;
  int sync_pos;

  // pthread_mutex_lock(&gNB->UL_INFO_mutex);

  // gNB->UL_INFO.rx_ind.sfn_sf                    = frame<<4| slot_rx;
  // gNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;

  // pdu                                    = &gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus];

  // pdu->rx_ue_information.handle          = gNB->ulsch[UE_id+1][0]->handle;
  // pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
  // pdu->rx_ue_information.rnti            = gNB->ulsch[UE_id+1][0]->rnti;
  // pdu->rx_indication_rel8.tl.tag         = NFAPI_RX_INDICATION_REL8_TAG;
  // pdu->rx_indication_rel8.length         = gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->TBS>>3;
  // pdu->rx_indication_rel8.offset         = 1;   // DJP - I dont understand - but broken unless 1 ????  0;  // filled in at the end of the UL_INFO formation
  // pdu->data                              = gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->b;
  // estimate timing advance for MAC
304
  sync_pos                               = nr_est_timing_advance_pusch(gNB, ULSCH_id);
305 306 307 308 309 310 311 312 313 314 315
  timing_advance_update                  = sync_pos; // - gNB->frame_parms.nb_prefix_samples/4; //to check
  // printf("\x1B[33m" "timing_advance_update = %d\n" "\x1B[0m", timing_advance_update);

  switch (gNB->frame_parms.N_RB_DL) {
    // case 6:   /* nothing to do */          break;
    // case 15:  timing_advance_update /= 2;  break;
    // case 25:  timing_advance_update /= 4;  break;
    // case 50:  timing_advance_update /= 8;  break;
    // case 75:  timing_advance_update /= 12; break;
    case 106: timing_advance_update /= 16; break;
    case 217: timing_advance_update /= 32; break;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
316
    case 273: timing_advance_update /= 32; break;
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    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;

  // pdu->rx_indication_rel8.timing_advance = timing_advance_update;

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

  // if      (SNRtimes10 < -640) pdu->rx_indication_rel8.ul_cqi=0;
  // else if (SNRtimes10 >  635) pdu->rx_indication_rel8.ul_cqi=255;
  // else                        pdu->rx_indication_rel8.ul_cqi=(640+SNRtimes10)/5;

  // LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n",
  // harq_pid,frame,slot_rx,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance,
  // timing_advance_update);

  // gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++;
  // gNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | slot_rx;

  // pthread_mutex_unlock(&gNB->UL_INFO_mutex);
}


346
void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
347 348

  uint8_t symbol;
349
  unsigned char aa;
350 351

  for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) {
352 353 354 355 356 357
    // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
    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,
358
                     slot_rx,
359 360 361
                     0,
                     0);
    }
362
  }
363 364 365

}

366
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
367

368 369
  nfapi_nr_ul_tti_request_t     *UL_tti_req  = &gNB->UL_tti_req;
  int num_pusch_pdu = UL_tti_req->n_pdus;
370

371
  LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d, num_pusch_pdu %d\n",frame_rx,slot_rx,num_pusch_pdu);
372
  
373
  for (int i = 0; i < num_pusch_pdu; i++) {
374

375 376 377
    switch (UL_tti_req->pdus_list[i].pdu_type) {
    case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
      {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
378
	LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE\n",frame_rx,slot_rx);
379

380 381 382
	nfapi_nr_pusch_pdu_t  *pusch_pdu = &UL_tti_req->pdus_list[0].pusch_pdu;
	nr_fill_ulsch(gNB,frame_rx,slot_rx,pusch_pdu);      
	
383
	uint8_t ULSCH_id =  find_nr_ulsch(pusch_pdu->rnti,gNB,SEARCH_EXIST);
384
	uint8_t harq_pid = pusch_pdu->pusch_data.harq_process_id;
385 386
	uint8_t symbol_start = pusch_pdu->start_symbol_index;
	uint8_t symbol_end = symbol_start + pusch_pdu->nr_of_symbols;
387 388
	
	for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) {
389
	  nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, symbol, harq_pid);
390
	}
391 392
	//LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[UE_id]->rxdataF_comp[0],6900,1,1);
	//LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[UE_id]->rxdataF_ext[0],6900,1,1);
393 394
	nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid);
	nr_fill_rx_indication(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid);  // indicate SDU to MAC
395
      }
396 397
    }
  }
398
}