gNB_scheduler_bch.c 30.1 KB
Newer Older
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
 */

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
22
/*! \file gNB_scheduler_bch.c
23
 * \brief procedures related to eNB for the BCH transport channel
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
24 25 26
 * \author  Navid Nikaein and Raymond Knopp, WEI-TAI CHEN
 * \date 2010 - 2014, 2018
 * \email: navid.nikaein@eurecom.fr, kroempa@gmail.com
27
 * \version 1.0
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
28
 * \company Eurecom, NTUST
29 30 31 32
 * @ingroup _mac

 */

33
#include "GNB_APP/RRC_nr_paramsvalues.h"
34
#include "assertions.h"
35 36 37
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_COMMON/nr_mac_extern.h"
Raymond Knopp's avatar
Raymond Knopp committed
38 39
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
40 41 42
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "RRC/NR/nr_rrc_extern.h"
43
#include "common/utils/nr/nr_common.h"
44 45 46 47 48 49 50 51 52


#include "pdcp.h"

#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1

#include "common/ran_context.h"

53 54
#include "executables/softmodem-common.h"

55 56 57
extern RAN_CONTEXT_t RC;


58
uint16_t get_ssboffset_pointa(NR_ServingCellConfigCommon_t *scc,const long band) {
59

60 61
  int ratio;
  switch (*scc->ssbSubcarrierSpacing) {
62
    case NR_SubcarrierSpacing_kHz15:
Robert Schmidt's avatar
Robert Schmidt committed
63 64 65 66 67
      AssertFatal(band <= 79,
                  "Band %ld is not possible for SSB with 15 kHz SCS\n",
                  band);
      if (band < 77)  // below 3GHz
        ratio = 3;    // NRARFCN step is 5 kHz
68
      else
Robert Schmidt's avatar
Robert Schmidt committed
69
        ratio = 1;  // NRARFCN step is 15 kHz
70 71
      break;
    case NR_SubcarrierSpacing_kHz30:
Robert Schmidt's avatar
Robert Schmidt committed
72 73 74 75 76
      AssertFatal(band <= 79,
                  "Band %ld is not possible for SSB with 15 kHz SCS\n",
                  band);
      if (band < 77)  // below 3GHz
        ratio = 6;    // NRARFCN step is 5 kHz
77
      else
Robert Schmidt's avatar
Robert Schmidt committed
78
        ratio = 2;  // NRARFCN step is 15 kHz
79 80
      break;
    case NR_SubcarrierSpacing_kHz120:
Robert Schmidt's avatar
Robert Schmidt committed
81 82 83 84
      AssertFatal(band >= 257,
                  "Band %ld is not possible for SSB with 120 kHz SCS\n",
                  band);
      ratio = 2;  // NRARFCN step is 15 kHz
85 86
      break;
    case NR_SubcarrierSpacing_kHz240:
Robert Schmidt's avatar
Robert Schmidt committed
87 88 89 90
      AssertFatal(band >= 257,
                  "Band %ld is not possible for SSB with 240 kHz SCS\n",
                  band);
      ratio = 4;  // NRARFCN step is 15 kHz
91 92
      break;
    default:
Robert Schmidt's avatar
Robert Schmidt committed
93
      AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n",
94
                  *scc->ssbSubcarrierSpacing);
95 96 97 98 99 100 101 102 103
  }

  const uint32_t ssb_offset0 = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;

  return (ssb_offset0/(ratio*12) - 10); // absoluteFrequencySSB is the center of SSB

}


francescomani's avatar
francescomani committed
104 105 106 107
void schedule_ssb(frame_t frame, sub_frame_t slot,
                  NR_ServingCellConfigCommon_t *scc,
                  nfapi_nr_dl_tti_request_body_t *dl_req,
                  int i_ssb, uint8_t scoffset, uint16_t offset_pointa, uint32_t payload) {
108

109
  uint8_t beam_index = 0;
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
  nfapi_nr_dl_tti_request_pdu_t  *dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
  memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
  dl_config_pdu->PDUType      = NFAPI_NR_DL_TTI_SSB_PDU_TYPE;
  dl_config_pdu->PDUSize      =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t);

  AssertFatal(scc->physCellId!=NULL,"ServingCellConfigCommon->physCellId is null\n");
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId          = *scc->physCellId;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss             = 0;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex       = i_ssb;
  AssertFatal(scc->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n");
  AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
  AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n");
  AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n",
              scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count);
  AssertFatal(scc->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n");
  AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n");

  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = scoffset; //kSSB
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA     = offset_pointa;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag      = 1;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload          = payload;
131 132 133 134 135
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs=1;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size=275; //1 PRG of max size for analogue beamforming
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces=1;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0;
  dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
136 137
  dl_req->nPDUs++;

francescomani's avatar
francescomani committed
138 139
  LOG_D(MAC,"Scheduling ssb %d at frame %d and slot %d\n",i_ssb,frame,slot);

140
}
141

142 143
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
{
144 145 146 147 148
  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc;
  nfapi_nr_dl_tti_request_t      *dl_tti_request;
  nfapi_nr_dl_tti_request_body_t *dl_req;
  NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib.message.choice.mib;
149
  uint8_t num_tdd_period,num_ssb;
150 151
  int mib_sdu_length;
  int CC_id;
152

153 154 155
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    cc = &gNB->common_channels[CC_id];
    NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
156
    const int slots_per_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
157 158 159 160
    dl_tti_request = &gNB->DL_req[CC_id];
    dl_req = &dl_tti_request->dl_tti_request_body;

    // get MIB every 8 frames
161 162
    if((slotP == 0) && (frameP & 7) == 0) {

163
      mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 0, 1, &cc->MIB_pdu.payload[0]);
164

165
      LOG_D(MAC,
166 167 168 169 170 171
            "[gNB %d] Frame %d : MIB->BCH  CC_id %d, Received %d bytes\n",
            module_idP,
            frameP,
            CC_id,
            mib_sdu_length);
    }
172

173 174
    int8_t ssb_period = *scc->ssb_periodicityServingCell;
    uint8_t ssb_frame_periodicity = 1;  // every how many frames SSB are generated
175

176 177
    if (ssb_period > 1) // 0 is every half frame
      ssb_frame_periodicity = 1 << (ssb_period -1);
178

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    if (!(frameP%ssb_frame_periodicity) &&
        ((slotP<(slots_per_frame>>1)) || (ssb_period == 0))) {
      // schedule SSB only for given frames according to SSB periodicity
      // and in first half frame unless periodicity of 5ms
      int rel_slot;
      if (ssb_period == 0) // scheduling every half frame
        rel_slot = slotP%(slots_per_frame>>1);
      else
        rel_slot = slotP;

      NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing;
      const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
      uint16_t offset_pointa = get_ssboffset_pointa(scc,band);
      uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset;

      const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
      const BIT_STRING_t *mediumBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap;
      const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;

      uint16_t ssb_start_symbol;

      switch (scc->ssb_PositionsInBurst->present) {
        case 1:
          // short bitmap (<3GHz) max 4 SSBs
          for (int i_ssb=0; i_ssb<4; i_ssb++) {
            if ((shortBitmap->buf[0]>>(7-i_ssb))&0x01) {
              ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
              // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
              if ((ssb_start_symbol/14) == rel_slot){
francescomani's avatar
francescomani committed
208
                schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
209 210
                fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id);
                if (get_softmodem_params()->sa == 1) {
211
                  get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
212 213 214 215
                                                        frameP,
                                                        mib,
                                                        slots_per_frame,
                                                        ssbSubcarrierOffset,
216
                                                        ssb_start_symbol,
217 218 219 220
                                                        scs,
                                                        FR1,
                                                        i_ssb,
                                                        offset_pointa);
221
                  gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
222 223 224 225 226 227 228 229 230 231 232 233
                }
              }
            }
          }
          break;
        case 2:
          // medium bitmap (<6GHz) max 8 SSBs
          for (int i_ssb=0; i_ssb<8; i_ssb++) {
            if ((mediumBitmap->buf[0]>>(7-i_ssb))&0x01) {
              ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
              // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
              if ((ssb_start_symbol/14) == rel_slot){
francescomani's avatar
francescomani committed
234
                schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
235 236
                fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id);
                if (get_softmodem_params()->sa == 1) {
237
                  get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
238 239 240 241
                                                        frameP,
                                                        mib,
                                                        slots_per_frame,
                                                        ssbSubcarrierOffset,
242
                                                        ssb_start_symbol,
243 244 245 246
                                                        scs,
                                                        FR1,
                                                        i_ssb,
                                                        offset_pointa);
247
                  gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
248 249 250 251 252 253 254
                }
              }
            }
          }
          break;
        case 3:
          // long bitmap FR2 max 64 SSBs
255
          num_ssb = 0;
256 257
          for (int i_ssb=0; i_ssb<64; i_ssb++) {
            if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) {
258 259 260
              ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
              // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
              if ((ssb_start_symbol/14) == rel_slot){
francescomani's avatar
francescomani committed
261
                schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
262
                fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id);
263 264 265 266
                const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
                const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0;
                const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots;
                num_tdd_period = rel_slot/nr_slots_period;
267 268 269
                gNB->tdd_beam_association[num_tdd_period]=i_ssb;
                num_ssb++;
                AssertFatal(num_ssb<2,"beamforming currently not supported for more than one SSB per slot\n");
270
                if (get_softmodem_params()->sa == 1) {
271
                  get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
272 273 274 275
                                                        frameP,
                                                        mib,
                                                        slots_per_frame,
                                                        ssbSubcarrierOffset,
276
                                                        ssb_start_symbol,
277 278 279 280
                                                        scs,
                                                        FR2,
                                                        i_ssb,
                                                        offset_pointa);
281
                  gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
282 283 284 285 286 287 288 289
                }
              }
            }
          }
          break;
        default:
          AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
                      scc->ssb_PositionsInBurst->present);
290
      }
291
    }
292 293
  }
}
294

295

296
void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
rmagueta's avatar
rmagueta committed
297
//----------------------------------------  
298 299
}

300 301 302 303 304 305
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart,  uint16_t symStart, int CC_id) {

  AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing !=
              NR_SubcarrierSpacing_kHz240,
              "240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n");

306
  uint16_t *vrb_map = cc[CC_id].vrb_map;
307

308
  for (int rb = 0; rb < 20; rb++)
309 310
    vrb_map[rbStart + rb] = 15<<symStart;

311
}
rmagueta's avatar
rmagueta committed
312 313 314

void schedule_control_sib1(module_id_t module_id,
                           int CC_id,
315
                           NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
rmagueta's avatar
rmagueta committed
316 317 318
                           int time_domain_allocation,
                           uint8_t mcsTableIdx,
                           uint8_t mcs,
319
                           uint8_t candidate_idx,
rmagueta's avatar
rmagueta committed
320 321 322 323
                           int num_total_bytes) {

  gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
  NR_ServingCellConfigCommon_t *servingcellconfigcommon = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
rmagueta's avatar
rmagueta committed
324
  uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
rmagueta's avatar
rmagueta committed
325 326

  if (gNB_mac->sched_ctrlCommon == NULL){
rmagueta's avatar
rmagueta committed
327
    LOG_D(NR_MAC,"schedule_control_common: Filling nr_mac->sched_ctrlCommon\n");
rmagueta's avatar
rmagueta committed
328 329 330
    gNB_mac->sched_ctrlCommon = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon));
    gNB_mac->sched_ctrlCommon->search_space = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->search_space));
    gNB_mac->sched_ctrlCommon->coreset = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->coreset));
331
    gNB_mac->sched_ctrlCommon->active_bwp = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->active_bwp));
rmagueta's avatar
rmagueta committed
332 333 334 335 336
    fill_default_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space);
    fill_default_coresetZero(gNB_mac->sched_ctrlCommon->coreset,servingcellconfigcommon);
    fill_default_initialDownlinkBWP(gNB_mac->sched_ctrlCommon->active_bwp,servingcellconfigcommon);
  }

337 338 339
  gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation = time_domain_allocation;
  gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx = mcsTableIdx;
  gNB_mac->sched_ctrlCommon->sched_pdsch.mcs = mcs;
rmagueta's avatar
rmagueta committed
340 341 342 343 344 345 346 347 348 349
  gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes;

  uint8_t nr_of_candidates;
  find_aggregation_candidates(&gNB_mac->sched_ctrlCommon->aggregation_level, &nr_of_candidates, gNB_mac->sched_ctrlCommon->search_space);

  gNB_mac->sched_ctrlCommon->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
                                                          gNB_mac->sched_ctrlCommon->active_bwp,
                                                          gNB_mac->sched_ctrlCommon->coreset,
                                                          gNB_mac->sched_ctrlCommon->aggregation_level,
                                                          0,
350
                                                          candidate_idx,
rmagueta's avatar
rmagueta committed
351 352
                                                          nr_of_candidates);

353
  AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n");
rmagueta's avatar
rmagueta committed
354

355 356
  const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs;
  int rbStart = type0_PDCCH_CSS_config->cset_start_rb;
rmagueta's avatar
rmagueta committed
357

358 359 360
  int startSymbolIndex = 0;
  int nrOfSymbols = 0;
  if(gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position == 0) {
361 362
    startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][1];
    nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][2];
363
  } else {
364 365
    startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][1];
    nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][2];
366
  }
rmagueta's avatar
rmagueta committed
367

368
  if (nrOfSymbols == 2) {
369
    gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 1;
370
  } else {
371
    gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 2;
372 373 374
  }

  // Calculate number of PRB_DMRS
375
  uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6;
376
  uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex);
377
  uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos);
rmagueta's avatar
rmagueta committed
378 379 380 381 382

  int rbSize = 0;
  uint32_t TBS = 0;
  do {
    rbSize++;
383 384 385 386
    TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
                                      gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
                         nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
                                             gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
387
                         rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3;
388
  } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes);
389

390 391
  gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize = rbSize;
  gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart = 0;
rmagueta's avatar
rmagueta committed
392

393 394
  LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex);
  LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols);
395
  LOG_D(MAC, "rbSize = %i\n", gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize);
rmagueta's avatar
rmagueta committed
396
  LOG_D(MAC,"TBS = %i\n", TBS);
397

rmagueta's avatar
rmagueta committed
398
  // Mark the corresponding RBs as used
399
  for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize; rb++) {
rmagueta's avatar
rmagueta committed
400 401 402 403 404 405
    vrb_map[rb + rbStart] = 1;
  }
}

void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
                               nfapi_nr_dl_tti_request_body_t *dl_req,
406
                               NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
rmagueta's avatar
rmagueta committed
407 408 409 410 411 412 413 414 415 416 417 418 419 420
                               uint32_t TBS,
                               int StartSymbolIndex,
                               int NrOfSymbols) {

  gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP];
  NR_COMMON_channels_t *cc = gNB_mac->common_channels;
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  NR_CellGroupConfig_t *secondaryCellGroup = gNB_mac->secondaryCellGroupCommon;
  NR_BWP_Downlink_t *bwp = gNB_mac->sched_ctrlCommon->active_bwp;

  nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
  memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
  dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
  dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
421 422 423 424 425 426 427
  dl_req->nPDUs += 1;
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
  nr_configure_pdcch(pdcch_pdu_rel15,
                     gNB_mac->sched_ctrlCommon->search_space,
                     gNB_mac->sched_ctrlCommon->coreset,
                     scc,
                     bwp);
rmagueta's avatar
rmagueta committed
428

429
  // TODO: This assignment should be done in function nr_configure_pdcch()
430 431
  pdcch_pdu_rel15->BWPSize = type0_PDCCH_CSS_config->num_rbs;
  pdcch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
432

433
  nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
rmagueta's avatar
rmagueta committed
434 435 436
  memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
  dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
  dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
437
  dl_req->nPDUs += 1;
rmagueta's avatar
rmagueta committed
438 439 440 441 442 443 444 445
  nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;

  pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1;

  pdsch_pdu_rel15->pduBitmap = 0;
  pdsch_pdu_rel15->rnti = SI_RNTI;
  pdsch_pdu_rel15->pduIndex = gNB_mac->pdu_index[0]++;

446 447
  pdsch_pdu_rel15->BWPSize  = type0_PDCCH_CSS_config->num_rbs;
  pdsch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
rmagueta's avatar
rmagueta committed
448 449 450 451 452 453 454 455 456

  pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
  if (bwp->bwp_Common->genericParameters.cyclicPrefix) {
    pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix;
  } else {
    pdsch_pdu_rel15->CyclicPrefix = 0;
  }

  pdsch_pdu_rel15->NrOfCodewords = 1;
457
  pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, 0);
rmagueta's avatar
rmagueta committed
458
  pdsch_pdu_rel15->qamModOrder[0] = 2;
459
  pdsch_pdu_rel15->mcsIndex[0] = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs;
rmagueta's avatar
rmagueta committed
460 461 462 463 464 465
  pdsch_pdu_rel15->mcsTable[0] = 0;
  pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[0];
  pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
  pdsch_pdu_rel15->nrOfLayers = 1;
  pdsch_pdu_rel15->transmissionScheme = 0;
  pdsch_pdu_rel15->refPoint = 1;
466
  pdsch_pdu_rel15->dmrsConfigType = 0;
rmagueta's avatar
rmagueta committed
467 468
  pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
  pdsch_pdu_rel15->SCID = 0;
469
  pdsch_pdu_rel15->numDmrsCdmGrpsNoData = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData;
rmagueta's avatar
rmagueta committed
470 471
  pdsch_pdu_rel15->dmrsPorts = 1;
  pdsch_pdu_rel15->resourceAlloc = 1;
472 473
  pdsch_pdu_rel15->rbStart = gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart;
  pdsch_pdu_rel15->rbSize = gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize;
rmagueta's avatar
rmagueta committed
474
  pdsch_pdu_rel15->VRBtoPRBMapping = 0;
475 476
  pdsch_pdu_rel15->qamModOrder[0] = nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
                                                 gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx);
rmagueta's avatar
rmagueta committed
477
  pdsch_pdu_rel15->TBSize[0] = TBS;
478
  pdsch_pdu_rel15->mcsTable[0] = gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx;
rmagueta's avatar
rmagueta committed
479 480 481
  pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
  pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;

482
  pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, pdsch_pdu_rel15->NrOfSymbols, pdsch_pdu_rel15->StartSymbolIndex);
rmagueta's avatar
rmagueta committed
483

484 485
  LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos);

486 487 488 489 490 491 492 493 494 495
  /* Fill PDCCH DL DCI PDU */
  nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
  pdcch_pdu_rel15->numDlDci++;
  dci_pdu->RNTI = SI_RNTI;
  dci_pdu->ScramblingId = *scc->physCellId;
  dci_pdu->ScramblingRNTI = 0;
  dci_pdu->AggregationLevel = gNB_mac->sched_ctrlCommon->aggregation_level;
  dci_pdu->CceIndex = gNB_mac->sched_ctrlCommon->cce_index;
  dci_pdu->beta_PDCCH_1_0 = 0;
  dci_pdu->powerControlOffsetSS = 1;
rmagueta's avatar
rmagueta committed
496

497 498 499
  /* DCI payload */
  dci_pdu_rel15_t dci_payload;
  memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));
rmagueta's avatar
rmagueta committed
500

501
  dci_payload.bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id;
rmagueta's avatar
rmagueta committed
502 503

  // frequency domain assignment
504
  dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(
505
      pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, type0_PDCCH_CSS_config->num_rbs);
506

507 508
  dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation;
  dci_payload.mcs = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs;
509 510 511 512 513 514 515 516 517
  dci_payload.rv = pdsch_pdu_rel15->rvIndex[0];
  dci_payload.harq_pid = 0;
  dci_payload.ndi = 0;
  dci_payload.dai[0].val = 0;
  dci_payload.tpc = 0; // table 7.2.1-1 in 38.213
  dci_payload.pucch_resource_indicator = 0;
  dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0;
  dci_payload.antenna_ports.val = 0;
  dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
rmagueta's avatar
rmagueta committed
518

519 520 521 522 523 524
  int dci_format = NR_DL_DCI_FORMAT_1_0;
  int rnti_type = NR_RNTI_SI;

  fill_dci_pdu_rel15(scc,
                     secondaryCellGroup,
                     &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1],
525
                     &dci_payload,
526 527 528 529
                     dci_format,
                     rnti_type,
                     pdsch_pdu_rel15->BWPSize,
                     gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id);
rmagueta's avatar
rmagueta committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549

  LOG_D(MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize);
  LOG_D(MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart);
  LOG_D(MAC,"SubcarrierSpacing: %i\n", pdcch_pdu_rel15->SubcarrierSpacing);
  LOG_D(MAC,"CyclicPrefix: %i\n", pdcch_pdu_rel15->CyclicPrefix);
  LOG_D(MAC,"StartSymbolIndex: %i\n", pdcch_pdu_rel15->StartSymbolIndex);
  LOG_D(MAC,"DurationSymbols: %i\n", pdcch_pdu_rel15->DurationSymbols);
  for(int n=0;n<6;n++) LOG_D(MAC,"FreqDomainResource[%i]: %x\n",n, pdcch_pdu_rel15->FreqDomainResource[n]);
  LOG_D(MAC,"CceRegMappingType: %i\n", pdcch_pdu_rel15->CceRegMappingType);
  LOG_D(MAC,"RegBundleSize: %i\n", pdcch_pdu_rel15->RegBundleSize);
  LOG_D(MAC,"InterleaverSize: %i\n", pdcch_pdu_rel15->InterleaverSize);
  LOG_D(MAC,"CoreSetType: %i\n", pdcch_pdu_rel15->CoreSetType);
  LOG_D(MAC,"ShiftIndex: %i\n", pdcch_pdu_rel15->ShiftIndex);
  LOG_D(MAC,"precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity);
  LOG_D(MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci);

}

void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {

550
  // TODO: Get these values from RRC
rmagueta's avatar
rmagueta committed
551
  const int CC_id = 0;
552
  int time_domain_allocation = 0;
rmagueta's avatar
rmagueta committed
553
  uint8_t mcsTableIdx = 0;
554
  uint8_t mcs = 6;
555
  uint8_t candidate_idx = 0;
rmagueta's avatar
rmagueta committed
556 557

  gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
558
  NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
rmagueta's avatar
rmagueta committed
559

560 561 562 563 564 565 566
  int L_max;
  switch (scc->ssb_PositionsInBurst->present) {
    case 1:
      L_max = 4;
      break;
    case 2:
      L_max = 8;
francescomani's avatar
francescomani committed
567
      break;
568 569
    case 3:
      L_max = 64;
francescomani's avatar
francescomani committed
570
      break;
571 572 573 574 575 576
    default:
      AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
                  scc->ssb_PositionsInBurst->present);
  }

  for (int i=0; i<L_max; i++) {
577 578

    NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
rmagueta's avatar
rmagueta committed
579

580 581 582 583
    if((frameP%2 == type0_PDCCH_CSS_config->sfn_c) &&
       (slotP == type0_PDCCH_CSS_config->n_0) &&
       (type0_PDCCH_CSS_config->num_rbs > 0) &&
       (type0_PDCCH_CSS_config->active == true)) {
rmagueta's avatar
rmagueta committed
584

585
      LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
rmagueta's avatar
rmagueta committed
586

587 588
      // Get SIB1
      uint8_t sib1_payload[NR_MAX_SIB_LENGTH/8];
589 590 591
      uint8_t sib1_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, BCCH, SI_RNTI, 1, sib1_payload);
      LOG_D(NR_MAC,"sib1_sdu_length = %i\n", sib1_sdu_length);
      LOG_D(NR_MAC,"SIB1: \n");
592 593
      for (int k=0;k<sib1_sdu_length;k++)
        LOG_D(NR_MAC,"byte %d : %x\n",k,((uint8_t*)sib1_payload)[k]);
rmagueta's avatar
rmagueta committed
594

595
      // Configure sched_ctrlCommon for SIB1
596
      schedule_control_sib1(module_idP, CC_id, type0_PDCCH_CSS_config, time_domain_allocation, mcsTableIdx, mcs, candidate_idx, sib1_sdu_length);
rmagueta's avatar
rmagueta committed
597

598 599 600
      int startSymbolIndex = 0;
      int nrOfSymbols = 0;
      if(gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position == 0) {
601 602
        startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][1];
        nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][2];
603
      } else {
604 605
        startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][1];
        nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation][2];
606
      }
rmagueta's avatar
rmagueta committed
607

608
      // Calculate number of PRB_DMRS
609
      uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6;
610 611
      uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex);
      uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos);
rmagueta's avatar
rmagueta committed
612

613 614 615
      const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
                                          nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
                                          gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0 ,0 ,1 ) >> 3;
rmagueta's avatar
rmagueta committed
616

617 618
      nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
      nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, type0_PDCCH_CSS_config, TBS, startSymbolIndex, nrOfSymbols);
rmagueta's avatar
rmagueta committed
619

620 621
      const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
      nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
rmagueta's avatar
rmagueta committed
622

623 624 625
      // Data to be transmitted
      bzero(tx_req->TLVs[0].value.direct,MAX_NR_DLSCH_PAYLOAD_BYTES);
      memcpy(tx_req->TLVs[0].value.direct, sib1_payload, sib1_sdu_length);
rmagueta's avatar
rmagueta committed
626

627 628 629 630 631 632 633
      tx_req->PDU_length = TBS;
      tx_req->PDU_index  = gNB_mac->pdu_index[0]++;
      tx_req->num_TLV = 1;
      tx_req->TLVs[0].length = TBS + 2;
      gNB_mac->TX_req[CC_id].Number_of_PDUs++;
      gNB_mac->TX_req[CC_id].SFN = frameP;
      gNB_mac->TX_req[CC_id].Slot = slotP;
634 635

      type0_PDCCH_CSS_config->active = false;
636
    }
rmagueta's avatar
rmagueta committed
637
  }
638
}