Compare commits

...

10 Commits

Author SHA1 Message Date
francescomani
f63b57388e fix CSI-RS slot determination according to SSB index
reworked version of commit c30ad1d07b

Co-Authored-By: @mjoang_oai
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:22:49 +02:00
Mario Joa-Ng
4cff137957 set ssb_index using get_ssbidx_from_beam() instead of using common_channels[0].ssb_index[] which was used in set_analog_beamforming = 1 previously 2026-05-30 10:22:49 +02:00
francescomani
c78f032529 harmonize update_cellGroupConfig functions
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:22:49 +02:00
francescomani
4703f16090 take into account the possibility to have multiple SSB in a slot when configuring CSI-RS according to SSB index
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:22:48 +02:00
francescomani
eae88d7fc9 apply the new csiMeasConfig to the cloned cellGroup to avoid nulling in the calling function
(this could have lead to no csiMeasConfig available if the reconfiguration fails)

Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:13:41 +02:00
francescomani
2ec3bef5e6 improve handling of UE context modification confirm/refuse
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:13:41 +02:00
francescomani
694f4f56cb trigger reconfiguration, conditional to having CSI-RS set
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:13:41 +02:00
francescomani
4da944390e add assertion to prevent CSI-RS offset to go beyond period
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:13:41 +02:00
francescomani
70013e8df0 simplify tci handling of beam switching by not returning unused new beam index
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:13:41 +02:00
francescomani
17d290982d fix formatting and remove unnecessary nulling of srs_Config
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 10:13:41 +02:00
10 changed files with 195 additions and 172 deletions

View File

@@ -981,7 +981,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
const NR_DownlinkConfigCommon_t *dlcc = scc->downlinkConfigCommon;
nr_rrc_config_dl_tda(dlcc->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
get_frame_type((int)*dlcc->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing),
scc->tdd_UL_DL_ConfigurationCommon,
scc,
num_symb_cset);
nr_rrc_config_ul_tda(scc, rc->minRXTXTIME, rc->do_SRS);
seq_arr_init(&nrmac->ul_tda, sizeof(NR_tda_info_t));
@@ -1190,7 +1190,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, false);
nr_mac_trigger_reconfiguration(nrmac, UE, bwp_id, -1);
success = true;
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);

View File

@@ -191,7 +191,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
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 / 14) == rel_slot) {
if ((ssb_start_symbol / NR_SYMBOLS_PER_SLOT) == rel_slot) {
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info,
frameP,
slotP,

View File

@@ -3678,9 +3678,14 @@ void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti)
void beam_switching_procedure(gNB_MAC_INST *mac, NR_UE_info_t *UE, int new_beam_index)
{
LOG_I(NR_MAC, "[UE %x] Switching to beam with ID %d (from %d)\n", UE->rnti, new_beam_index, UE->UE_beam_index);
UE->UE_beam_index = new_beam_index;
nr_mac_trigger_reconfiguration(mac, UE, -1, true);
// currently we only need to reconfigure if CSI-RS is enabled
// if we reconfigure we need to wait to switch the comfirmation of context modification
if (mac->radio_config.do_CSIRS)
nr_mac_trigger_reconfiguration(mac, UE, -1, new_beam_index);
else {
LOG_I(NR_MAC, "[UE %x] Switching to beam with ID %d (from %d)\n", UE->rnti, new_beam_index, UE->UE_beam_index);
UE->UE_beam_index = new_beam_index;
}
}
void nr_mac_update_timers(module_id_t module_id)
@@ -3884,7 +3889,7 @@ int 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 new_bf_index;
return -1; // no beam change now in case of TCI
}
void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data)
@@ -4065,42 +4070,41 @@ 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, bool new_beam)
void nr_mac_trigger_reconfiguration(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, int new_beam)
{
DevAssert(UE->CellGroup != NULL);
NR_CellGroupConfig_t *cellGroup_for_UE = NULL;
if (new_beam) {
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
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,
ssb_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);
}
int ssb_index = get_ssbidx_from_beam(nrmac, UE->UE_beam_index);
if (new_beam >= 0) {
UE->cm_info.trigger_info = BEAM_SWITCH;
UE->cm_info.new_state = new_beam;
cellGroup_for_UE = update_cellGroupConfig_for_reconfig(UE->CellGroup,
&nrmac->radio_config,
UE->capability,
nrmac->common_channels[0].ServingCellConfigCommon,
UE->uid,
UE->current_DL_BWP.bwp_id,
-1,
ssb_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->cm_info.trigger_info = BWP_SWITCH;
UE->cm_info.new_state = new_bwp_id;
cellGroup_for_UE = update_cellGroupConfig_for_reconfig(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);
}
}
} else
UE->cm_info.trigger_info = MSG3_CRNTI;
uint8_t buf[2048];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
NULL,

View File

@@ -842,7 +842,7 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
}
}
}
if ((new_bf_index !=-1) && !nrmac->radio_config.do_TCI)
if (new_bf_index != -1)
// Trigger RRCReconfiguration. Need to be out of the for loop as it may modify csi_MeasConfig
beam_switching_procedure(nrmac, UE, new_bf_index);
}

View File

@@ -859,7 +859,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, false);
nr_mac_trigger_reconfiguration(mac, old_UE, -1, -1);
// 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);
}

View File

@@ -518,7 +518,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, bool new_beam);
void nr_mac_trigger_reconfiguration(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, int 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

@@ -901,53 +901,69 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req)
void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm)
{
LOG_I(MAC, "Received UE Context Modification Confirm for UE %04x\n", confirm->gNB_DU_ue_id);
LOG_I(NR_MAC, "Received UE Context Modification Confirm for UE %04x\n", confirm->gNB_DU_ue_id);
gNB_MAC_INST *mac = RC.nrmac[0];
NR_SCHED_LOCK(&mac->sched_lock);
/* check first that the scheduler knows such UE */
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, confirm->gNB_DU_ue_id);
if (UE == NULL) {
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Confirm\n", confirm->gNB_DU_ue_id);
LOG_E(NR_MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Confirm\n", confirm->gNB_DU_ue_id);
NR_SCHED_UNLOCK(&mac->sched_lock);
return;
}
if (UE->cm_info.trigger_info == BEAM_SWITCH) {
LOG_I(NR_MAC, "[UE %x] Switching to beam with ID %d (from %d)\n", UE->rnti, UE->cm_info.new_state, UE->UE_beam_index);
UE->UE_beam_index = UE->cm_info.new_state;
} else if (UE->cm_info.trigger_info == BWP_SWITCH)
UE->local_bwp_id = UE->cm_info.new_state;
UE->cm_info.trigger_info = NO_TRIGGER;
NR_SCHED_UNLOCK(&mac->sched_lock);
if (confirm->rrc_container_length > 0) {
logical_chan_id_t id = 1;
nr_rlc_srb_recv_sdu(confirm->gNB_DU_ue_id, id, confirm->rrc_container, confirm->rrc_container_length);
}
/* nothing else to be done? */
}
void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse)
{
/* Currently, we only use the UE Context Modification Required procedure to
* trigger a RRC reconfigurtion after Msg.3 with C-RNTI MAC CE. If the CU
* refuses, it cannot do this reconfiguration, leaving the UE in an
* unconfigured state. Therefore, we just free all RA-related info, and
* request the release of the UE. */
LOG_W(MAC, "Received UE Context Modification Refuse for %04x, requesting release\n", refuse->gNB_DU_ue_id);
LOG_W(NR_MAC, "Received UE Context Modification Refuse for %04x\n", refuse->gNB_DU_ue_id);
gNB_MAC_INST *mac = RC.nrmac[0];
NR_SCHED_LOCK(&mac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, refuse->gNB_DU_ue_id);
if (UE == NULL) {
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Refuse\n", refuse->gNB_DU_ue_id);
LOG_E(NR_MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Refuse\n", refuse->gNB_DU_ue_id);
NR_SCHED_UNLOCK(&mac->sched_lock);
return;
}
bool release = false;
if (UE->cm_info.trigger_info == MSG3_CRNTI) {
/* if the UE Context Modification Required procedure was initiated
* for a RRC reconfigurtion after Msg.3 with C-RNTI MAC CE, if the CU
* refuses, it cannot do this reconfiguration, leaving the UE in an
* unconfigured state. Therefore, we just free all RA-related info, and
* request the release of the UE. */
LOG_W(NR_MAC, "Context Modification Required after MSG3 with C-RNTI, requesting release\n");
release = true;
} else {
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
UE->reconfigCellGroup = NULL;
}
UE->cm_info.trigger_info = NO_TRIGGER;
NR_SCHED_UNLOCK(&mac->sched_lock);
f1ap_ue_context_rel_req_t request = {
.gNB_CU_ue_id = refuse->gNB_CU_ue_id,
.gNB_DU_ue_id = refuse->gNB_DU_ue_id,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = F1AP_CauseRadioNetwork_procedure_cancelled,
};
mac->mac_rrc.ue_context_release_request(&request);
if (release) {
f1ap_ue_context_rel_req_t request = {
.gNB_CU_ue_id = refuse->gNB_CU_ue_id,
.gNB_DU_ue_id = refuse->gNB_DU_ue_id,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = F1AP_CauseRadioNetwork_procedure_cancelled,
};
mac->mac_rrc.ue_context_release_request(&request);
}
}
void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd)

View File

@@ -785,6 +785,18 @@ typedef struct measgap_config {
int mgl_slots;
} measgap_config_t;
typedef enum {
NO_TRIGGER,
MSG3_CRNTI,
BWP_SWITCH,
BEAM_SWITCH
} reconfig_trigger_state_t;
typedef struct {
int new_state;
reconfig_trigger_state_t trigger_info;
} context_modification_info_t;
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
typedef struct NR_UE_info {
rnti_t rnti;
@@ -822,6 +834,7 @@ typedef struct NR_UE_info {
// dedicated BWP is always 1 from the UE's point of view, even if the gNB has multiple BWPs.
// The below ID is the "true" (non-consecutive) BWP ID from the gNB's point of view
NR_BWP_Id_t local_bwp_id;
context_modification_info_t cm_info;
} NR_UE_info_t;
typedef struct {

View File

@@ -363,13 +363,13 @@ static int set_ideal_period(bool is_csi)
}
static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0,
int id,
int offset,
int ideal_period,
const frame_structure_t *fs)
{
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 = id; // id = ssb_index/2, offset should be set to ssb_index/2.
AssertFatal(offset < ideal_period, "CSI-RS offset %d goes beyond the assumed period %d\n", offset, ideal_period);
if (check_periodicity(4, ideal_period, fs)) {
nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots4;
nzpcsi0->periodicityAndOffset->choice.slots4 = offset;
@@ -410,12 +410,16 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0,
nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320;
const int nb_dl_slots_period = get_full_dl_slots_per_period(fs); // full DL slots
// checked for validity in verify_radio_configuration
AssertFatal(offset / 320 < nb_dl_slots_period, "Cannot allocate CSI-RS for BWP %d. Not enough resources for CSI-RS\n", id);
AssertFatal(offset / 320 < nb_dl_slots_period, "Cannot allocate CSI-RS for BWP %d. Not enough resources for CSI-RS\n", offset);
nzpcsi0->periodicityAndOffset->choice.slots320 = (offset % 320) + (offset / 320);
}
}
static NR_NZP_CSI_RS_Resource_t *get_nzp_csi_rs_resource(int id, int num_dl_antenna_ports, int curr_bwp, long scramblingID)
static NR_NZP_CSI_RS_Resource_t *get_nzp_csi_rs_resource(int id,
int num_dl_antenna_ports,
int curr_bwp,
int symbol_index,
long scramblingID)
{
NR_NZP_CSI_RS_Resource_t *nzpcsi = calloc(1, sizeof(*nzpcsi));
nzpcsi->nzp_CSI_RS_ResourceId = id;
@@ -471,7 +475,7 @@ static NR_NZP_CSI_RS_Resource_t *get_nzp_csi_rs_resource(int id, int num_dl_ante
default:
AssertFatal(false, "Number of ports not yet supported\n");
}
resourceMapping.firstOFDMSymbolInTimeDomain = 13; // last symbol of slot
resourceMapping.firstOFDMSymbolInTimeDomain = 13 - symbol_index;
resourceMapping.firstOFDMSymbolInTimeDomain2 = NULL;
resourceMapping.density.present = NR_CSI_RS_ResourceMapping__density_PR_one;
resourceMapping.density.choice.one = (NULL_t)0;
@@ -497,6 +501,7 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco
int num_dl_antenna_ports,
int curr_bwp,
int do_csirs,
int symbol_index,
int id)
{
if (do_csirs) {
@@ -515,7 +520,7 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco
if (!csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)
csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1, sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList));
NR_NZP_CSI_RS_Resource_t *nzpcsi0 =
get_nzp_csi_rs_resource(id, num_dl_antenna_ports, curr_bwp, *servingcellconfigcommon->physCellId);
get_nzp_csi_rs_resource(id, num_dl_antenna_ports, curr_bwp, symbol_index, *servingcellconfigcommon->physCellId);
asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list, nzpcsi0);
// Add NZP CSI-RS Resource ID: identifier used to reference one NZP-CSI-RS-Resource
@@ -1034,9 +1039,25 @@ void prepare_sim_uecap(NR_UE_NR_Capability_t *cap,
}
}
static int csi_symbols_in_slot(const NR_ServingCellConfigCommon_t *scc)
{
uint64_t ssb_bitmap = get_ssb_bitmap(scc);
bool two_ssb_per_slot = false;
for (int i = 0; i < 64; i += 2) {
// check if both even ssb and subsequent odd ssb are configured
bool even_set = (ssb_bitmap >> (63 - i)) & 0x01;
bool odd_set = (ssb_bitmap >> (63 - (i + 1))) & 0x01;
if (even_set && odd_set) {
two_ssb_per_slot = true;
break;
}
}
return two_ssb_per_slot ? 2 : 1;
}
void nr_rrc_config_dl_tda(NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList,
frame_type_t frame_type,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
const NR_ServingCellConfigCommon_t *scc,
int len_coreset)
{
// setting default TDA for DL with TDA index 0
@@ -1048,14 +1069,14 @@ void nr_rrc_config_dl_tda(NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_Tim
timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset); // basic slot configuration starting in symbol 1 til the end of the slot
asn1cSeqAdd(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation);
// setting TDA for CSI-RS symbol with index 1
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
NR_PDSCH_TimeDomainResourceAllocation_t *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
timedomainresourceallocation1->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
timedomainresourceallocation1->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset-1); // 1 symbol CSI-RS
timedomainresourceallocation1->startSymbolAndLength = get_SLIV(len_coreset, 14 - len_coreset - csi_symbols_in_slot(scc)); // CSI-RS symbols
asn1cSeqAdd(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation1);
if(frame_type==TDD) {
// TDD
if(tdd_UL_DL_ConfigurationCommon) {
if(frame_type == TDD) {
if(scc->tdd_UL_DL_ConfigurationCommon) {
int dl_symb = 0;
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = scc->tdd_UL_DL_ConfigurationCommon;
if (tdd_UL_DL_ConfigurationCommon->pattern2 && tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols)
AssertFatal(tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols == tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,
"nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n",
@@ -1068,7 +1089,7 @@ void nr_rrc_config_dl_tda(NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_Tim
}
if(dl_symb > 1) {
// mixed slot TDA with TDA index 2
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
NR_PDSCH_TimeDomainResourceAllocation_t *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
timedomainresourceallocation2->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
timedomainresourceallocation2->startSymbolAndLength = get_SLIV(len_coreset,dl_symb-len_coreset); // mixed slot configuration starting in symbol 1 til the end of the dl allocation
asn1cSeqAdd(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation2);
@@ -1837,7 +1858,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
nr_rrc_config_dl_tda(bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
get_frame_type((int)*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing),
scc->tdd_UL_DL_ConfigurationCommon,
scc,
coreset->duration);
if (!bwp->bwp_Dedicated) {
@@ -1925,7 +1946,6 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
set_pucch_power_config(pucch_Config);
scheduling_request_config(pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME);
ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration, scc, uecap);
ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc,
@@ -3442,7 +3462,7 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell
static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *configDedicated,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
const nr_mac_config_t *config,
int uid,
int bwp_id,
uint64_t bitmap,
@@ -3484,10 +3504,15 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
}
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, ssb_index / 2);
config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, ssb_index / 2);
int same_slot_index = (ssb_index % 2 == 0) ? (ssb_index + 1) : (ssb_index - 1);
bool has_companion = (bitmap >> (63 - same_slot_index)) & 0x01;
int symbol_index = has_companion ? ssb_index % 2 : 0;
int ssb_slot = get_ssb_start_symbol(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],
*scc->ssbSubcarrierSpacing,
ssb_index) / NR_SYMBOLS_PER_SLOT;
const int pdsch_AntennaPorts = config->pdsch_AntennaPorts.N1 * config->pdsch_AntennaPorts.N2 * config->pdsch_AntennaPorts.XP;
config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, config->do_CSIRS, symbol_index, ssb_slot);
config_csiim(config->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, ssb_slot);
NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1));
csires1->csi_ResourceConfigId = bwp_id + 20;
@@ -3504,7 +3529,7 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1);
int pucch_Resource = 2;
if (configuration->do_CSIRS) {
if (config->do_CSIRS) {
NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0));
csires0->csi_ResourceConfigId = bwp_id;
csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB;
@@ -3513,21 +3538,21 @@ 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 = ssb_index / 2;
*nzp0 = ssb_index;
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;
asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires0);
}
if (configuration->do_CSIRS) {
if (config->do_CSIRS) {
NR_CSI_ResourceConfig_t *csires2 = calloc(1, sizeof(*csires2));
csires2->csi_ResourceConfigId = bwp_id + 10;
csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList;
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 = ssb_index / 2;
*csiim00 = ssb_index;
asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00);
csires2->bwp_Id = bwp_id;
csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic;
@@ -3540,7 +3565,7 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
scc,
pucchcsi,
pdsch_Config,
&configuration->pdsch_AntennaPorts,
&config->pdsch_AntennaPorts,
*configDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers,
bwp_id,
uid,
@@ -3553,7 +3578,7 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
uecap,
scc,
pucchrsrp,
configuration,
config,
bwp_id + 10,
uid,
curr_bwp,
@@ -3833,92 +3858,64 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
return cellGroupConfig;
}
NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_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 old_bwp,
int new_bwp,
int ssb_index)
NR_CellGroupConfig_t *update_cellGroupConfig_for_reconfig(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 old_bwp,
int new_bwp,
int ssb_index)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
*configDedicated->firstActiveDownlinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0
NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig;
*uplinkConfig->firstActiveUplinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0
nr_mac_config_t local_config = *configuration;
long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap);
local_config.first_active_bwp = new_bwp;
uint64_t bitmap = get_ssb_bitmap(scc);
// add new BWP
if (new_bwp == 0) {
if (!configDedicated->initialDownlinkBWP)
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);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, bitmap, uecap, &local_config);
} else {
if (!configDedicated->downlinkBWP_ToAddModList)
configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
NR_BWP_Downlink_t *dl_bwp = config_downlinkBWP(scc, uecap, local_config.force_256qam_off, true, &local_config);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, dl_bwp);
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);
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp);
nr_mac_config_t local_config = *configuration;
if (new_bwp >= 0) {
*configDedicated->firstActiveDownlinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0
*uplinkConfig->firstActiveUplinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0
long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap);
local_config.first_active_bwp = new_bwp;
// add new BWP
if (new_bwp == 0) {
if (!configDedicated->initialDownlinkBWP)
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);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, bitmap, uecap, &local_config);
} else {
if (!configDedicated->downlinkBWP_ToAddModList)
configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
NR_BWP_Downlink_t *dl_bwp = config_downlinkBWP(scc, uecap, local_config.force_256qam_off, true, &local_config);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, dl_bwp);
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);
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp);
}
}
ASN_STRUCT_FREE(asn_DEF_NR_CSI_MeasConfig, configDedicated->csi_MeasConfig->choice.setup);
configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated,
uecap,
scc,
&local_config,
uid,
*uplinkConfig->firstActiveUplinkBWP_Id,
bitmap,
ssb_index);
// 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
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");
if (old_bwp > 0)
NR_ServingCellConfig_t *clone_configDedicated = clone_cg->spCellConfig->spCellConfigDedicated;
clone_configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated,
uecap,
scc,
&local_config,
uid,
*uplinkConfig->firstActiveUplinkBWP_Id,
bitmap,
ssb_index);
if (new_bwp >= 0 && old_bwp > 0)
clean_bwp_structures(clone_cg->spCellConfig);
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)
{
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);
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,

View File

@@ -29,7 +29,7 @@ typedef struct measgap_config measgap_config_t;
void nr_rrc_config_dl_tda(NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList,
frame_type_t frame_type,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
const NR_ServingCellConfigCommon_t *scc,
int len_coreset);
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, nr_srs_type_t do_SRS);
NR_SearchSpace_t *rrc_searchspace_config(bool is_common,
@@ -108,21 +108,14 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
NR_RLC_Config_PR rlc_conf,
long priority,
const nr_rlc_configuration_t *default_rlc_config);
NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_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 old_bwp,
int new_bwp,
int ssb_index);
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);
NR_CellGroupConfig_t *update_cellGroupConfig_for_reconfig(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 old_bwp,
int new_bwp,
int ssb_index);
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);