phy_procedures_nr_gNB.c 14.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"
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_t *cfg, NR_DL_FRAME_PARMS *fp) {
88 89
  fp->ssb_start_subcarrier = (12 * cfg->sch_config.n_ssb_crb.value + cfg->sch_config.ssb_subcarrier_offset.value)/(1<<cfg->subframe_config.numerology_index_mu.value);
  LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->sch_config.n_ssb_crb.value,cfg->sch_config.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;
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
94
  nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
95 96
  int **txdataF = gNB->common_vars.txdataF;
  uint8_t *pbch_pdu=&gNB->pbch_pdu[0];
97
  uint8_t ssb_index, n_hf;
98
  int ssb_start_symbol, rel_slot;
Guy De Souza's avatar
Guy De Souza committed
99

100
  n_hf = cfg->sch_config.half_frame_index.value;
101 102 103 104 105 106 107 108 109

  // if SSB periodicity is 5ms, they are transmitted in both half frames
  if ( cfg->sch_config.ssb_periodicity.value == 5) {
    if (slot<10)
      n_hf=0;
    else
      n_hf=1;
  }

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

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

115 116 117
  if(rel_slot<10 && rel_slot>=0)  {
     for (int i=0; i<2; i++)  {  // max two SSB per frame
     
118
	ssb_index = i + 2*rel_slot; // computing the ssb_index
119 120
	if ((fp->L_ssb >> ssb_index) & 0x01)  { // generating the ssb only if the bit of L_ssb at current ssb index is 1
	
121
	  int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp, ssb_index, n_hf); // computing the starting symbol for current ssb
122 123
	  ssb_start_symbol = ssb_start_symbol_abs % 14;  // start symbol wrt slot

124
	  nr_set_ssb_first_subcarrier(cfg, fp);  // setting the first subcarrier
125 126 127 128 129
	  
    	  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);

130 131 132 133
	  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);
134 135

    	  nr_generate_pbch(&gNB->pbch,
Guy De Souza's avatar
Guy De Souza committed
136 137
                      pbch_pdu,
                      gNB->nr_pbch_interleaver,
138
                      txdataF[0],
139
                      AMP,
Guy De Souza's avatar
Guy De Souza committed
140
                      ssb_start_symbol,
141
                      n_hf,fp->Lmax,ssb_index,
Guy De Souza's avatar
Guy De Souza committed
142
                      frame, cfg, fp);
143 144
	}
     }
145
  }
Guy De Souza's avatar
Guy De Souza committed
146 147 148
}

void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
149
                           int frame,int slot,
150
                           int do_meas) {
Guy De Souza's avatar
Guy De Souza committed
151
  int aa;
152
  uint8_t num_dci=0,num_pdsch_rnti;
Guy De Souza's avatar
Guy De Souza committed
153
  NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
154
  nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
Guy De Souza's avatar
Guy De Souza committed
155
  int offset = gNB->CC_id;
156 157 158 159 160 161
  uint8_t ssb_frame_periodicity;  // every how many frames SSB are generated

  if (cfg->sch_config.ssb_periodicity.value < 20)
    ssb_frame_periodicity = 1;
  else 
    ssb_frame_periodicity = (cfg->sch_config.ssb_periodicity.value)/10 ;  // 10ms is the frame length
Guy De Souza's avatar
Guy De Souza committed
162

163 164
  if ((cfg->subframe_config.duplex_mode.value == TDD) && 
      ((nr_slot_select(fp,frame,slot)&NR_UPLINK_SLOT) > 0)) return;
Guy De Souza's avatar
Guy De Souza committed
165

166
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
167

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

  // clear the transmit data array for the current subframe
171
  for (aa=0; aa<1/*15*/; aa++) {
172
    memset(gNB->common_vars.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
Guy De Souza's avatar
Guy De Souza committed
173 174
  }

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

  num_dci = gNB->pdcch_vars.num_dci;
183
  num_pdsch_rnti = gNB->pdcch_vars.num_pdsch_rnti;
184

185
  if (num_dci) {
Raymond Knopp's avatar
Raymond Knopp committed
186
    LOG_D(PHY, "[gNB %d] Frame %d slot %d \
187
    Calling nr_generate_dci_top (number of DCI %d)\n", gNB->Mod_id, frame, slot, num_dci);
Guy De Souza's avatar
Guy De Souza committed
188

Raymond Knopp's avatar
Raymond Knopp committed
189
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
190
    if (nfapi_mode == 0 || nfapi_mode == 1) {
191
      nr_generate_dci_top(gNB->pdcch_vars,
192
                          gNB->nr_gold_pdcch_dmrs[slot],
193
                          gNB->common_vars.txdataF[0],
194
                          AMP, *fp, *cfg);
Raymond Knopp's avatar
Raymond Knopp committed
195
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
Guy De Souza's avatar
Guy De Souza committed
196
      if (num_pdsch_rnti) {
Raymond Knopp's avatar
Raymond Knopp committed
197 198
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
        LOG_D(PHY, "PDSCH generation started (%d)\n", num_pdsch_rnti);
199 200
        nr_generate_pdsch(gNB->dlsch[0][0],
                          &gNB->pdcch_vars.dci_alloc[0],
201
                          gNB->nr_gold_pdsch_dmrs[slot],
Guy De Souza's avatar
Guy De Souza committed
202
                          gNB->common_vars.txdataF,
203 204 205 206 207
                          AMP, frame, slot, fp, cfg,
                          &gNB->dlsch_encoding_stats,
                          &gNB->dlsch_scrambling_stats,
                          &gNB->dlsch_modulation_stats);

Raymond Knopp's avatar
Raymond Knopp committed
208
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
Guy De Souza's avatar
Guy De Souza committed
209 210
      }
    }
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
*/

229
void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int UE_id, uint8_t harq_pid)
230 231
{
  NR_DL_FRAME_PARMS                    *frame_parms           = &gNB->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
232
  nfapi_nr_ul_config_ulsch_pdu         *rel15_ul              = &gNB->ulsch[ULSCH_id+1][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 261
  //ret = nr_ulsch_decoding(gNB,
  nr_ulsch_decoding(gNB,
Raymond Knopp's avatar
Raymond Knopp committed
262 263
                    ULSCH_id,
                    gNB->pusch_vars[ULSCH_id]->llr,
yilmazt's avatar
yilmazt committed
264
                    frame_parms,
265
                    frame_rx,
yilmazt's avatar
yilmazt committed
266
                    nfapi_ulsch_pdu_rel15->number_symbols,
267
                    slot_rx,
yilmazt's avatar
yilmazt committed
268 269
                    harq_pid,
                    0);
270 271 272 273 274 275 276
        
  // if (ret > ulsch_gNB->max_ldpc_iterations)
  //   n_errors++;

}


277 278 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 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
void nr_fill_rx_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int UE_id, uint8_t harq_pid)
{
  // --------------------
  // [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
  sync_pos                               = nr_est_timing_advance_pusch(gNB, UE_id);
  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;
    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);
}


344
void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
345 346

  uint8_t symbol;
347
  unsigned char aa;
348 349

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

}


365
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint8_t symbol_start, uint8_t symbol_end) {
366
  
Raymond Knopp's avatar
Raymond Knopp committed
367
  uint8_t ULSCH_id;
368 369 370 371
  uint8_t symbol;
  uint8_t harq_pid = 0; // [hna] Previously in LTE, the harq_pid was obtained from the subframe number (Synchronous HARQ)
                        //       In NR, this should be signaled through uplink scheduling dci (i.e, DCI 0_0, 0_1) (Asynchronous HARQ)  

372
  for (ULSCH_id = 0; ULSCH_id < /*NUMBER_OF_NR_ULSCH_MAX*/1; ULSCH_id++) { // temporary set to 1 untill list of connected UEs is implemented
373
    for(symbol = symbol_start; symbol < symbol_end; symbol++) {
374
      nr_rx_pusch(gNB, UE_id, frame_rx, slot_rx, symbol, harq_pid);
375
    }
376 377
    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
378
  }
379
}