Compare commits

...

3 Commits

Author SHA1 Message Date
Mario Joa-Ng
c38b07db0c Get ssb_index using UE_beam_index under different beam_mode correctly. 2026-02-26 01:27:53 +01:00
Mario Joa-Ng
d842c4e372 Configure periodic CSI reports, periodic SRS and periodic SR according to userid on different non-PRACH uplink slots to avoid beam allocation conflict among uplink signals 2026-02-25 13:14:44 -05:00
Mario Joa-Ng
795591210e Configure CSI-RS according to beam_id used by UE and reconfigure upon beam change.
No need to call get_config_srs() anymore in update_cellGroupConfig_for_BWP_switch().
2026-02-24 22:49:44 -05:00
10 changed files with 597 additions and 90 deletions

View File

@@ -814,7 +814,9 @@ int main(int argc, char **argv)
prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_DL, g_mcsTableIdx, 0);
rnti_t rnti = 0x1234;
int uid = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid);
int ssb_index = 0;
int beam_idx = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid, ssb_index, beam_idx);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame);
/* -U option modify DMRS */

View File

@@ -821,7 +821,9 @@ int main(int argc, char *argv[])
prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_UL, 0, mcs_table);
rnti_t rnti = 0x1234;
int uid = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid);
int ssb_index = 0;
int beam_idx = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid, ssb_index, beam_idx);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame);
NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);

View File

@@ -59,6 +59,82 @@
#include "nfapi_nr_interface_scf.h"
#include "utils.h"
bool is_prach_slot_set = false;
bool is_prach_slot[160] = {false};
bool get_nr_prach_sched_from_info_beam(nr_prach_info_t info,
int config_index,
int slot,
int mu,
frequency_range_t freq_range,
uint8_t unpaired)
{
if (freq_range == FR2) {
//Not checking n_sfn mod x = y
int slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz
if (((info.s_map >> slot_60khz) & 0x01)) {
if (mu == 3) {
if ((info.N_RA_slot == 1) && (slot % 2 == 0))
return false; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
}
return true;
} else
return false; // no prach in current slot
} else {
if (unpaired) { // TDD
//Not checking n_sfn mod x = y
int subframe = slot >> mu;
if ((info.s_map >> subframe) & 0x01) {
if (config_index >= 67) {
if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0))
return false; // no prach in even slots @ 30kHz for 1 prach per subframe
} else {
if ((slot % 2) && (mu > 0))
return false; // slot does not contain start symbol of this prach time resource
}
return true;
} else
return false; // no prach in current slot
} else { // FDD
//Not checking n_sfn mod x = y
int subframe = slot >> mu;
if ((info.s_map >> subframe) & 0x01) {
if (config_index >= 87) {
if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0)) {
return false; // no prach in even slots @ 30kHz for 1 prach per subframe
}
} else {
if ((slot % 2) && (mu > 0))
return 0; // slot does not contain start symbol of this prach time resource
}
return true;
} else
return false; // no prach in current slot
}
}
}
void set_prach_slot()
{
gNB_MAC_INST *gNB = RC.nrmac[0];
NR_COMMON_channels_t *cc = gNB->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_BWP_UplinkCommon_t *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP;
NR_RACH_ConfigCommon_t *rach_ConfigCommon = initialUplinkBWP->rach_ConfigCommon->choice.setup;
NR_MsgA_ConfigCommon_r16_t *msgacc = NULL;
if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16)
msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric;
uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu);
frequency_range_t freq_range = get_freq_range_from_arfcn(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
for (int j = 0; j < fs->numb_slots_frame; j++) {
is_prach_slot[j] = get_nr_prach_sched_from_info_beam(cc->prach_info, config_index, j, mu, freq_range, cc->frame_type);
}
}
c16_t convert_precoder_weight(double complex c_in)
{
return (c16_t) {.r = round(SHRT_MAX*creal(c_in)), .i = round(SHRT_MAX*cimag(c_in))};
@@ -289,6 +365,58 @@ int get_first_ul_slot(const frame_structure_t *fs, bool mixed)
return 0; // FDD
}
/**
* @brief Get the first UL slot index in period
* @param fs frame structure
* @param beam_idx beam index
* @param beams_per_period no of concurrent beams
* @param num_beam no of beams
* @return slot index
*
*/
int get_first_ul_slot_beam(const frame_structure_t *fs, int beam_idx, int beams_per_period, int num_beam)
{
DevAssert(fs);
// FDD
if (fs->frame_type == FDD)
return 1;
if (!is_prach_slot_set)
set_prach_slot();
// UL slots indexes in period
int ul_slot_idxs[fs->numb_slots_frame];
int ul_slot_count = 0;
for (int i = 0; i < fs->numb_slots_frame; i++) {
ul_slot_idxs[i] = 0;
}
int idx = beam_idx / beams_per_period;
LOG_D(NR_MAC, "get_first_ul_slot_beam 0 idx %d beam_idx %d num_beam %d\n", idx, beam_idx, num_beam);
/* Populate the indices of UL slots in the TDD period from the bitmap
* mixed slot is not used in multiple beams config file to avoid collision with SSB
*/
for (int j = 0; j < fs->numb_slots_frame; j++) {
int i = j % fs->numb_slots_period;
if ((fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) && !is_prach_slot[j]) {
ul_slot_idxs[ul_slot_count++] = j;
}
}
for (int i = 0; i < fs->numb_slots_frame; i++)
LOG_D(NR_MAC, "ul_slot_idxs[%d] %d\n", i, ul_slot_idxs[i]);
// Compute slot index offset
int period_idx = idx / ul_slot_count; // wrap up the count of complete TDD periods spanned by the index
int ul_slot_idx_in_period = idx % ul_slot_count; // wrap up the UL slot index within the current TDD period
int ret = ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_frame;
LOG_D(NR_MAC, "get_first_ul_slot_beam ret %d idx %d beam_idx %d ul_slot_count %d %d %d\n",
ret, idx, beam_idx, ul_slot_idx_in_period, period_idx, fs->numb_slots_period);
return ret;
}
/**
* @brief Get number of DL slots per period (full DL slots + mixed slots with DL symbols)
*/
@@ -391,6 +519,100 @@ int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed)
return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period;
}
/**
* @brief Get the nth UL slot offset for UE index idx in a TDD period using the frame structure bitmap
* @param fs frame structure
* @param idx UE index
* @param is_csi indicates whether it is csi or not
* @param beam_idx beam index
* @param beams_per_period no of concurrent beams
* @param num_beam no of beams
* @return slot index offset
*/
int get_ul_slot_offset_beam(const frame_structure_t *fs, int idx, bool is_csi, int beam_idx, int beams_per_period, int num_beam)
{
DevAssert(fs);
// FDD
if (fs->frame_type == FDD)
return idx;
if (!is_prach_slot_set)
set_prach_slot();
// UL slots indexes in period
int ul_slot_idxs[fs->numb_slots_frame];
int ul_slot_count = 0;
for (int i = 0; i < fs->numb_slots_frame; i++) {
ul_slot_idxs[i] = 0;
}
LOG_D(NR_MAC, "get_ul_slot_offset_beam 0 idx %d is_csi %d beam_idx %d num_beam %d\n", idx, is_csi, beam_idx, num_beam);
int id = (is_csi) ? idx/2 : idx;
id /= beams_per_period;
// For NO_BEAM_MODE
// Assuming num_pucch2 = 2 and ignoring mixed slotset_csi_meas_periodicity() and configure_periodic_srs() will give this assignment
// UL slot
// 0123456789
// uid0 S
// CR
// uid1 -S
// CR
// uid2 --S
// CR
// uid3 ---S
// CR
// With beamforming, the slot assignment is
// UL slot
// 0123456789
// uid0 SCR
// uid1 ---SCR
// uid2 ------SCR
// SRS
if (!is_csi) {
idx = 3 * id;
}
else {
// odd => RSRP report
if (idx % 2) {
idx = 3 * id + 2;
}
// even => CSI report
else {
idx = 3 * id + 1;
}
}
LOG_D(NR_MAC, "get_ul_slot_offset_beam 2 id %d idx %d is_csi %d beam_idx %d num_beam %d\n", id, idx, is_csi, beam_idx, num_beam);
// Allow the first NUM_SSB_period slot for SR. See get_first_ul_slot_beam()
int NUM_SSB_period = (num_beam % beams_per_period > 0) ? num_beam / beams_per_period + 1 : num_beam / beams_per_period;
idx += NUM_SSB_period;
/* Populate the indices of UL slots in the TDD period from the bitmap
* mixed slot is not used in multiple beams config file to avoid collision with SSB
*/
for (int j = 0; j < fs->numb_slots_frame; j++) {
int i = j % fs->numb_slots_period;
if ((fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) && !is_prach_slot[j]) {
ul_slot_idxs[ul_slot_count++] = j;
}
}
for (int i = 0; i < fs->numb_slots_frame; i++)
LOG_D(NR_MAC, "ul_slot_idxs[%d] %d, is_prach_slot[%d] %d\n", i, ul_slot_idxs[i], i, is_prach_slot[i]);
// Compute slot index offset
int period_idx = idx / ul_slot_count; // wrap up the count of complete TDD periods spanned by the index
int ul_slot_idx_in_period = idx % ul_slot_count; // wrap up the UL slot index within the current TDD period
int ret = ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_frame;
LOG_D(NR_MAC, "get_ul_slot_offset_beam ret %d idx %d beam_idx %d beams_period %d ul_slot_count %d %d %d\n", ret, idx, beam_idx, beams_per_period, ul_slot_idx_in_period, period_idx, fs->numb_slots_period);
return ret;
}
static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR_ServingCellConfigCommon_t *scc)
{
nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
@@ -1079,7 +1301,7 @@ bool nr_trigger_bwp_switch(uint16_t rnti, int bwp_id)
} else if (UE->current_DL_BWP.bwp_id == bwp_id) {
LOG_W(NR_MAC, "UE %04x is already on BWP ID %d, not triggering reconfiguration\n", rnti, bwp_id);
} else { // UE != NULL && current_DL_BWP.bwp_id != bwp_id
nr_mac_trigger_reconfiguration(nrmac, UE, bwp_id);
nr_mac_trigger_reconfiguration(nrmac, UE, bwp_id, false);
success = true;
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);

View File

@@ -124,6 +124,15 @@ static void determine_aggregation_level_search_order(int agg_level_search_order[
static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame);
int get_ssbidx_from_beam(gNB_MAC_INST *mac, int beam_idx)
{
for (int i = 0; i < MAX_NUM_OF_SSB; i++)
if (beam_idx == mac->beam_index_list[i])
return i;
AssertFatal(false, "beam_idx %d not found\n", beam_idx);
return 0;
}
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format)
{
// TODO check this but it should be enough for now
@@ -2914,7 +2923,11 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, *sched_ctrl->search_space->controlResourceSetId);
NR_COMMON_channels_t *cc = &nr_mac->common_channels[0];
int ssb_index = cc->ssb_index[UE->UE_beam_index];
int ssb_index = 0;
if (nr_mac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX)
ssb_index = cc->ssb_index[UE->UE_beam_index];
else if (nr_mac->beam_info.beam_mode == LOPHY_BEAM_IDX)
ssb_index = get_ssbidx_from_beam(nr_mac, UE->UE_beam_index);
sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac,
sched_ctrl->search_space,
sched_ctrl->coreset,
@@ -3742,20 +3755,23 @@ void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int16_t b
}
}
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
bool beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
{
// do not perform beam procedures if there is no beam information
if (mac->beam_info.beam_mode == NO_BEAM_MODE)
return;
return false;
// simple beam switching algorithm -> we select beam with highest RSRP from CSI report
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
RSRP_report_t *rsrp_report = &sched_ctrl->CSI_report.ssb_rsrp_report;
int new_bf_index = get_beam_from_ssbidx(mac, rsrp_report->resource_id[0]);
if (!mac->radio_config.do_TCI) { // if not TCI is configure we switch beam directly
if (UE->UE_beam_index != new_bf_index)
beam_switching_procedure(UE, new_bf_index);
return;
if (UE->UE_beam_index == new_bf_index)
return false; // no beam change needed
LOG_I(NR_MAC, "[UE %x] Switching to beam with ID %d (SSB number %d)\n", UE->rnti, new_bf_index, rsrp_report->resource_id[0]);
UE->UE_beam_index = new_bf_index;
return true;
}
tciStateInd_t *tci = &sched_ctrl->UE_mac_ce_ctrl.tci_state_ind;
@@ -3764,7 +3780,7 @@ void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
LOG_I(NR_MAC, "[UE %x] Stopping procedure to switch beam, old beam reported as best again\n", UE->rnti);
tci->is_scheduled = false;
}
return; // no beam change needed
return false; // no beam change needed
}
LOG_I(NR_MAC, "[UE %x] Starting procedure to switch beam\n", UE->rnti);
@@ -3774,6 +3790,7 @@ void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
tci->is_scheduled = true;
tci->coresetId = sched_ctrl->coreset->controlResourceSetId;
tci->tciStateId = new_bf_index; // assumption: this correspond to the TCI index
return true;
}
void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data)
@@ -3827,7 +3844,13 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
int CC_id = 0;
int srb_id = 1;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config);
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
int ssb_index = 0;
if (mac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX)
ssb_index = cc->ssb_index[UE->UE_beam_index];
else if (mac->beam_info.beam_mode == LOPHY_BEAM_IDX)
ssb_index = get_ssbidx_from_beam(mac, UE->UE_beam_index);
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config, ssb_index, UE->UE_beam_index);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = cellGroupConfig;
UE->local_bwp_id = mac->radio_config.first_active_bwp;
@@ -3953,24 +3976,42 @@ static bool verify_bwp_switch(const NR_UE_info_t *UE, const nr_mac_config_t *con
return false;
}
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id)
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam)
{
DevAssert(UE->CellGroup != NULL);
NR_CellGroupConfig_t *cellGroup_for_UE = NULL;
if (new_bwp_id >= 0) {
AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n");
if (!verify_bwp_switch(UE, &nrmac->radio_config, new_bwp_id))
return;
else {
if (new_beam) {
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
UE->local_bwp_id = new_bwp_id;
cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup,
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
current_BWP->srs_Config = NULL;
int ssb_index = nrmac->common_channels[0].ssb_index[UE->UE_beam_index];
cellGroup_for_UE = update_cellGroupConfig_for_beam_switch(UE->CellGroup,
&nrmac->radio_config,
UE->capability,
nrmac->common_channels[0].ServingCellConfigCommon,
UE->uid,
UE->current_DL_BWP.bwp_id,
new_bwp_id);
ssb_index,
UE->UE_beam_index);
} else {
if (new_bwp_id >= 0) {
AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n");
if (!verify_bwp_switch(UE, &nrmac->radio_config, new_bwp_id))
return;
else {
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
UE->local_bwp_id = new_bwp_id;
int ssb_index = nrmac->common_channels[0].ssb_index[UE->UE_beam_index];
cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup,
&nrmac->radio_config,
UE->capability,
nrmac->common_channels[0].ServingCellConfigCommon,
UE->uid,
UE->current_DL_BWP.bwp_id,
new_bwp_id,
ssb_index,
UE->UE_beam_index);
}
}
}
uint8_t buf[2048];

View File

@@ -757,6 +757,7 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
int cumul_bits = 0;
int r_index = -1;
bool beam_change = false;
for (int csi_report_id = 0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++) {
nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id];
csi_report->nb_of_csi_ssb_report = 0;
@@ -793,7 +794,7 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
break;
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
beam_selection_procedures(nrmac, UE);
beam_change = beam_selection_procedures(nrmac, UE);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
@@ -851,6 +852,9 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
}
}
}
if (beam_change && !nrmac->radio_config.do_TCI)
// Trigger RRCReconfiguration. Need to be out of the for loop as it may modify csi_MeasConfig
nr_mac_trigger_reconfiguration(nrmac, UE, -1, true);
}
static NR_UE_harq_t *find_harq(frame_t frame, slot_t slot, NR_UE_info_t * UE, int harq_round_max)

View File

@@ -879,7 +879,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
if (!old_UE->reconfigCellGroup) {
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti);
// Trigger RRCReconfiguration
nr_mac_trigger_reconfiguration(mac, old_UE, -1);
nr_mac_trigger_reconfiguration(mac, old_UE, -1, false);
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration
configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
}
@@ -1994,13 +1994,13 @@ static int pf_ul(gNB_MAC_INST *nrmac,
NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame);
if (dci_beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] ULSCH DCI Beam could not be allocated\n", UE->rnti, frame, slot);
continue;
}
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_per_frame);
if (beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] ULSCH Beam could not be allocated\n", UE->rnti, frame, slot);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame, dci_beam.new_beam);
continue;
}
@@ -2119,7 +2119,7 @@ static int pf_ul(gNB_MAC_INST *nrmac,
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, slots_per_frame);
if (beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] ULSCH Beam could not be allocated\n", iterator->UE->rnti, sched_frame, sched_slot);
iterator++;
continue;
}
@@ -2132,7 +2132,7 @@ static int pf_ul(gNB_MAC_INST *nrmac,
NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame);
if (dci_beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] ULSCH DCI Beam could not be allocated\n", iterator->UE->rnti, frame, slot);
reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, slots_per_frame, beam.new_beam);
iterator++;
continue;

View File

@@ -42,12 +42,14 @@ int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc);
bool is_ssb_configured(const NR_ServingCellConfigCommon_t *scc, int ssb_index);
int get_max_ssbs(const NR_ServingCellConfigCommon_t *scc);
int get_first_ul_slot(const frame_structure_t *fs, bool mixed);
int get_first_ul_slot_beam(const frame_structure_t *fs, int beam_idx, int beams_per_period, int num_beam);
int get_ul_slots_per_period(const frame_structure_t *fs);
int get_ul_slots_per_frame(const frame_structure_t *fs);
int get_dl_slots_per_period(const frame_structure_t *fs);
int get_full_ul_slots_per_period(const frame_structure_t *fs);
int get_full_dl_slots_per_period(const frame_structure_t *fs);
int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed);
int get_ul_slot_offset_beam(const frame_structure_t *fs, int idx, bool is_csi, int beam_idx, int beams_per_period, int num_beam);
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia);
void mac_top_init_gNB(ngran_node_t node_type,
@@ -455,7 +457,7 @@ int16_t get_allocated_beam(const NR_beam_info_t *beam_info, int frame, int slot,
uint16_t convert_to_fapi_beam(const uint16_t beam_idx, const nr_beam_mode_t mode);
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int16_t beam_index, int slots_per_frame);
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int16_t beam_index, int slots_per_frame, bool new_beam);
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE);
bool beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE);
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP);
bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE);
@@ -483,7 +485,7 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id);
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam);
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c);
nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid);

View File

@@ -567,12 +567,13 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
const nr_mac_config_t *configuration = &mac->radio_config;
int ssb_index = cc->ssb_index[UE->UE_beam_index];
if (is_SA) {
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config);
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config, ssb_index, UE->UE_beam_index);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
} else {
NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci);
cellGroupConfig = get_default_secondaryCellGroup(scc, cap, 1, 1, configuration, UE->uid);
cellGroupConfig = get_default_secondaryCellGroup(scc, cap, 1, 1, configuration, UE->uid, ssb_index, UE->UE_beam_index);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
// TODO: in NSA we assign capabilities here, otherwise outside => not logic
UE->capability = cap;
@@ -755,7 +756,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req)
if (ue_cap != NULL && cg_configinfo == NULL) {
// store the new UE capabilities, and update the cellGroupConfig
// only to be done if we did not already update through the cg_configinfo
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc, UE->UE_beam_index);
}
/* During re-establishment, prepare CellGroupConfig for UE Context Setup response.
@@ -882,7 +883,7 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req)
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
UE->capability = ue_cap;
LOG_I(NR_MAC, "UE %04x: received capabilities, updating CellGroupConfig\n", UE->rnti);
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc, UE->UE_beam_index);
}
/* 3GPP TS 38.473 Clause 8.3.4: If gNB-DU Configuration Query is present, include CellGroupConfig

View File

@@ -372,6 +372,14 @@ static int set_ideal_period(bool is_csi)
return is_csi ? MAX_MOBILES_PER_GNB * 2 * nb_slots_per_period / n_ul_slots_per_period : nb_slots_per_period * MAX_MOBILES_PER_GNB;
}
static int set_ideal_period_beam(bool is_csi, int NUM_SSB_period)
{
const frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
const int nb_slots_per_period = fs->numb_slots_period;
// 2 reports per UE (RSRP and RI-PMI-CQI)
return 3 * nb_slots_per_period * MAX_MOBILES_PER_GNB + NUM_SSB_period;
}
static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0,
int id,
int ideal_period,
@@ -379,7 +387,7 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0,
{
nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset));
// TODO ideal period to be set according to estimation by the gNB on how fast the channel changes
const int offset = fs->numb_slots_period * id;
const int offset = id; // id = ssb_index/2, offset should be set to ssb_index/2.
if (check_periodicity(4, ideal_period, fs)) {
nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots4;
nzpcsi0->periodicityAndOffset->choice.slots4 = offset;
@@ -494,7 +502,16 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco
*nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0;
nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId;
const int ideal_period = set_ideal_period(true); // same periodicity as CSI measurement report
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
int ideal_period;
if (beam_info->beam_mode != NO_BEAM_MODE) {
int num_beam = (RC.nrmac[0]->radio_config.nb_bfw[1] > 0) ? RC.nrmac[0]->radio_config.nb_bfw[1] : 1;
int beams_per_period = (beam_info->beams_per_period > 0) ? beam_info->beams_per_period : 1;
int NUM_SSB_period = (num_beam % beams_per_period > 0) ? num_beam / beams_per_period + 1 : num_beam / beams_per_period;
ideal_period = set_ideal_period_beam(true, NUM_SSB_period); // same periodicity as CSI measurement report
} else {
ideal_period = set_ideal_period(true); // same periodicity as CSI measurement report
}
const frame_structure_t *fs = &(RC.nrmac[0]->frame_structure);
set_csirs_periodicity(nzpcsi0, id, ideal_period, fs);
@@ -654,13 +671,28 @@ static void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcell
}
static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(const NR_ServingCellConfigCommon_t *scc,
const int uid)
const int uid,
int beam_idx)
{
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS
int offset;
int ideal_period;
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
if (beam_info->beam_mode != NO_BEAM_MODE) {
int num_beam = (RC.nrmac[0]->radio_config.nb_bfw[1] > 0) ? RC.nrmac[0]->radio_config.nb_bfw[1] : 1;
int beams_per_period = (beam_info->beams_per_period > 0) ? beam_info->beams_per_period : 1 ;
int NUM_SSB_period = (num_beam % beams_per_period > 0) ? num_beam / beams_per_period + 1 : num_beam / beams_per_period;
ideal_period = set_ideal_period_beam(false, NUM_SSB_period);
offset = get_ul_slot_offset_beam(fs, uid, false, beam_idx, beams_per_period, num_beam); // only full UL slots for SRS
LOG_I(NR_MAC, "configure_periodic_srs 0 idx %d count_mixed %d beam_idx %d num_beam %d ideal_period %d srs_offset %d\n",
uid, false, beam_idx, num_beam, ideal_period, offset);
} else {
offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS
ideal_period = set_ideal_period(false);
}
// checked for validity in verify_radio_configuration
AssertFatal(offset < 2560, "Cannot allocate SRS configuration for uid %d, not enough resources\n", uid);
const int ideal_period = set_ideal_period(false);
struct NR_SRS_Resource__resourceType__periodic *periodic_srs = calloc(1,sizeof(*periodic_srs));
if (check_periodicity(4, ideal_period, fs)) {
@@ -769,7 +801,8 @@ static NR_SRS_Resource_t *get_srs_resource(const NR_ServingCellConfigCommon_t *s
const int res_id,
const long maxMIMO_Layers,
const NR_SRS_Resource__transmissionComb_PR tx_comb,
int do_srs)
int do_srs,
int beam_idx)
{
NR_SRS_Resource_t *srs_res = calloc_or_fail(1, sizeof(*srs_res));
srs_res->srs_ResourceId = res_id;
@@ -840,7 +873,7 @@ static NR_SRS_Resource_t *get_srs_resource(const NR_ServingCellConfigCommon_t *s
srs_res->groupOrSequenceHopping = NR_SRS_Resource__groupOrSequenceHopping_neither;
if (do_srs) {
srs_res->resourceType.present = NR_SRS_Resource__resourceType_PR_periodic;
srs_res->resourceType.choice.periodic = configure_periodic_srs(scc, uid);
srs_res->resourceType.choice.periodic = configure_periodic_srs(scc, uid, beam_idx);
} else {
srs_res->resourceType.present = NR_SRS_Resource__resourceType_PR_aperiodic;
srs_res->resourceType.choice.aperiodic = calloc_or_fail(1, sizeof(*srs_res->resourceType.choice.aperiodic));
@@ -861,7 +894,8 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCo
const int res_id,
const long maxMIMO_Layers,
const int minRXTXTIME,
int do_srs)
int do_srs,
int beam_idx)
{
NR_SetupRelease_SRS_Config_t *setup_release_srs_Config = calloc_or_fail(1, sizeof(*setup_release_srs_Config));
setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup;
@@ -870,7 +904,7 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCo
srs_Config->srs_ResourceToAddModList = calloc_or_fail(1, sizeof(*srs_Config->srs_ResourceToAddModList));
NR_SRS_Resource_t *srs_res0 =
get_srs_resource(scc, uecap, curr_bwp, uid, res_id, maxMIMO_Layers, NR_SRS_Resource__transmissionComb_PR_n2, do_srs);
get_srs_resource(scc, uecap, curr_bwp, uid, res_id, maxMIMO_Layers, NR_SRS_Resource__transmissionComb_PR_n2, do_srs, beam_idx);
asn1cSeqAdd(&srs_Config->srs_ResourceToAddModList->list, srs_res0);
srs_Config->srs_ResourceSetToAddModList = calloc_or_fail(1, sizeof(*srs_Config->srs_ResourceSetToAddModList));
@@ -1354,7 +1388,75 @@ static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedul
}
}
static void scheduling_request_config(const NR_ServingCellConfigCommon_t *scc, NR_PUCCH_Config_t *pucch_Config, int scs)
static void set_SR_periodandoffset_beam(NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig, const NR_ServingCellConfigCommon_t *scc, int scs, int beam_idx)
{
const frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
int num_beam = (RC.nrmac[0]->radio_config.nb_bfw[1] > 0) ? RC.nrmac[0]->radio_config.nb_bfw[1] : 1;
int beams_per_period = (beam_info->beams_per_period > 0) ? beam_info->beams_per_period : 1;
int NUM_SSB_period = (num_beam % beams_per_period > 0) ? num_beam / beams_per_period + 1 : num_beam / beams_per_period;
int sr_slot = 1; // in FDD SR in slot 1
const int ideal_period = set_ideal_period_beam(false, NUM_SSB_period);
sr_slot = get_first_ul_slot_beam(fs, beam_idx, beams_per_period, num_beam);
schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset));
LOG_I(NR_MAC, "set_SR_periodandoffset_beam beam_idx %d num_beam %d ideal_period %d sr_slot %d\n",
beam_idx, num_beam, ideal_period, sr_slot);
if (check_periodicity(5, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl5 = sr_slot;
return;
}
else if(check_periodicity(8, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl8 = sr_slot;
return;
}
else if(check_periodicity(10, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = sr_slot;
return;
}
else if(check_periodicity(16, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl16 = sr_slot;
return;
}
else if(check_periodicity(20, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl20 = sr_slot;
return;
}
else if (check_periodicity(40, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl40 = sr_slot;
return;
}
else if (check_periodicity(80, ideal_period, fs)) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl80 = sr_slot;
return;
}
else if ((check_periodicity(160, ideal_period, fs))) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl160 = sr_slot;
return;
}
else if ((check_periodicity(320, ideal_period, fs))) {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl320 = sr_slot;
return;
}
else {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl640 = sr_slot;
}
}
static void scheduling_request_config(const NR_ServingCellConfigCommon_t *scc, NR_PUCCH_Config_t *pucch_Config, int scs, int beam_idx)
{
// format with <=2 bits in pucch resource set 0
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0];
@@ -1366,7 +1468,11 @@ static void scheduling_request_config(const NR_ServingCellConfigCommon_t *scc, N
schedulingRequestResourceConfig->schedulingRequestResourceId = 1;
schedulingRequestResourceConfig->schedulingRequestID = 0;
set_SR_periodandoffset(schedulingRequestResourceConfig, scc, scs);
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
if (beam_info->beam_mode == NO_BEAM_MODE)
set_SR_periodandoffset(schedulingRequestResourceConfig, scc, scs);
else
set_SR_periodandoffset_beam(schedulingRequestResourceConfig, scc, scs, beam_idx);
schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource));
*schedulingRequestResourceConfig->resource = *pucchressetid;
@@ -1840,7 +1946,8 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
int maxMIMO_Layers,
const nr_mac_config_t *configuration,
const NR_ServingCellConfigCommon_t *scc,
const NR_UE_NR_Capability_t *uecap)
const NR_UE_NR_Capability_t *uecap,
int beam_idx)
{
NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp));
ubwp->bwp_Id = 1;
@@ -1884,7 +1991,7 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
config_pucch_resset0(pucch_Config, uid, curr_bwp, num_pucch2, uecap);
config_pucch_resset1(pucch_Config, uid, num_pucch2, uecap);
set_pucch_power_config(pucch_Config, configuration->do_CSIRS);
scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing, beam_idx);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration, scc, uecap);
@@ -1896,7 +2003,8 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
ubwp->bwp_Id,
maxMIMO_Layers,
configuration->minRXTXTIME,
configuration->do_SRS);
configuration->do_SRS,
beam_idx);
ubwp->bwp_Dedicated->configuredGrantConfig = NULL;
ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL;
@@ -1917,14 +2025,38 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc,
NR_CSI_ReportConfig_t *csirep,
int uid,
int curr_bwp,
bool is_rsrp)
bool is_rsrp,
int beam_idx)
{
const int ideal_period = set_ideal_period(true);
int ideal_period;
const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp);
const int idx = (uid * 2 / num_pucch2) + is_rsrp;
int idx;
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int offset = get_ul_slot_offset(fs, idx, true);
LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period);
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
int offset;
if (beam_info->beam_mode != NO_BEAM_MODE) {
// For NO_BEAM_MODE
// C - CSI meas
// R - RSRP
// UL slot
// 0123456789
// uid0 CR
// uid1 -CR
// uid2 --CR
// With beamforming, uid0, uid1 and uid could be of different beams. CSI meas and Report of different uid could not be shared
idx = uid * 2 + is_rsrp;
int num_beam = (RC.nrmac[0]->radio_config.nb_bfw[1] > 0) ? RC.nrmac[0]->radio_config.nb_bfw[1]: 1;
int beams_per_period = (beam_info->beams_per_period > 0) ? beam_info->beams_per_period: 1;
int NUM_SSB_period = (num_beam % beams_per_period > 0) ? num_beam / beams_per_period + 1 : num_beam / beams_per_period;
ideal_period = set_ideal_period_beam(true, NUM_SSB_period);
LOG_I(NR_MAC, "set_csi_meas_periodicity 0 idx %d count_mixed %d beam_idx %d num_beam %d ideal_period %d\n", idx, true, beam_idx, num_beam, ideal_period);
offset = get_ul_slot_offset_beam(fs, idx, true, beam_idx, beams_per_period, num_beam);
} else {
ideal_period = set_ideal_period(true);
idx = (uid * 2 / num_pucch2) + is_rsrp;
offset = get_ul_slot_offset(fs, idx, true);
}
LOG_I(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d\n", uid, offset, ideal_period);
// checked for validity in verify_radio_configuration
AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n");
if (check_periodicity(4, ideal_period, fs)) {
@@ -2074,7 +2206,8 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
const int max_layers,
int rep_id,
int uid,
int curr_bwp)
int curr_bwp,
int beam_idx)
{
int resource_id = -1;
int im_id = -1;
@@ -2103,7 +2236,7 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
csirep->nzp_CSI_RS_ResourcesForInterference = NULL;
csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic;
csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic));
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, false);
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, false, beam_idx);
asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires);
csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI;
csirep->reportQuantity.choice.cri_RI_PMI_CQI = (NULL_t)0;
@@ -2171,7 +2304,8 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
int uid,
int curr_bwp,
int num_antenna_ports,
uint64_t ssb_bitmap)
uint64_t ssb_bitmap,
int beam_idx)
{
int resource_id = -1;
for (int csi_list = 0; csi_list < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_list++) {
@@ -2197,7 +2331,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
csirep->nzp_CSI_RS_ResourcesForInterference = NULL;
csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic;
csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic));
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, true);
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, true, beam_idx);
asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires);
if (configuration->report_type == SSB_SINR) {
csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_none;
@@ -3313,7 +3447,8 @@ static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellCo
const nr_mac_config_t *configuration,
int maxMIMO_Layers,
const NR_UE_NR_Capability_t *uecap,
int id)
int id,
int beam_idx)
{
NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP));
NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
@@ -3334,9 +3469,9 @@ static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellCo
initialUplinkBWP->pusch_Config = config_pusch(configuration, scc, uecap);
// We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1
initialUplinkBWP->srs_Config = get_config_srs(scc, uecap, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0);
initialUplinkBWP->srs_Config = get_config_srs(scc, uecap, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0, beam_idx);
scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing);
scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing, beam_idx);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, genericParameters->subcarrierSpacing);
return initialUplinkBWP;
}
@@ -3391,7 +3526,9 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
const nr_mac_config_t *configuration,
int uid,
int bwp_id,
uint64_t bitmap)
uint64_t bitmap,
int ssb_index,
int beam_idx)
{
NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1, sizeof(*csi_MeasConfig));
csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList));
@@ -3431,8 +3568,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
const int pdsch_AntennaPorts =
configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP;
config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, bwp_id);
config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, bwp_id);
config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, ssb_index / 2);
config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, ssb_index / 2);
NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1));
csires1->csi_ResourceConfigId = bwp_id + 20;
@@ -3458,7 +3595,7 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList =
calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList));
NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1, sizeof(*nzp0));
*nzp0 = bwp_id;
*nzp0 = ssb_index / 2;
asn1cSeqAdd(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list, nzp0);
csires0->bwp_Id = bwp_id;
csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic;
@@ -3472,7 +3609,7 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList =
calloc(1, sizeof(*csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList));
NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1, sizeof(*csiim00));
*csiim00 = bwp_id;
*csiim00 = ssb_index / 2;
asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00);
csires2->bwp_Id = bwp_id;
csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic;
@@ -3489,7 +3626,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
*configDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers,
bwp_id,
uid,
curr_bwp);
curr_bwp,
beam_idx);
}
NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp));
pucchrsrp->uplinkBandwidthPartId = bwp_id;
@@ -3503,13 +3641,16 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
uid,
curr_bwp,
pdsch_AntennaPorts,
bitmap);
bitmap,
beam_idx);
return csi_MeasConfig;
}
static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration)
const nr_mac_config_t *configuration,
int ssb_index,
int beam_idx)
{
const int pdsch_AntennaPorts =
configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP;
@@ -3549,7 +3690,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp);
asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp);
if (first_active_bwp == 0) {
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, NULL, uid);
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, NULL, uid, beam_idx);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, NULL, configuration);
} else {
configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
@@ -3561,7 +3702,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
configuration);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp);
uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(true, uid, maxMIMO_Layers, configuration, scc, NULL);
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(true, uid, maxMIMO_Layers, configuration, scc, NULL, beam_idx);
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
}
@@ -3573,7 +3714,9 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
configuration,
uid,
first_active_bwp,
bitmap);
bitmap,
ssb_index,
beam_idx);
fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq, first_active_bwp);
SpCellConfig->spCellConfigDedicated = configDedicated;
@@ -3706,10 +3849,21 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
return rlc_BearerConfig;
}
static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration)
static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration, int beam_idx)
{
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int srs_offset = get_ul_slot_offset(fs, uid, false);
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
int srs_offset;
if (beam_info->beam_mode != NO_BEAM_MODE) {
int num_beam = (RC.nrmac[0]->radio_config.nb_bfw[1] > 0) ? RC.nrmac[0]->radio_config.nb_bfw[1] : 1;
int beams_per_period = (beam_info->beams_per_period > 0) ? beam_info->beams_per_period : 1;
srs_offset = get_ul_slot_offset_beam(fs, uid, false, beam_idx, beams_per_period, num_beam);
LOG_I(NR_MAC, "verify_radio_configuration 0 idx %d count_mixed %d beam_idx %d num_beam %d srs_offset %d\n",
uid, false, beam_idx, num_beam, srs_offset);
} else {
srs_offset = get_ul_slot_offset(fs, uid, false);
}
// see configure_periodic_srs
if (srs_offset >= 2560) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for SRS, rejecting UE\n", uid);
@@ -3737,8 +3891,29 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon
LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH2, rejecting UE\n", uid);
return false; // cannot allocate resources for PUCCH2
}
const int idx = (uid * 2 / num_pucch2) + 1;
int offset = get_ul_slot_offset(fs, idx, true);
int offset;
if (beam_info->beam_mode != NO_BEAM_MODE) {
int num_beam = (RC.nrmac[0]->radio_config.nb_bfw[1] > 0) ? RC.nrmac[0]->radio_config.nb_bfw[1] : 1;
int beams_per_period = (beam_info->beams_per_period > 0) ? beam_info->beams_per_period : 1;
// For NO_BEAM_MODE
// C - CSI meas
// R - RSRP
// UL slot
// 0123456789
// uid0 CR
// uid1 -CR
// uid2 --CR
// With beamforming, uid0, uid1 and uid could be of different beams. CSI meas and Report of different uid could not be shared
const int idx = (uid * 2) + 1;
offset = get_ul_slot_offset_beam(fs, idx, true, beam_idx, beams_per_period, num_beam);
LOG_I(NR_MAC, "verify_radio_configuration 1 idx %d count_mixed %d beam_idx %d num_beam %d offset %d\n",
idx, true, beam_idx, num_beam, offset);
} else {
const int idx = (uid * 2 / num_pucch2) + 1;
offset = get_ul_slot_offset(fs, idx, true);;
}
// see set_csi_meas_periodicity
if (offset >= 320) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI reporting, rejecting UE\n", uid);
@@ -3751,12 +3926,14 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
const nr_rlc_configuration_t *default_rlc_config)
const nr_rlc_configuration_t *default_rlc_config,
int ssb_index,
int beam_idx)
{
if (!verify_radio_configuration(uid, scc, configuration))
if (!verify_radio_configuration(uid, scc, configuration, beam_idx))
return NULL;
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration);
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration, ssb_index, beam_idx);
NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig));
cellGroupConfig->cellGroupId = 0;
@@ -3787,7 +3964,9 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
const NR_ServingCellConfigCommon_t *scc,
int uid,
int old_bwp,
int new_bwp)
int new_bwp,
int ssb_index,
int beam_idx)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
@@ -3806,7 +3985,7 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP));
if (!uplinkConfig->initialUplinkBWP)
uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP));
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, ul_maxMIMO_Layers, uecap, uid);
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, ul_maxMIMO_Layers, uecap, uid, beam_idx);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, uecap, &local_config);
} else {
if (!configDedicated->downlinkBWP_ToAddModList)
@@ -3821,7 +4000,7 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
if (!uplinkConfig->uplinkBWP_ToAddModList)
uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(true, uid, ul_maxMIMO_Layers, &local_config, scc, uecap);
NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(true, uid, ul_maxMIMO_Layers, &local_config, scc, uecap, beam_idx);
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp);
}
@@ -3832,7 +4011,9 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
&local_config,
uid,
*uplinkConfig->firstActiveUplinkBWP_Id,
bitmap);
bitmap,
ssb_index,
beam_idx);
// we temporarily need to keep both the old and the new BWP in the CG used by the gNB
// while removing the old from the CG sent to the UE
@@ -3844,11 +4025,42 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
return clone_cg;
}
NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_t *cellGroupConfig,
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
int bwp,
int ssb_index,
int beam_idx)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
uint64_t bitmap = get_ssb_bitmap(scc);
ASN_STRUCT_FREE(asn_DEF_NR_CSI_MeasConfig, configDedicated->csi_MeasConfig->choice.setup);
configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated,
uecap,
scc,
configuration,
uid,
bwp,
bitmap,
ssb_index,
beam_idx);
NR_CellGroupConfig_t *clone_cg = NULL;
const int copy_result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&clone_cg, cellGroupConfig);
AssertFatal(copy_result == 0, "unable to copy NR_CellGroupConfig for cloning\n");
return clone_cg;
}
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
const int uid,
const NR_UE_NR_Capability_t *uecap,
const nr_mac_config_t *configuration,
const NR_ServingCellConfigCommon_t *scc)
const NR_ServingCellConfigCommon_t *scc,
int beam_idx)
{
DevAssert(cellGroupConfig != NULL);
DevAssert(cellGroupConfig->spCellConfig != NULL);
@@ -3930,7 +4142,8 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
bwp_id,
maxMIMO_Layers,
configuration->minRXTXTIME,
configuration->do_SRS);
configuration->do_SRS,
beam_idx);
}
set_ul_mcs_table(configuration->force_UL256qam_off ? NULL : uecap, scc, pusch_Config);
}
@@ -3983,7 +4196,9 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
int scg_id,
int servCellIndex,
const nr_mac_config_t *configuration,
int uid)
int uid,
int ssb_index,
int beam_idx)
{
const nr_pdsch_AntennaPorts_t *pdschap = &configuration->pdsch_AntennaPorts;
const int dl_antenna_ports = pdschap->N1 * pdschap->N2 * pdschap->XP;
@@ -4054,7 +4269,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
0,
maxMIMO_Layers,
configuration->minRXTXTIME,
configuration->do_SRS);
configuration->do_SRS,
beam_idx);
// Downlink BWPs
int firstActiveDownlinkBWP_Id = 1;
@@ -4074,7 +4290,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
// Uplink BWPs
int firstActiveUplinkBWP_Id = 1;
ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap);
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap, beam_idx);
asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp);
ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id));
*ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id;
@@ -4134,7 +4350,9 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
configuration,
uid,
firstActiveUplinkBWP_Id,
bitmap);
bitmap,
ssb_index,
beam_idx);
configDedicated->sCellDeactivationTimer = NULL;
configDedicated->crossCarrierSchedulingConfig = NULL;

View File

@@ -95,12 +95,15 @@ NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc);
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
const nr_rlc_configuration_t *default_rlc_config);
const nr_rlc_configuration_t *default_rlc_config,
int ssb_index,
int beam_idx);
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
const int uid,
const NR_UE_NR_Capability_t *uecap,
const nr_mac_config_t *configuration,
const NR_ServingCellConfigCommon_t *scc);
const NR_ServingCellConfigCommon_t *scc,
int beam_idx);
int encode_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, uint8_t *buffer, int max_buffer_size);
/* Note: this function returns a new CellGroupConfig for a user with given
@@ -111,7 +114,9 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
int scg_id,
int servCellIndex,
const nr_mac_config_t *configuration,
int uid);
int uid,
int ssb_index,
int beam_idx);
NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc, int frame);
@@ -133,7 +138,17 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
const NR_ServingCellConfigCommon_t *scc,
int uid,
int old_bwp,
int new_bwp);
int new_bwp,
int ssb_index,
int beam_idx);
NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_t *cellGroupConfig,
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
int bwp,
int ssb_index,
int beam_idx);
NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len);
measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime);
int encode_measgap_config(const measgap_config_t *c, uint8_t *buf);