mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-16 06:00:28 +00:00
Compare commits
15 Commits
develop
...
improve_pu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82ea17c0a3 | ||
|
|
57b646b433 | ||
|
|
ef22e593ed | ||
|
|
c90f972131 | ||
|
|
bf813153a3 | ||
|
|
934695c09d | ||
|
|
a737f70f10 | ||
|
|
5833b04197 | ||
|
|
afcc914983 | ||
|
|
a69bb4b8e8 | ||
|
|
ad828037d3 | ||
|
|
604af5a5ac | ||
|
|
6084d84147 | ||
|
|
068aed1403 | ||
|
|
51f364ea13 |
@@ -25,7 +25,7 @@ gNBs =
|
||||
pdsch_AntennaPorts_N1 = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = "periodic";
|
||||
do_SRS = "aperiodic";
|
||||
min_rxtxtime = 2;
|
||||
uess_agg_levels = [0, 4, 2, 1, 0];
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ gNBs =
|
||||
pdsch_AntennaPorts_N1 = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = "periodic";
|
||||
do_SRS = "aperiodic";
|
||||
min_rxtxtime = 2;
|
||||
force_UL256qam_off = 1;
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -63,6 +63,20 @@ in aggregation level 2 which translates to `uess_agg_levels` set to `[0, 2, 0,
|
||||
0, 0]`. For example, to enable one candidate on aggregation levels 2 and 4 set
|
||||
`uess_agg_levels` to `[0, 1, 1, 0, 0]`.
|
||||
|
||||
## Feedback time for ACK/NACK on PUCCH
|
||||
|
||||
Feedback time for DLSCH ACK/NACK on PUCCH is selected by looping among the values on a list
|
||||
(either default one or defined by upper layers). If the given element of the list provides
|
||||
a feedback slot compatible with the frame configuration and the configured minimum feedback time,
|
||||
the scheduler checks if there is an already active PUCCH in the given slot.
|
||||
If there is no active PUCCH, it activates one and it increases by one the DAI counter to signal
|
||||
the presence of one HARQ process feedback in the given PUCCH occasion.
|
||||
If there is an already active PUCCH, it tries to allocate the feedback on that instance
|
||||
pending multiple checks including
|
||||
* the possibility to schedule HARQ and CSI feedback simultaneously
|
||||
* the possibility to transition from a format with 2 bits limit to one without in case the limit is surpassed
|
||||
* resource availability in terms of beam, PRBs and PUCCH coderate
|
||||
|
||||
### Examples:
|
||||
#### Example 1:
|
||||
Say we have 90% PDCCH success rate at aggregation level 1, `pdcch_cl_adjust` will stay at 0
|
||||
|
||||
@@ -812,7 +812,7 @@ void nr_generate_pucch2(c16_t **txdataF,
|
||||
uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index;
|
||||
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
|
||||
|
||||
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
|
||||
for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) {
|
||||
// c_init calculation according to TS38.211 subclause
|
||||
uint64_t temp_x2 = 1ll << 17;
|
||||
temp_x2 *= 14UL * nr_slot_tx + l + startingSymbolIndex + 1;
|
||||
@@ -822,40 +822,19 @@ void nr_generate_pucch2(c16_t **txdataF,
|
||||
uint32_t m = (startingPRB * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER) % 32;
|
||||
const int seq_sz = ((startingPRB + pucch_pdu->prb_size) * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER + 31) / 32;
|
||||
uint32_t *seq = gold_cache(temp_x2, seq_sz);
|
||||
for (int rb=0; rb<pucch_pdu->prb_size; rb++) {
|
||||
//startingPRB = startingPRB + rb;
|
||||
const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
|
||||
const int halfRBs = frame_parms->N_RB_DL / 2;
|
||||
int symbol_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size;
|
||||
for (int rb = 0; rb < pucch_pdu->prb_size; rb++) {
|
||||
const int baseRB = rb + startingPRB;
|
||||
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size + 12 * baseRB;
|
||||
if (nb_rb_is_even) {
|
||||
if (baseRB < halfRBs) // if number RBs in bandwidth is even and current PRB is lower band
|
||||
re_offset += frame_parms->first_carrier_offset;
|
||||
else
|
||||
re_offset -= halfRBs;
|
||||
} else {
|
||||
if (baseRB < halfRBs) // if number RBs in bandwidth is odd and current PRB is lower band
|
||||
re_offset += frame_parms->first_carrier_offset;
|
||||
else if (baseRB > halfRBs) // if number RBs in bandwidth is odd and current PRB is upper band
|
||||
re_offset += -halfRBs + 6;
|
||||
else
|
||||
re_offset += frame_parms->first_carrier_offset;
|
||||
}
|
||||
|
||||
//txptr = &txdataF[0][re_offset];
|
||||
int re_offset = (frame_parms->first_carrier_offset + 12 * baseRB) % frame_parms->ofdm_symbol_size;
|
||||
int k=0;
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
int kk=0;
|
||||
#endif
|
||||
|
||||
for (int n=0; n<12; n++) {
|
||||
if (n == 6 && baseRB == halfRBs && !nb_rb_is_even) {
|
||||
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
|
||||
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
|
||||
}
|
||||
for (int n = 0; n < 12; n++) {
|
||||
|
||||
if (n%3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
|
||||
txdataF[0][re_offset] = d[outSample + k];
|
||||
if (n % 3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
|
||||
txdataF[0][re_offset + symbol_offset] = d[outSample + k];
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf(
|
||||
"\t [nr_generate_pucch2] (n=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
|
||||
@@ -869,15 +848,15 @@ void nr_generate_pucch2(c16_t **txdataF,
|
||||
re_offset,
|
||||
l,
|
||||
n,
|
||||
txdataF[0][re_offset].r,
|
||||
txdataF[0][re_offset].i);
|
||||
txdataF[0][re_offset + symbol_offset].r,
|
||||
txdataF[0][re_offset + symbol_offset].i);
|
||||
#endif
|
||||
k++;
|
||||
}
|
||||
|
||||
if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
|
||||
txdataF[0][re_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m)) & 1)))));
|
||||
txdataF[0][re_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m + 1)) & 1)))));
|
||||
if (n % 3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
|
||||
txdataF[0][re_offset + symbol_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m)) & 1)))));
|
||||
txdataF[0][re_offset + symbol_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m + 1)) & 1)))));
|
||||
m += 2;
|
||||
#ifdef DEBUG_NR_PUCCH_TX
|
||||
printf(
|
||||
@@ -892,13 +871,14 @@ void nr_generate_pucch2(c16_t **txdataF,
|
||||
re_offset,
|
||||
l,
|
||||
n,
|
||||
txdataF[0][re_offset].r,
|
||||
txdataF[0][re_offset].i);
|
||||
txdataF[0][re_offset + symbol_offset].r,
|
||||
txdataF[0][re_offset + symbol_offset].i);
|
||||
kk++;
|
||||
#endif
|
||||
}
|
||||
|
||||
re_offset++;
|
||||
if (re_offset >= frame_parms->ofdm_symbol_size)
|
||||
re_offset -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
outSample += 8;
|
||||
|
||||
@@ -332,11 +332,6 @@ typedef struct {
|
||||
int prach_I0;
|
||||
} PHY_MEASUREMENTS_gNB;
|
||||
|
||||
// the current RRC resource allocation is that each UE gets its
|
||||
// "own" PUCCH resource (for F0) in a dedicated PRB in each slot
|
||||
// therefore, we can have up to "number of UE" UCI PDUs
|
||||
#define MAX_NUM_NR_UCI_PDUS MAX_MOBILES_PER_GNB
|
||||
|
||||
/// Top-level PHY Data Structure for gNB
|
||||
typedef struct PHY_VARS_gNB_s {
|
||||
/// Module ID indicator for this instance
|
||||
|
||||
@@ -828,7 +828,20 @@ 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);
|
||||
NR_UE_UL_RRC_info_t sr_info = {.allocated = true,
|
||||
.resource = 0,
|
||||
.offset = get_ul_slot_offset(&frame_structure, 0, true),
|
||||
.period = frame_structure.numb_slots_period};
|
||||
NR_UE_UL_RRC_info_t csimeas_info = sr_info;
|
||||
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc,
|
||||
UE_Capability_nr,
|
||||
sr_info,
|
||||
csimeas_info,
|
||||
0,
|
||||
1,
|
||||
&conf,
|
||||
uid,
|
||||
ssb_index);
|
||||
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame);
|
||||
|
||||
/* -U option modify DMRS */
|
||||
@@ -851,7 +864,6 @@ int main(int argc, char **argv)
|
||||
phy_init_nr_gNB(gNB);
|
||||
N_RB_DL = gNB->frame_parms.N_RB_DL;
|
||||
NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0];
|
||||
|
||||
configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
|
||||
|
||||
// stub to configure frame_parms
|
||||
|
||||
@@ -837,7 +837,20 @@ 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);
|
||||
NR_UE_UL_RRC_info_t sr_info = {.allocated = true,
|
||||
.resource = 0,
|
||||
.offset = get_ul_slot_offset(&frame_structure, 0, true),
|
||||
.period = frame_structure.numb_slots_period};
|
||||
NR_UE_UL_RRC_info_t csimeas_info = sr_info;
|
||||
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc,
|
||||
UE_Capability_nr,
|
||||
sr_info,
|
||||
csimeas_info,
|
||||
0,
|
||||
1,
|
||||
&conf,
|
||||
uid,
|
||||
ssb_index);
|
||||
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame);
|
||||
|
||||
NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "asn_internal.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "NR_MAC_gNB/mac_proto.h"
|
||||
#include "NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "common/5g_platform_types.h"
|
||||
#include "common/config/config_paramdesc.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "BIT_STRING.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "LAYER2/NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "GNB_APP/gnb_config.h"
|
||||
#include "NR_MIB.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
@@ -962,6 +963,9 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
LOG_D(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
|
||||
|
||||
config_common(nrmac, config, scc);
|
||||
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
int bw = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
config_ul_rrc_info(nrmac, config, *scc->ssbSubcarrierSpacing, bw);
|
||||
fill_beam_index_list(scc, config, nrmac);
|
||||
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
@@ -1257,7 +1261,7 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
|
||||
bool res = add_connected_nr_ue(nrmac, UE);
|
||||
if (!res) {
|
||||
LOG_E(NR_MAC, "Error adding UE %04x\n", rnti);
|
||||
delete_nr_ue_data(UE, &nrmac->UE_info.uid_allocator);
|
||||
delete_nr_ue_data(UE, nrmac, &nrmac->UE_info.uid_allocator);
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -216,13 +216,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
|
||||
nr_schedule_ulsch(module_idP, frame, slot, &sched_info->UL_dci_req);
|
||||
stop_meas(&gNB->schedule_ulsch);
|
||||
|
||||
nr_sr_reporting(gNB, frame, slot);
|
||||
|
||||
// This schedules the DCI for Downlink and PDSCH
|
||||
start_meas(&gNB->schedule_dlsch);
|
||||
nr_schedule_ue_spec(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req);
|
||||
stop_meas(&gNB->schedule_dlsch);
|
||||
|
||||
nr_sr_reporting(gNB, frame, slot);
|
||||
|
||||
nr_schedule_pucch(gNB, frame, slot);
|
||||
|
||||
/* TODO: we copy from gNB->UL_tti_req_ahead[0][current_index], ie. CC_id == 0,
|
||||
|
||||
@@ -707,7 +707,7 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL, &nr_mac->radio_config);
|
||||
if (!add_new_UE_RA(nr_mac, UE)) {
|
||||
LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index);
|
||||
delete_nr_ue_data(UE, &nr_mac->UE_info.uid_allocator);
|
||||
delete_nr_ue_data(UE, nr_mac, &nr_mac->UE_info.uid_allocator);
|
||||
NR_SCHED_UNLOCK(&nr_mac->sched_lock);
|
||||
return;
|
||||
}
|
||||
@@ -793,9 +793,9 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
ra->Msg3_tda_id);
|
||||
|
||||
int slots_frame = nr_mac->frame_structure.numb_slots_frame;
|
||||
uint16_t K2 = tda_info.k2 + get_NTN_Koffset(scc);
|
||||
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
|
||||
const int sched_slot = (slot + K2) % slots_frame;
|
||||
int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
const int sched_frame = get_fb_frame(frame, slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
|
||||
const int sched_slot = get_fb_slot(slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
|
||||
uint16_t slot_bitmap = get_ul_bitmap(&nr_mac->frame_structure, sched_slot);
|
||||
uint16_t msg3_mask = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
|
||||
@@ -985,7 +985,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
start_ra_contention_resolution_timer(
|
||||
ra,
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,
|
||||
K2,
|
||||
NTN_gNB_Koffset + tda_info.k2,
|
||||
ul_bwp->scs);
|
||||
|
||||
// reset state to wait msg3
|
||||
@@ -1011,10 +1011,9 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
|
||||
int slots_per_frame = fs->numb_slots_frame;
|
||||
for (int i = 0; i < tda_list->list.count; i++) {
|
||||
// check if it is UL
|
||||
long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset;
|
||||
int abs_slot = slot + k2 + mu_delta;
|
||||
int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023;
|
||||
int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213
|
||||
// msg3 slot according to 8.3 in 38.213
|
||||
int temp_frame = get_fb_frame(frame, slot, *tda_list->list.array[i]->k2 + mu_delta, slots_per_frame, NTN_gNB_Koffset);
|
||||
int temp_slot = get_fb_slot(slot, *tda_list->list.array[i]->k2 + mu_delta, slots_per_frame, NTN_gNB_Koffset);
|
||||
if (fs->frame_type == TDD && !is_ul_slot(temp_slot, fs))
|
||||
continue;
|
||||
|
||||
@@ -1026,7 +1025,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
|
||||
int start, nr;
|
||||
SLIV2SL(startSymbolAndLength, &start, &nr);
|
||||
uint16_t msg3_mask = SL_to_bitmap(start, nr);
|
||||
LOG_D(NR_MAC, "Check Msg3 TDA %d for slot %d: k2 %ld, S %d L %d\n", i, temp_slot, k2, start, nr);
|
||||
LOG_D(NR_MAC, "Check Msg3 TDA %d for slot %d: k2 %ld, S %d L %d\n", i, temp_slot, *tda_list->list.array[i]->k2, start, nr);
|
||||
/* if this start and length of this TDA cannot be fulfilled, skip */
|
||||
if ((slot_mask & msg3_mask) != msg3_mask)
|
||||
continue;
|
||||
@@ -2133,7 +2132,7 @@ void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti)
|
||||
NR_UEs_t *UE_info = &mac->UE_info;
|
||||
NR_UE_info_t *UE = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, rnti);
|
||||
if (UE) {
|
||||
delete_nr_ue_data(UE, &UE_info->uid_allocator);
|
||||
delete_nr_ue_data(UE, mac, &UE_info->uid_allocator);
|
||||
} else {
|
||||
LOG_W(NR_MAC,"Call to release RA UE with rnti %04x, but not existing\n", rnti);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "assertions.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "NR_MAC_gNB/mac_proto.h"
|
||||
#include "NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "UTIL/OPT/opt.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
|
||||
/*TAG*/
|
||||
|
||||
@@ -250,10 +250,10 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p
|
||||
tda);
|
||||
DevAssert(tda_info.valid_tda);
|
||||
|
||||
int K2 = tda_info.k2 + get_NTN_Koffset(scc);
|
||||
int slots_frame = nr_mac->frame_structure.numb_slots_frame;
|
||||
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
|
||||
const int sched_slot = (slot + K2) % slots_frame;
|
||||
int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
const int sched_frame = get_fb_frame(frame, slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
|
||||
const int sched_slot = get_fb_slot(slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
|
||||
|
||||
/* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
|
||||
* limitations). Note that if K2 or the TDD configuration is changed, below
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "NR_MAC_gNB/mac_proto.h"
|
||||
#include "NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "common/utils/bits.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "UTIL/OPT/opt.h"
|
||||
@@ -92,6 +93,18 @@ static const uint16_t cqi_table3[16][2] = {{0, 0},
|
||||
{6, 6660},
|
||||
{6, 7720}};
|
||||
|
||||
int get_fb_frame(int frame, int slot, int K, int n_slots_frame, int NTN_gNB_Koffset)
|
||||
{
|
||||
// K is the feedback time in slot
|
||||
return (frame + ((slot + K + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
|
||||
}
|
||||
|
||||
int get_fb_slot(int slot, int K, int n_slots_frame, int NTN_gNB_Koffset)
|
||||
{
|
||||
// K is the feedback time in slot
|
||||
return (slot + K + NTN_gNB_Koffset) % n_slots_frame;
|
||||
}
|
||||
|
||||
int get_ssbidx_from_beam(gNB_MAC_INST *mac, int beam_idx)
|
||||
{
|
||||
for (int i = 0; i < MAX_NUM_OF_SSB; i++)
|
||||
@@ -2544,8 +2557,14 @@ NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_nr_ue_data(NR_UE_info_t *UE, uid_allocator_t *uia)
|
||||
void delete_nr_ue_data(NR_UE_info_t *UE, gNB_MAC_INST *nrmac, uid_allocator_t *uia)
|
||||
{
|
||||
if (UE->sr_info.allocated)
|
||||
nrmac->ul_rrc_info.sr_resources[UE->sr_info.resource][UE->sr_info.offset] = -1;
|
||||
if (UE->csimeas_info.allocated) {
|
||||
nrmac->ul_rrc_info.csimeas_resources[UE->csimeas_info.resource][UE->csimeas_info.offset] = -1;
|
||||
nrmac->ul_rrc_info.csimeas_resources[UE->csimeas_info.resource][UE->csimeas_info.offset2] = -1;
|
||||
}
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
|
||||
@@ -3110,7 +3129,7 @@ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
|
||||
bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE);
|
||||
if (!success) {
|
||||
LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti);
|
||||
delete_nr_ue_data(UE, &UE_info->uid_allocator);
|
||||
delete_nr_ue_data(UE, nr_mac, &UE_info->uid_allocator);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3181,7 +3200,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti)
|
||||
NR_UEs_t *UE_info = &nr_mac->UE_info;
|
||||
NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti);
|
||||
if (UE)
|
||||
delete_nr_ue_data(UE, &UE_info->uid_allocator);
|
||||
delete_nr_ue_data(UE, nr_mac, &UE_info->uid_allocator);
|
||||
else
|
||||
nr_release_ra_UE(nr_mac, rnti);
|
||||
}
|
||||
@@ -3913,6 +3932,51 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le
|
||||
mac->mac_rrc.initial_ul_rrc_message_transfer(0, &ul_rrc_msg);
|
||||
}
|
||||
|
||||
bool mac_ul_rrc_periodic_resources(gNB_MAC_INST *mac, NR_UE_info_t *UE, const NR_ServingCellConfigCommon_t *scc, int active_bwp)
|
||||
{
|
||||
int bwp_size = 0;
|
||||
int bwp_start = 0;
|
||||
const nr_mac_config_t *configuration = &mac->radio_config;
|
||||
if(configuration->num_additional_bwps > 0 && active_bwp != 0) {
|
||||
bwp_size = NRRIV2BW(configuration->bwp_config[active_bwp - 1].location_and_bw, MAX_BWP_SIZE);
|
||||
bwp_start = NRRIV2PRBOFFSET(configuration->bwp_config[active_bwp - 1].location_and_bw, MAX_BWP_SIZE);
|
||||
} else {
|
||||
bwp_size = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
bwp_start = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
}
|
||||
|
||||
bool sr_allocated = UE->sr_info.allocated; // allocation information of SR resource
|
||||
bool sr = set_ul_periodic_resources(mac->ul_rrc_info.sr_resources,
|
||||
configuration,
|
||||
&UE->sr_info,
|
||||
&mac->frame_structure,
|
||||
false,
|
||||
UE->uid,
|
||||
bwp_start,
|
||||
bwp_size,
|
||||
mac->ul_rrc_info.sr_period);
|
||||
|
||||
if (sr) {
|
||||
bool csi = set_ul_periodic_resources(mac->ul_rrc_info.csimeas_resources,
|
||||
configuration,
|
||||
&UE->csimeas_info,
|
||||
&mac->frame_structure,
|
||||
true,
|
||||
UE->uid,
|
||||
bwp_start,
|
||||
bwp_size,
|
||||
mac->ul_rrc_info.csimeas_period);
|
||||
if (csi)
|
||||
return true;
|
||||
else if (!sr_allocated) {
|
||||
// if it was a new allocation for SR but we can't allocate CSI we need to revert SR allocation
|
||||
UE->sr_info.allocated = false;
|
||||
mac->ul_rrc_info.sr_resources[UE->sr_info.resource][UE->sr_info.offset] = -1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
|
||||
{
|
||||
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
|
||||
@@ -3939,13 +4003,24 @@ 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);
|
||||
bool alloc = mac_ul_rrc_periodic_resources(mac, UE, scc, mac->radio_config.first_active_bwp);
|
||||
NR_CellGroupConfig_t *cellGroupConfig = NULL;
|
||||
if (alloc)
|
||||
cellGroupConfig = get_initial_cellGroupConfig(UE->uid,
|
||||
UE->sr_info,
|
||||
UE->csimeas_info,
|
||||
scc,
|
||||
&mac->radio_config,
|
||||
&mac->rlc_config,
|
||||
ssb_index);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = cellGroupConfig;
|
||||
UE->local_bwp_id = mac->radio_config.first_active_bwp;
|
||||
|
||||
if (!cellGroupConfig)
|
||||
if (!cellGroupConfig) {
|
||||
LOG_W(NR_MAC, "Couldn't allocate RRC resources to the UE %04x, to be rejected\n", UE->rnti);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* the cellGroup sent to CU specifies there is SRB1, so create it */
|
||||
DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1);
|
||||
@@ -4065,20 +4140,21 @@ 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, bool 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,
|
||||
current_BWP->pucch_Config,
|
||||
UE->csimeas_info,
|
||||
UE->current_DL_BWP.bwp_id,
|
||||
ssb_index);
|
||||
} else {
|
||||
@@ -4089,11 +4165,19 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE,
|
||||
else {
|
||||
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
|
||||
UE->local_bwp_id = new_bwp_id;
|
||||
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon;
|
||||
bool alloc = mac_ul_rrc_periodic_resources(nrmac, UE, scc, new_bwp_id);
|
||||
if (!alloc) {
|
||||
LOG_E(NR_MAC, "Cannot switch to BWP %d. Couldn't allocate resources\n", new_bwp_id);
|
||||
return;
|
||||
}
|
||||
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->sr_info,
|
||||
UE->csimeas_info,
|
||||
UE->uid,
|
||||
UE->current_DL_BWP.bwp_id,
|
||||
new_bwp_id,
|
||||
|
||||
@@ -187,6 +187,80 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot)
|
||||
}
|
||||
}
|
||||
|
||||
static int find_pucch_resource_index(const NR_PUCCH_Config_t *pucch_Config, int resset_idx, int pucch_idx)
|
||||
{
|
||||
// resset_idx 0 for f0 and f1, resset_idx 1 for f2 and f3
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[resset_idx];
|
||||
const int n = pucchresset->resourceList.list.count;
|
||||
int res_index = 0;
|
||||
for (; res_index < n; res_index++)
|
||||
if (*pucchresset->resourceList.list.array[res_index] == pucch_idx)
|
||||
break;
|
||||
AssertFatal(res_index < n, "PUCCH resource with index %d not found among PUCCH resources\n", pucch_idx);
|
||||
return res_index;
|
||||
}
|
||||
|
||||
static bool pucch23_vrb_occupation(gNB_MAC_INST *nrmac,
|
||||
NR_PUCCH_Config_t *pucch_Config,
|
||||
NR_sched_pucch_t *curr_pucch,
|
||||
NR_beam_alloc_t beam,
|
||||
int res_id,
|
||||
int bwp_start,
|
||||
int sched_frame,
|
||||
int sched_slot)
|
||||
{
|
||||
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
|
||||
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;
|
||||
for (int j = 0; j < m; j++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
|
||||
if (pucchres->pucch_ResourceId != res_id)
|
||||
continue;
|
||||
int start = pucchres->startingPRB;
|
||||
int len = 1;
|
||||
uint64_t mask = 0;
|
||||
switch(pucchres->format.present) {
|
||||
case NR_PUCCH_Resource__format_PR_format2 :
|
||||
len = pucchres->format.choice.format2->nrofPRBs;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
LOG_D(NR_MAC,
|
||||
"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n",
|
||||
sched_frame,
|
||||
sched_slot,
|
||||
start,
|
||||
len,
|
||||
curr_pucch->simultaneous_harqcsi,
|
||||
curr_pucch->csi_bits);
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3 :
|
||||
len = pucchres->format.choice.format3->nrofPRBs;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format3->startingSymbolIndex, pucchres->format.choice.format3->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format4:
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format4->startingSymbolIndex, pucchres->format.choice.format4->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Invalid PUCCH format type\n");
|
||||
}
|
||||
// verify resources are free
|
||||
for (int i = start; i < start + len; ++i) {
|
||||
if((vrb_map_UL[i + bwp_start] & mask) != 0) {
|
||||
LOG_E(NR_MAC, "VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n", sched_frame, sched_slot);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// reserve resources
|
||||
for (int i = start; i < start + len; ++i)
|
||||
vrb_map_UL[i + bwp_start] |= mask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
|
||||
{
|
||||
const int CC_id = 0;
|
||||
@@ -225,94 +299,43 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
|
||||
// we schedule CSI reporting max_fb_time slots in advance
|
||||
int period, offset;
|
||||
csi_period_offset(csirep, NULL, &period, &offset);
|
||||
const int sched_slot = (slot + ul_bwp->max_fb_time + NTN_gNB_Koffset) % n_slots_frame;
|
||||
const int sched_frame = (frame + ((slot + ul_bwp->max_fb_time + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
|
||||
const int sched_slot = get_fb_slot(slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
|
||||
const int sched_frame = get_fb_frame(frame, slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
|
||||
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
|
||||
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
|
||||
continue;
|
||||
|
||||
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot);
|
||||
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not an uplink slot\n", sched_slot);
|
||||
LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", sched_frame, sched_slot, csirep->reportConfigId);
|
||||
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
|
||||
const int n = pucchresset->resourceList.list.count;
|
||||
int res_index = 0;
|
||||
for (; res_index < n; res_index++)
|
||||
if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource)
|
||||
break;
|
||||
AssertFatal(res_index < n,
|
||||
"CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource);
|
||||
|
||||
int res_index = find_pucch_resource_index(pucch_Config, 1, pucchcsires->pucch_Resource); // index 1 for F2
|
||||
const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||
if (curr_pucch->active) {
|
||||
LOG_E(NR_MAC, "CSI structure is scheduled in advance. It should be free!\n");
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
|
||||
// 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");
|
||||
curr_pucch->beam_idx = beam.idx;
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
|
||||
bool ret = pucch23_vrb_occupation(nrmac,
|
||||
pucch_Config,
|
||||
curr_pucch,
|
||||
beam,
|
||||
*pucchresset->resourceList.list.array[res_index],
|
||||
ul_bwp->BWPStart,
|
||||
sched_frame,
|
||||
sched_slot);
|
||||
|
||||
AssertFatal(ret, "Resources not free to schedule CSI report\n");
|
||||
curr_pucch->r_pucch = -1;
|
||||
curr_pucch->frame = sched_frame;
|
||||
curr_pucch->ul_slot = sched_slot;
|
||||
curr_pucch->resource_indicator = res_index;
|
||||
curr_pucch->csi_bits += nr_get_csi_bitlen(&UE->csi_report_template[csi_report_id]);
|
||||
curr_pucch->active = true;
|
||||
|
||||
int bwp_start = ul_bwp->BWPStart;
|
||||
|
||||
// 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");
|
||||
curr_pucch->beam_idx = beam.idx;
|
||||
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;
|
||||
for (int j = 0; j < m; j++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
|
||||
if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index])
|
||||
continue;
|
||||
int start = pucchres->startingPRB;
|
||||
int len = 1;
|
||||
uint64_t mask = 0;
|
||||
switch(pucchres->format.present){
|
||||
case NR_PUCCH_Resource__format_PR_format2:
|
||||
len = pucchres->format.choice.format2->nrofPRBs;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
LOG_D(NR_MAC,
|
||||
"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n",
|
||||
sched_frame,
|
||||
sched_slot,
|
||||
start,
|
||||
len,
|
||||
curr_pucch->simultaneous_harqcsi,
|
||||
curr_pucch->csi_bits);
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
len = pucchres->format.choice.format3->nrofPRBs;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format3->startingSymbolIndex, pucchres->format.choice.format3->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format4:
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format4->startingSymbolIndex, pucchres->format.choice.format4->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Invalid PUCCH format type\n");
|
||||
}
|
||||
// verify resources are free
|
||||
for (int i = start; i < start + len; ++i) {
|
||||
if((vrb_map_UL[i+bwp_start] & mask) != 0) {
|
||||
LOG_E(NR_MAC,
|
||||
"%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n",
|
||||
frame,
|
||||
slot,
|
||||
sched_frame,
|
||||
sched_slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
else
|
||||
vrb_map_UL[i+bwp_start] |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1009,15 +1032,17 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
|
||||
T_INT(uci_234->rssi));
|
||||
}
|
||||
|
||||
// TODO: handle SR
|
||||
if (uci_234->pduBitmap & 0x1) {
|
||||
if (uci_234->sr.sr_payload && uci_234->sr.sr_payload[0])
|
||||
sched_ctrl->SR = true;
|
||||
free(uci_234->sr.sr_payload);
|
||||
}
|
||||
|
||||
if ((uci_234->pduBitmap >> 1) & 0x01) {
|
||||
// iterate over received harq bits
|
||||
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
|
||||
const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01;
|
||||
int rev_bit = uci_234->harq.harq_bit_len - 1 - harq_bit;
|
||||
const int acknack = ((uci_234->harq.harq_payload[rev_bit >> 3]) >> (rev_bit & 7)) & 0x01;
|
||||
NR_UE_harq_t *harq = find_harq(frame, slot, UE, RC.nrmac[mod_id]->dl_bler.harq_round_max);
|
||||
if (!harq) {
|
||||
LOG_E(NR_MAC, "UE %04x: Could not find a HARQ process at %4d.%2d!\n", UE->rnti, frame, slot);
|
||||
@@ -1057,17 +1082,72 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
}
|
||||
|
||||
static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch)
|
||||
static bool test_pucch0_vrb_occupation(const NR_PUCCH_Resource_t *resource,
|
||||
uint16_t *vrb_map_UL,
|
||||
const int bwp_start,
|
||||
const int bwp_size)
|
||||
{
|
||||
if(r_pucch<0){
|
||||
const NR_PUCCH_Resource_t *resource = ul_bwp->pucch_Config->resourceToAddModList->list.array[0];
|
||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||
pucch->second_hop_prb = resource->secondHopPRB!= NULL ? *resource->secondHopPRB : 0;
|
||||
pucch->nr_of_symb = resource->format.choice.format0->nrofSymbols;
|
||||
pucch->start_symb = resource->format.choice.format0->startingSymbolIndex;
|
||||
pucch->prb_start = resource->startingPRB;
|
||||
if (!resource)
|
||||
return false;
|
||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||
// We assume initial cyclic shift is always 0 so different pucch resources can't overlap
|
||||
// verifying occupation of PRBs for ACK/NACK on dedicated pucch
|
||||
for (int l = 0; l < resource->format.choice.format0->nrofSymbols; l++) {
|
||||
uint16_t symb = SL_to_bitmap(resource->format.choice.format0->startingSymbolIndex + l, 1);
|
||||
int prb = (l == 1 && resource->secondHopPRB) ? *resource->secondHopPRB : resource->startingPRB;
|
||||
AssertFatal(prb < bwp_size, "PUCCH0 PRB %d\n exceeds BWP size %d\n", prb, bwp_size);
|
||||
if ((vrb_map_UL[bwp_start + prb] & symb) != 0) {
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
|
||||
static NR_PUCCH_Resource_t *get_pucch_resource(const NR_PUCCH_Config_t *pucch_Config, const NR_PUCCH_ResourceId_t *resource_id)
|
||||
{
|
||||
DevAssert(resource_id);
|
||||
DevAssert(pucch_Config->resourceSetToAddModList);
|
||||
for (int n = 0; n < pucch_Config->resourceToAddModList->list.count; n++) {
|
||||
NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[n];
|
||||
if (resource->pucch_ResourceId == *resource_id)
|
||||
return resource;
|
||||
}
|
||||
LOG_E(NR_MAC, "Couldn't find PUCCH resource with ID %ld\n", *resource_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void set_pucch_allocation(const NR_PUCCH_Resource_t *resource, NR_sched_pucch_t *pucch, int resource_ind)
|
||||
{
|
||||
pucch->second_hop_prb = resource->secondHopPRB != NULL ? *resource->secondHopPRB : 0;
|
||||
pucch->nr_of_symb = resource->format.choice.format0->nrofSymbols;
|
||||
pucch->start_symb = resource->format.choice.format0->startingSymbolIndex;
|
||||
pucch->prb_start = resource->startingPRB;
|
||||
pucch->resource_indicator = resource_ind;
|
||||
}
|
||||
|
||||
static bool find_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp,
|
||||
uint16_t *vrb_map_UL,
|
||||
const int r_pucch,
|
||||
const int bwp_start,
|
||||
const int bwp_size,
|
||||
NR_sched_pucch_t *pucch)
|
||||
{
|
||||
if (r_pucch < 0) {
|
||||
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
|
||||
// PUCCH resource set for F0 or 1 is the one with index 0
|
||||
DevAssert(pucch_Config->resourceSetToAddModList);
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0];
|
||||
for (int i = 0; i < pucchresset->resourceList.list.count; i++) {
|
||||
NR_PUCCH_ResourceId_t *resource_id = pucchresset->resourceList.list.array[i];
|
||||
NR_PUCCH_Resource_t *resource = get_pucch_resource(pucch_Config, resource_id);
|
||||
if (test_pucch0_vrb_occupation(resource, vrb_map_UL, bwp_start, bwp_size)) {
|
||||
set_pucch_allocation(resource, pucch, i);
|
||||
return true; // we found a valid occasion (otherwise we try with the following one)
|
||||
}
|
||||
}
|
||||
return false; // we couldn't find any valid occasion
|
||||
} else {
|
||||
int rsetindex = *ul_bwp->pucch_ConfigCommon->pucch_ResourceCommon;
|
||||
set_r_pucch_parms(rsetindex,
|
||||
r_pucch,
|
||||
@@ -1076,43 +1156,27 @@ static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch
|
||||
&pucch->second_hop_prb,
|
||||
&pucch->nr_of_symb,
|
||||
&pucch->start_symb);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start)
|
||||
static void set_reset_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start, bool set)
|
||||
{
|
||||
// We assume initial cyclic shift is always 0 so different pucch resources can't overlap
|
||||
|
||||
// verifying occupation of PRBs for ACK/NACK on dedicated pucch
|
||||
for (int l=0; l<pucch->nr_of_symb; l++) {
|
||||
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
|
||||
for (int l = 0; l < pucch->nr_of_symb; l++) {
|
||||
uint16_t symb = SL_to_bitmap(pucch->start_symb + l, 1);
|
||||
int prb;
|
||||
if (l==1 && pucch->second_hop_prb != 0)
|
||||
if (l == 1 && pucch->second_hop_prb != 0)
|
||||
prb = pucch->second_hop_prb;
|
||||
else
|
||||
prb = pucch->prb_start;
|
||||
if ((vrb_map_UL[bwp_start+prb] & symb) != 0) {
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start)
|
||||
{
|
||||
for (int l=0; l<pucch->nr_of_symb; l++) {
|
||||
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
|
||||
int prb;
|
||||
if (l==1 && pucch->second_hop_prb != 0)
|
||||
prb = pucch->second_hop_prb;
|
||||
if (set)
|
||||
vrb_map_UL[bwp_start + prb] |= symb;
|
||||
else
|
||||
prb = pucch->prb_start;
|
||||
vrb_map_UL[bwp_start+prb] |= symb;
|
||||
vrb_map_UL[bwp_start + prb] &= ~symb;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource)
|
||||
static bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource)
|
||||
{
|
||||
int resource_id = get_pucch_resourceid(pucch_Config, O_uci, pucch_resource);
|
||||
AssertFatal(pucch_Config->resourceToAddModList != NULL, "PUCCH resourceToAddModList is null\n");
|
||||
@@ -1159,44 +1223,32 @@ bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, in
|
||||
|
||||
// this function returns an index to NR_sched_pucch structure
|
||||
// if the function returns -1 it was not possible to schedule acknack
|
||||
int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
NR_UE_info_t *UE,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
int ue_beam,
|
||||
int r_pucch,
|
||||
int is_common)
|
||||
int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot, int ue_beam, int r_pucch, int is_common)
|
||||
{
|
||||
/* we assume that this function is mutex-protected from outside. Since it is
|
||||
* called often, don't try to lock every time */
|
||||
|
||||
const int CC_id = 0;
|
||||
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
|
||||
const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset;
|
||||
const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const frame_structure_t *fs = &mac->frame_structure;
|
||||
const int n_slots_frame = fs->numb_slots_frame;
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
|
||||
|
||||
const int bwp_start = ul_bwp->BWPStart;
|
||||
const int bwp_size = ul_bwp->BWPSize;
|
||||
|
||||
nr_dci_format_t dci_format = NR_DL_DCI_FORMAT_1_0;
|
||||
if(is_common == 0)
|
||||
dci_format = UE->current_DL_BWP.dci_format;
|
||||
|
||||
uint8_t pdsch_to_harq_feedback[8];
|
||||
int fb_size = get_pdsch_to_harq_feedback(pucch_Config, dci_format, pdsch_to_harq_feedback);
|
||||
|
||||
for (int f = 0; f < fb_size; f++) {
|
||||
// can't schedule ACKNACK before minimum feedback time
|
||||
if((pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) < minfbtime)
|
||||
continue;
|
||||
const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame;
|
||||
const int pucch_slot = get_fb_slot(slot, pdsch_to_harq_feedback[f], n_slots_frame, NTN_gNB_Koffset);
|
||||
// check if the slot is UL
|
||||
if (fs->frame_type == TDD) {
|
||||
int mod_slot = get_slot_idx_in_period(pucch_slot, fs);
|
||||
@@ -1206,19 +1258,22 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
if (r_pucch >= 0 && is_mixed_slot(mod_slot, fs) && pc->tdd_slot_bitmap[mod_slot].num_ul_symbols < 2)
|
||||
continue;
|
||||
}
|
||||
const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
|
||||
const int pucch_frame = get_fb_frame(frame, slot, pdsch_to_harq_feedback[f], n_slots_frame, NTN_gNB_Koffset);
|
||||
// we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures
|
||||
const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, &mac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||
if (curr_pucch->active &&
|
||||
curr_pucch->frame == pucch_frame &&
|
||||
curr_pucch->ul_slot == pucch_slot) { // if there is already a PUCCH in given frame and slot
|
||||
LOG_D(NR_MAC, "pucch_acknack DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n",
|
||||
frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits);
|
||||
// we can't schedule if short pucch is already full
|
||||
if (curr_pucch->csi_bits == 0 &&
|
||||
curr_pucch->dai_c == 2)
|
||||
continue;
|
||||
// if there is already a PUCCH in given frame and slot
|
||||
if (curr_pucch->active && curr_pucch->frame == pucch_frame && curr_pucch->ul_slot == pucch_slot) {
|
||||
LOG_D(NR_MAC,
|
||||
"pucch_acknack DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: SR %d DAI_C %d CSI %d\n",
|
||||
frame,
|
||||
slot,
|
||||
pucch_frame,
|
||||
pucch_slot,
|
||||
curr_pucch->sr_flag,
|
||||
curr_pucch->dai_c,
|
||||
curr_pucch->csi_bits);
|
||||
|
||||
// if there is CSI but simultaneous HARQ+CSI is disable we can't schedule
|
||||
if (curr_pucch->csi_bits > 0 && !curr_pucch->simultaneous_harqcsi)
|
||||
continue;
|
||||
@@ -1226,11 +1281,10 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
// according to PUCCH code rate (if not we search for another allocation)
|
||||
// the number of bits in the check need to include possible SR (1 bit)
|
||||
// and the ack/nack bit to be scheduled (1 bit)
|
||||
// so the number of bits already scheduled in current pucch + 2
|
||||
if (curr_pucch->csi_bits > 0
|
||||
&& !check_bits_vs_coderate_limit(pucch_Config,
|
||||
curr_pucch->csi_bits + curr_pucch->dai_c + 2,
|
||||
curr_pucch->resource_indicator))
|
||||
// so the number of bits already scheduled in current pucch + SR flag + 1
|
||||
int tot_bits = curr_pucch->csi_bits + curr_pucch->dai_c + curr_pucch->sr_flag + 1;
|
||||
if (curr_pucch->csi_bits + curr_pucch->dai_c > 2
|
||||
&& !check_bits_vs_coderate_limit(pucch_Config, tot_bits, curr_pucch->resource_indicator))
|
||||
continue;
|
||||
// TODO temporarily limit ack/nak to 3 bits because of performances of polar for PUCCH (required for > 11 bits)
|
||||
if (curr_pucch->csi_bits > 0 && curr_pucch->dai_c >= 3)
|
||||
@@ -1239,12 +1293,43 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
// otherwise we can schedule in this active PUCCH
|
||||
// no need to check VRB occupation because already done when PUCCH has been activated
|
||||
curr_pucch->timing_indicator = f;
|
||||
// if we already reached the limit for PUCCH F0 or 1, we need to switch to another format
|
||||
if (curr_pucch->dai_c == 2 && curr_pucch->csi_bits == 0) {
|
||||
if (!pucch_Config) // in common PUCCH we can transmit at most 2 bits
|
||||
continue;
|
||||
const int index = ul_buffer_index(pucch_frame, pucch_slot, n_slots_frame, mac->vrb_map_UL_size);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, ue_beam, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Beam should have been already allocated when setting PUCCH0, so it should be available\n");
|
||||
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
|
||||
// resetting PUCCH0 occupation
|
||||
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, false);
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1];
|
||||
bool ret = pucch23_vrb_occupation(mac,
|
||||
pucch_Config,
|
||||
curr_pucch,
|
||||
beam,
|
||||
*pucchresset->resourceList.list.array[curr_pucch->resource_indicator],
|
||||
bwp_start,
|
||||
pucch_frame,
|
||||
pucch_slot);
|
||||
if (!ret) { // if we can't allocate a PUCCH able to carry more than 2 bits we need to keep looking
|
||||
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
curr_pucch->dai_c++;
|
||||
LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n",
|
||||
frame,slot,curr_pucch->frame,curr_pucch->ul_slot,pucch_index,f,curr_pucch->dai_c,curr_pucch->csi_bits);
|
||||
LOG_D(NR_MAC,
|
||||
"DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n",
|
||||
frame,
|
||||
slot,
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
pucch_index,
|
||||
f,
|
||||
curr_pucch->dai_c,
|
||||
curr_pucch->csi_bits);
|
||||
return pucch_index; // index of current PUCCH structure
|
||||
}
|
||||
else if (curr_pucch->active) {
|
||||
} else if (curr_pucch->active) {
|
||||
LOG_E(NR_MAC,
|
||||
"current PUCCH inactive: curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
|
||||
curr_pucch->frame,
|
||||
@@ -1252,10 +1337,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
pucch_frame,
|
||||
pucch_slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
else { // unoccupied occasion
|
||||
// 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);
|
||||
} else { // unoccupied occasion
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, ue_beam, n_slots_frame);
|
||||
if (beam.idx < 0) {
|
||||
LOG_D(NR_MAC,
|
||||
@@ -1267,10 +1349,11 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
continue;
|
||||
}
|
||||
curr_pucch->beam_idx = beam.idx;
|
||||
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
|
||||
const int index = ul_buffer_index(pucch_frame, pucch_slot, n_slots_frame, mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
|
||||
bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
|
||||
if(!ret) {
|
||||
bool valid = find_pucch_allocation(ul_bwp, vrb_map_UL, r_pucch, bwp_start, bwp_size, curr_pucch);
|
||||
if(!valid) {
|
||||
LOG_D(NR_MAC,
|
||||
"DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n",
|
||||
frame,
|
||||
@@ -1286,15 +1369,19 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
curr_pucch->ul_slot = pucch_slot;
|
||||
curr_pucch->timing_indicator = f; // index in the list of timing indicators
|
||||
curr_pucch->dai_c++;
|
||||
curr_pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources
|
||||
curr_pucch->r_pucch=r_pucch;
|
||||
|
||||
LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n",
|
||||
frame, slot, curr_pucch->frame, curr_pucch->ul_slot, pucch_index, f, curr_pucch->dai_c);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n",
|
||||
frame,
|
||||
slot,
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
pucch_index,
|
||||
f,
|
||||
curr_pucch->dai_c);
|
||||
// blocking resources for current PUCCH in VRB map
|
||||
set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
|
||||
|
||||
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, true);
|
||||
return pucch_index; // index of current PUCCH structure
|
||||
}
|
||||
}
|
||||
@@ -1302,15 +1389,13 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
|
||||
{
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
|
||||
|
||||
if (!is_ul_slot(slot, &nrmac->frame_structure))
|
||||
return;
|
||||
const int CC_id = 0;
|
||||
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
@@ -1322,67 +1407,66 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
|
||||
if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList)
|
||||
continue;
|
||||
|
||||
AssertFatal(pucch_Config->schedulingRequestResourceToAddModList->list.count>0,"NO SR configuration available");
|
||||
|
||||
for (int SR_resource_id = 0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) {
|
||||
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
|
||||
|
||||
struct NR_PUCCH_Config__schedulingRequestResourceToAddModList *sr_list = pucch_Config->schedulingRequestResourceToAddModList;
|
||||
AssertFatal(sr_list->list.count > 0, "NO SR configuration available");
|
||||
for (int id = 0; id < sr_list->list.count; id++) {
|
||||
NR_SchedulingRequestResourceConfig_t *srConf = sr_list->list.array[id];
|
||||
int SR_period; int SR_offset;
|
||||
|
||||
find_period_offset_SR(SchedulingRequestResourceConfig, &SR_period, &SR_offset);
|
||||
// convert to int to avoid underflow of uint
|
||||
int sfn_sf = SFN * n_slots_frame + slot;
|
||||
LOG_D(NR_MAC,"SR_resource_id %d: SR_period %d, SR_offset %d\n", SR_resource_id, SR_period, SR_offset);
|
||||
find_period_offset_SR(srConf, &SR_period, &SR_offset);
|
||||
// we schedule SR max_fb_time slots in advance
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
const int sched_slot = get_fb_slot(slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
|
||||
const int sched_frame = get_fb_frame(SFN, slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
|
||||
// convert to int to avoid underflow of uint
|
||||
int sfn_sf = sched_frame * n_slots_frame + sched_slot;
|
||||
LOG_D(NR_MAC, "SR_resource_id %d: SR_period %d, SR_offset %d\n", id, SR_period, SR_offset);
|
||||
if ((sfn_sf - SR_offset) % SR_period != 0)
|
||||
continue;
|
||||
LOG_D(NR_MAC, "%4d.%2d Scheduling Request UE %04x identified\n", SFN, slot, UE->rnti);
|
||||
NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource;
|
||||
|
||||
int idx = -1;
|
||||
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1
|
||||
int n_list = pucchresset->resourceList.list.count;
|
||||
for (int i=0; i<n_list; i++) {
|
||||
if (*pucchresset->resourceList.list.array[i] == *PucchResourceId )
|
||||
idx = i;
|
||||
}
|
||||
AssertFatal(idx > -1, "SR resource not found among PUCCH resources");
|
||||
|
||||
const int pucch_index = get_pucch_index(SFN, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "SR slot %d is not set for an uplink slot\n", sched_slot);
|
||||
LOG_D(NR_MAC, "%4d.%2d Scheduling Request UE %04x identified\n", sched_frame, sched_slot, UE->rnti);
|
||||
NR_PUCCH_ResourceId_t *PucchResourceId = srConf->resource;
|
||||
int idx = find_pucch_resource_index(pucch_Config, 0, *PucchResourceId); // index 0 for F0
|
||||
const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||
|
||||
if (curr_pucch->active && curr_pucch->frame == SFN && curr_pucch->ul_slot == slot && curr_pucch->resource_indicator == idx)
|
||||
if (curr_pucch->active
|
||||
&& curr_pucch->frame == sched_frame
|
||||
&& curr_pucch->ul_slot == sched_slot
|
||||
&& curr_pucch->resource_indicator == idx)
|
||||
curr_pucch->sr_flag = true;
|
||||
else if (curr_pucch->active) {
|
||||
LOG_E(NR_MAC,
|
||||
"current PUCCH inactive: curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
SFN,
|
||||
slot);
|
||||
sched_frame,
|
||||
sched_slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, SFN, slot, UE->UE_beam_index, n_slots_frame);
|
||||
} else {
|
||||
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 SR in any available beam\n");
|
||||
const int index = ul_buffer_index(SFN, slot, n_slots_frame, nrmac->vrb_map_UL_size);
|
||||
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[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
|
||||
const int bwp_start = ul_bwp->BWPStart;
|
||||
const int bwp_size = ul_bwp->BWPSize;
|
||||
set_pucch_allocation(ul_bwp, -1, bwp_size, curr_pucch);
|
||||
bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
|
||||
NR_PUCCH_Resource_t *resource = get_pucch_resource(pucch_Config, PucchResourceId);
|
||||
bool ret = test_pucch0_vrb_occupation(resource, vrb_map_UL, bwp_start, bwp_size);
|
||||
if (!ret) {
|
||||
LOG_E(NR_MAC,"Cannot schedule SR. PRBs not available\n");
|
||||
LOG_E(NR_MAC, "Cannot schedule SR. PRBs not available\n");
|
||||
continue;
|
||||
}
|
||||
set_pucch_allocation(resource, curr_pucch, idx);
|
||||
curr_pucch->beam_idx = beam.idx;
|
||||
curr_pucch->frame = SFN;
|
||||
curr_pucch->ul_slot = slot;
|
||||
curr_pucch->frame = sched_frame;
|
||||
curr_pucch->ul_slot = sched_slot;
|
||||
curr_pucch->sr_flag = true;
|
||||
curr_pucch->resource_indicator = idx;
|
||||
curr_pucch->r_pucch = -1;
|
||||
curr_pucch->active = true;
|
||||
set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
|
||||
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "utils.h"
|
||||
@@ -757,7 +758,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
|
||||
UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER;
|
||||
if (!transition_ra_connected_nr_ue(mac, UE)) {
|
||||
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
|
||||
delete_nr_ue_data(UE, &mac->UE_info.uid_allocator);
|
||||
delete_nr_ue_data(UE, mac, &mac->UE_info.uid_allocator);
|
||||
} else {
|
||||
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
|
||||
}
|
||||
@@ -2541,8 +2542,8 @@ void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch)
|
||||
int k2 = fsn_get_diff(*next, current) - koffset;
|
||||
DevAssert(k2 > 0);
|
||||
int slots_per_frame = nr_mac->frame_structure.numb_slots_frame;
|
||||
int sched_frame = (frame + (slot + k2 + koffset) / slots_per_frame) % MAX_FRAME_NUMBER;
|
||||
int sched_slot = (slot + k2 + koffset) % slots_per_frame;
|
||||
int sched_frame = get_fb_frame(frame, slot, k2, slots_per_frame, koffset);
|
||||
int sched_slot = get_fb_slot(slot, k2, slots_per_frame, koffset);
|
||||
|
||||
/* Check that at least one TDA can reach this slot, if not, no future slot is reachable either */
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ 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);
|
||||
void delete_nr_ue_data(NR_UE_info_t *UE, uid_allocator_t *uia);
|
||||
void delete_nr_ue_data(NR_UE_info_t *UE, gNB_MAC_INST *nrmac, uid_allocator_t *uia);
|
||||
|
||||
void mac_top_init_gNB(ngran_node_t node_type,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
@@ -179,13 +179,7 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, slot_t slotP);
|
||||
|
||||
void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot);
|
||||
|
||||
int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
NR_UE_info_t *UE,
|
||||
frame_t frameP,
|
||||
slot_t slotP,
|
||||
int beam_index,
|
||||
int r_pucch,
|
||||
int do_common);
|
||||
int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot, int ue_beam, int r_pucch, int is_common);
|
||||
|
||||
int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config,
|
||||
nr_dci_format_t dci_format,
|
||||
@@ -517,8 +511,9 @@ bool nr_mac_ue_is_active(const NR_UE_info_t *ue);
|
||||
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
|
||||
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 config_ul_rrc_info(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, int scs, int bw);
|
||||
void nr_mac_trigger_reconfiguration(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam);
|
||||
bool mac_ul_rrc_periodic_resources(gNB_MAC_INST *mac, NR_UE_info_t *UE, const NR_ServingCellConfigCommon_t *scc, int active_bwp);
|
||||
|
||||
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);
|
||||
@@ -584,4 +579,6 @@ bool nr_ul_check_phr(const nr_ul_sched_params_t *params,
|
||||
uint16_t rbSize,
|
||||
uint8_t mcs,
|
||||
nr_ul_phr_advice_t *advice);
|
||||
int get_fb_frame(int frame, int slot, int K, int n_slots_frame, int NTN_gNB_Koffset);
|
||||
int get_fb_slot(int slot, int K, int n_slots_frame, int NTN_gNB_Koffset);
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -543,12 +543,29 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
|
||||
const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
const nr_mac_config_t *configuration = &mac->radio_config;
|
||||
int ssb_index = get_ssbidx_from_beam(mac, UE->UE_beam_index);
|
||||
bool alloc = mac_ul_rrc_periodic_resources(mac, UE, scc, mac->radio_config.first_active_bwp);
|
||||
if (is_SA) {
|
||||
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config, ssb_index);
|
||||
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
|
||||
} else {
|
||||
if (alloc) {
|
||||
cellGroupConfig = get_initial_cellGroupConfig(UE->uid,
|
||||
UE->sr_info,
|
||||
UE->csimeas_info,
|
||||
scc,
|
||||
&mac->radio_config,
|
||||
&mac->rlc_config,
|
||||
ssb_index);
|
||||
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
|
||||
}
|
||||
} else if (alloc) {
|
||||
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,
|
||||
UE->sr_info,
|
||||
UE->csimeas_info,
|
||||
1,
|
||||
1,
|
||||
configuration,
|
||||
UE->uid,
|
||||
ssb_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;
|
||||
@@ -569,7 +586,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
|
||||
DevAssert(res);
|
||||
} else {
|
||||
if (!add_new_UE_RA(mac, UE)) {
|
||||
delete_nr_ue_data(UE, &mac->UE_info.uid_allocator);
|
||||
delete_nr_ue_data(UE, mac, &mac->UE_info.uid_allocator);
|
||||
LOG_E(NR_MAC, "UE list full while creating new UE\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "NR_MAC_gNB/mac_proto.h"
|
||||
#include "NR_MAC_gNB/mac_rrc_ul.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "NR_MAC_gNB/nr_radio_config.h"
|
||||
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "NR_RLC-BearerConfig.h"
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
@@ -358,13 +359,19 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac)
|
||||
NR_UEs_t *UE_info = &mac->UE_info;
|
||||
for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i)
|
||||
if (UE_info->connected_ue_list[i])
|
||||
delete_nr_ue_data(UE_info->connected_ue_list[i], &UE_info->uid_allocator);
|
||||
delete_nr_ue_data(UE_info->connected_ue_list[i], mac, &UE_info->uid_allocator);
|
||||
for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i)
|
||||
if (UE_info->access_ue_list[i])
|
||||
delete_nr_ue_data(UE_info->access_ue_list[i], &UE_info->uid_allocator);
|
||||
delete_nr_ue_data(UE_info->access_ue_list[i], mac, &UE_info->uid_allocator);
|
||||
if (mac->f1_config.setup_resp)
|
||||
free_f1ap_setup_response(mac->f1_config.setup_resp);
|
||||
free(mac->f1_config.setup_resp);
|
||||
for (int i = 0; i < mac->ul_rrc_info.max_num_res; i++) {
|
||||
free(mac->ul_rrc_info.csimeas_resources[i]);
|
||||
free(mac->ul_rrc_info.sr_resources[i]);
|
||||
}
|
||||
free(mac->ul_rrc_info.csimeas_resources);
|
||||
free(mac->ul_rrc_info.sr_resources);
|
||||
}
|
||||
|
||||
void nr_mac_send_f1_setup_req(void)
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
#include "NR_BCCH-BCH-Message.h"
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "NR_BCCH-DL-SCH-Message.h"
|
||||
#include "nr_radio_config.h"
|
||||
|
||||
/* PHY */
|
||||
#include "time_meas.h"
|
||||
@@ -785,6 +784,14 @@ typedef struct measgap_config {
|
||||
int mgl_slots;
|
||||
} measgap_config_t;
|
||||
|
||||
typedef struct NR_UE_UL_RRC_info {
|
||||
bool allocated;
|
||||
int resource;
|
||||
int offset;
|
||||
int offset2;
|
||||
int period;
|
||||
} NR_UE_UL_RRC_info_t;
|
||||
|
||||
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
|
||||
typedef struct NR_UE_info {
|
||||
rnti_t rnti;
|
||||
@@ -816,6 +823,8 @@ typedef struct NR_UE_info {
|
||||
long pdsch_HARQ_ACK_Codebook;
|
||||
bool is_redcap;
|
||||
bool reestablish_rlc;
|
||||
NR_UE_UL_RRC_info_t sr_info;
|
||||
NR_UE_UL_RRC_info_t csimeas_info;
|
||||
NR_RA_t *ra;
|
||||
// 3GPP mandates that BWPs are enumerated consecutively, but we only send one (dedicated)
|
||||
// BWP to the UE (and modify that BWP on reconfiguration); consequently, the BWP ID for a
|
||||
@@ -1153,6 +1162,14 @@ typedef struct NR_du_stats {
|
||||
uint32_t pusch_mcs_dist[8][2][32];
|
||||
} NR_du_stats_t;
|
||||
|
||||
typedef struct {
|
||||
int **sr_resources;
|
||||
int **csimeas_resources;
|
||||
int sr_period;
|
||||
int csimeas_period;
|
||||
int max_num_res;
|
||||
} NR_UL_RRC_res_list_t;
|
||||
|
||||
/*! \brief top level eNB MAC structure */
|
||||
typedef struct gNB_MAC_INST_s {
|
||||
/// Ethernet parameters for northbound midhaul interface
|
||||
@@ -1211,6 +1228,7 @@ typedef struct gNB_MAC_INST_s {
|
||||
time_stats_t rx_ulsch_sdu; // include rlc_data_ind
|
||||
|
||||
NR_beam_info_t beam_info;
|
||||
NR_UL_RRC_res_list_t ul_rrc_info;
|
||||
|
||||
/// maximum number of slots before a UE will be scheduled ULSCH automatically
|
||||
uint32_t ulsch_max_frame_inactivity;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "assertions.h"
|
||||
#include "common/openairinterface5g_limits.h"
|
||||
#include "common/utils/T/T.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "constr_TYPE.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "oai_asn1.h"
|
||||
@@ -32,7 +31,8 @@
|
||||
#include "xer_encoder.h"
|
||||
|
||||
#define NR_MAX_SUPPORTED_DL_LAYERS 4
|
||||
|
||||
#define MAX_PUCCH_PER_SET 8
|
||||
#define MAX_PUCCH_RESOURCES 128
|
||||
/* Default values for measurement gap configuration */
|
||||
#define DEFAULT_MGRP NR_GapConfig__mgrp_ms160
|
||||
#define DEFAULT_MGTA NR_GapConfig__mgta_ms0dot5
|
||||
@@ -204,27 +204,6 @@ static int get_pucch2_size(const int num_ant_ports)
|
||||
return (num_ant_ports <= 4 ? 8 : 12);
|
||||
}
|
||||
|
||||
static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int bwp_size, const nr_pdsch_AntennaPorts_t *ap)
|
||||
{
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing];
|
||||
int ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0) : n_slots_frame;
|
||||
int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
int max_meas_report_period = 320; // slots
|
||||
int max_csi_reports = MAX_MOBILES_PER_GNB << 1; // 2 reports per UE (RSRP and RI-PMI-CQI)
|
||||
int available_report_occasions = max_meas_report_period * ul_slots_period / n_slots_period;
|
||||
int nb_pucch2 = (max_csi_reports / (available_report_occasions + 1)) + 1;
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
// in current implementation we need (nb_pucch2 * pucch2_size) prbs for PUCCH2
|
||||
// and MAX_MOBILES_PER_GNB prbs for PUCCH1
|
||||
// checked for validity in verify_radio_configuration
|
||||
AssertFatal((nb_pucch2 * pucch2_size) + MAX_MOBILES_PER_GNB <= bwp_size,
|
||||
"Cannot allocate all required PUCCH resources for max number of %d UEs in BWP with %d PRBs\n",
|
||||
MAX_MOBILES_PER_GNB,
|
||||
bwp_size);
|
||||
return nb_pucch2;
|
||||
}
|
||||
|
||||
NR_SearchSpace_t *rrc_searchspace_config(bool is_common,
|
||||
int searchspaceid,
|
||||
int coresetid,
|
||||
@@ -1226,32 +1205,26 @@ static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedbac
|
||||
}
|
||||
|
||||
// PUCCH resource set 0 for configuration with O_uci <= 2 bits and/or a positive or negative SR (section 9.2.1 of 38.213)
|
||||
static void config_pucch_resset0(const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_PUCCH_Config_t *pucch_Config,
|
||||
int uid,
|
||||
int curr_bwp,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const nr_pdsch_AntennaPorts_t *ap)
|
||||
static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config,
|
||||
NR_PUCCH_ResourceSet_t *pucchresset,
|
||||
int id,
|
||||
const nr_pdsch_AntennaPorts_t *ap,
|
||||
const NR_UE_NR_Capability_t *uecap)
|
||||
{
|
||||
NR_PUCCH_ResourceSet_t *pucchresset = calloc(1,sizeof(*pucchresset));
|
||||
pucchresset->pucch_ResourceSetId = 0;
|
||||
NR_PUCCH_ResourceId_t *pucchid = calloc(1,sizeof(*pucchid));
|
||||
*pucchid = 0;
|
||||
asn1cSeqAdd(&pucchresset->resourceList.list,pucchid);
|
||||
pucchresset->maxPayloadSize = NULL;
|
||||
NR_PUCCH_ResourceId_t *pucchid = calloc(1, sizeof(*pucchid));
|
||||
*pucchid = id;
|
||||
asn1cSeqAdd(&pucchresset->resourceList.list, pucchid);
|
||||
|
||||
if(uecap) {
|
||||
long *pucch_F0_2WithoutFH = uecap->phy_Parameters.phy_ParametersFRX_Diff->pucch_F0_2WithoutFH;
|
||||
AssertFatal(pucch_F0_2WithoutFH == NULL,"UE does not support PUCCH F0 without frequency hopping. Current configuration is without FH\n");
|
||||
AssertFatal(!pucch_F0_2WithoutFH, "UE doesn't support PUCCH F0 without frequency hopping. In OAI PUCCH0 is without FH.\n");
|
||||
}
|
||||
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
NR_PUCCH_Resource_t *pucchres0 = calloc(1,sizeof(*pucchres0));
|
||||
pucchres0->pucch_ResourceId = *pucchid;
|
||||
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, ap);
|
||||
pucchres0->startingPRB = (pucch2_size * num_pucch2) + uid;
|
||||
pucchres0->startingPRB = pucch2_size * id;
|
||||
// checked for validity in verify_radio_configuration
|
||||
AssertFatal(pucchres0->startingPRB < curr_bwp, "Not enough resources in current BWP (size %d) to allocate uid %d\n", curr_bwp, uid);
|
||||
pucchres0->intraSlotFrequencyHopping = NULL;
|
||||
pucchres0->secondHopPRB = NULL;
|
||||
pucchres0->format.present = NR_PUCCH_Resource__format_PR_format0;
|
||||
@@ -1259,37 +1232,30 @@ static void config_pucch_resset0(const NR_ServingCellConfigCommon_t *scc,
|
||||
pucchres0->format.choice.format0->initialCyclicShift = 0;
|
||||
pucchres0->format.choice.format0->nrofSymbols = 1;
|
||||
pucchres0->format.choice.format0->startingSymbolIndex = 13;
|
||||
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list,pucchres0);
|
||||
|
||||
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list,pucchresset);
|
||||
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list, pucchres0);
|
||||
}
|
||||
|
||||
|
||||
// PUCCH resource set 1 for configuration with O_uci > 2 bits (currently format2)
|
||||
static void config_pucch_resset1(const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_PUCCH_Config_t *pucch_Config,
|
||||
int uid,
|
||||
int curr_bwp,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const nr_pdsch_AntennaPorts_t *ap)
|
||||
static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config,
|
||||
NR_PUCCH_ResourceSet_t *pucchresset,
|
||||
int id,
|
||||
const nr_pdsch_AntennaPorts_t *ap,
|
||||
const NR_UE_NR_Capability_t *uecap)
|
||||
{
|
||||
NR_PUCCH_ResourceSet_t *pucchresset=calloc(1,sizeof(*pucchresset));
|
||||
pucchresset->pucch_ResourceSetId = 1;
|
||||
NR_PUCCH_ResourceId_t *pucchressetid=calloc(1,sizeof(*pucchressetid));
|
||||
*pucchressetid = 2;
|
||||
asn1cSeqAdd(&pucchresset->resourceList.list,pucchressetid);
|
||||
pucchresset->maxPayloadSize = NULL;
|
||||
NR_PUCCH_ResourceId_t *pucchressetid = calloc(1, sizeof(*pucchressetid));
|
||||
*pucchressetid = (MAX_PUCCH_RESOURCES / 2) + id;
|
||||
asn1cSeqAdd(&pucchresset->resourceList.list, pucchressetid);
|
||||
|
||||
if(uecap) {
|
||||
long *pucch_F0_2WithoutFH = uecap->phy_Parameters.phy_ParametersFRX_Diff->pucch_F0_2WithoutFH;
|
||||
AssertFatal(pucch_F0_2WithoutFH == NULL,"UE does not support PUCCH F2 without frequency hopping. Current configuration is without FH\n");
|
||||
AssertFatal(!pucch_F0_2WithoutFH, "UE does not support PUCCH2 without frequency hopping. In OAI PUCCH2 is without FH\n");
|
||||
}
|
||||
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
NR_PUCCH_Resource_t *pucchres2 = calloc(1,sizeof(*pucchres2));
|
||||
pucchres2->pucch_ResourceId = *pucchressetid;
|
||||
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, ap);
|
||||
pucchres2->startingPRB = pucch2_size * (uid % num_pucch2);
|
||||
pucchres2->startingPRB = pucch2_size * id;
|
||||
pucchres2->intraSlotFrequencyHopping = NULL;
|
||||
pucchres2->secondHopPRB = NULL;
|
||||
pucchres2->format.present = NR_PUCCH_Resource__format_PR_format2;
|
||||
@@ -1297,10 +1263,11 @@ static void config_pucch_resset1(const NR_ServingCellConfigCommon_t *scc,
|
||||
pucchres2->format.choice.format2->nrofPRBs = pucch2_size;
|
||||
pucchres2->format.choice.format2->nrofSymbols = 1;
|
||||
pucchres2->format.choice.format2->startingSymbolIndex = 13;
|
||||
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list,pucchres2);
|
||||
|
||||
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list,pucchresset);
|
||||
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list, pucchres2);
|
||||
}
|
||||
|
||||
static void config_pucch_f2(NR_PUCCH_Config_t *pucch_Config)
|
||||
{
|
||||
pucch_Config->format2 = calloc(1,sizeof(*pucch_Config->format2));
|
||||
pucch_Config->format2->present = NR_SetupRelease_PUCCH_FormatConfig_PR_setup;
|
||||
NR_PUCCH_FormatConfig_t *pucchfmt2 = calloc(1,sizeof(*pucchfmt2));
|
||||
@@ -1311,7 +1278,6 @@ static void config_pucch_resset1(const NR_ServingCellConfigCommon_t *scc,
|
||||
*pucchfmt2->maxCodeRate = NR_PUCCH_MaxCodeRate_zeroDot15;
|
||||
pucchfmt2->nrofSlots = NULL;
|
||||
pucchfmt2->pi2BPSK = NULL;
|
||||
|
||||
// to check UE capabilities for that in principle
|
||||
pucchfmt2->simultaneousHARQ_ACK_CSI = calloc(1,sizeof(*pucchfmt2->simultaneousHARQ_ACK_CSI));
|
||||
*pucchfmt2->simultaneousHARQ_ACK_CSI = NR_PUCCH_FormatConfig__simultaneousHARQ_ACK_CSI_true;
|
||||
@@ -1354,67 +1320,62 @@ static void set_pucch_power_config(NR_PUCCH_Config_t *pucch_Config)
|
||||
asn1cSeqAdd(&pucch_Config->spatialRelationInfoToAddModList->list,pucchspatial);
|
||||
}
|
||||
|
||||
static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig, int scs)
|
||||
static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *srResourceConfig, NR_UE_UL_RRC_info_t sr_info)
|
||||
{
|
||||
const frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
|
||||
int sr_slot = 1; // in FDD SR in slot 1
|
||||
if (fs->frame_type == TDD)
|
||||
sr_slot = get_first_ul_slot(fs, true);
|
||||
|
||||
schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset));
|
||||
|
||||
if(sr_slot < 10 && scs < NR_SubcarrierSpacing_kHz60){
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = sr_slot;
|
||||
int period = sr_info.period;
|
||||
srResourceConfig->periodicityAndOffset = calloc(1, sizeof(*srResourceConfig->periodicityAndOffset));
|
||||
struct NR_SchedulingRequestResourceConfig__periodicityAndOffset *periodicityAndOffset = srResourceConfig->periodicityAndOffset;
|
||||
if(period == 10) {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
|
||||
periodicityAndOffset->choice.sl10 = sr_info.offset;
|
||||
return;
|
||||
}
|
||||
else if(sr_slot < 20 && scs < NR_SubcarrierSpacing_kHz120){
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl20 = sr_slot;
|
||||
} else if(period == 20) {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20;
|
||||
periodicityAndOffset->choice.sl20 = sr_info.offset;
|
||||
return;
|
||||
}
|
||||
else if(sr_slot < 40){
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl40 = sr_slot;
|
||||
} else if(period == 40) {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40;
|
||||
periodicityAndOffset->choice.sl40 = sr_info.offset;
|
||||
return;
|
||||
}
|
||||
else if(sr_slot < 80 || scs == NR_SubcarrierSpacing_kHz15){
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl80 = sr_slot;
|
||||
} else if(period == 80) {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80;
|
||||
periodicityAndOffset->choice.sl80 = sr_info.offset;
|
||||
return;
|
||||
}
|
||||
else if(sr_slot < 160 || scs == NR_SubcarrierSpacing_kHz30){
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl160 = sr_slot;
|
||||
} else if(period == 160) {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160;
|
||||
periodicityAndOffset->choice.sl160 = sr_info.offset;
|
||||
return;
|
||||
}
|
||||
else if(sr_slot < 320 || scs == NR_SubcarrierSpacing_kHz60){
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl320 = sr_slot;
|
||||
} else if(period == 320) {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320;
|
||||
periodicityAndOffset->choice.sl320 = sr_info.offset;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl640 = sr_slot;
|
||||
} else {
|
||||
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640;
|
||||
periodicityAndOffset->choice.sl640 = sr_info.offset;
|
||||
}
|
||||
}
|
||||
|
||||
static void scheduling_request_config(NR_PUCCH_Config_t *pucch_Config, int scs)
|
||||
static int get_pucch_start_idx(int bwp_start, int pucch2_size)
|
||||
{
|
||||
// format with <=2 bits in pucch resource set 0
|
||||
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0];
|
||||
// assigning the 1st pucch resource in the set to scheduling request
|
||||
NR_PUCCH_ResourceId_t *pucchressetid = pucchresset->resourceList.list.array[0];
|
||||
return bwp_start / pucch2_size + (bwp_start % pucch2_size > 0);
|
||||
}
|
||||
|
||||
pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList));
|
||||
NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1,sizeof(*schedulingRequestResourceConfig));
|
||||
static int get_num_pucch(int bwp_start, int bwp_size, int pucch2_size)
|
||||
{
|
||||
int start_prb = ceil(bwp_start / pucch2_size) * pucch2_size; // first PRB of first valid group
|
||||
int available = bwp_start + bwp_size - start_prb; // PRBs from there to end of BWP
|
||||
return min(MAX_PUCCH_PER_SET, available / pucch2_size);
|
||||
}
|
||||
|
||||
static void scheduling_request_config(NR_PUCCH_Config_t *pucch_Config, NR_UE_UL_RRC_info_t sr_info)
|
||||
{
|
||||
pucch_Config->schedulingRequestResourceToAddModList = calloc(1, sizeof(*pucch_Config->schedulingRequestResourceToAddModList));
|
||||
NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1, sizeof(*schedulingRequestResourceConfig));
|
||||
schedulingRequestResourceConfig->schedulingRequestResourceId = 1;
|
||||
schedulingRequestResourceConfig->schedulingRequestID = 0;
|
||||
|
||||
set_SR_periodandoffset(schedulingRequestResourceConfig, scs);
|
||||
|
||||
set_SR_periodandoffset(schedulingRequestResourceConfig, sr_info);
|
||||
schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource));
|
||||
*schedulingRequestResourceConfig->resource = *pucchressetid;
|
||||
*schedulingRequestResourceConfig->resource = sr_info.resource;
|
||||
asn1cSeqAdd(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig);
|
||||
}
|
||||
|
||||
@@ -1875,9 +1836,39 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
|
||||
return bwp;
|
||||
}
|
||||
|
||||
static NR_PUCCH_Config_t *config_pucch(const NR_UE_NR_Capability_t *uecap,
|
||||
int bwp_start,
|
||||
int bwp_size,
|
||||
const nr_pdsch_AntennaPorts_t *ap,
|
||||
NR_UE_UL_RRC_info_t sr_info)
|
||||
{
|
||||
NR_PUCCH_Config_t *pucch_Config = calloc_or_fail(1, sizeof(*pucch_Config));
|
||||
pucch_Config->resourceSetToAddModList = calloc_or_fail(1, sizeof(*pucch_Config->resourceSetToAddModList));
|
||||
pucch_Config->resourceSetToReleaseList = NULL;
|
||||
pucch_Config->resourceToAddModList = calloc_or_fail(1, sizeof(*pucch_Config->resourceToAddModList));
|
||||
pucch_Config->resourceToReleaseList = NULL;
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
int pucch_start_idx = get_pucch_start_idx(bwp_start, pucch2_size);
|
||||
int num_pucch = get_num_pucch(bwp_start, bwp_size, pucch2_size);
|
||||
NR_PUCCH_ResourceSet_t *pucchresset0 = calloc_or_fail(1, sizeof(*pucchresset0));
|
||||
pucchresset0->pucch_ResourceSetId = 0;
|
||||
for (int i = 0; i < num_pucch; i++)
|
||||
config_pucch_resset0(pucch_Config, pucchresset0, i + pucch_start_idx, ap, uecap);
|
||||
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list, pucchresset0);
|
||||
NR_PUCCH_ResourceSet_t *pucchresset1 = calloc_or_fail(1, sizeof(*pucchresset1));
|
||||
pucchresset1->pucch_ResourceSetId = 1;
|
||||
for (int i = 0; i < num_pucch; i++)
|
||||
config_pucch_resset1(pucch_Config, pucchresset1, i + pucch_start_idx, ap, uecap);
|
||||
config_pucch_f2(pucch_Config);
|
||||
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list, pucchresset1);
|
||||
scheduling_request_config(pucch_Config, sr_info);
|
||||
return pucch_Config;
|
||||
}
|
||||
|
||||
static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
|
||||
int uid,
|
||||
int maxMIMO_Layers,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
const nr_mac_config_t *configuration,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_UE_NR_Capability_t *uecap)
|
||||
@@ -1896,7 +1887,6 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
|
||||
ubwp->bwp_Common->genericParameters.cyclicPrefix = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.cyclicPrefix;
|
||||
}
|
||||
|
||||
int curr_bwp = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
|
||||
ubwp->bwp_Common->rach_ConfigCommon = is_SA ? NULL : clone_rach_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon);
|
||||
ubwp->bwp_Common->pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon);
|
||||
ubwp->bwp_Common->pucch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PUCCH_ConfigCommon));
|
||||
@@ -1912,25 +1902,20 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
|
||||
ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated));
|
||||
}
|
||||
|
||||
int bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
ubwp->bwp_Dedicated->pucch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pucch_Config));
|
||||
ubwp->bwp_Dedicated->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup;
|
||||
NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config));
|
||||
ubwp->bwp_Dedicated->pucch_Config->choice.setup = pucch_Config;
|
||||
pucch_Config->resourceSetToAddModList = calloc(1,sizeof(*pucch_Config->resourceSetToAddModList));
|
||||
pucch_Config->resourceSetToReleaseList = NULL;
|
||||
pucch_Config->resourceToAddModList = calloc(1,sizeof(*pucch_Config->resourceToAddModList));
|
||||
pucch_Config->resourceToReleaseList = NULL;
|
||||
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);
|
||||
NR_PUCCH_Config_t *pucch_Config = config_pucch(uecap, bwp_start, bwp_size, &configuration->pdsch_AntennaPorts, sr_info);
|
||||
set_pucch_power_config(pucch_Config);
|
||||
scheduling_request_config(pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
|
||||
ubwp->bwp_Dedicated->pucch_Config->choice.setup = pucch_Config;
|
||||
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,
|
||||
NULL,
|
||||
curr_bwp,
|
||||
bwp_size,
|
||||
uid,
|
||||
ubwp->bwp_Id,
|
||||
maxMIMO_Layers,
|
||||
@@ -1952,46 +1937,34 @@ static void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig)
|
||||
mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1;
|
||||
}
|
||||
|
||||
static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_CSI_ReportConfig_t *csirep,
|
||||
int uid,
|
||||
int curr_bwp,
|
||||
const nr_pdsch_AntennaPorts_t *antennaports,
|
||||
bool is_rsrp)
|
||||
static void set_csi_meas_periodicity(NR_CSI_ReportConfig_t *csirep, NR_UE_UL_RRC_info_t csi_info, bool is_rsrp)
|
||||
{
|
||||
const int ideal_period = set_ideal_period(true);
|
||||
const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, antennaports);
|
||||
const int idx = (uid * 2 / num_pucch2) + is_rsrp;
|
||||
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);
|
||||
// checked for validity in verify_radio_configuration
|
||||
AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n");
|
||||
if (check_periodicity(4, ideal_period, fs)) {
|
||||
int offset = is_rsrp ? csi_info.offset : csi_info.offset2;
|
||||
if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.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)) {
|
||||
} else if (csi_info.period == 160) {
|
||||
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots160;
|
||||
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160 = offset;
|
||||
} else {
|
||||
@@ -2109,14 +2082,12 @@ static NR_CodebookConfig_t *config_csi_codebook(const nr_pdsch_AntennaPorts_t *a
|
||||
}
|
||||
|
||||
static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
NR_PUCCH_CSI_Resource_t *pucchcsires,
|
||||
struct NR_SetupRelease_PDSCH_Config *pdsch_Config,
|
||||
const nr_pdsch_AntennaPorts_t *antennaports,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
const int max_layers,
|
||||
int rep_id,
|
||||
int uid,
|
||||
int curr_bwp)
|
||||
int rep_id)
|
||||
{
|
||||
int resource_id = -1;
|
||||
int im_id = -1;
|
||||
@@ -2145,7 +2116,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(csirep, csi_info, false);
|
||||
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;
|
||||
@@ -2208,9 +2179,8 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
NR_PUCCH_CSI_Resource_t *pucchcsires,
|
||||
const nr_mac_config_t *configuration,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int rep_id,
|
||||
int uid,
|
||||
int curr_bwp,
|
||||
uint64_t ssb_bitmap)
|
||||
{
|
||||
int resource_id = -1;
|
||||
@@ -2239,7 +2209,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(csirep, csi_info, true);
|
||||
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;
|
||||
@@ -3354,36 +3324,30 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u
|
||||
|
||||
static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellConfigCommon_t *scc,
|
||||
const nr_mac_config_t *configuration,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
int maxMIMO_Layers,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
int id)
|
||||
{
|
||||
NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP));
|
||||
NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||||
int curr_bwp = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
initialUplinkBWP->pucch_Config = calloc(1, sizeof(*initialUplinkBWP->pucch_Config));
|
||||
initialUplinkBWP->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup;
|
||||
NR_PUCCH_Config_t *pucch_Config = calloc(1, sizeof(*pucch_Config));
|
||||
initialUplinkBWP->pucch_Config->choice.setup = pucch_Config;
|
||||
pucch_Config->resourceSetToAddModList = calloc(1, sizeof(*pucch_Config->resourceSetToAddModList));
|
||||
pucch_Config->resourceSetToReleaseList = NULL;
|
||||
pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList));
|
||||
pucch_Config->resourceToReleaseList = NULL;
|
||||
config_pucch_resset0(scc, pucch_Config, id, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
|
||||
config_pucch_resset1(scc, pucch_Config, id, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
|
||||
NR_PUCCH_Config_t *pucch_Config = config_pucch(NULL, bwp_start, bwp_size, &configuration->pdsch_AntennaPorts, sr_info);
|
||||
set_pucch_power_config(pucch_Config);
|
||||
|
||||
initialUplinkBWP->pucch_Config->choice.setup = pucch_Config;
|
||||
initialUplinkBWP->pusch_Config = config_pusch(configuration, scc, uecap);
|
||||
initialUplinkBWP->srs_Config = get_config_srs(scc,
|
||||
uecap,
|
||||
curr_bwp,
|
||||
bwp_size,
|
||||
id,
|
||||
0,
|
||||
maxMIMO_Layers,
|
||||
configuration->minRXTXTIME,
|
||||
configuration->do_SRS);
|
||||
|
||||
scheduling_request_config(pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing);
|
||||
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME);
|
||||
return initialUplinkBWP;
|
||||
}
|
||||
@@ -3443,6 +3407,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nr_mac_config_t *configuration,
|
||||
const NR_PUCCH_Config_t *pucch_Config,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int uid,
|
||||
int bwp_id,
|
||||
uint64_t bitmap,
|
||||
@@ -3502,8 +3468,6 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
|
||||
csires1->bwp_Id = bwp_id;
|
||||
csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic;
|
||||
asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1);
|
||||
|
||||
int pucch_Resource = 2;
|
||||
if (configuration->do_CSIRS) {
|
||||
NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0));
|
||||
csires0->csi_ResourceConfigId = bwp_id;
|
||||
@@ -3535,28 +3499,25 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
|
||||
|
||||
NR_PUCCH_CSI_Resource_t *pucchcsi = calloc(1, sizeof(*pucchcsi));
|
||||
pucchcsi->uplinkBandwidthPartId = bwp_id;
|
||||
pucchcsi->pucch_Resource = pucch_Resource;
|
||||
pucchcsi->pucch_Resource = csi_info.resource + (MAX_PUCCH_RESOURCES / 2);
|
||||
config_csi_meas_report(csi_MeasConfig,
|
||||
scc,
|
||||
pucchcsi,
|
||||
pdsch_Config,
|
||||
&configuration->pdsch_AntennaPorts,
|
||||
csi_info,
|
||||
*configDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers,
|
||||
bwp_id,
|
||||
uid,
|
||||
curr_bwp);
|
||||
bwp_id);
|
||||
}
|
||||
NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp));
|
||||
pucchrsrp->uplinkBandwidthPartId = bwp_id;
|
||||
pucchrsrp->pucch_Resource = pucch_Resource;
|
||||
pucchrsrp->pucch_Resource = csi_info.resource + (MAX_PUCCH_RESOURCES / 2);
|
||||
config_rsrp_meas_report(csi_MeasConfig,
|
||||
uecap,
|
||||
scc,
|
||||
pucchrsrp,
|
||||
configuration,
|
||||
csi_info,
|
||||
bwp_id + 10,
|
||||
uid,
|
||||
curr_bwp,
|
||||
bitmap);
|
||||
return csi_MeasConfig;
|
||||
}
|
||||
@@ -3564,6 +3525,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
|
||||
static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nr_mac_config_t *configuration,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int ssb_index)
|
||||
{
|
||||
NR_SpCellConfig_t *SpCellConfig = calloc(1, sizeof(*SpCellConfig));
|
||||
@@ -3601,15 +3564,18 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
|
||||
asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp);
|
||||
asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp);
|
||||
NR_PUCCH_Config_t *pucch_Config = NULL;
|
||||
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, sr_info, maxMIMO_Layers, NULL, uid);
|
||||
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, bitmap, NULL, configuration);
|
||||
pucch_Config = uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
|
||||
} 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, sr_info, configuration, scc, NULL);
|
||||
pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
|
||||
}
|
||||
|
||||
@@ -3619,6 +3585,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
NULL,
|
||||
scc,
|
||||
configuration,
|
||||
pucch_Config,
|
||||
csi_info,
|
||||
uid,
|
||||
first_active_bwp,
|
||||
bitmap,
|
||||
@@ -3755,6 +3723,64 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
|
||||
return rlc_BearerConfig;
|
||||
}
|
||||
|
||||
bool set_ul_periodic_resources(int **list,
|
||||
const nr_mac_config_t *configuration,
|
||||
NR_UE_UL_RRC_info_t *info,
|
||||
const frame_structure_t *fs,
|
||||
bool is_csi,
|
||||
int id,
|
||||
int bwp_start,
|
||||
int bwp_size,
|
||||
int period)
|
||||
{
|
||||
const nr_pdsch_AntennaPorts_t *ap = &configuration->pdsch_AntennaPorts;
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
int pucch_start_idx = get_pucch_start_idx(bwp_start, pucch2_size);
|
||||
int num_pucch = get_num_pucch(bwp_start, bwp_size, pucch2_size);
|
||||
AssertFatal(num_pucch > 0, "No PUCCH could be allocated\n");
|
||||
if (info->allocated) {
|
||||
// if the already allocated resource can be still used in current BWP
|
||||
if (info->resource >= pucch_start_idx && info->resource < pucch_start_idx + num_pucch) {
|
||||
if (list[info->resource][info->offset] == id)
|
||||
return true;
|
||||
else {
|
||||
LOG_E(NR_MAC, "Resource should be allocated but not present in the list\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// old resource is outside new BWP range — release it before reallocating
|
||||
list[info->resource][info->offset] = -1;
|
||||
if (is_csi)
|
||||
list[info->resource][info->offset2] = -1; // if CSI has a second slot
|
||||
info->allocated = false;
|
||||
}
|
||||
|
||||
int pucch_res = pucch_start_idx + (id % num_pucch);
|
||||
do {
|
||||
int idx = is_csi;
|
||||
int offset = get_ul_slot_offset(fs, idx, true);
|
||||
while (offset < period) {
|
||||
if (list[pucch_res][offset] == -1) {
|
||||
info->resource = pucch_res;
|
||||
info->offset = offset;
|
||||
if (is_csi) {
|
||||
int offset2 = get_ul_slot_offset(fs, idx - 1, true);
|
||||
info->offset2 = offset2;
|
||||
list[pucch_res][offset2] = id;
|
||||
}
|
||||
info->period = period;
|
||||
info->allocated = true;
|
||||
list[pucch_res][offset] = id;
|
||||
return true;
|
||||
}
|
||||
idx += 2;
|
||||
offset = get_ul_slot_offset(fs, idx, true);
|
||||
}
|
||||
pucch_res = (pucch_res == pucch_start_idx + num_pucch - 1) ? pucch_start_idx : pucch_res + 1;
|
||||
} while (pucch_res != pucch_start_idx + (id % num_pucch));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration)
|
||||
{
|
||||
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
|
||||
@@ -3772,34 +3798,12 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon
|
||||
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI-RS, rejecting UE\n", uid);
|
||||
return false; // cannot allocate resources for CSI-RS
|
||||
}
|
||||
|
||||
const nr_pdsch_AntennaPorts_t *ap = &configuration->pdsch_AntennaPorts;
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, ap);
|
||||
int pucchres0_startingPRB = (pucch2_size * num_pucch2) + uid;
|
||||
// see config_pucch_resset0
|
||||
if (pucchres0_startingPRB >= curr_bwp) {
|
||||
LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH0, rejecting UE\n", uid);
|
||||
return false; // cannot allocate resources for PUCCH0
|
||||
}
|
||||
// see get_nb_pucch2_per_slot
|
||||
if ((num_pucch2 * pucch2_size) + MAX_MOBILES_PER_GNB > curr_bwp) {
|
||||
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);
|
||||
// see set_csi_meas_periodicity
|
||||
if (offset >= 320) {
|
||||
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI reporting, rejecting UE\n", uid);
|
||||
return false; // cannot allocate resources for CSI report
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nr_mac_config_t *configuration,
|
||||
const nr_rlc_configuration_t *default_rlc_config,
|
||||
@@ -3808,7 +3812,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
|
||||
if (!verify_radio_configuration(uid, scc, configuration))
|
||||
return NULL;
|
||||
|
||||
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration, ssb_index);
|
||||
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration, sr_info, csi_info, ssb_index);
|
||||
NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig));
|
||||
cellGroupConfig->cellGroupId = 0;
|
||||
|
||||
@@ -3837,6 +3841,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
|
||||
const nr_mac_config_t *configuration,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int uid,
|
||||
int old_bwp,
|
||||
int new_bwp,
|
||||
@@ -3850,6 +3856,7 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
|
||||
nr_mac_config_t local_config = *configuration;
|
||||
long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap);
|
||||
local_config.first_active_bwp = new_bwp;
|
||||
NR_PUCCH_Config_t *pucch_Config = NULL;
|
||||
uint64_t bitmap = get_ssb_bitmap(scc);
|
||||
// add new BWP
|
||||
if (new_bwp == 0) {
|
||||
@@ -3857,8 +3864,9 @@ 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);
|
||||
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, bitmap, uecap, &local_config);
|
||||
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, sr_info, ul_maxMIMO_Layers, uecap, uid);
|
||||
pucch_Config = uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
|
||||
} else {
|
||||
if (!configDedicated->downlinkBWP_ToAddModList)
|
||||
configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
|
||||
@@ -3867,7 +3875,8 @@ 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, sr_info, &local_config, scc, uecap);
|
||||
pucch_Config = ul_bwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp);
|
||||
}
|
||||
|
||||
@@ -3876,6 +3885,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
|
||||
uecap,
|
||||
scc,
|
||||
&local_config,
|
||||
pucch_Config,
|
||||
csi_info,
|
||||
uid,
|
||||
*uplinkConfig->firstActiveUplinkBWP_Id,
|
||||
bitmap,
|
||||
@@ -3896,18 +3907,21 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
int uid,
|
||||
const NR_PUCCH_Config_t *pucch_Config,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
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,
|
||||
pucch_Config,
|
||||
csi_info,
|
||||
uid,
|
||||
bwp,
|
||||
bitmap,
|
||||
@@ -4057,6 +4071,8 @@ static NR_ServingCellConfigCommon_t *clone_ServingCellConfigCommon(const NR_Serv
|
||||
|
||||
NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
const nr_mac_config_t *configuration,
|
||||
@@ -4148,7 +4164,8 @@ 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, sr_info, configuration, servingcellconfigcommon, uecap);
|
||||
NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp);
|
||||
ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id));
|
||||
*ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id;
|
||||
@@ -4206,6 +4223,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
|
||||
uecap,
|
||||
servingcellconfigcommon,
|
||||
configuration,
|
||||
pucch_Config,
|
||||
csi_info,
|
||||
uid,
|
||||
firstActiveUplinkBWP_Id,
|
||||
bitmap,
|
||||
@@ -4276,6 +4295,47 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u
|
||||
return reconfigurationWithSync;
|
||||
}
|
||||
|
||||
void config_ul_rrc_info(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, int scs, int bw)
|
||||
{
|
||||
// to have a constant periodicity report among all BWPs we need to set it according to the smallest configured BWP
|
||||
const nr_pdsch_AntennaPorts_t *ap = &config->pdsch_AntennaPorts;
|
||||
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
|
||||
nrmac->ul_rrc_info.max_num_res = bw / pucch2_size;
|
||||
int min_num_pucch = get_num_pucch(0, bw, pucch2_size);
|
||||
for (int i = 0; i < config->num_additional_bwps; i++) {
|
||||
int bwp_size = NRRIV2BW(config->bwp_config[i].location_and_bw, MAX_BWP_SIZE);
|
||||
int bwp_start = NRRIV2PRBOFFSET(config->bwp_config[i].location_and_bw, MAX_BWP_SIZE);
|
||||
int num_pucch = get_num_pucch(bwp_start, bwp_size, pucch2_size);
|
||||
if (num_pucch < min_num_pucch)
|
||||
min_num_pucch = num_pucch;
|
||||
}
|
||||
const frame_structure_t *fs = &nrmac->frame_structure;
|
||||
int period = fs->numb_slots_period;
|
||||
int n_ul_slots = get_ul_slots_per_period(fs);
|
||||
while (period < 10 || n_ul_slots * min_num_pucch < MAX_MOBILES_PER_GNB || period <= (80 << scs)) {
|
||||
period *= 2;
|
||||
n_ul_slots *= 2;
|
||||
}
|
||||
nrmac->ul_rrc_info.sr_period = period;
|
||||
nrmac->ul_rrc_info.sr_resources = malloc_or_fail(nrmac->ul_rrc_info.max_num_res * sizeof(int*));
|
||||
for (int i = 0; i < nrmac->ul_rrc_info.max_num_res; i++)
|
||||
nrmac->ul_rrc_info.sr_resources[i] = malloc_or_fail(period * sizeof(int));
|
||||
int ideal_csi_period = set_ideal_period(true) / min_num_pucch;
|
||||
period = 5;
|
||||
while (!check_periodicity(period, ideal_csi_period, fs) || period <= 160) // max CSI periodicity 320
|
||||
period *= 2;
|
||||
nrmac->ul_rrc_info.csimeas_period = period;
|
||||
nrmac->ul_rrc_info.csimeas_resources = malloc_or_fail(nrmac->ul_rrc_info.max_num_res * sizeof(int*));
|
||||
for (int i = 0; i < nrmac->ul_rrc_info.max_num_res; i++)
|
||||
nrmac->ul_rrc_info.csimeas_resources[i] = malloc_or_fail(period * sizeof(int));
|
||||
|
||||
for (int k = 0; k < nrmac->ul_rrc_info.max_num_res; k++) {
|
||||
for (int i = 0; i < nrmac->ul_rrc_info.sr_period; i++)
|
||||
nrmac->ul_rrc_info.sr_resources[k][i] = -1;
|
||||
for (int j = 0; j < nrmac->ul_rrc_info.csimeas_period; j++)
|
||||
nrmac->ul_rrc_info.csimeas_resources[k][j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
|
||||
@@ -16,16 +16,15 @@
|
||||
#include "NR_UL-CCCH-Message.h"
|
||||
#include "f1ap_messages_types.h"
|
||||
#include "common/platform_types.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
|
||||
struct NR_MeasurementTimingConfiguration;
|
||||
struct NR_PDSCH_TimeDomainResourceAllocationList;
|
||||
|
||||
// forward declaration of MAC configuration parameters, definition is included in C file
|
||||
typedef struct nr_mac_config_s nr_mac_config_t;
|
||||
typedef enum nr_srs_type_e nr_srs_type_t;
|
||||
typedef struct nr_mac_timers nr_mac_timers_t;
|
||||
typedef struct measgap_config measgap_config_t;
|
||||
typedef struct NR_UE_UL_RRC_info NR_UE_UL_RRC_info_t;
|
||||
|
||||
void nr_rrc_config_dl_tda(NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList,
|
||||
frame_type_t frame_type,
|
||||
@@ -70,8 +69,18 @@ void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
int encode_SIB_NR(NR_BCCH_DL_SCH_Message_t *sib, uint8_t *buffer, int max_buffer_size);
|
||||
void add_sib_to_systeminformation(NR_SystemInformation_IEs_t *si, struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type);
|
||||
NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc);
|
||||
|
||||
bool set_ul_periodic_resources(int **list,
|
||||
const nr_mac_config_t *configuration,
|
||||
NR_UE_UL_RRC_info_t *info,
|
||||
const frame_structure_t *fs,
|
||||
bool is_csi,
|
||||
int id,
|
||||
int bwp_start,
|
||||
int bwp_size,
|
||||
int period);
|
||||
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nr_mac_config_t *configuration,
|
||||
const nr_rlc_configuration_t *default_rlc_config,
|
||||
@@ -88,6 +97,8 @@ int encode_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, uint8_t *buffe
|
||||
* parameter servingcellconfigdedicated! */
|
||||
NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
const nr_mac_config_t *configuration,
|
||||
@@ -112,6 +123,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
|
||||
const nr_mac_config_t *configuration,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_UE_UL_RRC_info_t sr_info,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int uid,
|
||||
int old_bwp,
|
||||
int new_bwp,
|
||||
@@ -121,6 +134,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
int uid,
|
||||
const NR_PUCCH_Config_t *pucch_Config,
|
||||
NR_UE_UL_RRC_info_t csi_info,
|
||||
int bwp,
|
||||
int ssb_index);
|
||||
NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len);
|
||||
|
||||
Reference in New Issue
Block a user