mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f63b57388e | ||
|
|
4cff137957 | ||
|
|
c78f032529 | ||
|
|
4703f16090 | ||
|
|
eae88d7fc9 | ||
|
|
2ec3bef5e6 | ||
|
|
694f4f56cb | ||
|
|
4da944390e | ||
|
|
70013e8df0 | ||
|
|
17d290982d |
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user