Compare commits

...

26 Commits

Author SHA1 Message Date
Karim Boutiba
7b496cbcfc revert commit aa6c8f1550 2026-04-16 15:11:29 +02:00
Karim Boutiba
34fbf47f05 Avoid segfault when PUCCH resource id out of index 2026-04-16 14:53:01 +02:00
Karim Boutiba
d4ce0a6a80 add beam index to periodic UE log 2026-04-16 13:45:05 +02:00
francescomani
32f11998c8 improve handling of UE context modification confirm/refuse 2026-04-16 11:26:01 +02:00
Karim Boutiba
1fcf919a93 Revert "Merge remote-tracking branch 'origin/fix_3870' into microamp_multi_beams"
This reverts commit cf85d8a8eb, reversing
changes made to 7e55ac311f.
2026-04-16 10:59:09 +02:00
Karim Boutiba
cf85d8a8eb Merge remote-tracking branch 'origin/fix_3870' into microamp_multi_beams 2026-04-16 10:29:27 +02:00
francescomani
7e55ac311f option to change TDA in case of MUX23 2026-04-16 10:11:56 +02:00
francescomani
5d795aa701 call functions to configure TDA in nr_mac_config_scc
this is done to be able to set DL TDA after calling config_sched_ctrlSIB1 and knowing the potential configuration of commonControlResourceSet for MUX pattern 3 which duration doesn't depend on the BWP size
2026-04-16 10:11:28 +02:00
Mario Joa-Ng
169eb9a134 Fix CSI-RS slot which should not be SSB_index / 2. 2026-04-16 10:01:51 +02:00
Mario Joa-Ng
15c10866f7 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-04-16 09:59:57 +02:00
Mario Joa-Ng
c0ce54c3b8 handle start symbol on non-zeroth symbol for SIB for mux 3. 2026-04-16 09:58:56 +02:00
Mario Joa-Ng
0eae3ab55e Use reserve arrays so that MSG3 and PUSCH that are scheduled in advance will check if the slot which will be used by periodic UL signal (SR, SRS, CSI reports) 2026-04-16 09:55:44 +02:00
Mario Joa-Ng
9cd15a9c11 Get beam loc in beam_weights and use it to assign the corresponding uplink slot for SR. 2026-04-16 09:49:47 +02:00
Karim Boutiba
aa6c8f1550 temporary fixing SR slot to avoid bug 2026-04-16 09:46:19 +02:00
Mario Joa-Ng
b9d10b32be Limit the number of uplink slot dedicated to SR to 16 to allow enough slots for other UL signals when SSB >= 16 2026-04-15 16:20:29 +02:00
Mario Joa-Ng
a0245e324d 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-04-15 16:19:21 +02:00
francescomani
518eacab67 fix CSI-RS slot determination according to SSB index
reworked version of commit c30ad1d07b

Co-Authored-By: @mjoang_oai
2026-04-10 12:18:03 +02:00
Mario Joa-Ng
8ba92b53c4 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-04-10 12:18:03 +02:00
francescomani
0e6a435349 harmonize update_cellGroupConfig functions 2026-04-10 12:18:01 +02:00
francescomani
fb414bc86b take into account the possibility to have multiple SSB in a slot when configuring CSI-RS according to SSB index 2026-04-10 12:13:03 +02:00
francescomani
f4e422b4dc 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)
2026-04-10 11:24:20 +02:00
francescomani
7a63d80d09 improve handling of UE context modification confirm/refuse 2026-04-10 11:24:20 +02:00
francescomani
e8927c992e trigger reconfiguration, conditional to having CSI-RS set 2026-04-10 11:24:20 +02:00
francescomani
2e37e2222a add assertion to prevent CSI-RS offset to go beyond period 2026-04-10 11:24:20 +02:00
francescomani
1b3421235c simplify tci handling of beam switching by not returning unused new beam index 2026-04-10 11:24:19 +02:00
francescomani
b32e61e436 fix formatting and remove unnecessary nulling of srs_Config 2026-04-10 11:24:19 +02:00
17 changed files with 832 additions and 156 deletions

View File

@@ -807,7 +807,8 @@ int main(int argc, char **argv)
rnti_t rnti = 0x1234;
int uid = 0;
int ssb_index = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid, ssb_index);
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

@@ -823,7 +823,8 @@ int main(int argc, char *argv[])
rnti_t rnti = 0x1234;
int uid = 0;
int ssb_index = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid, ssb_index);
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

@@ -524,12 +524,6 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap)
}
DevAssert(rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow >= 0);
// prepare DL Allocation lists
nr_rrc_config_dl_tda(dlcc->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
frame_type,
scc->tdd_UL_DL_ConfigurationCommon,
NRRIV2BW(dlcc->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE));
if (frame_type == FDD) {
ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, scc->tdd_UL_DL_ConfigurationCommon);
scc->tdd_UL_DL_ConfigurationCommon = NULL;
@@ -944,7 +938,6 @@ static NR_ServingCellConfigCommon_t *get_scc_config(int minRXTXTIME, int do_SRS)
check_ssb_raster(ssb_freq, *frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
fix_scc(scc, ssb_bitmap);
}
nr_rrc_config_ul_tda(scc, minRXTXTIME, do_SRS);
// the gNB uses the servingCellConfigCommon everywhere, even when it should use the servingCellConfigCommonSIB.
// previously (before this commit), the following fields were indirectly populated through get_SIB1_NR().
@@ -1771,9 +1764,9 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
// each beam is described by a set of weights (one for each antenna)
// in case of analog beamforming an index to the RU beam identifier is provided
// (one for each beam regardless of the number of antennas per beam)
config.nb_bfw[0] = num_tx; // number of tx antennas
config.nb_bfw[1] = num_beam; // number of beams weights/indices
config.bw_list = calloc_or_fail(n, sizeof(*config.bw_list));
RC.nrmac[j]->radio_config.nb_bfw[0] = config.nb_bfw[0] = num_tx; // number of tx antennas
RC.nrmac[j]->radio_config.nb_bfw[1] = config.nb_bfw[1] = num_beam; // number of beams weights/indices
RC.nrmac[j]->radio_config.bw_list = config.bw_list = calloc_or_fail(n, sizeof(*config.bw_list));
for (int b = 0; b < n; b++)
config.bw_list[b] = gpd(params, np, MACRLC_BEAM_WEIGHTS_LIST)->iptr[b];
} else if (das_enabled) {

View File

@@ -471,6 +471,7 @@ typedef struct nr_csi_report {
uint16_t offset;
long **SSB_Index_list;
long **CSI_Index_list;
int nb_resources;
// uint8_t nb_of_nzp_csi_report;
uint8_t nb_of_csi_ssb_report;
L1_Meas_bitlen_t CSI_report_bitlen;

View File

@@ -4708,6 +4708,7 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
nb_resources = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.count;
csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.array;
csi_report->CSI_Index_list = NULL;
csi_report->nb_resources = nb_resources;
break;
}
}
@@ -4722,6 +4723,7 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
nb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.count;
csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.array;
csi_report->SSB_Index_list = NULL;
csi_report->nb_resources = nb_resources;
break;
}
}

View File

@@ -36,6 +36,125 @@
#include "nfapi_nr_interface_scf.h"
#include "utils.h"
bool is_prach_slot_set = false;
bool is_prach_slot[160] = {false};
#define SLOT_TYPE_SRS 0
#define SLOT_TYPE_CSIR 1
#define SLOT_TYPE_RSRP 2
#define SLOT_TYPE_SR 3
#define SLOT_TYPE_NUM (SLOT_TYPE_SR + 1)
#define MAX_SR_SLOT_PERIOD 16
int reserve_offset[MAX_MOBILES_PER_GNB * SLOT_TYPE_NUM] = {[0 ... (MAX_MOBILES_PER_GNB * SLOT_TYPE_NUM - 1)] -1};
int reserve_period[MAX_MOBILES_PER_GNB * SLOT_TYPE_NUM] = {[0 ... (MAX_MOBILES_PER_GNB * SLOT_TYPE_NUM - 1)] -1};
void unset_period_offset_beam(int uid)
{
for (int i = 0; i < SLOT_TYPE_NUM; i++) {
reserve_offset[uid * SLOT_TYPE_NUM + i] = -1;
reserve_period[uid * SLOT_TYPE_NUM + i] = -1;
}
}
bool check_period_offset_reserve(int sched_frame, int sched_slot, int n_slots_frame) {
for (int i = 0; i < MAX_MOBILES_PER_GNB * SLOT_TYPE_NUM; i++) {
if ((reserve_period[i] == -1) || (reserve_offset[i] == -1))
continue;
if ((sched_frame * n_slots_frame + sched_slot - reserve_offset[i]) % reserve_period[i] == 0) {
return true;
}
}
return false;
}
int get_beamloc_from_beam(int beam_index)
{
gNB_MAC_INST *mac = RC.nrmac[0];
if (mac->beam_info.beam_mode == LOPHY_BEAM_IDX) {
for (int i = 0; i < mac->radio_config.nb_bfw[1]; i++) {
if (mac->radio_config.bw_list[i] == beam_index)
return i;
}
AssertFatal(false, "beam_index %d not found\n", beam_index);
return 0;
}
return beam_index;
}
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))};
@@ -301,6 +420,70 @@ 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
* @param uid UE id
* @return slot index
*
*/
int get_first_ul_slot_beam(const frame_structure_t *fs, int beam_idx, int beams_per_period, int num_beam, int uid)
{
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 = get_beamloc_from_beam(beam_idx) / beams_per_period;
LOG_D(NR_MAC, "get_first_ul_slot_beam 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 / MAX_SR_SLOT_PERIOD; // wrap up the count of complete TDD periods spanned by the index
int ul_slot_idx_in_period = idx % MAX_SR_SLOT_PERIOD; // 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;
}
void get_first_ul_slot_period_beam(const frame_structure_t *fs, int beam_idx, int period, int uid)
{
DevAssert(fs);
// FDD
if (fs->frame_type == FDD)
return;
reserve_period[uid * SLOT_TYPE_NUM + SLOT_TYPE_SR] = period;
LOG_D(NR_MAC, "get_first_ul_slot_period_beam uid %d beam_idx %d period %d\n", uid, beam_idx, period);
}
/**
* @brief Get number of DL slots per period (full DL slots + mixed slots with DL symbols)
*/
@@ -403,6 +586,162 @@ 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, bool set)
{
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 idx %d is_csi %d beam_idx %d num_beam %d\n", idx, is_csi, beam_idx, num_beam);
int uid = (is_csi) ? idx/2 : idx;
int id = uid / 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
int type;
// SRS
if (!is_csi) {
type = SLOT_TYPE_SRS;
}
else {
// odd => RSRP report
if (idx % 2) {
type = SLOT_TYPE_RSRP;
}
// even => CSI report
else {
type = SLOT_TYPE_CSIR;
}
}
idx = 3 * id + type;
LOG_D(NR_MAC, "get_ul_slot_offset_beam uid %d type %d id %d idx %d is_csi %d beam_idx %d num_beam %d\n", uid, type, 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 > MAX_SR_SLOT_PERIOD) ? MAX_SR_SLOT_PERIOD: 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;
if (set)
{
reserve_offset[uid * SLOT_TYPE_NUM + type] = ret;
}
LOG_D(NR_MAC, "get_ul_slot_offset_beam ret %d uid %d type %d id %d idx %d beam_idx %d beams_period %d ul_slot_count %d %d %d\n", ret, uid, type, id, idx, beam_idx, beams_per_period, ul_slot_idx_in_period, period_idx, fs->numb_slots_period);
return ret;
}
void get_ul_slot_period_beam(const frame_structure_t *fs, int idx, bool is_csi, int beam_idx, int period, bool set)
{
DevAssert(fs);
// FDD
if (fs->frame_type == FDD)
return;
LOG_D(NR_MAC, "get_ul_slot_period_beam idx %d is_csi %d beam_idx %d period %d\n", idx, is_csi, beam_idx, period);
int uid = (is_csi) ? idx/2 : idx;
// 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
int type;
// SRS
if (!is_csi) {
type = SLOT_TYPE_SRS;
}
else {
// odd => RSRP report
if (idx % 2) {
type = SLOT_TYPE_RSRP;
}
// even => CSI report
else {
type = SLOT_TYPE_CSIR;
}
}
if (set)
{
reserve_period[uid * SLOT_TYPE_NUM + type] = period;
}
LOG_D(NR_MAC, "get_ul_slot_period_beam uid %d type %d is_csi %d beam_idx %d period %d\n", uid, type, is_csi, beam_idx, period);
}
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];
@@ -844,7 +1183,7 @@ static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int s
}
}
static void config_sched_ctrlSIB1(gNB_MAC_INST *nr_mac)
static bool config_sched_ctrlSIB1(gNB_MAC_INST *nr_mac)
{
const NR_MIB_t *mib = nr_mac->common_channels[0].mib->message.choice.mib;
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
@@ -888,16 +1227,23 @@ static void config_sched_ctrlSIB1(gNB_MAC_INST *nr_mac)
fill_coresetZero(&sched_ctrlCommon->coreset, &type0_PDCCH_CSS_config);
nr_mac->cset0_bwp_start = type0_PDCCH_CSS_config.cset_start_rb;
nr_mac->cset0_bwp_size = type0_PDCCH_CSS_config.num_rbs;
int bwp_size = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
bool long_cset = false;
if (type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern > 1) {
int bwp_start = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,
MAX_BWP_SIZE);
int bwp_size = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
// we need to configure a commonControlResourceSet != 0
// because CSET0 would start from a symbol != 0 and that's unwanted for anything but SIB1
// The network configures the commonControlResourceSet in SIB1 so that it is contained in the bandwidth of CSET0
bool do_TCI = nr_mac->radio_config.do_TCI;
configure_coreset_for_mux23(scc, nr_mac->cset0_bwp_start - bwp_start, nr_mac->cset0_bwp_size, bwp_start, bwp_size, do_TCI);
long_cset = configure_coreset_for_mux23(scc,
nr_mac->cset0_bwp_start - bwp_start,
nr_mac->cset0_bwp_size,
bwp_start,
bwp_size,
do_TCI);
}
return long_cset || bwp_size < 48;
}
/**
@@ -966,9 +1312,17 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
find_SSB_and_RO_available(nrmac);
bool two_symb_cset = false;
if (IS_SA_MODE(get_softmodem_params()))
config_sched_ctrlSIB1(nrmac);
two_symb_cset = config_sched_ctrlSIB1(nrmac);
const nr_mac_config_t *rc = &nrmac->radio_config;
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,
two_symb_cset);
nr_rrc_config_ul_tda(scc, rc->minRXTXTIME, rc->do_SRS);
seq_arr_init(&nrmac->ul_tda, sizeof(NR_tda_info_t));
init_ul_tda_info(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList, &nrmac->ul_tda);
}
@@ -1146,7 +1500,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

@@ -798,6 +798,10 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|| !((msg3_mask & slot_bitmap) == msg3_mask))
return;
if (check_period_offset_reserve(sched_frame, sched_slot, slots_frame)) {
LOG_I(NR_MAC, "[UE %04x][%4d.%2d] MSG3 Beam could not be allocated due to periodic UL signal\n", UE->rnti, sched_frame, sched_slot);
return;
}
NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame);
if (beam_ul.idx < 0)
return;
@@ -1011,6 +1015,10 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
if ((slot_mask & msg3_mask) != msg3_mask)
continue;
if (check_period_offset_reserve(temp_frame, temp_frame, slots_per_frame)) {
LOG_I(NR_MAC, "[%4d.%2d] MSG3 Beam could not be allocated due to periodic UL signal\n", temp_frame, temp_slot);
continue;
}
// check if it is possible to allocate MSG3 in a beam in this slot
NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ue_beam_idx, slots_per_frame);
if (beam.idx < 0)

View File

@@ -3591,9 +3591,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)
@@ -3851,7 +3856,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
int srb_id = 1;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
int 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);
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;
@@ -3977,42 +3982,45 @@ 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(const 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) {
if (new_beam >= 0) {
UE->cm_info.trigger_info = BEAM_SWITCH;
UE->cm_info.new_state = new_beam;
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
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,
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
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
current_BWP->srs_Config = NULL;
UE->cm_info.trigger_info = BWP_SWITCH;
UE->cm_info.new_state = new_bwp_id;
int ssb_index = nrmac->common_channels[0].ssb_index[UE->UE_beam_index];
cellGroup_for_UE = update_cellGroupConfig_for_beam_switch(UE->CellGroup,
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,
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);
}
new_bwp_id,
ssb_index,
UE->UE_beam_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

@@ -258,6 +258,12 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
// going through the list of PUCCH resources to find the one indexed by resource_id
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate CSI measurements on PUCCH in any available beam\n");
// Keep the following in case AssertFatal needs to comment out for testing
if (beam.idx < 0) {
LOG_I(NR_MAC, "Cannot allocate CSI measurements on PUCCH in any available beam\n");
continue;
}
const int index = ul_buffer_index(sched_frame, sched_slot, n_slots_frame, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
const int m = pucch_Config->resourceToAddModList->list.count;
@@ -530,14 +536,17 @@ static void evaluate_rsrp_report(NR_UE_info_t *UE,
nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id];
RSRP_report_list_t *rsrp_report;
long **index_list;
int nb_resources = 0;
switch (reportQuantity_type) {
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
rsrp_report = &sched_ctrl->CSI_report.ssb_rsrp_report;
index_list = csi_report->SSB_Index_list;
nb_resources = csi_report->nb_resources;
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP :
rsrp_report = &sched_ctrl->CSI_report.csirs_rsrp_report;
index_list = csi_report->CSI_Index_list;
nb_resources = csi_report->nb_resources;
break;
default :
AssertFatal(false, "Invalid RSRP report type\n");
@@ -547,6 +556,12 @@ static void evaluate_rsrp_report(NR_UE_info_t *UE,
int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen;
for (RSRP_report_t *i = rsrp_report->r; i < rsrp_report->r + rsrp_report->nb; i++) {
uint8_t idx_payload = pickandreverse_bits(payload, bitlen, *cumul_bits);
uint8_t idx = (bitlen > 0 ? (idx_payload & ~(~1U << (bitlen - 1))) : bitlen) < nb_resources ? (bitlen > 0 ? (idx_payload & ~(~1U << (bitlen - 1))) : bitlen) : 255;
if (idx == 255) {
LOG_E(NR_MAC, "UE %04x: reported index %d for SSB/CSI-RS resource is out of range for index_list %d\n", UE->rnti, idx_payload, bitlen);
return;
}
LOG_D(NR_MAC, "idx_payload %d bitlen %d index %d\n", idx_payload, bitlen, bitlen > 0 ? (idx_payload & ~(~1U << (bitlen - 1))) : bitlen);
i->resource_id = *(index_list[bitlen > 0 ? (idx_payload & ~(~1U << (bitlen - 1))) : bitlen]);
*cumul_bits += bitlen;
}
@@ -1219,6 +1234,15 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
else { // unoccupied occasion
if (check_period_offset_reserve(pucch_frame, pucch_slot, n_slots_frame)) {
LOG_I(NR_MAC,
"DL %4d.%2d, UL_ACK %4d.%2d beam resources for this occasion to be used by periodic UL signal, move to the following occasion\n",
frame,
slot,
pucch_frame,
pucch_slot);
continue;
}
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
set_pucch_allocation(ul_bwp, r_pucch, bwp_size, curr_pucch);
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, ue_beam, n_slots_frame);
@@ -1329,6 +1353,11 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
else {
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, SFN, slot, UE->UE_beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SR in any available beam\n");
// Keep the following in case AssertFatal needs to comment out for testing
if (beam.idx < 0) {
LOG_E(NR_MAC,"Cannot allocate SR in any available beam\n");
continue;
}
const int index = ul_buffer_index(SFN, slot, n_slots_frame, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
const int bwp_start = ul_bwp->BWPStart;

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);
}
@@ -1936,6 +1936,11 @@ static int pf_ul(gNB_MAC_INST *nrmac,
continue;
}
if (check_period_offset_reserve(sched_frame, sched_slot, slots_per_frame)) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] ULSCH Beam could not be allocated due to periodic UL signal\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;
}
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] ULSCH Beam could not be allocated\n", UE->rnti, frame, slot);
@@ -2055,6 +2060,12 @@ static int pf_ul(gNB_MAC_INST *nrmac,
NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP;
NR_UE_sched_ctrl_t *sched_ctrl = &iterator->UE->UE_sched_ctrl;
if (check_period_offset_reserve(sched_frame, sched_slot, slots_per_frame)) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] ULSCH Beam could not be allocated due to periodic UL signal\n", iterator->UE->rnti, frame, slot);
iterator++;
continue;
}
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] ULSCH Beam could not be allocated\n", iterator->UE->rnti, sched_frame, sched_slot);

View File

@@ -14,18 +14,24 @@
#include "common/ngran_types.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
void unset_period_offset_beam(int uid);
bool check_period_offset_reserve(int sched_frame, int sched_slot, int n_slots_frame);
void set_cset_offset(uint16_t);
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers);
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 uid);
void get_first_ul_slot_period_beam(const frame_structure_t *fs, int beam_idx, int period, int uid);
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, bool set);
void get_ul_slot_period_beam(const frame_structure_t *fs, int idx, bool is_csi, int beam_idx, int period, bool set);
void delete_nr_ue_data(NR_UE_info_t *UE, uid_allocator_t *uia);
void mac_top_init_gNB(ngran_node_t node_type,
@@ -479,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, bool new_beam);
void nr_mac_trigger_reconfiguration(const 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

@@ -557,11 +557,11 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
const nr_mac_config_t *configuration = &mac->radio_config;
int ssb_index = get_ssbidx_from_beam(mac, UE->UE_beam_index);
if (is_SA) {
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config, ssb_index);
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, ssb_index);
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;
@@ -748,7 +748,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.
@@ -875,7 +875,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
@@ -914,53 +914,67 @@ 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->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

@@ -135,7 +135,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
sched_ctrl->pcmax);
if (stats->num_rsrp_meas)
output = st_append(output, end, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas);
output = st_append(output, end, ", average RSRP %d (%d meas), beam index %d", avg_rsrp, stats->num_rsrp_meas, UE->UE_beam_index);
if (stats->num_sinr_meas) {
output = st_append(output,

View File

@@ -764,6 +764,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;
@@ -794,6 +806,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,14 +363,24 @@ 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 ssb_index,
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.
gNB_MAC_INST *gNB_mac = RC.nrmac[0];
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[ssb_index];
const int offset = type0_PDCCH_CSS_config->slot;
if (check_periodicity(4, ideal_period, fs)) {
nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots4;
nzpcsi0->periodicityAndOffset->choice.slots4 = offset;
@@ -411,7 +421,7 @@ 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 ssb_index %d. Not enough resources for CSI-RS\n", ssb_index);
nzpcsi0->periodicityAndOffset->choice.slots320 = (offset % 320) + (offset / 320);
}
}
@@ -421,16 +431,16 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco
int num_dl_antenna_ports,
int curr_bwp,
int do_csirs,
int id)
int ssb_index)
{
if (do_csirs) {
if(!csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList)
csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList));
NR_NZP_CSI_RS_ResourceSet_t *nzpcsirs0 = calloc(1,sizeof(*nzpcsirs0));
nzpcsirs0->nzp_CSI_ResourceSetId = id;
nzpcsirs0->nzp_CSI_ResourceSetId = ssb_index / 2; //max value is 32
NR_NZP_CSI_RS_ResourceId_t *nzpid0 = calloc(1,sizeof(*nzpid0));
*nzpid0 = id;
*nzpid0 = ssb_index / 2; //max value is 32
asn1cSeqAdd(&nzpcsirs0->nzp_CSI_RS_Resources,nzpid0);
nzpcsirs0->repetition = NULL;
nzpcsirs0->aperiodicTriggeringOffset = NULL;
@@ -439,7 +449,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 = calloc(1,sizeof(*nzpcsi0));
nzpcsi0->nzp_CSI_RS_ResourceId = id;
nzpcsi0->nzp_CSI_RS_ResourceId = ssb_index / 2; //max value is 32
NR_CSI_RS_ResourceMapping_t resourceMapping = {0};
switch (num_dl_antenna_ports) {
case 1:
@@ -503,9 +513,18 @@ 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);
set_csirs_periodicity(nzpcsi0, ssb_index, ideal_period, fs);
nzpcsi0->qcl_InfoPeriodicCSI_RS = calloc(1,sizeof(*nzpcsi0->qcl_InfoPeriodicCSI_RS));
*nzpcsi0->qcl_InfoPeriodicCSI_RS = 0;
@@ -572,13 +591,13 @@ static void config_csiim(int do_csirs,
int dl_antenna_ports,
int curr_bwp,
NR_CSI_MeasConfig_t *csi_MeasConfig,
int id)
int ssb_index)
{
if (do_csirs && dl_antenna_ports > 1) {
if (!csi_MeasConfig->csi_IM_ResourceToAddModList)
csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList));
NR_CSI_IM_Resource_t *imres = calloc(1,sizeof(*imres));
imres->csi_IM_ResourceId = id;
imres->csi_IM_ResourceId = ssb_index / 2; //max value is 32
NR_NZP_CSI_RS_Resource_t *nzpcsi = NULL;
for (int i=0; i<csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list.count; i++){
nzpcsi = csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list.array[i];
@@ -605,9 +624,9 @@ static void config_csiim(int do_csirs,
if (!csi_MeasConfig->csi_IM_ResourceSetToAddModList)
csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList));
NR_CSI_IM_ResourceSet_t *imset = calloc(1,sizeof(*imset));
imset->csi_IM_ResourceSetId = id;
imset->csi_IM_ResourceSetId = ssb_index / 2; //max value is 32
NR_CSI_IM_ResourceId_t *res = calloc(1,sizeof(*res));
*res = id;
*res = ssb_index / 2; //max value is 32
asn1cSeqAdd(&imset->csi_IM_Resources,res);
asn1cSeqAdd(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imset);
}
@@ -662,75 +681,110 @@ static void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcell
*pdsch_servingcellconfig->ext1->maxMIMO_Layers = min(maxMIMO_layers, ue_supported_layers);
}
static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(const int uid)
static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(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, true); // only full UL slots for SRS
LOG_I(NR_MAC, "configure_periodic_srs 0 idx %d is_csi %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);
int period;
struct NR_SRS_Resource__resourceType__periodic *periodic_srs = calloc(1,sizeof(*periodic_srs));
if (check_periodicity(4, ideal_period, fs)) {
period = 4;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl4;
periodic_srs->periodicityAndOffset_p.choice.sl4 = offset;
}
else if (check_periodicity(5, ideal_period, fs)) {
period = 5;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl5;
periodic_srs->periodicityAndOffset_p.choice.sl5 = offset;
}
else if (check_periodicity(8, ideal_period, fs)) {
period = 8;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl8;
periodic_srs->periodicityAndOffset_p.choice.sl8 = offset;
}
else if (check_periodicity(10, ideal_period, fs)) {
period = 10;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl10;
periodic_srs->periodicityAndOffset_p.choice.sl10 = offset;
}
else if (check_periodicity(16, ideal_period, fs)) {
period = 10;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl16;
periodic_srs->periodicityAndOffset_p.choice.sl16 = offset;
}
else if (check_periodicity(20, ideal_period, fs)) {
period = 20;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl20;
periodic_srs->periodicityAndOffset_p.choice.sl20 = offset;
}
else if (check_periodicity(32, ideal_period, fs)) {
period = 32;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl32;
periodic_srs->periodicityAndOffset_p.choice.sl32 = offset;
}
else if (check_periodicity(40, ideal_period, fs)) {
period = 40;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl40;
periodic_srs->periodicityAndOffset_p.choice.sl40 = offset;
}
else if (check_periodicity(64, ideal_period, fs)) {
period = 64;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl64;
periodic_srs->periodicityAndOffset_p.choice.sl64 = offset;
}
else if (check_periodicity(80, ideal_period, fs)) {
period = 80;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl80;
periodic_srs->periodicityAndOffset_p.choice.sl80 = offset;
}
else if (check_periodicity(160, ideal_period, fs)) {
period = 160;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160;
periodic_srs->periodicityAndOffset_p.choice.sl160 = offset;
}
else if (check_periodicity(320, ideal_period, fs)) {
period = 320;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl320;
periodic_srs->periodicityAndOffset_p.choice.sl320 = offset;
}
else if (check_periodicity(640, ideal_period, fs)) {
period = 640;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl640;
periodic_srs->periodicityAndOffset_p.choice.sl640 = offset;
}
else if (check_periodicity(1280, ideal_period, fs)) {
period = 1280;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl1280;
periodic_srs->periodicityAndOffset_p.choice.sl1280 = offset;
}
else {
period = 2560;
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl2560;
periodic_srs->periodicityAndOffset_p.choice.sl2560 = offset;
}
if (beam_info->beam_mode != NO_BEAM_MODE) {
get_ul_slot_period_beam(fs, uid, false, beam_idx, period, true);
LOG_I(NR_MAC, "configure_periodic_srs 10 uid %d beam_idx %d period %d\n",
uid, beam_idx, period);
}
return periodic_srs;
}
@@ -776,7 +830,8 @@ static NR_SRS_Resource_t *get_srs_resource(const NR_UE_NR_Capability_t *uecap,
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;
@@ -847,7 +902,7 @@ static NR_SRS_Resource_t *get_srs_resource(const NR_UE_NR_Capability_t *uecap,
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(uid);
srs_res->resourceType.choice.periodic = configure_periodic_srs(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));
@@ -867,7 +922,8 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_UE_NR_Capability_t
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;
@@ -876,7 +932,7 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_UE_NR_Capability_t
srs_Config->srs_ResourceToAddModList = calloc_or_fail(1, sizeof(*srs_Config->srs_ResourceToAddModList));
NR_SRS_Resource_t *srs_res0 =
get_srs_resource(uecap, curr_bwp, uid, res_id, maxMIMO_Layers, NR_SRS_Resource__transmissionComb_PR_n2, do_srs);
get_srs_resource(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));
@@ -1004,17 +1060,17 @@ void prepare_sim_uecap(NR_UE_NR_Capability_t *cap,
}
}
void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList,
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,
int curr_bwp)
bool small_bwp)
{
// coreset duration setting to be improved in the framework of RRC harmonization, potentially using a common function
int len_coreset = 1;
if (curr_bwp < 48)
if (small_bwp)
len_coreset = 2;
// setting default TDA for DL with TDA index 0
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
NR_PDSCH_TimeDomainResourceAllocation_t *timedomainresourceallocation = CALLOC(1, sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
// k0: Slot offset between DCI and its scheduled PDSCH (see TS 38.214 clause 5.1.2.1) When the field is absent the UE applies the value 0.
//timedomainresourceallocation->k0 = calloc(1,sizeof(*timedomainresourceallocation->k0));
//*timedomainresourceallocation->k0 = 0;
@@ -1373,7 +1429,80 @@ static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedul
}
}
static void scheduling_request_config(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, int uid)
{
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, uid);
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);
int period;
if (check_periodicity(5, ideal_period, fs)) {
period = 5;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl5 = sr_slot;
}
else if(check_periodicity(8, ideal_period, fs)) {
period = 8;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl8 = sr_slot;
}
else if(check_periodicity(10, ideal_period, fs)) {
period = 10;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = sr_slot; return;
}
else if(check_periodicity(16, ideal_period, fs)) {
period = 16;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl16 = sr_slot;
}
else if(check_periodicity(20, ideal_period, fs)) {
period = 20;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl20 = sr_slot;
}
else if (check_periodicity(40, ideal_period, fs)) {
period = 40;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl40 = sr_slot;
}
else if (check_periodicity(80, ideal_period, fs)) {
period = 80;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl80 = sr_slot;
}
else if ((check_periodicity(160, ideal_period, fs))) {
period = 160;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl160 = sr_slot;
}
else if ((check_periodicity(320, ideal_period, fs))) {
period = 320;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl320 = sr_slot;
}
else {
period = 640;
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl640 = sr_slot;
}
LOG_I(NR_MAC, "set_SR_periodandoffset_beam 10 uid %d beam_idx %d period %d\n",
uid, beam_idx, period);
get_first_ul_slot_period_beam(fs, beam_idx, period, uid);
}
static void scheduling_request_config(const NR_ServingCellConfigCommon_t *scc, NR_PUCCH_Config_t *pucch_Config, int scs, int beam_idx, int uid)
{
// format with <=2 bits in pucch resource set 0
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0];
@@ -1385,7 +1514,11 @@ static void scheduling_request_config(NR_PUCCH_Config_t *pucch_Config, int scs)
schedulingRequestResourceConfig->schedulingRequestResourceId = 1;
schedulingRequestResourceConfig->schedulingRequestID = 0;
set_SR_periodandoffset(schedulingRequestResourceConfig, scs);
NR_beam_info_t *beam_info = &RC.nrmac[0]->beam_info;
if (beam_info->beam_mode == NO_BEAM_MODE)
set_SR_periodandoffset(schedulingRequestResourceConfig, scs);
else
set_SR_periodandoffset_beam(schedulingRequestResourceConfig, scc, scs, beam_idx, uid);
schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource));
*schedulingRequestResourceConfig->resource = *pucchressetid;
@@ -1812,7 +1945,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,
bwp_size);
bwp_size < 48);
if (!bwp->bwp_Dedicated) {
bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated));
@@ -1854,7 +1987,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;
@@ -1897,7 +2031,7 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
config_pucch_resset0(scc, pucch_Config, uid, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
config_pucch_resset1(scc, pucch_Config, uid, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
set_pucch_power_config(pucch_Config);
scheduling_request_config(pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing, beam_idx, uid);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME);
ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration, scc, uecap);
@@ -1908,7 +2042,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;
@@ -1930,47 +2065,87 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc,
int uid,
int curr_bwp,
const nr_pdsch_AntennaPorts_t *antennaports,
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, antennaports);
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 is_csi %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, true);
} 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");
int period;
if (check_periodicity(4, ideal_period, fs)) {
period = 4;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots4;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4 = offset;
} else if (check_periodicity(5, ideal_period, fs)) {
period = 5;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots5;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5 = offset;
} else if (check_periodicity(8, ideal_period, fs)) {
period = 8;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots8;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8 = offset;
} else if (check_periodicity(10, ideal_period, fs)) {
period = 10;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots10;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10 = offset;
} else if (check_periodicity(16, ideal_period, fs)) {
period = 16;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots16;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16 = offset;
} else if (check_periodicity(20, ideal_period, fs)) {
period = 20;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots20;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20 = offset;
} else if (check_periodicity(40, ideal_period, fs)) {
period = 40;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots40;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40 = offset;
} else if (check_periodicity(80, ideal_period, fs)) {
period = 80;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots80;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80 = offset;
} else if (check_periodicity(160, ideal_period, fs)) {
period = 160;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots160;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160 = offset;
} else {
period = 320;
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots320;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = offset;
}
if (beam_info->beam_mode != NO_BEAM_MODE) {
LOG_I(NR_MAC, "set_csi_meas_periodicity 10 idx %d beam_idx %d period %d\n", idx, beam_idx, period);
get_ul_slot_period_beam(fs, idx, true, beam_idx, period, true);
}
}
static void config_csi_codebook(const nr_pdsch_AntennaPorts_t *antennaports,
@@ -2087,7 +2262,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;
@@ -2116,7 +2292,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, antennaports, false);
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, antennaports, 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;
@@ -2183,7 +2359,8 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
int rep_id,
int uid,
int curr_bwp,
uint64_t ssb_bitmap)
uint64_t ssb_bitmap,
int beam_idx)
{
int resource_id = -1;
const nr_pdsch_AntennaPorts_t *pdschap = &configuration->pdsch_AntennaPorts;
@@ -2211,7 +2388,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, pdschap, true);
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, pdschap, 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;
@@ -2729,7 +2906,7 @@ static BIT_STRING_t bit_string_clone(const BIT_STRING_t *orig)
return bs;
}
void configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc,
bool configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc,
int offset,
int limit,
int bwp_start,
@@ -2737,11 +2914,12 @@ void configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc,
bool do_TCI)
{
NR_ControlResourceSet_t *coreset = get_coreset_config(5, offset, limit, bwp_start, bwp_size, get_ssb_bitmap(scc), do_TCI);
NR_PDCCH_ConfigCommon_t *pdcch_common = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
NR_DownlinkConfigCommon_t *dlcc = scc->downlinkConfigCommon;
NR_PDCCH_ConfigCommon_t *pdcch_common = dlcc->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
pdcch_common->commonControlResourceSet = coreset;
for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++) {
for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++)
*pdcch_common->commonSearchSpaceList->list.array[i]->controlResourceSetId = coreset->controlResourceSetId;
}
return coreset->duration > 1;
}
NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc,
@@ -3327,7 +3505,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;
@@ -3347,9 +3526,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(uecap, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0);
initialUplinkBWP->srs_Config = get_config_srs(uecap, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0, beam_idx);
scheduling_request_config(pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing);
scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing, beam_idx, id);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME);
return initialUplinkBWP;
}
@@ -3405,7 +3584,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
int uid,
int bwp_id,
uint64_t bitmap,
int ssb_index)
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));
@@ -3445,8 +3625,9 @@ 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, ssb_index / 2);
config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, ssb_index / 2);
config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, ssb_index);
config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, ssb_index);
NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1));
csires1->csi_ResourceConfigId = bwp_id + 20;
@@ -3472,7 +3653,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 = ssb_index / 2;
*nzp0 = ssb_index / 2; //max value is 32
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;
@@ -3486,7 +3667,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 = ssb_index / 2;
*csiim00 = ssb_index / 2; //max value is 32
asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00);
csires2->bwp_Id = bwp_id;
csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic;
@@ -3503,7 +3684,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;
@@ -3516,14 +3698,16 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
bwp_id + 10,
uid,
curr_bwp,
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,
int ssb_index)
int ssb_index,
int beam_idx)
{
const int pdsch_AntennaPorts =
configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP;
@@ -3563,14 +3747,14 @@ 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));
NR_BWP_Downlink_t *bwp = config_downlinkBWP(scc, NULL, false, true, 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);
}
@@ -3583,7 +3767,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
uid,
first_active_bwp,
bitmap,
ssb_index);
ssb_index,
beam_idx);
fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq, first_active_bwp);
SpCellConfig->spCellConfigDedicated = configDedicated;
@@ -3716,10 +3901,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, false);
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);
@@ -3749,8 +3945,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, false);
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);
@@ -3764,12 +3981,13 @@ 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,
int ssb_index)
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, ssb_index);
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;
@@ -3801,7 +4019,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
int uid,
int old_bwp,
int new_bwp,
int ssb_index)
int ssb_index,
int beam_idx)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
@@ -3820,7 +4039,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)
@@ -3830,7 +4049,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);
}
@@ -3842,7 +4061,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
uid,
*uplinkConfig->firstActiveUplinkBWP_Id,
bitmap,
ssb_index);
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
@@ -3860,7 +4080,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_
const NR_ServingCellConfigCommon_t *scc,
int uid,
int bwp,
int ssb_index)
int ssb_index,
int beam_idx)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
@@ -3874,7 +4095,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_
uid,
bwp,
bitmap,
ssb_index);
ssb_index,
beam_idx);
NR_CellGroupConfig_t *clone_cg = NULL;
const int copy_result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&clone_cg, cellGroupConfig);
@@ -3886,7 +4108,8 @@ 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);
@@ -3967,7 +4190,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);
}
@@ -4021,7 +4245,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
int servCellIndex,
const nr_mac_config_t *configuration,
int uid,
int ssb_index)
int ssb_index,
int beam_idx)
{
AssertFatal(servingcellconfigcommon, "servingcellconfigcommon is null\n");
@@ -4088,7 +4313,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;
@@ -4107,7 +4333,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;
@@ -4168,7 +4394,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
uid,
firstActiveUplinkBWP_Id,
bitmap,
ssb_index);
ssb_index,
beam_idx);
configDedicated->sCellDeactivationTimer = NULL;
configDedicated->crossCarrierSchedulingConfig = NULL;

View File

@@ -25,10 +25,10 @@ typedef struct nr_mac_config_s nr_mac_config_t;
typedef struct nr_mac_timers nr_mac_timers_t;
typedef struct measgap_config measgap_config_t;
void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList,
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,
int curr_bwp);
bool small_bwp);
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, int do_SRS);
NR_SearchSpace_t *rrc_searchspace_config(bool is_common,
int searchspaceid,
@@ -46,7 +46,7 @@ NR_BCCH_BCH_Message_t *get_new_MIB_NR(const NR_ServingCellConfigCommon_t *scc);
void free_MIB_NR(NR_BCCH_BCH_Message_t *mib);
int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size);
int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size);
void configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc,
bool configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc,
int offset,
int limit,
int bwp_start,
@@ -74,12 +74,14 @@ 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,
int ssb_index);
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
@@ -91,7 +93,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
int servCellIndex,
const nr_mac_config_t *configuration,
int uid,
int ssb_index);
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);
@@ -114,14 +117,16 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
int uid,
int old_bwp,
int new_bwp,
int ssb_index);
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 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);

View File

@@ -633,10 +633,13 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
int16_t payload_len = 0;
uint8_t *dst = (uint8_t *)u8dptr;
for (uint32_t idxElm = 0; idxElm < pPrbMap->nPrbElm; idxElm++) {
struct xran_section_desc *p_sec_desc = NULL;
struct xran_prb_elm *p_prbMapElm = &pPrbMap->prbMap[idxElm];
// ant_id / no of antenna per beam gives the beam_nb
int16_t beam_id = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx];
if ( beam_id != -1)
p_prbMapElm->nBeamIndex = beam_id;
// radio-transport fragmentation is not supported in xran F release;
// E-bit = 1 => each ethernet frame is considered as the last fragment;