gNB_scheduler_bch.c 29.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 59 60 61
uint16_t get_ssboffset_pointa(NR_ServingCellConfigCommon_t *scc,const long band) {

  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 95 96 97 98 99 100 101 102 103
                  *scc->ssbSubcarrierSpacing);
  }

  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
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {
143 144 145 146 147
  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;
148
  uint8_t num_tdd_period,num_ssb;
149 150 151 152 153 154
  int mib_sdu_length;
  int CC_id;

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

    // get MIB every 8 frames
160 161
    if(((slotP == 0) && (frameP & 7) == 0) ||
       gNB->first_MIB) {
162

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

165 166 167
      // flag to avoid sending an empty MIB in the first frames of execution since gNB doesn't get at the beginning in frame 0 slot 0
      gNB->first_MIB = false;

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

176 177
    int8_t ssb_period = *scc->ssb_periodicityServingCell;
    uint8_t ssb_frame_periodicity = 1;  // every how many frames SSB are generated
178

179 180
    if (ssb_period > 1) // 0 is every half frame
      ssb_frame_periodicity = 1 << (ssb_period -1);
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 208 209 210
    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
211
                schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
212 213
                fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id);
                if (get_softmodem_params()->sa == 1) {
214
                  get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
215 216 217 218
                                                        frameP,
                                                        mib,
                                                        slots_per_frame,
                                                        ssbSubcarrierOffset,
219
                                                        ssb_start_symbol,
220 221 222
                                                        scs,
                                                        FR1,
                                                        i_ssb,
223
                                                        ssb_frame_periodicity,
224
                                                        offset_pointa);
225
                  gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
226 227 228 229 230 231 232 233 234 235 236 237
                }
              }
            }
          }
          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
238
                schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
239 240
                fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id);
                if (get_softmodem_params()->sa == 1) {
241
                  get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
242 243 244 245
                                                        frameP,
                                                        mib,
                                                        slots_per_frame,
                                                        ssbSubcarrierOffset,
246
                                                        ssb_start_symbol,
247 248 249
                                                        scs,
                                                        FR1,
                                                        i_ssb,
250
                                                        ssb_frame_periodicity,
251
                                                        offset_pointa);
252
                  gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
253 254 255 256 257 258 259
                }
              }
            }
          }
          break;
        case 3:
          // long bitmap FR2 max 64 SSBs
260
          num_ssb = 0;
261 262
          for (int i_ssb=0; i_ssb<64; i_ssb++) {
            if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) {
263 264 265
              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
266
                schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1));
267
                fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id);
268 269 270 271
                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;
272 273 274
                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");
275
                if (get_softmodem_params()->sa == 1) {
276
                  get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
277 278 279 280
                                                        frameP,
                                                        mib,
                                                        slots_per_frame,
                                                        ssbSubcarrierOffset,
281
                                                        ssb_start_symbol,
282 283 284
                                                        scs,
                                                        FR2,
                                                        i_ssb,
285
                                                        ssb_frame_periodicity,
286
                                                        offset_pointa);
287
                  gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
288 289 290 291 292 293 294 295 296
                }
              }
            }
          }
          break;
        default:
          AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
                      scc->ssb_PositionsInBurst->present);
      }
297
    }
298 299
  }
}
300

301

302
void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
rmagueta's avatar
rmagueta committed
303
//----------------------------------------  
304 305
}

306 307 308 309 310 311
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");

312
  uint16_t *vrb_map = cc[CC_id].vrb_map;
313

314
  for (int rb = 0; rb < 20; rb++)
315 316
    vrb_map[rbStart + rb] = 15<<symStart;

317
}
rmagueta's avatar
rmagueta committed
318

319 320 321 322 323 324
uint32_t schedule_control_sib1(module_id_t module_id,
                               int CC_id,
                               NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
                               int time_domain_allocation,
                               int startSymbolIndex,
                               int nrOfSymbols,
325
                               uint16_t dlDmrsSymbPos,
326 327
                               uint8_t candidate_idx,
                               int num_total_bytes) {
rmagueta's avatar
rmagueta committed
328 329

  gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
rmagueta's avatar
rmagueta committed
330
  uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
rmagueta's avatar
rmagueta committed
331 332

  if (gNB_mac->sched_ctrlCommon == NULL){
rmagueta's avatar
rmagueta committed
333
    LOG_D(NR_MAC,"schedule_control_common: Filling nr_mac->sched_ctrlCommon\n");
rmagueta's avatar
rmagueta committed
334 335 336
    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));
francescomani's avatar
francescomani committed
337
    fill_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space,type0_PDCCH_CSS_config);
338
    fill_coresetZero(gNB_mac->sched_ctrlCommon->coreset,type0_PDCCH_CSS_config);
rmagueta's avatar
rmagueta committed
339 340
  }

341
  gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation = time_domain_allocation;
342 343
  gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx = 0;
  gNB_mac->sched_ctrlCommon->sched_pdsch.mcs = 0; // starting from mcs 0
rmagueta's avatar
rmagueta committed
344 345 346
  gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes;

  uint8_t nr_of_candidates;
347 348 349 350 351

  for (int i=0; i<3; i++) {
    find_aggregation_candidates(&gNB_mac->sched_ctrlCommon->aggregation_level, &nr_of_candidates, gNB_mac->sched_ctrlCommon->search_space,4<<i);
    if (nr_of_candidates>0) break; // choosing the lower value of aggregation level available
  }
Eurecom's avatar
Eurecom committed
352
  AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n");
rmagueta's avatar
rmagueta committed
353
  gNB_mac->sched_ctrlCommon->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
354
                                                          NULL,
rmagueta's avatar
rmagueta committed
355 356 357
                                                          gNB_mac->sched_ctrlCommon->coreset,
                                                          gNB_mac->sched_ctrlCommon->aggregation_level,
                                                          0,
358
                                                          candidate_idx,
rmagueta's avatar
rmagueta committed
359 360
                                                          nr_of_candidates);

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

363 364
  const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs;
  int rbStart = type0_PDCCH_CSS_config->cset_start_rb;
rmagueta's avatar
rmagueta committed
365

366 367 368
  // TODO: There are exceptions to this in table 5.1.2.1.1-4,5 (Default time domain allocation tables B, C)
  int mappingtype = (startSymbolIndex <= 3)? typeA: typeB;

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

  // Calculate number of PRB_DMRS
376
  uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6;
377
  uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos);
rmagueta's avatar
rmagueta committed
378

379
  LOG_D(MAC,"dlDmrsSymbPos %x\n",dlDmrsSymbPos);
rmagueta's avatar
rmagueta committed
380 381 382
  int rbSize = 0;
  uint32_t TBS = 0;
  do {
383 384 385
    if(rbSize < bwpSize && !vrb_map[rbStart + rbSize])
      rbSize++;
    else{
386 387
      if (gNB_mac->sched_ctrlCommon->sched_pdsch.mcs<10)
        gNB_mac->sched_ctrlCommon->sched_pdsch.mcs++;
388 389 390
      else
        break;
    }
391 392
    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),
393
                         rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3;
394 395 396 397
  } while (TBS < gNB_mac->sched_ctrlCommon->num_total_bytes);

  AssertFatal(TBS>=gNB_mac->sched_ctrlCommon->num_total_bytes,"Couldn't allocate enough resources for %d bytes in SIB1 PDSCH\n",
              gNB_mac->sched_ctrlCommon->num_total_bytes);
398

399 400
  gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize = rbSize;
  gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart = 0;
rmagueta's avatar
rmagueta committed
401

402
  LOG_D(MAC,"mcs = %i\n", gNB_mac->sched_ctrlCommon->sched_pdsch.mcs);
francescomani's avatar
francescomani committed
403 404
  LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex);
  LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols);
405
  LOG_D(MAC, "rbSize = %i\n", gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize);
francescomani's avatar
francescomani committed
406 407 408
  LOG_D(MAC,"TBS = %i\n", TBS);
  LOG_D(MAC,"dmrs_length %d\n",dmrs_length);
  LOG_D(MAC,"N_PRB_DMRS = %d\n",N_PRB_DMRS);
409
  LOG_D(MAC,"mappingtype = %d\n", mappingtype);
410

rmagueta's avatar
rmagueta committed
411
  // Mark the corresponding RBs as used
412
  for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize; rb++) {
rmagueta's avatar
rmagueta committed
413 414
    vrb_map[rb + rbStart] = 1;
  }
415
  return TBS;
rmagueta's avatar
rmagueta committed
416 417 418 419
}

void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
                               nfapi_nr_dl_tti_request_body_t *dl_req,
420
                               NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
rmagueta's avatar
rmagueta committed
421 422
                               uint32_t TBS,
                               int StartSymbolIndex,
423 424
                               int NrOfSymbols,
                               uint16_t dlDmrsSymbPos) {
rmagueta's avatar
rmagueta committed
425 426 427 428 429 430 431 432 433

  gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP];
  NR_COMMON_channels_t *cc = gNB_mac->common_channels;
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;

  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));
434 435
  dl_req->nPDUs += 1;
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
436
  nr_configure_pdcch(pdcch_pdu_rel15,
437 438 439
                     gNB_mac->sched_ctrlCommon->search_space,
                     gNB_mac->sched_ctrlCommon->coreset,
                     scc,
440 441
                     NULL,
                     type0_PDCCH_CSS_config);
442

443
  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
444 445 446
  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));
447
  dl_req->nPDUs += 1;
rmagueta's avatar
rmagueta committed
448 449 450 451 452 453 454 455
  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]++;

456 457
  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
458

459 460
  pdsch_pdu_rel15->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch;
  pdsch_pdu_rel15->CyclicPrefix = 0;
rmagueta's avatar
rmagueta committed
461 462

  pdsch_pdu_rel15->NrOfCodewords = 1;
463
  pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, 0);
rmagueta's avatar
rmagueta committed
464
  pdsch_pdu_rel15->qamModOrder[0] = 2;
465
  pdsch_pdu_rel15->mcsIndex[0] = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs;
rmagueta's avatar
rmagueta committed
466 467 468 469 470 471
  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;
472
  pdsch_pdu_rel15->dmrsConfigType = 0;
rmagueta's avatar
rmagueta committed
473 474
  pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
  pdsch_pdu_rel15->SCID = 0;
475
  pdsch_pdu_rel15->numDmrsCdmGrpsNoData = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData;
rmagueta's avatar
rmagueta committed
476 477
  pdsch_pdu_rel15->dmrsPorts = 1;
  pdsch_pdu_rel15->resourceAlloc = 1;
478 479
  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
480
  pdsch_pdu_rel15->VRBtoPRBMapping = 0;
481 482
  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
483
  pdsch_pdu_rel15->TBSize[0] = TBS;
484
  pdsch_pdu_rel15->mcsTable[0] = gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx;
rmagueta's avatar
rmagueta committed
485 486
  pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
  pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
487
  pdsch_pdu_rel15->dlDmrsSymbPos = dlDmrsSymbPos;
488 489
  LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos);

490 491 492 493 494 495 496 497 498 499
  /* 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
500

501 502 503 504
  /* DCI payload */
  dci_pdu_rel15_t dci_payload;
  memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));

505
  dci_payload.bwp_indicator.val = 0;
rmagueta's avatar
rmagueta committed
506 507

  // frequency domain assignment
508
  dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(
509
      pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, type0_PDCCH_CSS_config->num_rbs);
510

511 512
  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;
513 514 515 516 517 518 519 520 521
  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
522

523 524 525 526
  int dci_format = NR_DL_DCI_FORMAT_1_0;
  int rnti_type = NR_RNTI_SI;

  fill_dci_pdu_rel15(scc,
527
                     NULL,
528
                     &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1],
529
                     &dci_payload,
530 531 532
                     dci_format,
                     rnti_type,
                     pdsch_pdu_rel15->BWPSize,
533
                     0);
rmagueta's avatar
rmagueta committed
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553

  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) {

554
  // TODO: Get these values from RRC
rmagueta's avatar
rmagueta committed
555
  const int CC_id = 0;
556
  uint8_t candidate_idx = 0;
rmagueta's avatar
rmagueta committed
557 558

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

francescomani's avatar
francescomani committed
561 562
  int time_domain_allocation = gNB_mac->sib1_tda;

563 564 565 566 567 568 569
  int L_max;
  switch (scc->ssb_PositionsInBurst->present) {
    case 1:
      L_max = 4;
      break;
    case 2:
      L_max = 8;
francescomani's avatar
francescomani committed
570
      break;
571 572
    case 3:
      L_max = 64;
francescomani's avatar
francescomani committed
573
      break;
574 575 576 577 578 579
    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++) {
580 581

    NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
582 583 584 585 586

    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
587

588
      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
589

590 591
      // Get SIB1
      uint8_t sib1_payload[NR_MAX_SIB_LENGTH/8];
592 593 594
      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");
595 596
      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
597

598 599
      int startSymbolIndex = 0;
      int nrOfSymbols = 0;
600 601 602 603 604 605

      get_info_from_tda_tables(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern,
                               time_domain_allocation,
                               gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position,
                               1, &startSymbolIndex, &nrOfSymbols);

606
      // TODO: There are exceptions to this in table 5.1.2.1.1-4,5 (Default time domain allocation tables B, C)
607
      int mappingtype = (startSymbolIndex <= 3)? typeA: typeB;
rmagueta's avatar
rmagueta committed
608

609
      uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex, mappingtype);
rmagueta's avatar
rmagueta committed
610

611 612 613 614 615 616
      // Configure sched_ctrlCommon for SIB1
      uint32_t TBS = schedule_control_sib1(module_idP, CC_id,
                                           type0_PDCCH_CSS_config,
                                           time_domain_allocation,
                                           startSymbolIndex,
                                           nrOfSymbols,
617
                                           dlDmrsSymbPos,
618 619
                                           candidate_idx, sib1_sdu_length);

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

623 624
      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
625

626 627 628
      // 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
629

630 631 632 633 634 635 636
      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;
637 638

      type0_PDCCH_CSS_config->active = false;
639
    }
rmagueta's avatar
rmagueta committed
640
  }
641
}