mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
reworked version of commit c30ad1d07b
Co-Authored-By: @mjoang_oai
Signed-off-by: francescomani <email@francescomani.it>
876 lines
39 KiB
C
876 lines
39 KiB
C
/*
|
||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||
*/
|
||
|
||
/*!
|
||
* \brief procedures related to gNB for the BCH transport channel
|
||
*/
|
||
|
||
#include "assertions.h"
|
||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||
#include "NR_MAC_gNB/mac_proto.h"
|
||
#include "common/utils/LOG/log.h"
|
||
#include "UTIL/OPT/opt.h"
|
||
#include "common/utils/nr/nr_common.h"
|
||
|
||
#define ENABLE_MAC_PAYLOAD_DEBUG
|
||
|
||
#include "common/ran_context.h"
|
||
|
||
#include "executables/softmodem-common.h"
|
||
|
||
static void schedule_ssb(frame_t frame,
|
||
slot_t slot,
|
||
NR_ServingCellConfigCommon_t *scc,
|
||
nfapi_nr_dl_tti_request_body_t *dl_req,
|
||
int i_ssb,
|
||
int beam_index,
|
||
uint8_t scoffset,
|
||
uint16_t offset_pointa,
|
||
uint32_t payload,
|
||
uint16_t stream_idx)
|
||
{
|
||
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");
|
||
AssertFatal(*scc->physCellId < 1008 && *scc->physCellId >=0, "5G physicall cell id out of range: %ld\n", *scc->physCellId);
|
||
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,"scc->downlinkConfigCommonL is null\n");
|
||
AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
|
||
AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB,
|
||
"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;
|
||
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 = 20; //SSB is always 20RBs
|
||
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;
|
||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.param_v4.spatialStreamIndexPresent = 1;
|
||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.param_v4.spatialStreamIndex = stream_idx;
|
||
dl_req->nPDUs++;
|
||
|
||
LOG_D(NR_MAC,"Scheduling ssb %d at frame %d and slot %d\n", i_ssb, frame, slot);
|
||
}
|
||
|
||
static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc,
|
||
int rbStart,
|
||
int ssb_subcarrier_offset,
|
||
uint16_t symStart,
|
||
int CC_id,
|
||
int beam)
|
||
{
|
||
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");
|
||
|
||
uint16_t *vrb_map = cc[CC_id].vrb_map[beam];
|
||
const int extra_prb = ssb_subcarrier_offset > 0;
|
||
for (int rb = 0; rb < 20 + extra_prb; rb++)
|
||
vrb_map[rbStart + rb] = SL_to_bitmap(symStart % NR_SYMBOLS_PER_SLOT, 4);
|
||
}
|
||
|
||
static int encode_mib(NR_BCCH_BCH_Message_t *mib, frame_t frame, uint8_t *buffer, int buf_size)
|
||
{
|
||
int encode_size = 3;
|
||
AssertFatal(buf_size >= encode_size, "buffer of size %d too small, need 3 bytes\n", buf_size);
|
||
int encoded = encode_MIB_NR(mib, frame, buffer, encode_size);
|
||
DevAssert(encoded == encode_size);
|
||
return encode_size;
|
||
}
|
||
|
||
int get_max_ssbs(const NR_ServingCellConfigCommon_t *scc)
|
||
{
|
||
int L_max = 0;
|
||
switch (scc->ssb_PositionsInBurst->present) {
|
||
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap:
|
||
L_max = 4;
|
||
break;
|
||
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap:
|
||
L_max = 8;
|
||
break;
|
||
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap:
|
||
L_max = 64;
|
||
break;
|
||
default:
|
||
AssertFatal(false, "Invalid SSB configuration\n");
|
||
}
|
||
return L_max;
|
||
}
|
||
|
||
bool is_ssb_configured(const NR_ServingCellConfigCommon_t *scc, int ssb_index)
|
||
{
|
||
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;
|
||
|
||
int pos = 0;
|
||
switch (scc->ssb_PositionsInBurst->present) {
|
||
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap:
|
||
pos = shortBitmap->buf[0] >> (7 - ssb_index);
|
||
break;
|
||
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap:
|
||
pos = mediumBitmap->buf[0] >> (7 - ssb_index);
|
||
break;
|
||
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap:
|
||
pos = longBitmap->buf[ssb_index / 8] >> (7 - (ssb_index % 8));
|
||
break;
|
||
default:
|
||
AssertFatal(false, "Invalid SSB configuration\n");
|
||
}
|
||
return pos & 0x01;
|
||
}
|
||
|
||
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi_nr_dl_tti_request_t *DL_req)
|
||
{
|
||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||
nfapi_nr_dl_tti_request_body_t *dl_req;
|
||
|
||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||
NR_COMMON_channels_t *cc = &gNB->common_channels[CC_id];
|
||
const NR_MIB_t *mib = cc->mib->message.choice.mib;
|
||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||
const int slots_per_frame = gNB->frame_structure.numb_slots_frame;
|
||
dl_req = &DL_req->dl_tti_request_body;
|
||
|
||
// get MIB every 8 frames
|
||
if(((slotP == 0) && (frameP & 7) == 0) ||
|
||
gNB->first_MIB) {
|
||
int mib_sdu_length = encode_mib(cc->mib, frameP, cc->MIB_pdu, sizeof(cc->MIB_pdu));
|
||
|
||
// 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;
|
||
|
||
LOG_D(MAC,
|
||
"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",
|
||
module_idP,
|
||
frameP,
|
||
CC_id,
|
||
mib_sdu_length);
|
||
}
|
||
|
||
uint32_t mib_pdu = (*(uint32_t *)cc->MIB_pdu) & ((1 << 24) - 1);
|
||
int8_t ssb_period = *scc->ssb_periodicityServingCell;
|
||
uint8_t ssb_frame_periodicity = 1; // every how many frames SSB are generated
|
||
|
||
if (ssb_period > 1) // 0 is every half frame
|
||
ssb_frame_periodicity = 1 << (ssb_period -1);
|
||
|
||
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];
|
||
const int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||
const uint16_t offset_pointa = gNB->ssb_OffsetPointA;
|
||
uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset;
|
||
const int L_max = get_max_ssbs(scc);
|
||
const frequency_range_t frequency_range = scc->ssb_PositionsInBurst->present == 3 ? FR2 : FR1;
|
||
const int prb_offset = frequency_range == FR1 ? offset_pointa >> scs : offset_pointa >> (scs - 2);
|
||
for (int i_ssb = 0; i_ssb < L_max; i_ssb++) {
|
||
if (is_ssb_configured(scc, i_ssb)) {
|
||
uint16_t 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 / NR_SYMBOLS_PER_SLOT) == rel_slot) {
|
||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info,
|
||
frameP,
|
||
slotP,
|
||
get_beam_from_ssbidx(gNB, i_ssb),
|
||
slots_per_frame);
|
||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||
const uint16_t alloc_beam_idx = get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx);
|
||
const uint16_t fapi_beam = convert_to_fapi_beam(alloc_beam_idx, gNB->beam_info.beam_mode);
|
||
schedule_ssb(frameP,
|
||
slotP,
|
||
scc,
|
||
dl_req,
|
||
i_ssb,
|
||
fapi_beam,
|
||
ssbSubcarrierOffset,
|
||
offset_pointa,
|
||
mib_pdu,
|
||
gNB->radio_config.spatial_stream_index[beam.idx]);
|
||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
|
||
if (IS_SA_MODE(get_softmodem_params())) {
|
||
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
|
||
frameP,
|
||
mib,
|
||
slots_per_frame,
|
||
ssbSubcarrierOffset,
|
||
ssb_start_symbol,
|
||
scs,
|
||
frequency_range,
|
||
band,
|
||
bw,
|
||
i_ssb,
|
||
ssb_frame_periodicity,
|
||
prb_offset);
|
||
gNB->type0_PDCCH_CSS_config[i_ssb].active = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static bool update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, uint16_t *vrb_map)
|
||
{
|
||
const NR_tda_info_t *tda_info = &pdsch->tda_info;
|
||
|
||
// Calculate number of PRB_DMRS
|
||
uint8_t N_PRB_DMRS = pdsch->dmrs_parms.N_PRB_DMRS;
|
||
LOG_D(MAC, "dlDmrsSymbPos %x\n", pdsch->dmrs_parms.dl_dmrs_symb_pos);
|
||
int mcsTableIdx = 0;
|
||
const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
|
||
int bwpSize = pdsch->bwp_info.bwpSize;
|
||
int bwpStart = pdsch->bwp_info.bwpStart;
|
||
|
||
for (pdsch->mcs = 0; pdsch->mcs < 10; pdsch->mcs++) {
|
||
pdsch->Qm = nr_get_Qm_dl(pdsch->mcs, mcsTableIdx);
|
||
pdsch->R = nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx);
|
||
if (!nr_find_nb_rb(pdsch->Qm,
|
||
pdsch->R,
|
||
1, // no transform precoding for DL
|
||
1, // single layer
|
||
tda_info->nrOfSymbols,
|
||
pdsch->dmrs_parms.N_PRB_DMRS * pdsch->dmrs_parms.N_DMRS_SLOT,
|
||
num_total_bytes,
|
||
1, // min_rbSize
|
||
bwpSize, // max_rbSize,
|
||
&pdsch->tb_size,
|
||
&pdsch->rbSize))
|
||
continue;
|
||
int rbStart, rbSize;
|
||
if (get_rb_alloc(pdsch->rbSize, pdsch->rbSize, bwpStart, bwpSize, vrb_map, slbitmap, &rbStart, &rbSize)) {
|
||
pdsch->rbStart = rbStart;
|
||
pdsch->rbSize = rbSize;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (pdsch->mcs >= 10 || pdsch->tb_size < num_total_bytes) {
|
||
LOG_D(NR_MAC,
|
||
"Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n",
|
||
num_total_bytes,
|
||
pdsch->rbStart,
|
||
pdsch->rbSize,
|
||
bwpSize);
|
||
return false;
|
||
}
|
||
|
||
LOG_D(NR_MAC,
|
||
"mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n",
|
||
pdsch->mcs,
|
||
tda_info->startSymbolIndex,
|
||
tda_info->nrOfSymbols,
|
||
pdsch->rbSize,
|
||
pdsch->tb_size,
|
||
pdsch->dmrs_parms.N_DMRS_SLOT,
|
||
N_PRB_DMRS,
|
||
tda_info->mapping_type);
|
||
return true;
|
||
}
|
||
|
||
static NR_sched_pdsch_t allocate_sib1(gNB_MAC_INST *gNB_mac,
|
||
int CC_id,
|
||
NR_sched_pdcch_t *pdcch,
|
||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||
int aggregation_level,
|
||
int cce_index,
|
||
int time_domain_allocation,
|
||
NR_tda_info_t *tda_info,
|
||
int beam,
|
||
uint16_t num_total_bytes)
|
||
{
|
||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
|
||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, tda_info, 1);
|
||
const uint16_t *sidx = gNB_mac->radio_config.spatial_stream_index;
|
||
NR_sched_pdsch_t pdsch = {
|
||
.bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL),
|
||
.time_domain_allocation = time_domain_allocation,
|
||
.dmrs_parms = dmrs_parms,
|
||
.tda_info = *tda_info,
|
||
.nrOfLayers = 1,
|
||
.pm_index = 0,
|
||
.mcs = 0, // starting from mcs 0
|
||
// no of layers 1 and pmi 0 gives only one log antenna port
|
||
.ant_port_idx = {.numSpatialStreamIndices = 1, .spatialStreamIndices[0] = sidx[beam]},
|
||
};
|
||
|
||
uint16_t *vrb_map = cc->vrb_map[beam];
|
||
bool success = update_rb_mcs_tbs(&pdsch, num_total_bytes, vrb_map);
|
||
if (success) {
|
||
// Mark the corresponding RBs as used
|
||
fill_pdcch_vrb_map(gNB_mac, CC_id, pdcch, cce_index, aggregation_level, beam);
|
||
for (int rb = 0; rb < pdsch.rbSize; rb++)
|
||
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
|
||
} else {
|
||
pdsch.tb_size = 0; // to signal we couldn't allocate TBS
|
||
pdsch.time_domain_allocation = -1;
|
||
}
|
||
|
||
return pdsch;
|
||
}
|
||
|
||
static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
|
||
NR_sched_pdsch_t *pdsch,
|
||
NR_sched_pdcch_t *pdcch,
|
||
NR_SearchSpace_t *search_space,
|
||
NR_ControlResourceSet_t *coreset,
|
||
int aggregation_level,
|
||
int cce_index,
|
||
nfapi_nr_dl_tti_request_body_t *dl_req,
|
||
int pdu_index,
|
||
bool is_sib1,
|
||
int beam_index)
|
||
{
|
||
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(dl_tti_pdcch_pdu, 0, sizeof(*dl_tti_pdcch_pdu));
|
||
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
|
||
dl_tti_pdcch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||
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, coreset, pdcch);
|
||
|
||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||
memset(dl_tti_pdsch_pdu, 0, sizeof(*dl_tti_pdcch_pdu));
|
||
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
|
||
dl_tti_pdsch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||
dl_req->nPDUs += 1;
|
||
|
||
const uint16_t fapi_beam = convert_to_fapi_beam(beam_index, gNB_mac->beam_info.beam_mode);
|
||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 =
|
||
prepare_pdsch_pdu(dl_tti_pdsch_pdu, gNB_mac, NULL, pdsch, NULL, is_sib1, 0, SI_RNTI, fapi_beam, 1, pdu_index);
|
||
LOG_D(NR_MAC,
|
||
"OtherSI:bwpStart %d, bwpSize %d, rbStart %d, rbSize %d, dlDmrsSymbPos = 0x%x\n",
|
||
pdsch_pdu_rel15->BWPStart,
|
||
pdsch_pdu_rel15->BWPSize,
|
||
pdsch_pdu_rel15->rbStart,
|
||
pdsch_pdu_rel15->rbSize,
|
||
pdsch_pdu_rel15->dlDmrsSymbPos);
|
||
|
||
/* Fill PDCCH DL DCI PDU */
|
||
nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15,
|
||
scc,
|
||
search_space,
|
||
coreset,
|
||
pdsch->ant_port_idx.spatialStreamIndices,
|
||
aggregation_level,
|
||
cce_index,
|
||
fapi_beam,
|
||
SI_RNTI);
|
||
pdcch_pdu_rel15->numDlDci++;
|
||
|
||
/* DCI payload */
|
||
int dci_format = NR_DL_DCI_FORMAT_1_0;
|
||
int rnti_type = TYPE_SI_RNTI_;
|
||
dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(gNB_mac,
|
||
NULL,
|
||
rnti_type,
|
||
NR_SearchSpace__searchSpaceType_PR_common,
|
||
pdsch_pdu_rel15,
|
||
pdsch,
|
||
NULL,
|
||
1,
|
||
0,
|
||
0,
|
||
is_sib1);
|
||
|
||
fill_dci_pdu_rel15(NULL,
|
||
NULL,
|
||
NULL,
|
||
dci_pdu,
|
||
&dci_payload,
|
||
dci_format,
|
||
rnti_type,
|
||
0,
|
||
search_space,
|
||
coreset,
|
||
0,
|
||
gNB_mac->cset0_bwp_size);
|
||
|
||
LOG_D(MAC,
|
||
"BWPSize: %3i, BWPStart: %3i, SubcarrierSpacing: %i, CyclicPrefix: %i, StartSymbolIndex: %i, DurationSymbols: %i, "
|
||
"CceRegMappingType: %i, RegBundleSize: %i, InterleaverSize: %i, CoreSetType: %i, ShiftIndex: %i, precoderGranularity: %i, "
|
||
"numDlDci: %i\n",
|
||
pdcch_pdu_rel15->BWPSize,
|
||
pdcch_pdu_rel15->BWPStart,
|
||
pdcch_pdu_rel15->SubcarrierSpacing,
|
||
pdcch_pdu_rel15->CyclicPrefix,
|
||
pdcch_pdu_rel15->StartSymbolIndex,
|
||
pdcch_pdu_rel15->DurationSymbols,
|
||
pdcch_pdu_rel15->CceRegMappingType,
|
||
pdcch_pdu_rel15->RegBundleSize,
|
||
pdcch_pdu_rel15->InterleaverSize,
|
||
pdcch_pdu_rel15->CoreSetType,
|
||
pdcch_pdu_rel15->ShiftIndex,
|
||
pdcch_pdu_rel15->precoderGranularity,
|
||
pdcch_pdu_rel15->numDlDci);
|
||
}
|
||
|
||
static bool check_sib1_tda(gNB_MAC_INST *gNB_mac,
|
||
NR_sched_pdcch_t *sched_pdcch,
|
||
NR_beam_alloc_t *beam,
|
||
int aggregation_level,
|
||
int cce_index,
|
||
int tda,
|
||
int ssb_index,
|
||
int CC_id)
|
||
{
|
||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
|
||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[ssb_index];
|
||
default_table_type_t table_type = get_default_table_type(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern);
|
||
// If the PDSCH was scheduled with SI-RNTI in PDCCH Type0 common search space,
|
||
// the UE may assume that this PDSCH resource allocation is not applied (Table 5.1.2.1.1-4 and 5 in 38.214)
|
||
int row = tda + 1;
|
||
if (table_type == defaultB && (row == 12 || row == 13 || row == 14))
|
||
return false;
|
||
if (table_type == defaultC && (row == 1 || row == 6 || row == 7 ||row > 12))
|
||
return false;
|
||
// assuming normal CP
|
||
NR_tda_info_t tda_info = get_info_from_tda_tables(table_type, tda, scc->dmrs_TypeA_Position, true);
|
||
// SIB1 TDA going to the last symbol would cause overlap with CSI-RS
|
||
if (!tda_info.valid_tda || tda_info.startSymbolIndex + tda_info.nrOfSymbols == 14)
|
||
return false;
|
||
if (tda_info.startSymbolIndex < type0_PDCCH_CSS_config->first_symbol_index + type0_PDCCH_CSS_config->num_symbols)
|
||
return false;
|
||
|
||
gNB_mac->sib1_pdsch[ssb_index] = allocate_sib1(gNB_mac,
|
||
CC_id,
|
||
sched_pdcch,
|
||
type0_PDCCH_CSS_config,
|
||
aggregation_level,
|
||
cce_index,
|
||
tda,
|
||
&tda_info,
|
||
beam->idx,
|
||
cc->sib1_bcch_length);
|
||
|
||
if (gNB_mac->sib1_pdsch[ssb_index].tb_size > 0) {
|
||
LOG_D(NR_MAC, "Found TDA for SIB1: %d\n", tda);
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
static bool check_frame_sib1(NR_ServingCellConfigCommon_t *scc, NR_Type0_PDCCH_CSS_config_t *type0, int frame)
|
||
{
|
||
if (type0->type0_pdcch_ss_mux_pattern == 1)
|
||
return frame % 2 == type0->sfn_c;
|
||
else {
|
||
long ssb_period = *scc->ssb_periodicityServingCell;
|
||
int ssb_frame_periodicity = 1; // every how many frames SSB are generated
|
||
if (ssb_period > 1) // 0 is every half frame
|
||
ssb_frame_periodicity = 1 << (ssb_period -1);
|
||
return frame % ssb_frame_periodicity == 0;
|
||
}
|
||
}
|
||
|
||
void schedule_nr_sib1(module_id_t module_idP,
|
||
frame_t frameP,
|
||
slot_t slotP,
|
||
nfapi_nr_dl_tti_request_t *DL_req,
|
||
nfapi_nr_tx_data_request_t *TX_req)
|
||
{
|
||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||
// TODO: Get these values from RRC
|
||
const int CC_id = 0;
|
||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
|
||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
|
||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||
int L_max;
|
||
switch (scc->ssb_PositionsInBurst->present) {
|
||
case 1:
|
||
L_max = 4;
|
||
break;
|
||
case 2:
|
||
L_max = 8;
|
||
break;
|
||
case 3:
|
||
L_max = 64;
|
||
break;
|
||
default:
|
||
AssertFatal(false, "SSB bitmap size value %d undefined (allowed values 1,2,3)\n", scc->ssb_PositionsInBurst->present);
|
||
}
|
||
|
||
for (int i = 0; i < L_max; i++) {
|
||
|
||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
|
||
|
||
if(check_frame_sib1(scc, type0_PDCCH_CSS_config, frameP) &&
|
||
(slotP == type0_PDCCH_CSS_config->slot) &&
|
||
(type0_PDCCH_CSS_config->num_rbs > 0) &&
|
||
(type0_PDCCH_CSS_config->active == true)) {
|
||
|
||
AssertFatal(is_dl_slot(slotP, &gNB_mac->frame_structure),
|
||
"Trying to schedule SIB1 for SSB %d in slot %d which is not DL. Check searchSpaceZero configuration.\n",
|
||
type0_PDCCH_CSS_config->ssb_index,
|
||
slotP);
|
||
const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
|
||
int beam_index = get_beam_from_ssbidx(gNB_mac, i);
|
||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame);
|
||
AssertFatal(beam.idx >= 0, "Cannot allocate SIB1 corresponding to SSB %d in any available beam\n", i);
|
||
LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
|
||
NR_sched_pdcch_t sched_pdcch = set_pdcch_structure(NULL,
|
||
&gNB_mac->sched_ctrlSIB1->search_space[i],
|
||
&gNB_mac->sched_ctrlSIB1->coreset,
|
||
scc,
|
||
NULL,
|
||
type0_PDCCH_CSS_config);
|
||
|
||
int nr_of_candidates, aggregation_level;
|
||
for (int c = 0; c < 3; c++) {
|
||
find_aggregation_candidates(&aggregation_level,
|
||
&nr_of_candidates,
|
||
&gNB_mac->sched_ctrlSIB1->search_space[i],
|
||
4 << c);
|
||
if (nr_of_candidates > 0)
|
||
break; // choosing the lower value of aggregation level available
|
||
}
|
||
AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
|
||
int cce_index = find_pdcch_candidate(gNB_mac,
|
||
CC_id,
|
||
aggregation_level,
|
||
nr_of_candidates,
|
||
beam.idx,
|
||
&sched_pdcch,
|
||
&gNB_mac->sched_ctrlSIB1->coreset,
|
||
0);
|
||
|
||
bool res = false;
|
||
if (gNB_mac->sib1_pdsch[i].time_domain_allocation < 0) {
|
||
for (int t = 0; t < 16; t++) {
|
||
if (check_sib1_tda(gNB_mac, &sched_pdcch, &beam, aggregation_level, cce_index, t, i, CC_id)) {
|
||
res = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
AssertFatal(gNB_mac->sib1_pdsch[i].time_domain_allocation >= 0, "Couldn't select any TDA for SIB1\n");
|
||
if (!res)
|
||
res = check_sib1_tda(gNB_mac,
|
||
&sched_pdcch,
|
||
&beam,
|
||
aggregation_level,
|
||
cce_index,
|
||
gNB_mac->sib1_pdsch[i].time_domain_allocation,
|
||
i,
|
||
CC_id);
|
||
int tb_size = gNB_mac->sib1_pdsch[i].tb_size;
|
||
AssertFatal(res && tb_size > 0, "Couldn't allocate TB for SIB1 for an already allocated TDA\n");
|
||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||
int pdu_index = gNB_mac->pdu_index[0]++;
|
||
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
|
||
&gNB_mac->sib1_pdsch[i],
|
||
&sched_pdcch,
|
||
&gNB_mac->sched_ctrlSIB1->search_space[i],
|
||
&gNB_mac->sched_ctrlSIB1->coreset,
|
||
aggregation_level,
|
||
cce_index,
|
||
dl_req,
|
||
pdu_index,
|
||
true,
|
||
beam_index);
|
||
|
||
const int ntx_req = TX_req->Number_of_PDUs;
|
||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
|
||
|
||
// Data to be transmitted
|
||
memcpy(tx_req->TLVs[0].value.direct, cc->sib1_bcch_pdu, tb_size);
|
||
|
||
tx_req->PDU_index = pdu_index;
|
||
tx_req->num_TLV = 1;
|
||
tx_req->TLVs[0].length = tb_size;
|
||
tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length);
|
||
TX_req->Number_of_PDUs++;
|
||
TX_req->SFN = frameP;
|
||
TX_req->Slot = slotP;
|
||
|
||
type0_PDCCH_CSS_config->active = false;
|
||
|
||
T(T_GNB_MAC_DL_PDU_WITH_DATA,
|
||
T_INT(module_idP),
|
||
T_INT(CC_id),
|
||
T_INT(0xffff),
|
||
T_INT(frameP),
|
||
T_INT(slotP),
|
||
T_INT(0 /* harq_pid */),
|
||
T_BUFFER(cc->sib1_bcch_pdu, cc->sib1_bcch_length));
|
||
}
|
||
}
|
||
}
|
||
|
||
struct NR_SchedulingInfo2_r17 *find_sib19_sched_info(const struct NR_SI_SchedulingInfo_v1700 *si_schedulinginfo2_r17)
|
||
{
|
||
for (int i = 0; i < si_schedulinginfo2_r17->schedulingInfoList2_r17.list.count; i++) {
|
||
const struct NR_SIB_Mapping_v1700 *sib_MappingInfo_r17 =
|
||
&si_schedulinginfo2_r17->schedulingInfoList2_r17.list.array[i]->sib_MappingInfo_r17;
|
||
for (int j = 0; j < sib_MappingInfo_r17->list.count; j++) {
|
||
if (sib_MappingInfo_r17->list.array[j]->sibType_r17.choice.type1_r17
|
||
== NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19) {
|
||
return si_schedulinginfo2_r17->schedulingInfoList2_r17.list.array[i];
|
||
}
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static void other_sib_sched_control(module_id_t module_idP,
|
||
frame_t frame,
|
||
slot_t slot,
|
||
int beam_index,
|
||
NR_SearchSpace_t *ss,
|
||
nfapi_nr_dl_tti_request_t *DL_req,
|
||
nfapi_nr_tx_data_request_t *TX_req,
|
||
int payload_idx)
|
||
{
|
||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
|
||
AssertFatal(is_dl_slot(slot, &gNB_mac->frame_structure),
|
||
"Trying to schedule otherSIB in slot %d which is not DL. Wrong Configuration\n",
|
||
slot);
|
||
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
|
||
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
|
||
beam_index = get_beam_from_ssbidx(gNB_mac, beam_index);
|
||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame);
|
||
AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index);
|
||
LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index);
|
||
|
||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
|
||
int ssb_index = get_ssbidx_from_beam(gNB_mac, beam_index);
|
||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[ssb_index];
|
||
NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup;
|
||
int time_domain_allocation = 1;
|
||
NR_tda_info_t tda_info = set_tda_info_from_list(pdsch_ConfigCommon->pdsch_TimeDomainAllocationList, time_domain_allocation);
|
||
LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||
|
||
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1);
|
||
|
||
int aggregation_level = 0;
|
||
int nr_of_candidates = 0;
|
||
for (int i = 0; i < 5; i++) {
|
||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 16 >> i);
|
||
if (nr_of_candidates > 0)
|
||
break; // choosing the higher value of aggregation level available
|
||
}
|
||
|
||
AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
|
||
AssertFatal(ss->controlResourceSetId, "ss->controlResourceSetId is NULL\n");
|
||
NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, *ss->controlResourceSetId);
|
||
if (!gNB_mac->sched_pdcch_otherSI) {
|
||
gNB_mac->sched_pdcch_otherSI = calloc(1, sizeof(*gNB_mac->sched_pdcch_otherSI));
|
||
*gNB_mac->sched_pdcch_otherSI = set_pdcch_structure(gNB_mac, ss, coreset, scc, NULL, type0_PDCCH_CSS_config);
|
||
}
|
||
int cce_index = find_pdcch_candidate(gNB_mac,
|
||
0,
|
||
aggregation_level,
|
||
nr_of_candidates,
|
||
beam.idx,
|
||
gNB_mac->sched_pdcch_otherSI,
|
||
coreset,
|
||
0);
|
||
|
||
AssertFatal(cce_index >= 0, "Could not find CCE for otherSIB DCI\n");
|
||
|
||
// Mark the corresponding RBs as used
|
||
fill_pdcch_vrb_map(gNB_mac, 0, gNB_mac->sched_pdcch_otherSI, cce_index, aggregation_level, beam.idx);
|
||
|
||
const uint16_t *sidx = gNB_mac->radio_config.spatial_stream_index;
|
||
NR_sched_pdsch_t sched_pdsch_otherSI = {
|
||
.time_domain_allocation = time_domain_allocation,
|
||
.bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL),
|
||
.dmrs_parms = dmrs_parms,
|
||
.tda_info = tda_info,
|
||
.nrOfLayers = 1,
|
||
.pm_index = 0,
|
||
.mcs = 0, // starting from mcs 0
|
||
.ant_port_idx = {.numSpatialStreamIndices = 1, .spatialStreamIndices[0] = sidx[beam.idx]}};
|
||
|
||
uint16_t *vrb_map = cc->vrb_map[beam.idx];
|
||
uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx];
|
||
int num_total_bytes = cc->other_sib_bcch_length[payload_idx];
|
||
bool success = update_rb_mcs_tbs(&sched_pdsch_otherSI, num_total_bytes, vrb_map);
|
||
AssertFatal(success, "Couldn't allocate TBS for other SIB\n");
|
||
|
||
for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) {
|
||
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||
}
|
||
|
||
int pdu_index = gNB_mac->pdu_index[0]++;
|
||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
|
||
&sched_pdsch_otherSI,
|
||
gNB_mac->sched_pdcch_otherSI,
|
||
ss,
|
||
coreset,
|
||
aggregation_level,
|
||
cce_index,
|
||
dl_req,
|
||
pdu_index,
|
||
false,
|
||
beam_index);
|
||
|
||
const int ntx_req = TX_req->Number_of_PDUs;
|
||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
|
||
|
||
// Data to be transmitted
|
||
memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, sched_pdsch_otherSI.tb_size);
|
||
|
||
tx_req->PDU_index = pdu_index;
|
||
tx_req->num_TLV = 1;
|
||
tx_req->TLVs[0].length = sched_pdsch_otherSI.tb_size;
|
||
tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length);
|
||
TX_req->Number_of_PDUs++;
|
||
TX_req->SFN = frame;
|
||
TX_req->Slot = slot;
|
||
|
||
T(T_GNB_MAC_DL_PDU_WITH_DATA,
|
||
T_INT(module_idP),
|
||
T_INT(0),
|
||
T_INT(SI_RNTI),
|
||
T_INT(frame),
|
||
T_INT(slot),
|
||
T_INT(0), // harq_pid
|
||
T_BUFFER(sib_bcch_pdu, num_total_bytes));
|
||
}
|
||
|
||
// This function verifies if we need to schedule otherSIB in frame and slot
|
||
static bool test_other_sib_sched_occasion(int window_pos,
|
||
int window_len,
|
||
int period,
|
||
int n_slots_frame,
|
||
int frame,
|
||
int slot,
|
||
int rel_frame,
|
||
int rel_slot)
|
||
{
|
||
int x = (window_pos - 1) * window_len;
|
||
int T = 8 << period;
|
||
int test_frame = (frame - rel_frame) % MAX_FRAME_NUMBER;
|
||
int si_slot = (x % n_slots_frame) + rel_slot;
|
||
bool res = ((test_frame % T) != (x / n_slots_frame)) || (si_slot != slot);
|
||
return res;
|
||
}
|
||
|
||
void schedule_nr_other_sib(module_id_t module_idP,
|
||
frame_t frame,
|
||
slot_t slot,
|
||
nfapi_nr_dl_tti_request_t *DL_req,
|
||
nfapi_nr_tx_data_request_t *TX_req)
|
||
{
|
||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
|
||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
|
||
NR_SIB1_t *sib1 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1;
|
||
NR_SI_SchedulingInfo_t *schedInfo = sib1->si_SchedulingInfo;
|
||
if (!schedInfo)
|
||
return;
|
||
|
||
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
|
||
NR_PDCCH_ConfigCommon_t *pdcch_common = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
|
||
NR_SearchSpaceId_t *ss_id = pdcch_common->searchSpaceOtherSystemInformation;
|
||
AssertFatal(ss_id, "searchSpaceOtherSystemInformation not present\n");
|
||
NR_SearchSpace_t *ss = NULL;
|
||
for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++) {
|
||
if (pdcch_common->commonSearchSpaceList->list.array[i]->searchSpaceId == *ss_id)
|
||
ss = pdcch_common->commonSearchSpaceList->list.array[i];
|
||
}
|
||
AssertFatal(ss, "searchSpaceOtherSystemInformation not found\n");
|
||
|
||
NR_SI_SchedulingInfo_v1700_t *schedInfo17 = NULL;
|
||
if (sib1->nonCriticalExtension) {
|
||
NR_SIB1_v1610_IEs_t *sib1_v1610 = sib1->nonCriticalExtension;
|
||
if (sib1_v1610 && sib1_v1610->nonCriticalExtension && sib1_v1610->nonCriticalExtension->nonCriticalExtension) {
|
||
NR_SIB1_v1700_IEs_t *sib1_v17 = sib1_v1610->nonCriticalExtension->nonCriticalExtension;
|
||
schedInfo17 = sib1_v17->si_SchedulingInfo_v1700;
|
||
}
|
||
}
|
||
|
||
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
|
||
int window_length_sl = 5 << schedInfo->si_WindowLength;
|
||
int window_length_f = (window_length_sl / n_slots_frame) + ((window_length_sl % n_slots_frame) > 0);
|
||
int num_ssb = cc->num_active_ssb;
|
||
// number of PDCCH monitoring occasions in SI-window
|
||
int period, offset;
|
||
get_monitoring_period_offset(ss, &period, &offset);
|
||
// The UE assumes that, in the SI window, PDCCH for an SI message is transmitted
|
||
// in at least one PDCCH monitoring occasion corresponding to each transmitted SSB
|
||
// frame and slot relative to start of window
|
||
// The [x×N+K]th PDCCH monitoring occasion(s) for SI message in SI-window corresponds to the Kth transmitted SSB
|
||
// in our implmentation we transmit only once per SSB per window so N = 1
|
||
// Section 5.2.2.3.2 of 38.331
|
||
int temp_slot = offset % n_slots_frame;
|
||
int temp_frame = offset / n_slots_frame;
|
||
int rel_slot[num_ssb];
|
||
int rel_frame[num_ssb];
|
||
int ssb = 0;
|
||
while (ssb < num_ssb) {
|
||
AssertFatal(temp_frame < window_length_f, "Couldn't fit %d SSB in window length of %d slots\n", num_ssb, window_length_sl);
|
||
if (is_dl_slot(temp_slot, &gNB_mac->frame_structure)) {
|
||
rel_slot[ssb] = temp_slot;
|
||
rel_frame[ssb] = temp_frame;
|
||
ssb++;
|
||
}
|
||
temp_frame += (temp_slot + period) / n_slots_frame;
|
||
temp_slot = (temp_slot + period) % n_slots_frame;
|
||
}
|
||
|
||
for (int ssb = 0; ssb < num_ssb; ssb++) {
|
||
for (int i = 0; i < schedInfo->schedulingInfoList.list.count; i++) {
|
||
NR_SchedulingInfo_t *schedulingInfo = schedInfo->schedulingInfoList.list.array[i];
|
||
if (test_other_sib_sched_occasion(i + 1,
|
||
window_length_sl,
|
||
schedulingInfo->si_Periodicity,
|
||
n_slots_frame,
|
||
frame,
|
||
slot,
|
||
rel_frame[ssb],
|
||
rel_slot[ssb]))
|
||
continue;
|
||
|
||
other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 0);
|
||
}
|
||
if (!schedInfo17)
|
||
continue;
|
||
for (int i = 0; i < schedInfo17->schedulingInfoList2_r17.list.count; i++) {
|
||
NR_SchedulingInfo2_r17_t *schedulingInfo2_r17 = schedInfo17->schedulingInfoList2_r17.list.array[i];
|
||
if (test_other_sib_sched_occasion(schedulingInfo2_r17->si_WindowPosition_r17,
|
||
window_length_sl,
|
||
schedulingInfo2_r17->si_Periodicity_r17,
|
||
n_slots_frame,
|
||
frame,
|
||
slot,
|
||
rel_frame[ssb],
|
||
rel_slot[ssb]))
|
||
continue;
|
||
|
||
other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 1);
|
||
}
|
||
}
|
||
}
|