3064 lines
143 KiB
C
3064 lines
143 KiB
C
/*
|
||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||
* contributor license agreements. See the NOTICE file distributed with
|
||
* this work for additional information regarding copyright ownership.
|
||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||
* except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.openairinterface.org/?page_id=698
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*-------------------------------------------------------------------------------
|
||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||
* contact@openairinterface.org
|
||
*/
|
||
|
||
/*! \file gNB_scheduler_primitives.c
|
||
* \brief primitives used by gNB for BCH, RACH, ULSCH, DLSCH scheduling
|
||
* \author Raymond Knopp, Guy De Souza
|
||
* \date 2018, 2019
|
||
* \email: knopp@eurecom.fr, desouza@eurecom.fr
|
||
* \version 1.0
|
||
* \company Eurecom
|
||
* @ingroup _mac
|
||
|
||
*/
|
||
|
||
#include <softmodem-common.h>
|
||
#include "assertions.h"
|
||
|
||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||
|
||
#include "NR_MAC_gNB/mac_proto.h"
|
||
#include "common/utils/LOG/log.h"
|
||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||
#include "common/utils/nr/nr_common.h"
|
||
#include "UTIL/OPT/opt.h"
|
||
#include "OCG.h"
|
||
#include "OCG_extern.h"
|
||
|
||
#include "RRC/LTE/rrc_extern.h"
|
||
#include "RRC/NR/nr_rrc_extern.h"
|
||
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
|
||
|
||
#include "intertask_interface.h"
|
||
|
||
#include "T.h"
|
||
#include "NR_PDCCH-ConfigCommon.h"
|
||
#include "NR_ControlResourceSet.h"
|
||
#include "NR_SearchSpace.h"
|
||
|
||
#include "nfapi_nr_interface.h"
|
||
|
||
#define ENABLE_MAC_PAYLOAD_DEBUG
|
||
#define DEBUG_gNB_SCHEDULER 1
|
||
|
||
#include "common/ran_context.h"
|
||
|
||
extern RAN_CONTEXT_t RC;
|
||
|
||
// Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs
|
||
/// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config)
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3};
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_30[14] = {2,2,2,2,3,3,3,3,1,1,2,2,3,3};
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[9] = {1,1,2,2,3,3,1,2,3};
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[9] = {1,2,3,1,1,2,2,3,3};
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[16] = {2,2,2,2,2,3,3,3,3,3,1,1,1,2,2,2}; // below 40Mhz bw
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[10] = {2,2,3,3,1,1,2,2,3,3}; // above 40Mhz bw
|
||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_120_60[12] = {1,1,2,2,3,3,1,2,1,1,1,1};
|
||
|
||
/// LUT for the number of RBs in the coreset indexed by coreset index
|
||
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_15_15[15] = {0,2,4,0,2,4,12,16,12,16,12,16,38,38,38};
|
||
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_15_30[14] = {5,6,7,8,5,6,7,8,18,20,18,20,18,20};
|
||
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[9] = {2,6,2,6,2,6,28,28,28};
|
||
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[9] = {4,4,4,0,56,0,56,0,56};
|
||
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[16] = {0,1,2,3,4,0,1,2,3,4,12,14,16,12,14,16};
|
||
uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[10] = {0,4,0,4,0,28,0,28,0,28};
|
||
int8_t nr_coreset_rb_offset_pdcch_type_0_scs_120_60[12] = {0,8,0,8,0,8,28,28,-1,49,-1,97};
|
||
int8_t nr_coreset_rb_offset_pdcch_type_0_scs_120_120[8] = {0,4,14,14,-1,24,-1,48};
|
||
int8_t nr_coreset_rb_offset_pdcch_type_0_scs_240_120[8] = {0,8,0,8,-1,25,-1,49};
|
||
|
||
/// LUT for monitoring occasions param O indexed by ss index (4 LSB rmsi_pdcch_config)
|
||
// Note: scaling is used to avoid decimal values for O and M, original values commented
|
||
uint8_t nr_ss_param_O_type_0_mux1_FR1[16] = {0,0,2,2,5,5,7,7,0,5,0,0,2,2,5,5};
|
||
uint8_t nr_ss_param_O_type_0_mux1_FR2[14] = {0,0,5,5,5,5,0,5,5,15,15,15,0,5}; //{0,0,2.5,2.5,5,5,0,2.5,5,7.5,7.5,7.5,0,5}
|
||
uint8_t nr_ss_scale_O_mux1_FR2[14] = {0,0,1,1,0,0,0,1,0,1,1,1,0,0};
|
||
|
||
/// LUT for number of SS sets per slot indexed by ss index
|
||
uint8_t nr_ss_sets_per_slot_type_0_FR1[16] = {1,2,1,2,1,2,1,2,1,1,1,1,1,1,1,1};
|
||
uint8_t nr_ss_sets_per_slot_type_0_FR2[14] = {1,2,1,2,1,2,2,2,2,1,2,2,1,1};
|
||
|
||
/// LUT for monitoring occasions param M indexed by ss index
|
||
uint8_t nr_ss_param_M_type_0_mux1_FR1[16] = {1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1}; //{1,0.5,1,0.5,1,0.5,1,0.5,2,2,1,1,1,1,1,1}
|
||
uint8_t nr_ss_scale_M_mux1_FR1[16] = {0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0};
|
||
uint8_t nr_ss_param_M_type_0_mux1_FR2[14] = {1,1,1,1,1,1,1,1,1,1,1,1,2,2}; //{1,0.5,1,0.5,1,0.5,0.5,0.5,0.5,1,0.5,0.5,2,2}
|
||
uint8_t nr_ss_scale_M_mux1_FR2[14] = {0,1,0,1,0,1,1,1,1,0,1,1,0,0};
|
||
|
||
/// LUT for SS first symbol index indexed by ss index
|
||
uint8_t nr_ss_first_symb_idx_type_0_mux1_FR1[8] = {0,0,1,2,1,2,1,2};
|
||
// Mux pattern type 2
|
||
uint8_t nr_ss_first_symb_idx_scs_120_60_mux2[4] = {0,1,6,7};
|
||
uint8_t nr_ss_first_symb_idx_scs_240_120_set1_mux2[6] = {0,1,2,3,0,1};
|
||
// Mux pattern type 3
|
||
uint8_t nr_ss_first_symb_idx_scs_120_120_mux3[4] = {4,8,2,6};
|
||
|
||
/// Search space max values indexed by scs
|
||
uint8_t nr_max_number_of_candidates_per_slot[4] = {44, 36, 22, 20};
|
||
uint8_t nr_max_number_of_cces_per_slot[4] = {56, 56, 48, 32};
|
||
|
||
// CQI TABLES
|
||
// Table 1 (38.214 5.2.2.1-2)
|
||
uint16_t cqi_table1[16][2] = {{0,0},{2,78},{2,120},{2,193},{2,308},{2,449},{2,602},{4,378},
|
||
{4,490},{4,616},{6,466},{6,567},{6,666},{6,772},{6,873},{6,948}};
|
||
|
||
// Table 2 (38.214 5.2.2.1-3)
|
||
uint16_t cqi_table2[16][2] = {{0,0},{2,78},{2,193},{2,449},{4,378},{4,490},{4,616},{6,466},
|
||
{6,567},{6,666},{6,772},{6,873},{8,711},{8,797},{8,885},{8,948}};
|
||
|
||
// Table 2 (38.214 5.2.2.1-4)
|
||
uint16_t cqi_table3[16][2] = {{0,0},{2,30},{2,50},{2,78},{2,120},{2,193},{2,308},{2,449},
|
||
{2,602},{4,378},{4,490},{4,616},{6,466},{6,567},{6,666},{6,772}};
|
||
|
||
|
||
static inline uint8_t get_max_candidates(uint8_t scs) {
|
||
AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs);
|
||
return (nr_max_number_of_candidates_per_slot[scs]);
|
||
}
|
||
|
||
static inline uint8_t get_max_cces(uint8_t scs) {
|
||
AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs);
|
||
return (nr_max_number_of_cces_per_slot[scs]);
|
||
}
|
||
|
||
uint8_t set_dl_nrOfLayers(NR_UE_sched_ctrl_t *sched_ctrl) {
|
||
|
||
// TODO check this but it should be enough for now
|
||
// if there is not csi report RI is 0 from initialization
|
||
return (sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1);
|
||
|
||
}
|
||
|
||
void set_dl_mcs(NR_sched_pdsch_t *sched_pdsch,
|
||
NR_UE_sched_ctrl_t *sched_ctrl,
|
||
uint8_t *target_mcs,
|
||
uint8_t mcs_table_idx) {
|
||
|
||
if (sched_ctrl->set_mcs) {
|
||
// TODO for wideband case and multiple TB
|
||
int cqi_idx = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
|
||
uint16_t target_coderate,target_qm;
|
||
if (cqi_idx>0) {
|
||
int cqi_table = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cqi_table;
|
||
AssertFatal(cqi_table == mcs_table_idx, "Indices of MCS tables don't correspond\n");
|
||
switch (cqi_table) {
|
||
case 0:
|
||
target_qm = cqi_table1[cqi_idx][0];
|
||
target_coderate = cqi_table1[cqi_idx][1];
|
||
break;
|
||
case 1:
|
||
target_qm = cqi_table2[cqi_idx][0];
|
||
target_coderate = cqi_table2[cqi_idx][1];
|
||
break;
|
||
case 2:
|
||
target_qm = cqi_table3[cqi_idx][0];
|
||
target_coderate = cqi_table3[cqi_idx][1];
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Invalid cqi table index %d\n",cqi_table);
|
||
}
|
||
int max_mcs = 28;
|
||
int R,Qm;
|
||
if (mcs_table_idx == 1)
|
||
max_mcs = 27;
|
||
for (int i=0; i<=max_mcs; i++) {
|
||
R = nr_get_code_rate_dl(i, mcs_table_idx);
|
||
Qm = nr_get_Qm_dl(i, mcs_table_idx);
|
||
if ((Qm == target_qm) && (target_coderate <= R)) {
|
||
*target_mcs = i;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
sched_ctrl->set_mcs = FALSE;
|
||
}
|
||
}
|
||
|
||
void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps) {
|
||
|
||
//TODO first basic implementation of dmrs port selection
|
||
// only vaild for a single codeword
|
||
// for now it assumes a selection of Nl consecutive dmrs ports
|
||
// and a single front loaded symbol
|
||
// dmrs_ports_id is the index of Tables 7.3.1.2.2-1/2/3/4
|
||
// number of front loaded symbols need to be consistent with maxLength
|
||
// when a more complete implementation is done
|
||
|
||
switch (ps->nrOfLayers) {
|
||
case 1:
|
||
ps->dmrs_ports_id = 0;
|
||
ps->numDmrsCdmGrpsNoData = 1;
|
||
ps->frontloaded_symb = 1;
|
||
break;
|
||
case 2:
|
||
ps->dmrs_ports_id = 2;
|
||
ps->numDmrsCdmGrpsNoData = 1;
|
||
ps->frontloaded_symb = 1;
|
||
break;
|
||
case 3:
|
||
ps->dmrs_ports_id = 9;
|
||
ps->numDmrsCdmGrpsNoData = 2;
|
||
ps->frontloaded_symb = 1;
|
||
break;
|
||
case 4:
|
||
ps->dmrs_ports_id = 10;
|
||
ps->numDmrsCdmGrpsNoData = 2;
|
||
ps->frontloaded_symb = 1;
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Number of layers %d\n not supported or not valid\n",ps->nrOfLayers);
|
||
}
|
||
}
|
||
|
||
NR_BWP_t *get_dl_bwp_genericParameters(NR_BWP_Downlink_t *active_bwp,
|
||
NR_ServingCellConfigCommon_t *ServingCellConfigCommon,
|
||
const NR_SIB1_t *sib1) {
|
||
NR_BWP_t *genericParameters = NULL;
|
||
if (active_bwp) {
|
||
genericParameters = &active_bwp->bwp_Common->genericParameters;
|
||
} else if (ServingCellConfigCommon) {
|
||
genericParameters = &ServingCellConfigCommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||
} else {
|
||
genericParameters = &sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.genericParameters;
|
||
}
|
||
return genericParameters;
|
||
}
|
||
|
||
NR_BWP_t *get_ul_bwp_genericParameters(NR_BWP_Uplink_t *active_ubwp,
|
||
NR_ServingCellConfigCommon_t *ServingCellConfigCommon,
|
||
const NR_SIB1_t *sib1) {
|
||
NR_BWP_t *genericParameters = NULL;
|
||
if (active_ubwp) {
|
||
genericParameters = &active_ubwp->bwp_Common->genericParameters;
|
||
} else if (ServingCellConfigCommon) {
|
||
genericParameters = &ServingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||
} else {
|
||
genericParameters = &sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.genericParameters;
|
||
}
|
||
return genericParameters;
|
||
}
|
||
|
||
NR_PDSCH_TimeDomainResourceAllocationList_t *get_pdsch_TimeDomainAllocationList(const NR_BWP_Downlink_t *active_bwp,
|
||
const NR_ServingCellConfigCommon_t *ServingCellConfigCommon,
|
||
const NR_SIB1_t *sib1) {
|
||
NR_PDSCH_TimeDomainResourceAllocationList_t *tdaList = NULL;
|
||
if (active_bwp) {
|
||
tdaList = active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||
} else if (ServingCellConfigCommon) {
|
||
tdaList = ServingCellConfigCommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||
} else {
|
||
tdaList = sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||
}
|
||
return tdaList;
|
||
}
|
||
|
||
|
||
NR_ControlResourceSet_t *get_coreset(module_id_t module_idP,
|
||
NR_ServingCellConfigCommon_t *scc,
|
||
void *bwp,
|
||
NR_SearchSpace_t *ss,
|
||
NR_SearchSpace__searchSpaceType_PR ss_type) {
|
||
NR_ControlResourceSetId_t coreset_id = *ss->controlResourceSetId;
|
||
|
||
if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { // common search space
|
||
NR_ControlResourceSet_t *coreset;
|
||
if(coreset_id == 0) {
|
||
coreset = RC.nrmac[module_idP]->sched_ctrlCommon->coreset; // this is coreset 0
|
||
} else if (bwp) {
|
||
coreset = ((NR_BWP_Downlink_t*)bwp)->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet;
|
||
} else if (scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet) {
|
||
coreset = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet;
|
||
} else {
|
||
coreset = NULL;
|
||
}
|
||
|
||
if (coreset) AssertFatal(coreset_id == coreset->controlResourceSetId,
|
||
"ID of common ss coreset does not correspond to id set in the "
|
||
"search space\n");
|
||
return coreset;
|
||
} else {
|
||
const int n = ((NR_BWP_DownlinkDedicated_t*)bwp)->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.count;
|
||
for (int i = 0; i < n; i++) {
|
||
NR_ControlResourceSet_t *coreset =
|
||
((NR_BWP_DownlinkDedicated_t*)bwp)->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[i];
|
||
if (coreset_id == coreset->controlResourceSetId) {
|
||
return coreset;
|
||
}
|
||
}
|
||
AssertFatal(0, "Couldn't find coreset with id %ld\n", coreset_id);
|
||
}
|
||
}
|
||
|
||
NR_SearchSpace_t *get_searchspace(const NR_SIB1_t *sib1,
|
||
NR_ServingCellConfigCommon_t *scc,
|
||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
|
||
NR_SearchSpace__searchSpaceType_PR target_ss) {
|
||
|
||
int n = 0;
|
||
if(bwp_Dedicated) {
|
||
n = bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;
|
||
} else if(scc) {
|
||
n = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.count;
|
||
} else {
|
||
n = sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.count;
|
||
}
|
||
|
||
for (int i=0;i<n;i++) {
|
||
NR_SearchSpace_t *ss = NULL;
|
||
if(bwp_Dedicated) {
|
||
ss = bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i];
|
||
} else if(scc) {
|
||
ss = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.array[i];
|
||
} else {
|
||
ss = sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.array[i];
|
||
}
|
||
AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n");
|
||
AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n");
|
||
if (ss->searchSpaceType->present == target_ss) {
|
||
return ss;
|
||
}
|
||
}
|
||
AssertFatal(0, "Couldn't find an adequate searchspace bwp_Dedicated %p\n",bwp_Dedicated);
|
||
}
|
||
|
||
NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac,
|
||
NR_SearchSpace_t *ss,
|
||
NR_ControlResourceSet_t *coreset,
|
||
NR_ServingCellConfigCommon_t *scc,
|
||
NR_BWP_t *bwp,
|
||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) {
|
||
|
||
int sps;
|
||
NR_sched_pdcch_t pdcch;
|
||
|
||
AssertFatal(*ss->controlResourceSetId == coreset->controlResourceSetId,
|
||
"coreset id in SS %ld does not correspond to the one in coreset %ld",
|
||
*ss->controlResourceSetId, coreset->controlResourceSetId);
|
||
|
||
if (bwp) { // This is not for SIB1
|
||
if(coreset->controlResourceSetId == 0){
|
||
pdcch.BWPSize = gNB_mac->cset0_bwp_size;
|
||
pdcch.BWPStart = gNB_mac->cset0_bwp_start;
|
||
}
|
||
else {
|
||
pdcch.BWPSize = NRRIV2BW(bwp->locationAndBandwidth, MAX_BWP_SIZE);
|
||
pdcch.BWPStart = NRRIV2PRBOFFSET(bwp->locationAndBandwidth, MAX_BWP_SIZE);
|
||
}
|
||
pdcch.SubcarrierSpacing = bwp->subcarrierSpacing;
|
||
pdcch.CyclicPrefix = (bwp->cyclicPrefix==NULL) ? 0 : *bwp->cyclicPrefix;
|
||
|
||
//AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored");
|
||
sps = bwp->cyclicPrefix == NULL ? 14 : 12;
|
||
}
|
||
else {
|
||
AssertFatal(type0_PDCCH_CSS_config!=NULL,"type0_PDCCH_CSS_config is null,bwp %p\n",bwp);
|
||
pdcch.BWPSize = type0_PDCCH_CSS_config->num_rbs;
|
||
pdcch.BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
|
||
pdcch.SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch;
|
||
pdcch.CyclicPrefix = 0;
|
||
sps = 14;
|
||
}
|
||
|
||
AssertFatal(ss->monitoringSymbolsWithinSlot!=NULL,"ss->monitoringSymbolsWithinSlot is null\n");
|
||
AssertFatal(ss->monitoringSymbolsWithinSlot->buf!=NULL,"ss->monitoringSymbolsWithinSlot->buf is null\n");
|
||
|
||
// for SPS=14 8 MSBs in positions 13 downto 6
|
||
uint16_t monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) |
|
||
(ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
||
|
||
for (int i=0; i<sps; i++) {
|
||
if ((monitoringSymbolsWithinSlot>>(sps-1-i))&1) {
|
||
pdcch.StartSymbolIndex=i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
pdcch.DurationSymbols = coreset->duration;
|
||
|
||
//cce-REG-MappingType
|
||
pdcch.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved?
|
||
NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED : NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED;
|
||
|
||
if (pdcch.CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) {
|
||
pdcch.RegBundleSize = (coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize ==
|
||
NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize);
|
||
pdcch.InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize ==
|
||
NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize);
|
||
AssertFatal(scc->physCellId != NULL,"scc->physCellId is null\n");
|
||
pdcch.ShiftIndex = coreset->cce_REG_MappingType.choice.interleaved->shiftIndex != NULL ? *coreset->cce_REG_MappingType.choice.interleaved->shiftIndex : *scc->physCellId;
|
||
}
|
||
else {
|
||
pdcch.RegBundleSize = 6;
|
||
pdcch.InterleaverSize = 0;
|
||
pdcch.ShiftIndex = 0;
|
||
}
|
||
|
||
int N_rb = 0; // nb of rbs of coreset per symbol
|
||
for (int i=0;i<6;i++) {
|
||
for (int t=0;t<8;t++) {
|
||
N_rb+=((coreset->frequencyDomainResources.buf[i]>>t)&1);
|
||
}
|
||
}
|
||
pdcch.n_rb = N_rb*=6; // each bit of frequencyDomainResources represents 6 PRBs
|
||
|
||
return pdcch;
|
||
}
|
||
|
||
|
||
int find_pdcch_candidate(gNB_MAC_INST *mac,
|
||
int cc_id,
|
||
int aggregation,
|
||
int nr_of_candidates,
|
||
NR_sched_pdcch_t *pdcch,
|
||
NR_ControlResourceSet_t *coreset,
|
||
uint16_t Y){
|
||
|
||
uint16_t *vrb_map = mac->common_channels[cc_id].vrb_map;
|
||
const int N_ci = 0;
|
||
|
||
const int N_rb = pdcch->n_rb; // nb of rbs of coreset per symbol
|
||
const int N_symb = coreset->duration; // nb of coreset symbols
|
||
const int N_regs = N_rb*N_symb; // nb of REGs per coreset
|
||
const int N_cces = N_regs / NR_NB_REG_PER_CCE; // nb of cces in coreset
|
||
const int R = pdcch->InterleaverSize;
|
||
const int L = pdcch->RegBundleSize;
|
||
const int C = R>0 ? N_regs/(L*R) : 0;
|
||
const int B_rb = L/N_symb; // nb of RBs occupied by each REG bundle
|
||
|
||
// loop over all the available candidates
|
||
// this implements TS 38.211 Sec. 7.3.2.2
|
||
for(int m=0; m<nr_of_candidates; m++) { // loop over candidates
|
||
bool taken = false; // flag if the resource for a given candidate are taken
|
||
int first_cce = aggregation * (( Y + CEILIDIV((m*N_cces),(aggregation*nr_of_candidates)) + N_ci ) % CEILIDIV(N_cces,aggregation));
|
||
LOG_D(NR_MAC,"Candidate %d of %d first_cce %d (L %d N_cces %d Y %d)\n", m, nr_of_candidates, first_cce, aggregation, N_cces, Y);
|
||
for (int j=first_cce; (j<first_cce+aggregation) && !taken; j++) { // loop over CCEs
|
||
for (int k=6*j/L; (k<(6*j/L+6/L)) && !taken; k++) { // loop over REG bundles
|
||
int f = cce_to_reg_interleaving(R, k, pdcch->ShiftIndex, C, L, N_regs);
|
||
for(int rb=0; rb<B_rb; rb++) { // loop over the RBs of the bundle
|
||
if(vrb_map[pdcch->BWPStart + f*B_rb + rb]&SL_to_bitmap(pdcch->StartSymbolIndex,N_symb)) {
|
||
taken = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if(!taken)
|
||
return first_cce;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
void fill_pdcch_vrb_map(gNB_MAC_INST *mac,
|
||
int CC_id,
|
||
NR_sched_pdcch_t *pdcch,
|
||
int first_cce,
|
||
int aggregation){
|
||
|
||
uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map;
|
||
|
||
int N_rb = pdcch->n_rb; // nb of rbs of coreset per symbol
|
||
int L = pdcch->RegBundleSize;
|
||
int R = pdcch->InterleaverSize;
|
||
int n_shift = pdcch->ShiftIndex;
|
||
int N_symb = pdcch->DurationSymbols;
|
||
int N_regs = N_rb*N_symb; // nb of REGs per coreset
|
||
int B_rb = L/N_symb; // nb of RBs occupied by each REG bundle
|
||
int C = R>0 ? N_regs/(L*R) : 0;
|
||
|
||
for (int j=first_cce; j<first_cce+aggregation; j++) { // loop over CCEs
|
||
for (int k=6*j/L; k<(6*j/L+6/L); k++) { // loop over REG bundles
|
||
int f = cce_to_reg_interleaving(R, k, n_shift, C, L, N_regs);
|
||
for(int rb=0; rb<B_rb; rb++) // loop over the RBs of the bundle
|
||
vrb_map[pdcch->BWPStart + f*B_rb + rb] |= SL_to_bitmap(pdcch->StartSymbolIndex, N_symb);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
bool nr_find_nb_rb(uint16_t Qm,
|
||
uint16_t R,
|
||
uint8_t nrOfLayers,
|
||
uint16_t nb_symb_sch,
|
||
uint16_t nb_dmrs_prb,
|
||
uint32_t bytes,
|
||
uint16_t nb_rb_min,
|
||
uint16_t nb_rb_max,
|
||
uint32_t *tbs,
|
||
uint16_t *nb_rb)
|
||
{
|
||
/* is the maximum (not even) enough? */
|
||
*nb_rb = nb_rb_max;
|
||
*tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, nrOfLayers) >> 3;
|
||
/* check whether it does not fit, or whether it exactly fits. Some algorithms
|
||
* might depend on the return value! */
|
||
if (bytes > *tbs)
|
||
return false;
|
||
if (bytes == *tbs)
|
||
return true;
|
||
|
||
/* is the minimum enough? */
|
||
*nb_rb = nb_rb_min;
|
||
*tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, nrOfLayers) >> 3;
|
||
if (bytes <= *tbs)
|
||
return true;
|
||
|
||
/* perform binary search to allocate all bytes within a TBS up to nb_rb_max
|
||
* RBs */
|
||
int hi = nb_rb_max;
|
||
int lo = nb_rb_min;
|
||
for (int p = (hi + lo) / 2; lo + 1 < hi; p = (hi + lo) / 2) {
|
||
const uint32_t TBS = nr_compute_tbs(Qm, R, p, nb_symb_sch, nb_dmrs_prb, 0, 0, nrOfLayers) >> 3;
|
||
if (bytes == TBS) {
|
||
hi = p;
|
||
break;
|
||
} else if (bytes < TBS) {
|
||
hi = p;
|
||
} else {
|
||
lo = p;
|
||
}
|
||
}
|
||
*nb_rb = hi;
|
||
*tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, nrOfLayers) >> 3;
|
||
/* return whether we could allocate all bytes and stay below nb_rb_max */
|
||
return *tbs >= bytes && *nb_rb <= nb_rb_max;
|
||
}
|
||
|
||
void nr_set_pdsch_semi_static(const NR_SIB1_t *sib1,
|
||
const NR_ServingCellConfigCommon_t *scc,
|
||
const NR_CellGroupConfig_t *secondaryCellGroup,
|
||
const NR_BWP_Downlink_t *bwp,
|
||
const NR_BWP_DownlinkDedicated_t *bwpd0,
|
||
int tda,
|
||
uint8_t layers,
|
||
NR_UE_sched_ctrl_t *sched_ctrl,
|
||
NR_pdsch_semi_static_t *ps)
|
||
{
|
||
bool reset_dmrs = false;
|
||
|
||
NR_BWP_DownlinkDedicated_t *bwpd;
|
||
|
||
if (bwp && bwp->bwp_Dedicated) {
|
||
bwpd = bwp->bwp_Dedicated;
|
||
} else {
|
||
bwpd = (NR_BWP_DownlinkDedicated_t*)bwpd0;
|
||
}
|
||
|
||
if (bwpd &&
|
||
bwpd->pdsch_Config &&
|
||
bwpd->pdsch_Config->choice.setup &&
|
||
bwpd->pdsch_Config->choice.setup->mcs_Table) {
|
||
if (*bwpd->pdsch_Config->choice.setup->mcs_Table == 0)
|
||
ps->mcsTableIdx = 1;
|
||
else
|
||
ps->mcsTableIdx = 2;
|
||
}
|
||
else ps->mcsTableIdx = 0;
|
||
LOG_D(NR_MAC,"MCS Table Index: %d\n",ps->mcsTableIdx);
|
||
|
||
NR_PDSCH_Config_t *pdsch_Config;
|
||
if (bwp &&
|
||
bwp->bwp_Dedicated &&
|
||
bwp->bwp_Dedicated->pdsch_Config &&
|
||
bwp->bwp_Dedicated->pdsch_Config->choice.setup)
|
||
pdsch_Config = bwp->bwp_Dedicated->pdsch_Config->choice.setup;
|
||
else
|
||
pdsch_Config = NULL;
|
||
|
||
if (ps->time_domain_allocation != tda) {
|
||
reset_dmrs = true;
|
||
ps->time_domain_allocation = tda;
|
||
NR_PDSCH_TimeDomainResourceAllocationList_t *tdaList = get_pdsch_TimeDomainAllocationList(bwp, scc, sib1);
|
||
AssertFatal(tda < tdaList->list.count, "time_domain_allocation %d>=%d\n", tda, tdaList->list.count);
|
||
ps->mapping_type = tdaList->list.array[tda]->mappingType;
|
||
if (pdsch_Config) {
|
||
if (ps->mapping_type == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB)
|
||
ps->dmrsConfigType = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type == NULL ? 0 : 1;
|
||
else
|
||
ps->dmrsConfigType = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
|
||
}
|
||
else
|
||
ps->dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
|
||
const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
|
||
SLIV2SL(startSymbolAndLength, &ps->startSymbolIndex, &ps->nrOfSymbols);
|
||
}
|
||
|
||
const long f = ((bwp || bwpd) &&
|
||
sched_ctrl->search_space &&
|
||
sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) ?
|
||
sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats : 0;
|
||
|
||
int dci_format;
|
||
if (sched_ctrl->search_space) {
|
||
dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0;
|
||
}
|
||
else {
|
||
dci_format = NR_DL_DCI_FORMAT_1_0;
|
||
}
|
||
if (dci_format == NR_DL_DCI_FORMAT_1_0) {
|
||
if (ps->nrOfSymbols == 2)
|
||
ps->numDmrsCdmGrpsNoData = 1;
|
||
else
|
||
ps->numDmrsCdmGrpsNoData = 2;
|
||
ps->dmrs_ports_id = 0;
|
||
ps->frontloaded_symb = 1;
|
||
ps->nrOfLayers = 1;
|
||
}
|
||
else {
|
||
if (ps->nrOfLayers != layers ||
|
||
ps->numDmrsCdmGrpsNoData == 0) {
|
||
reset_dmrs = true;
|
||
ps->nrOfLayers = layers;
|
||
set_dl_dmrs_ports(ps);
|
||
}
|
||
}
|
||
|
||
ps->N_PRB_DMRS = ps->numDmrsCdmGrpsNoData * (ps->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4);
|
||
|
||
if (reset_dmrs) {
|
||
ps->dl_dmrs_symb_pos = fill_dmrs_mask(bwpd ? bwpd->pdsch_Config->choice.setup : NULL, scc ? scc->dmrs_TypeA_Position : 0, ps->nrOfSymbols, ps->startSymbolIndex, ps->mapping_type, ps->frontloaded_symb);
|
||
ps->N_DMRS_SLOT = get_num_dmrs(ps->dl_dmrs_symb_pos);
|
||
}
|
||
LOG_D(NR_MAC,"bwpd0 %p, bwpd %p : Filling dmrs info, ps->N_PRB_DMRS %d, ps->dl_dmrs_symb_pos %x, ps->N_DMRS_SLOT %d\n",bwpd0,bwpd,ps->N_PRB_DMRS,ps->dl_dmrs_symb_pos,ps->N_DMRS_SLOT);
|
||
}
|
||
|
||
void nr_set_pusch_semi_static(const NR_SIB1_t *sib1,
|
||
const NR_ServingCellConfigCommon_t *scc,
|
||
const NR_BWP_Uplink_t *ubwp,
|
||
const NR_BWP_UplinkDedicated_t *ubwpd,
|
||
long dci_format,
|
||
int tda,
|
||
uint8_t num_dmrs_cdm_grps_no_data,
|
||
NR_pusch_semi_static_t *ps) {
|
||
ps->dci_format = dci_format;
|
||
ps->time_domain_allocation = tda;
|
||
|
||
NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = NULL;
|
||
if(ubwp) {
|
||
tdaList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
|
||
} else if(scc) {
|
||
tdaList = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
|
||
} else {
|
||
tdaList = sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
|
||
}
|
||
|
||
const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
|
||
SLIV2SL(startSymbolAndLength,
|
||
&ps->startSymbolIndex,
|
||
&ps->nrOfSymbols);
|
||
|
||
ps->pusch_Config = ubwp && ubwp->bwp_Dedicated && ubwp->bwp_Dedicated->pusch_Config ?
|
||
ubwp->bwp_Dedicated->pusch_Config->choice.setup : (ubwpd ? ubwpd->pusch_Config->choice.setup : NULL);
|
||
if (ps->pusch_Config == NULL || !ps->pusch_Config->transformPrecoder)
|
||
ps->transform_precoding = !scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder;
|
||
else
|
||
ps->transform_precoding = *ps->pusch_Config->transformPrecoder;
|
||
const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
|
||
if (ps->transform_precoding)
|
||
ps->mcs_table = get_pusch_mcs_table(ps->pusch_Config ? ps->pusch_Config->mcs_Table : NULL,
|
||
0,
|
||
ps->dci_format,
|
||
NR_RNTI_C,
|
||
target_ss,
|
||
false);
|
||
else {
|
||
ps->mcs_table = get_pusch_mcs_table(ps->pusch_Config ? ps->pusch_Config->mcs_TableTransformPrecoder : NULL,
|
||
1,
|
||
ps->dci_format,
|
||
NR_RNTI_C,
|
||
target_ss,
|
||
false);
|
||
num_dmrs_cdm_grps_no_data = 2; // in case of transform precoding - no Data sent in DMRS symbol
|
||
}
|
||
|
||
ps->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
|
||
|
||
/* DMRS calculations */
|
||
ps->mapping_type = tdaList->list.array[tda]->mappingType;
|
||
ps->NR_DMRS_UplinkConfig = ps->pusch_Config ?
|
||
(ps->mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA ?
|
||
ps->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup :
|
||
ps->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup) : NULL;
|
||
ps->dmrs_config_type = ps->NR_DMRS_UplinkConfig ? ((ps->NR_DMRS_UplinkConfig->dmrs_Type == NULL ? 0 : 1)) : 0;
|
||
const pusch_dmrs_AdditionalPosition_t additional_pos =
|
||
ps->NR_DMRS_UplinkConfig ? (ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL
|
||
? 2
|
||
: (*ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition ==
|
||
NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3
|
||
? 3
|
||
: *ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)):2;
|
||
const pusch_maxLength_t pusch_maxLength =
|
||
ps->NR_DMRS_UplinkConfig ? (ps->NR_DMRS_UplinkConfig->maxLength == NULL ? 1 : 2) : 1;
|
||
ps->ul_dmrs_symb_pos = get_l_prime(ps->nrOfSymbols,
|
||
ps->mapping_type,
|
||
additional_pos,
|
||
pusch_maxLength,
|
||
ps->startSymbolIndex,
|
||
scc->dmrs_TypeA_Position);
|
||
uint8_t num_dmrs_symb = 0;
|
||
for(int i = ps->startSymbolIndex; i < ps->startSymbolIndex + ps->nrOfSymbols; i++)
|
||
num_dmrs_symb += (ps->ul_dmrs_symb_pos >> i) & 1;
|
||
ps->num_dmrs_symb = num_dmrs_symb;
|
||
ps->N_PRB_DMRS = ps->dmrs_config_type == 0
|
||
? num_dmrs_cdm_grps_no_data * 6
|
||
: num_dmrs_cdm_grps_no_data * 4;
|
||
}
|
||
|
||
void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
|
||
nr_scs_e scs_common,
|
||
nr_scs_e pdcch_scs,
|
||
nr_frequency_range_e freq_range,
|
||
uint8_t rmsi_pdcch_config,
|
||
uint8_t ssb_idx,
|
||
uint8_t k_ssb,
|
||
uint16_t sfn_ssb,
|
||
uint8_t n_ssb, /*slot index overlapping the corresponding SSB index*/
|
||
uint16_t nb_slots_per_frame,
|
||
uint16_t N_RB)
|
||
{
|
||
// uint8_t O, M;
|
||
// uint8_t ss_idx = rmsi_pdcch_config&0xf;
|
||
// uint8_t cset_idx = (rmsi_pdcch_config>>4)&0xf;
|
||
// uint8_t mu = scs_common;
|
||
// uint8_t O_scale=0, M_scale=0; // used to decide if the values of O and M need to be divided by 2
|
||
|
||
AssertFatal(1==0,"todo\n");
|
||
/*
|
||
/// Coreset params
|
||
switch(scs_common) {
|
||
|
||
case kHz15:
|
||
|
||
switch(pdcch_scs) {
|
||
case kHz15:
|
||
AssertFatal(cset_idx<15,"Coreset index %d reserved for scs kHz15/kHz15\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = (cset_idx < 6)? 24 : (cset_idx < 12)? 48 : 96;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_15[cset_idx];
|
||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx];
|
||
break;
|
||
|
||
case kHz30:
|
||
AssertFatal(cset_idx<14,"Coreset index %d reserved for scs kHz15/kHz30\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = (cset_idx < 8)? 24 : 48;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_30[cset_idx];
|
||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx];
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||
|
||
}
|
||
break;
|
||
|
||
case kHz30:
|
||
|
||
if (N_RB < 106) { // Minimum 40Mhz bandwidth not satisfied
|
||
switch(pdcch_scs) {
|
||
case kHz15:
|
||
AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = (cset_idx < 10)? 48 : 96;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[cset_idx];
|
||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[cset_idx];
|
||
break;
|
||
|
||
case kHz30:
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = (cset_idx < 6)? 24 : 48;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[cset_idx];
|
||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[cset_idx];
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||
}
|
||
}
|
||
|
||
else { // above 40Mhz
|
||
switch(pdcch_scs) {
|
||
case kHz15:
|
||
AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = (cset_idx < 3)? 48 : 96;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[cset_idx];
|
||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[cset_idx];
|
||
break;
|
||
|
||
case kHz30:
|
||
AssertFatal(cset_idx<10,"Coreset index %d reserved for scs kHz30/kHz30\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = (cset_idx < 4)? 24 : 48;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[cset_idx];
|
||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[cset_idx];
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case kHz120:
|
||
switch(pdcch_scs) {
|
||
case kHz60:
|
||
AssertFatal(cset_idx<12,"Coreset index %d reserved for scs kHz120/kHz60\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = (cset_idx < 8)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2;
|
||
pdcch_pdu->n_rb = (cset_idx < 6)? 48 : (cset_idx < 8)? 96 : (cset_idx < 10)? 48 : 96;
|
||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_120_60[cset_idx];
|
||
pdcch_pdu->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx]>0)?nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx] :
|
||
(k_ssb == 0)? -41 : -42;
|
||
break;
|
||
|
||
case kHz120:
|
||
AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz120/kHz120\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = (cset_idx < 4)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3;
|
||
pdcch_pdu->n_rb = (cset_idx < 2)? 24 : (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48;
|
||
pdcch_pdu->n_symb = (cset_idx == 2)? 1 : 2;
|
||
pdcch_pdu->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx] :
|
||
(k_ssb == 0)? -20 : -21;
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||
}
|
||
break;
|
||
|
||
case kHz240:
|
||
switch(pdcch_scs) {
|
||
case kHz60:
|
||
AssertFatal(cset_idx<4,"Coreset index %d reserved for scs kHz240/kHz60\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||
pdcch_pdu->n_rb = 96;
|
||
pdcch_pdu->n_symb = (cset_idx < 2)? 1 : 2;
|
||
pdcch_pdu->rb_offset = (cset_idx&1)? 16 : 0;
|
||
break;
|
||
|
||
case kHz120:
|
||
AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz240/kHz120\n", cset_idx);
|
||
pdcch_pdu->mux_pattern = (cset_idx < 4)? NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2;
|
||
pdcch_pdu->n_rb = (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48;
|
||
pdcch_pdu->n_symb = ((cset_idx==2)||(cset_idx==3))? 2 : 1;
|
||
pdcch_pdu->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx] :
|
||
(k_ssb == 0)? -41 : -42;
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0,"Invalid common subcarrier spacing %d\n", scs_common);
|
||
|
||
}
|
||
|
||
/// Search space params
|
||
switch(pdcch_pdu->mux_pattern) {
|
||
|
||
case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1:
|
||
if (freq_range == nr_FR1) {
|
||
O = nr_ss_param_O_type_0_mux1_FR1[ss_idx];
|
||
pdcch_pdu->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR1[ss_idx];
|
||
M = nr_ss_param_M_type_0_mux1_FR1[ss_idx];
|
||
M_scale = nr_ss_scale_M_mux1_FR1[ss_idx];
|
||
pdcch_pdu->first_symbol = (ss_idx < 8)? ( (ssb_idx&1)? pdcch_pdu->n_symb : 0 ) : nr_ss_first_symb_idx_type_0_mux1_FR1[ss_idx - 8];
|
||
}
|
||
|
||
else {
|
||
AssertFatal(ss_idx<14 ,"Invalid search space index for multiplexing type 1 and FR2 %d\n", ss_idx);
|
||
O = nr_ss_param_O_type_0_mux1_FR2[ss_idx];
|
||
O_scale = nr_ss_scale_O_mux1_FR2[ss_idx];
|
||
pdcch_pdu->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR2[ss_idx];
|
||
M = nr_ss_param_M_type_0_mux1_FR2[ss_idx];
|
||
M_scale = nr_ss_scale_M_mux1_FR2[ss_idx];
|
||
pdcch_pdu->first_symbol = (ss_idx < 12)? ( (ss_idx&1)? 7 : 0 ) : 0;
|
||
}
|
||
pdcch_pdu->nb_slots = 2;
|
||
pdcch_pdu->sfn_mod2 = (CEILIDIV( (((O<<mu)>>O_scale) + ((ssb_idx*M)>>M_scale)), nb_slots_per_frame ) & 1)? 1 : 0;
|
||
pdcch_pdu->first_slot = (((O<<mu)>>O_scale) + ((ssb_idx*M)>>M_scale)) % nb_slots_per_frame;
|
||
|
||
break;
|
||
|
||
case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2:
|
||
AssertFatal( ((scs_common==kHz120)&&(pdcch_scs==kHz60)) || ((scs_common==kHz240)&&(pdcch_scs==kHz120)),
|
||
"Invalid scs_common/pdcch_scs combination %d/%d for Mux type 2\n", scs_common, pdcch_scs );
|
||
AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs);
|
||
|
||
pdcch_pdu->nb_slots = 1;
|
||
|
||
if ((scs_common==kHz120)&&(pdcch_scs==kHz60)) {
|
||
pdcch_pdu->first_symbol = nr_ss_first_symb_idx_scs_120_60_mux2[ssb_idx&3];
|
||
// Missing in pdcch_pdu sfn_C and n_C here and in else case
|
||
}
|
||
else {
|
||
pdcch_pdu->first_symbol = ((ssb_idx&7)==4)?12 : ((ssb_idx&7)==4)?13 : nr_ss_first_symb_idx_scs_240_120_set1_mux2[ssb_idx&7]; //???
|
||
}
|
||
|
||
break;
|
||
|
||
case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3:
|
||
AssertFatal( (scs_common==kHz120)&&(pdcch_scs==kHz120),
|
||
"Invalid scs_common/pdcch_scs combination %d/%d for Mux type 3\n", scs_common, pdcch_scs );
|
||
AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs);
|
||
|
||
pdcch_pdu->first_symbol = nr_ss_first_symb_idx_scs_120_120_mux3[ssb_idx&3];
|
||
|
||
break;
|
||
|
||
default:
|
||
AssertFatal(1==0, "Invalid SSB and coreset multiplexing pattern %d\n", pdcch_pdu->mux_pattern);
|
||
}
|
||
pdcch_pdu->config_type = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
||
pdcch_pdu->cr_mapping_type = NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED;
|
||
pdcch_pdu->precoder_granularity = NFAPI_NR_CSET_SAME_AS_REG_BUNDLE;
|
||
pdcch_pdu->reg_bundle_size = 6;
|
||
pdcch_pdu->interleaver_size = 2;
|
||
// set initial banwidth part to full bandwidth
|
||
pdcch_pdu->n_RB_BWP = N_RB;
|
||
|
||
*/
|
||
|
||
}
|
||
|
||
void config_uldci(const NR_SIB1_t *sib1,
|
||
const NR_BWP_Uplink_t *ubwp,
|
||
const NR_BWP_UplinkDedicated_t *ubwpd,
|
||
const NR_ServingCellConfigCommon_t *scc,
|
||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||
int dci_format,
|
||
int time_domain_assignment,
|
||
uint8_t tpc,
|
||
int n_ubwp,
|
||
int bwp_id) {
|
||
|
||
NR_BWP_t *genericParameters = get_ul_bwp_genericParameters((NR_BWP_Uplink_t *)ubwp,
|
||
(NR_ServingCellConfigCommon_t *)scc,
|
||
(NR_SIB1_t *)sib1);
|
||
|
||
const int bw = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||
|
||
dci_pdu_rel15->frequency_domain_assignment.val =
|
||
PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw);
|
||
dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment;
|
||
dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping;
|
||
dci_pdu_rel15->mcs = pusch_pdu->mcs_index;
|
||
dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator;
|
||
dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index;
|
||
dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id;
|
||
dci_pdu_rel15->tpc = tpc;
|
||
const NR_BWP_UplinkDedicated_t *ubwpd2 = (ubwp) ? ubwp->bwp_Dedicated : ubwpd;
|
||
|
||
if (ubwpd2) AssertFatal(ubwpd2->pusch_Config->choice.setup->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1,
|
||
"Only frequency resource allocation type 1 is currently supported\n");
|
||
switch (dci_format) {
|
||
case NR_UL_DCI_FORMAT_0_0:
|
||
dci_pdu_rel15->format_indicator = 0;
|
||
break;
|
||
case NR_UL_DCI_FORMAT_0_1:
|
||
LOG_D(NR_MAC,"Configuring DCI Format 0_1\n");
|
||
dci_pdu_rel15->dai[0].val = 0; //TODO
|
||
// bwp indicator as per table 7.3.1.1.2-1 in 38.212
|
||
dci_pdu_rel15->bwp_indicator.val = n_ubwp < 4 ? bwp_id : bwp_id - 1;
|
||
// SRS resource indicator
|
||
if (ubwpd2 &&
|
||
ubwpd2->pusch_Config &&
|
||
ubwpd2->pusch_Config->choice.setup &&
|
||
ubwpd2->pusch_Config->choice.setup->txConfig != NULL) {
|
||
AssertFatal(*ubwpd2->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook,
|
||
"Non Codebook configuration non supported\n");
|
||
dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS
|
||
}
|
||
// Antenna Ports
|
||
dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank
|
||
// DMRS sequence initialization
|
||
dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid;
|
||
break;
|
||
default :
|
||
AssertFatal(0, "Valid UL formats are 0_0 and 0_1\n");
|
||
}
|
||
|
||
LOG_D(NR_MAC,
|
||
"%s() ULDCI type 0 payload: freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n",
|
||
__func__,
|
||
dci_pdu_rel15->frequency_domain_assignment.val,
|
||
dci_pdu_rel15->time_domain_assignment.val,
|
||
dci_pdu_rel15->frequency_hopping_flag.val,
|
||
dci_pdu_rel15->mcs,
|
||
dci_pdu_rel15->tpc,
|
||
dci_pdu_rel15->ndi,
|
||
dci_pdu_rel15->rv);
|
||
}
|
||
|
||
const int default_pucch_fmt[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1};
|
||
const int default_pucch_firstsymb[] = {12,12,12,10,10,10,10,4,4,4,4,0,0,0,0,0};
|
||
const int default_pucch_numbsymb[] = {2,2,2,2,4,4,4,4,10,10,10,10,14,14,14,14,14};
|
||
const int default_pucch_prboffset[] = {0,0,3,0,0,2,4,0,0,2,4,0,0,2,4,-1};
|
||
const int default_pucch_csset[] = {2,3,3,2,4,4,4,2,4,4,4,2,4,4,4,4};
|
||
|
||
int nr_get_default_pucch_res(int pucch_ResourceCommon) {
|
||
|
||
AssertFatal(pucch_ResourceCommon>=0 && pucch_ResourceCommon < 16, "illegal pucch_ResourceCommon %d\n",pucch_ResourceCommon);
|
||
|
||
return(default_pucch_csset[pucch_ResourceCommon]);
|
||
}
|
||
|
||
|
||
|
||
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||
NR_ControlResourceSet_t *coreset,
|
||
NR_BWP_t *bwp,
|
||
NR_sched_pdcch_t *pdcch) {
|
||
|
||
|
||
pdcch_pdu->BWPSize = pdcch->BWPSize;
|
||
pdcch_pdu->BWPStart = pdcch->BWPStart;
|
||
pdcch_pdu->SubcarrierSpacing = pdcch->SubcarrierSpacing;
|
||
pdcch_pdu->CyclicPrefix = pdcch->CyclicPrefix;
|
||
pdcch_pdu->StartSymbolIndex = pdcch->StartSymbolIndex;
|
||
|
||
pdcch_pdu->DurationSymbols = coreset->duration;
|
||
|
||
for (int i=0;i<6;i++)
|
||
pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i];
|
||
|
||
LOG_D(MAC,"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %d\n",
|
||
pdcch_pdu->BWPStart,pdcch_pdu->BWPSize,(int)pdcch_pdu->SubcarrierSpacing,(int)coreset->frequencyDomainResources.buf[0],(int)coreset->duration);
|
||
|
||
pdcch_pdu->CceRegMappingType = pdcch->CceRegMappingType;
|
||
pdcch_pdu->RegBundleSize = pdcch->RegBundleSize;
|
||
pdcch_pdu->InterleaverSize = pdcch->InterleaverSize;
|
||
pdcch_pdu->ShiftIndex = pdcch->ShiftIndex;
|
||
|
||
if(coreset->controlResourceSetId == 0) {
|
||
if(bwp == NULL)
|
||
pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
||
else
|
||
pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0;
|
||
} else{
|
||
pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
|
||
}
|
||
|
||
//precoderGranularity
|
||
pdcch_pdu->precoderGranularity = coreset->precoderGranularity;
|
||
}
|
||
|
||
int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset,
|
||
NR_BWP_Uplink_t *bwp,
|
||
NR_BWP_UplinkDedicated_t *bwpd,
|
||
int CCEIndex) {
|
||
int r_pucch = -1;
|
||
if(bwp == NULL && bwpd == NULL) {
|
||
int n_rb,rb_offset;
|
||
get_coreset_rballoc(coreset->frequencyDomainResources.buf,&n_rb,&rb_offset);
|
||
const uint16_t N_cce = n_rb * coreset->duration / NR_NB_REG_PER_CCE;
|
||
const int delta_PRI=0;
|
||
r_pucch = ((CCEIndex<<1)/N_cce)+(delta_PRI<<1);
|
||
}
|
||
return r_pucch;
|
||
}
|
||
|
||
// This function configures pucch pdu fapi structure
|
||
void nr_configure_pucch(const NR_SIB1_t *sib1,
|
||
nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||
NR_ServingCellConfigCommon_t *scc,
|
||
NR_CellGroupConfig_t *CellGroup,
|
||
NR_BWP_Uplink_t *bwp,
|
||
NR_BWP_UplinkDedicated_t *bwpd,
|
||
uint16_t rnti,
|
||
uint8_t pucch_resource,
|
||
uint16_t O_csi,
|
||
uint16_t O_ack,
|
||
uint8_t O_sr,
|
||
int r_pucch) {
|
||
|
||
NR_PUCCH_Config_t *pucch_Config;
|
||
NR_PUCCH_Resource_t *pucchres;
|
||
NR_PUCCH_ResourceSet_t *pucchresset;
|
||
NR_PUCCH_FormatConfig_t *pucchfmt;
|
||
NR_PUCCH_ResourceId_t *resource_id = NULL;
|
||
|
||
long *id0 = NULL;
|
||
int n_list, n_set;
|
||
uint16_t N2,N3;
|
||
int res_found = 0;
|
||
|
||
pucch_pdu->bit_len_harq = O_ack;
|
||
pucch_pdu->bit_len_csi_part1 = O_csi;
|
||
|
||
uint16_t O_uci = O_csi + O_ack;
|
||
|
||
NR_PUSCH_Config_t *pusch_Config = NULL;
|
||
if(bwp && bwp->bwp_Dedicated && bwp->bwp_Dedicated->pusch_Config) {
|
||
pusch_Config = bwp->bwp_Dedicated->pusch_Config->choice.setup;
|
||
} else if(bwpd && bwpd->pusch_Config) {
|
||
pusch_Config = bwpd->pusch_Config->choice.setup;
|
||
}
|
||
|
||
long *pusch_id = pusch_Config ? pusch_Config->dataScramblingIdentityPUSCH : NULL;
|
||
|
||
if (pusch_Config && pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL)
|
||
id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0;
|
||
else if (pusch_Config && pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL)
|
||
id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0;
|
||
else id0 = scc->physCellId;
|
||
|
||
NR_PUCCH_ConfigCommon_t *pucch_ConfigCommon = NULL;
|
||
if(bwp) {
|
||
pucch_ConfigCommon = bwp->bwp_Common->pucch_ConfigCommon->choice.setup;
|
||
} else if(scc) {
|
||
pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup;
|
||
} else {
|
||
pucch_ConfigCommon = sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup;
|
||
}
|
||
|
||
// hop flags and hopping id are valid for any BWP
|
||
switch (pucch_ConfigCommon->pucch_GroupHopping){
|
||
case 0 :
|
||
// if neither, both disabled
|
||
pucch_pdu->group_hop_flag = 0;
|
||
pucch_pdu->sequence_hop_flag = 0;
|
||
break;
|
||
case 1 :
|
||
// if enable, group enabled
|
||
pucch_pdu->group_hop_flag = 1;
|
||
pucch_pdu->sequence_hop_flag = 0;
|
||
break;
|
||
case 2 :
|
||
// if disable, sequence disabled
|
||
pucch_pdu->group_hop_flag = 0;
|
||
pucch_pdu->sequence_hop_flag = 1;
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Group hopping flag %ld undefined (0,1,2) \n", pucch_ConfigCommon->pucch_GroupHopping);
|
||
}
|
||
|
||
if (pucch_ConfigCommon->hoppingId != NULL)
|
||
pucch_pdu->hopping_id = *pucch_ConfigCommon->hoppingId;
|
||
else
|
||
pucch_pdu->hopping_id = *scc->physCellId;
|
||
|
||
NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(bwp,scc, sib1);
|
||
|
||
pucch_pdu->bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||
pucch_pdu->bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE);
|
||
pucch_pdu->subcarrier_spacing = genericParameters->subcarrierSpacing;
|
||
pucch_pdu->cyclic_prefix = (genericParameters->cyclicPrefix==NULL) ? 0 : *genericParameters->cyclicPrefix;
|
||
if (r_pucch<0 || bwp ){
|
||
LOG_D(NR_MAC,"pucch_acknak: Filling dedicated configuration for PUCCH\n");
|
||
// we have either a dedicated BWP or Dedicated PUCCH configuration on InitialBWP
|
||
AssertFatal(bwp!=NULL || bwpd!=NULL,"We need one dedicated configuration for a BWP (neither additional or initial BWP has a dedicated configuration)\n");
|
||
pucch_Config = bwp && bwp->bwp_Dedicated && bwp->bwp_Dedicated->pucch_Config ?
|
||
bwp->bwp_Dedicated->pucch_Config->choice.setup : bwpd->pucch_Config->choice.setup;
|
||
|
||
AssertFatal(pucch_Config->resourceSetToAddModList!=NULL,
|
||
"PUCCH resourceSetToAddModList is null\n");
|
||
|
||
n_set = pucch_Config->resourceSetToAddModList->list.count;
|
||
AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n");
|
||
|
||
LOG_D(NR_MAC, "UCI n_set= %d\n", n_set);
|
||
|
||
N2 = 2;
|
||
// procedure to select pucch resource id from resource sets according to
|
||
// number of uci bits and pucch resource indicator pucch_resource
|
||
// ( see table 9.2.3.2 in 38.213)
|
||
for (int i=0; i<n_set; i++) {
|
||
pucchresset = pucch_Config->resourceSetToAddModList->list.array[i];
|
||
n_list = pucchresset->resourceList.list.count;
|
||
if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) {
|
||
if (pucch_resource < n_list)
|
||
resource_id = pucchresset->resourceList.list.array[pucch_resource];
|
||
else
|
||
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
|
||
}
|
||
if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) {
|
||
#if (NR_RRC_VERSION >= MAKE_VERSION(16, 0, 0))
|
||
N3 = pucchresset->maxPayloadSize!= NULL ? *pucchresset->maxPayloadSize : 1706;
|
||
#else
|
||
N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706;
|
||
#endif
|
||
if (N2<O_uci && N3>O_uci) {
|
||
if (pucch_resource < n_list)
|
||
resource_id = pucchresset->resourceList.list.array[pucch_resource];
|
||
else
|
||
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
|
||
}
|
||
else N2 = N3;
|
||
}
|
||
}
|
||
|
||
AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets");
|
||
|
||
AssertFatal(pucch_Config->resourceToAddModList!=NULL,
|
||
"PUCCH resourceToAddModList is null\n");
|
||
|
||
n_list = pucch_Config->resourceToAddModList->list.count;
|
||
AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n");
|
||
|
||
// going through the list of PUCCH resources to find the one indexed by resource_id
|
||
for (int i=0; i<n_list; i++) {
|
||
pucchres = pucch_Config->resourceToAddModList->list.array[i];
|
||
if (pucchres->pucch_ResourceId == *resource_id) {
|
||
res_found = 1;
|
||
pucch_pdu->prb_start = pucchres->startingPRB;
|
||
pucch_pdu->rnti = rnti;
|
||
// FIXME why there is only one frequency hopping flag
|
||
// what about inter slot frequency hopping?
|
||
pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0;
|
||
pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0;
|
||
switch(pucchres->format.present) {
|
||
case NR_PUCCH_Resource__format_PR_format0 :
|
||
pucch_pdu->format_type = 0;
|
||
pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift;
|
||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
|
||
pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
|
||
pucch_pdu->sr_flag = O_sr;
|
||
pucch_pdu->prb_size = 1;
|
||
break;
|
||
case NR_PUCCH_Resource__format_PR_format1 :
|
||
pucch_pdu->format_type = 1;
|
||
pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift;
|
||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
|
||
pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
|
||
pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC;
|
||
pucch_pdu->sr_flag = O_sr;
|
||
pucch_pdu->prb_size = 1;
|
||
break;
|
||
case NR_PUCCH_Resource__format_PR_format2 :
|
||
pucch_pdu->format_type = 2;
|
||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
|
||
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
|
||
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
||
pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId;
|
||
pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs,
|
||
O_uci+O_sr,O_csi,pucch_Config->format2->choice.setup->maxCodeRate,
|
||
2,pucchres->format.choice.format2->nrofSymbols,8);
|
||
pucch_pdu->bit_len_csi_part1 = O_csi;
|
||
break;
|
||
case NR_PUCCH_Resource__format_PR_format3 :
|
||
pucch_pdu->format_type = 3;
|
||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
|
||
pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
|
||
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
||
if (pucch_Config->format3 == NULL) {
|
||
pucch_pdu->pi_2bpsk = 0;
|
||
pucch_pdu->add_dmrs_flag = 0;
|
||
}
|
||
else {
|
||
pucchfmt = pucch_Config->format3->choice.setup;
|
||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
|
||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
|
||
}
|
||
int f3_dmrs_symbols;
|
||
if (pucchres->format.choice.format3->nrofSymbols==4)
|
||
f3_dmrs_symbols = 1<<pucch_pdu->freq_hop_flag;
|
||
else {
|
||
if(pucchres->format.choice.format3->nrofSymbols<10)
|
||
f3_dmrs_symbols = 2;
|
||
else
|
||
f3_dmrs_symbols = 2<<pucch_pdu->add_dmrs_flag;
|
||
}
|
||
pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs,
|
||
O_uci+O_sr,O_csi,pucch_Config->format3->choice.setup->maxCodeRate,
|
||
2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12);
|
||
pucch_pdu->bit_len_csi_part1 = O_csi;
|
||
break;
|
||
case NR_PUCCH_Resource__format_PR_format4 :
|
||
pucch_pdu->format_type = 4;
|
||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols;
|
||
pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex;
|
||
pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length;
|
||
pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index;
|
||
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
||
if (pucch_Config->format3 == NULL) {
|
||
pucch_pdu->pi_2bpsk = 0;
|
||
pucch_pdu->add_dmrs_flag = 0;
|
||
}
|
||
else {
|
||
pucchfmt = pucch_Config->format3->choice.setup;
|
||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
|
||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
|
||
}
|
||
pucch_pdu->bit_len_csi_part1 = O_csi;
|
||
break;
|
||
default :
|
||
AssertFatal(1==0,"Undefined PUCCH format \n");
|
||
}
|
||
}
|
||
}
|
||
AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id);
|
||
}
|
||
else { // this is the default PUCCH configuration, PUCCH format 0 or 1
|
||
LOG_D(NR_MAC,"pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, bwp %p)\n",r_pucch,bwp);
|
||
int rsetindex = *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon;
|
||
int prb_start, second_hop_prb, nr_of_symb, start_symb;
|
||
set_r_pucch_parms(rsetindex,
|
||
r_pucch,
|
||
pucch_pdu->bwp_size,
|
||
&prb_start,
|
||
&second_hop_prb,
|
||
&nr_of_symb,
|
||
&start_symb);
|
||
|
||
pucch_pdu->prb_start = prb_start;
|
||
pucch_pdu->rnti = rnti;
|
||
pucch_pdu->freq_hop_flag = 1;
|
||
pucch_pdu->second_hop_prb = second_hop_prb;
|
||
pucch_pdu->format_type = default_pucch_fmt[rsetindex];
|
||
pucch_pdu->initial_cyclic_shift = r_pucch%default_pucch_csset[rsetindex];
|
||
if (rsetindex==3||rsetindex==7||rsetindex==11) pucch_pdu->initial_cyclic_shift*=6;
|
||
else if (rsetindex==1||rsetindex==2) pucch_pdu->initial_cyclic_shift*=3;
|
||
else pucch_pdu->initial_cyclic_shift*=4;
|
||
pucch_pdu->nr_of_symbols = nr_of_symb;
|
||
pucch_pdu->start_symbol_index = start_symb;
|
||
if (pucch_pdu->format_type == 1) pucch_pdu->time_domain_occ_idx = 0; // check this!!
|
||
pucch_pdu->sr_flag = O_sr;
|
||
pucch_pdu->prb_size=1;
|
||
}
|
||
}
|
||
|
||
|
||
void set_r_pucch_parms(int rsetindex,
|
||
int r_pucch,
|
||
int bwp_size,
|
||
int *prb_start,
|
||
int *second_hop_prb,
|
||
int *nr_of_symbols,
|
||
int *start_symbol_index) {
|
||
|
||
// procedure described in 38.213 section 9.2.1
|
||
|
||
int prboffset = r_pucch/default_pucch_csset[rsetindex];
|
||
int prboffsetm8 = (r_pucch-8)/default_pucch_csset[rsetindex];
|
||
|
||
*prb_start = (r_pucch>>3)==0 ?
|
||
default_pucch_prboffset[rsetindex] + prboffset:
|
||
bwp_size-1-default_pucch_prboffset[rsetindex]-prboffsetm8;
|
||
|
||
*second_hop_prb = (r_pucch>>3)==0?
|
||
bwp_size-1-default_pucch_prboffset[rsetindex]-prboffset:
|
||
default_pucch_prboffset[rsetindex] + prboffsetm8;
|
||
|
||
*nr_of_symbols = default_pucch_numbsymb[rsetindex];
|
||
*start_symbol_index = default_pucch_firstsymb[rsetindex];
|
||
}
|
||
|
||
|
||
void prepare_dci(const NR_CellGroupConfig_t *CellGroup,
|
||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||
nr_dci_format_t format,
|
||
int bwp_id) {
|
||
|
||
AssertFatal(CellGroup!=NULL,"CellGroup shouldn't be null here\n");
|
||
|
||
const NR_BWP_DownlinkDedicated_t *bwpd = NULL;
|
||
const NR_PDSCH_Config_t *pdsch_Config = NULL;
|
||
const NR_PDCCH_Config_t *pdcch_Config = NULL;
|
||
|
||
if (bwp_id>0) {
|
||
bwpd=CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||
}
|
||
else {
|
||
bwpd=CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP;
|
||
}
|
||
pdsch_Config = (bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL;
|
||
pdcch_Config = (bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL;
|
||
|
||
|
||
switch(format) {
|
||
case NR_UL_DCI_FORMAT_0_1:
|
||
// format indicator
|
||
dci_pdu_rel15->format_indicator = 0;
|
||
// carrier indicator
|
||
if (CellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL)
|
||
AssertFatal(1==0,"Cross Carrier Scheduling Config currently not supported\n");
|
||
// supplementary uplink
|
||
if (CellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL)
|
||
AssertFatal(1==0,"Supplementary Uplink currently not supported\n");
|
||
// SRS request
|
||
dci_pdu_rel15->srs_request.val = 0;
|
||
dci_pdu_rel15->ulsch_indicator = 1;
|
||
break;
|
||
case NR_DL_DCI_FORMAT_1_1:
|
||
// format indicator
|
||
dci_pdu_rel15->format_indicator = 1;
|
||
// carrier indicator
|
||
if (CellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL)
|
||
AssertFatal(1==0,"Cross Carrier Scheduling Config currently not supported\n");
|
||
//vrb to prb mapping
|
||
if (pdsch_Config->vrb_ToPRB_Interleaver==NULL)
|
||
dci_pdu_rel15->vrb_to_prb_mapping.val = 0;
|
||
else
|
||
dci_pdu_rel15->vrb_to_prb_mapping.val = 1;
|
||
//bundling size indicator
|
||
if (pdsch_Config->prb_BundlingType.present == NR_PDSCH_Config__prb_BundlingType_PR_dynamicBundling)
|
||
AssertFatal(1==0,"Dynamic PRB bundling type currently not supported\n");
|
||
//rate matching indicator
|
||
uint16_t msb = (pdsch_Config->rateMatchPatternGroup1==NULL)?0:1;
|
||
uint16_t lsb = (pdsch_Config->rateMatchPatternGroup2==NULL)?0:1;
|
||
dci_pdu_rel15->rate_matching_indicator.val = lsb | (msb<<1);
|
||
// aperiodic ZP CSI-RS trigger
|
||
if (pdsch_Config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList != NULL)
|
||
AssertFatal(1==0,"Aperiodic ZP CSI-RS currently not supported\n");
|
||
// transmission configuration indication
|
||
if (pdcch_Config->controlResourceSetToAddModList->list.array[0]->tci_PresentInDCI != NULL)
|
||
AssertFatal(1==0,"TCI in DCI currently not supported\n");
|
||
//srs resource set
|
||
if (CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching!=NULL) {
|
||
NR_SRS_CarrierSwitching_t *cs = CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching->choice.setup;
|
||
if (cs->srs_TPC_PDCCH_Group!=NULL){
|
||
switch(cs->srs_TPC_PDCCH_Group->present) {
|
||
case NR_SRS_CarrierSwitching__srs_TPC_PDCCH_Group_PR_NOTHING:
|
||
dci_pdu_rel15->srs_request.val = 0;
|
||
break;
|
||
case NR_SRS_CarrierSwitching__srs_TPC_PDCCH_Group_PR_typeA:
|
||
AssertFatal(1==0,"SRS TPC PRCCH group type A currently not supported\n");
|
||
break;
|
||
case NR_SRS_CarrierSwitching__srs_TPC_PDCCH_Group_PR_typeB:
|
||
AssertFatal(1==0,"SRS TPC PRCCH group type B currently not supported\n");
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
dci_pdu_rel15->srs_request.val = 0;
|
||
}
|
||
else
|
||
dci_pdu_rel15->srs_request.val = 0;
|
||
// CBGTI and CBGFI
|
||
if (CellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig &&
|
||
CellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup &&
|
||
CellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL)
|
||
AssertFatal(1==0,"CBG transmission currently not supported\n");
|
||
break;
|
||
default :
|
||
AssertFatal(1==0,"Prepare dci currently only implemented for 1_1 and 0_1 \n");
|
||
}
|
||
}
|
||
|
||
|
||
void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc,
|
||
const NR_CellGroupConfig_t *CellGroup,
|
||
nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu,
|
||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||
int dci_format,
|
||
int rnti_type,
|
||
int N_RB,
|
||
int bwp_id,
|
||
uint16_t cset0_bwp_size) {
|
||
uint8_t fsize = 0, pos = 0;
|
||
|
||
uint64_t *dci_pdu = (uint64_t *)pdcch_dci_pdu->Payload;
|
||
*dci_pdu=0;
|
||
int dci_size = nr_dci_size(scc->downlinkConfigCommon->initialDownlinkBWP,scc->uplinkConfigCommon->initialUplinkBWP, CellGroup, dci_pdu_rel15, dci_format, rnti_type, N_RB, bwp_id, cset0_bwp_size);
|
||
pdcch_dci_pdu->PayloadSizeBits = dci_size;
|
||
AssertFatal(dci_size <= 64, "DCI sizes above 64 bits not yet supported");
|
||
if (dci_format == NR_DL_DCI_FORMAT_1_1 || dci_format == NR_UL_DCI_FORMAT_0_1)
|
||
prepare_dci(CellGroup, dci_pdu_rel15, dci_format, bwp_id);
|
||
|
||
/// Payload generation
|
||
switch (dci_format) {
|
||
case NR_DL_DCI_FORMAT_1_0:
|
||
switch (rnti_type) {
|
||
case NR_RNTI_RA:
|
||
// Freq domain assignment
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
pos = fsize;
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos));
|
||
LOG_D(NR_MAC,
|
||
"RA_RNTI, size %d frequency-domain assignment %d (%d bits) N_RB_BWP %d=> %d (0x%lx)\n",
|
||
dci_size,dci_pdu_rel15->frequency_domain_assignment.val,
|
||
fsize,
|
||
N_RB,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// Time domain assignment
|
||
pos += 4;
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos));
|
||
LOG_D(NR_MAC,
|
||
"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->time_domain_assignment.val,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// VRB to PRB mapping
|
||
pos++;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 0x1) << (dci_size - pos);
|
||
LOG_D(NR_MAC,
|
||
"vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->vrb_to_prb_mapping.val,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// MCS
|
||
pos += 5;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
|
||
LOG_D(NR_MAC, "mcs %d (5 bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, dci_size - pos, *dci_pdu);
|
||
// TB scaling
|
||
pos += 2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling & 0x3) << (dci_size - pos);
|
||
LOG_D(NR_MAC, "tb_scaling %d (2 bits)=> %d (0x%lx)\n", dci_pdu_rel15->tb_scaling, dci_size - pos, *dci_pdu);
|
||
break;
|
||
|
||
case NR_RNTI_C:
|
||
// indicating a DL DCI format 1bit
|
||
pos++;
|
||
*dci_pdu |= ((uint64_t)1) << (dci_size - pos);
|
||
LOG_D(NR_MAC,
|
||
"DCI1_0 (size %d): Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",
|
||
dci_size,
|
||
dci_pdu_rel15->format_indicator,
|
||
1,
|
||
N_RB,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// Freq domain assignment (275rb >> fsize = 16)
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
pos += fsize;
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos));
|
||
LOG_D(NR_MAC,
|
||
"Freq domain assignment %d (%d bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->frequency_domain_assignment.val,
|
||
fsize,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
uint16_t is_ra = 1;
|
||
for (int i = 0; i < fsize; i++) {
|
||
if (!((dci_pdu_rel15->frequency_domain_assignment.val >> i) & 1)) {
|
||
is_ra = 0;
|
||
break;
|
||
}
|
||
}
|
||
if (is_ra) { // fsize are all 1 38.212 p86
|
||
// ra_preamble_index 6 bits
|
||
pos += 6;
|
||
*dci_pdu |= ((dci_pdu_rel15->ra_preamble_index & 0x3f) << (dci_size - pos));
|
||
// UL/SUL indicator 1 bit
|
||
pos++;
|
||
*dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val & 1) << (dci_size - pos);
|
||
// SS/PBCH index 6 bits
|
||
pos += 6;
|
||
*dci_pdu |= ((dci_pdu_rel15->ss_pbch_index & 0x3f) << (dci_size - pos));
|
||
// prach_mask_index 4 bits
|
||
pos += 4;
|
||
*dci_pdu |= ((dci_pdu_rel15->prach_mask_index & 0xf) << (dci_size - pos));
|
||
} else {
|
||
// Time domain assignment 4bit
|
||
pos += 4;
|
||
*dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos));
|
||
LOG_D(NR_MAC,
|
||
"Time domain assignment %d (%d bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->time_domain_assignment.val,
|
||
4,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// VRB to PRB mapping 1bit
|
||
pos++;
|
||
*dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos);
|
||
LOG_D(NR_MAC,
|
||
"VRB to PRB %d (%d bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->vrb_to_prb_mapping.val,
|
||
1,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// MCS 5bit //bit over 32, so dci_pdu ++
|
||
pos += 5;
|
||
*dci_pdu |= (dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
|
||
LOG_D(NR_MAC, "MCS %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, 5, dci_size - pos, *dci_pdu);
|
||
// New data indicator 1bit
|
||
pos++;
|
||
*dci_pdu |= (dci_pdu_rel15->ndi & 1) << (dci_size - pos);
|
||
LOG_D(NR_MAC, "NDI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->ndi, 1, dci_size - pos, *dci_pdu);
|
||
// Redundancy version 2bit
|
||
pos += 2;
|
||
*dci_pdu |= (dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
|
||
LOG_D(NR_MAC, "RV %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->rv, 2, dci_size - pos, *dci_pdu);
|
||
// HARQ process number 4bit
|
||
pos += 4;
|
||
*dci_pdu |= ((dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos));
|
||
LOG_D(NR_MAC, "HARQ_PID %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->harq_pid, 4, dci_size - pos, *dci_pdu);
|
||
// Downlink assignment index 2bit
|
||
pos += 2;
|
||
*dci_pdu |= ((dci_pdu_rel15->dai[0].val & 3) << (dci_size - pos));
|
||
LOG_D(NR_MAC, "DAI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->dai[0].val, 2, dci_size - pos, *dci_pdu);
|
||
// TPC command for scheduled PUCCH 2bit
|
||
pos += 2;
|
||
*dci_pdu |= ((dci_pdu_rel15->tpc & 3) << (dci_size - pos));
|
||
LOG_D(NR_MAC, "TPC %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->tpc, 2, dci_size - pos, *dci_pdu);
|
||
// PUCCH resource indicator 3bit
|
||
pos += 3;
|
||
*dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos));
|
||
LOG_D(NR_MAC,
|
||
"PUCCH RI %d (%d bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->pucch_resource_indicator,
|
||
3,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
// PDSCH-to-HARQ_feedback timing indicator 3bit
|
||
pos += 3;
|
||
*dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & 0x7) << (dci_size - pos));
|
||
LOG_D(NR_MAC,
|
||
"PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",
|
||
dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val,
|
||
3,
|
||
dci_size - pos,
|
||
*dci_pdu);
|
||
} // end else
|
||
break;
|
||
|
||
case NR_RNTI_P:
|
||
// Short Messages Indicator – 2 bits
|
||
for (int i = 0; i < 2; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator >> (1 - i)) & 1) << (dci_size - pos++);
|
||
// Short Messages – 8 bits
|
||
for (int i = 0; i < 8; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages >> (7 - i)) & 1) << (dci_size - pos++);
|
||
// Freq domain assignment 0-16 bit
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
for (int i = 0; i < fsize; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
|
||
// Time domain assignment 4 bit
|
||
for (int i = 0; i < 4; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
|
||
// VRB to PRB mapping 1 bit
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++);
|
||
// MCS 5 bit
|
||
for (int i = 0; i < 5; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
|
||
// TB scaling 2 bit
|
||
for (int i = 0; i < 2; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling >> (1 - i)) & 1) << (dci_size - pos++);
|
||
break;
|
||
|
||
case NR_RNTI_SI:
|
||
pos = 1;
|
||
// Freq domain assignment 0-16 bit
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
LOG_D(NR_MAC, "fsize = %i\n", fsize);
|
||
for (int i = 0; i < fsize; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
|
||
LOG_D(NR_MAC, "dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
|
||
// Time domain assignment 4 bit
|
||
for (int i = 0; i < 4; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
|
||
LOG_D(NR_MAC, "dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
|
||
// VRB to PRB mapping 1 bit
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++);
|
||
LOG_D(NR_MAC, "dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val);
|
||
// MCS 5bit //bit over 32, so dci_pdu ++
|
||
for (int i = 0; i < 5; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
|
||
LOG_D(NR_MAC, "dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
|
||
// Redundancy version 2bit
|
||
for (int i = 0; i < 2; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++);
|
||
LOG_D(NR_MAC, "dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
|
||
// System information indicator 1bit
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->system_info_indicator&1)<<(dci_size-pos++);
|
||
LOG_D(NR_MAC, "dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator);
|
||
break;
|
||
|
||
case NR_RNTI_TC:
|
||
pos = 1;
|
||
// indicating a DL DCI format 1bit
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++);
|
||
// Freq domain assignment 0-16 bit
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
for (int i = 0; i < fsize; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
|
||
// Time domain assignment 4 bit
|
||
for (int i = 0; i < 4; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
|
||
// VRB to PRB mapping 1 bit
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++);
|
||
// MCS 5bit //bit over 32, so dci_pdu ++
|
||
for (int i = 0; i < 5; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
|
||
// New data indicator 1bit
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++);
|
||
// Redundancy version 2bit
|
||
for (int i = 0; i < 2; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++);
|
||
// HARQ process number 4bit
|
||
for (int i = 0; i < 4; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++);
|
||
// Downlink assignment index – 2 bits
|
||
for (int i = 0; i < 2; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val >> (1 - i)) & 1) << (dci_size - pos++);
|
||
// TPC command for scheduled PUCCH – 2 bits
|
||
for (int i = 0; i < 2; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++);
|
||
// PUCCH resource indicator – 3 bits
|
||
for (int i = 0; i < 3; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->pucch_resource_indicator >> (2 - i)) & 1) << (dci_size - pos++);
|
||
// PDSCH-to-HARQ_feedback timing indicator – 3 bits
|
||
for (int i = 0; i < 3; i++)
|
||
*dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val >> (2 - i)) & 1) << (dci_size - pos++);
|
||
|
||
LOG_D(NR_MAC,"N_RB = %i\n", N_RB);
|
||
LOG_D(NR_MAC,"dci_size = %i\n", dci_size);
|
||
LOG_D(NR_MAC,"fsize = %i\n", fsize);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->format_indicator = %i\n", dci_pdu_rel15->format_indicator);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->dai[0].val = %i\n", dci_pdu_rel15->dai[0].val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = %i\n", dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val);
|
||
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case NR_UL_DCI_FORMAT_0_0:
|
||
switch (rnti_type) {
|
||
case NR_RNTI_C:
|
||
LOG_D(NR_MAC,"Filling format 0_0 DCI for CRNTI (size %d bits, format ind %d)\n",dci_size,dci_pdu_rel15->format_indicator);
|
||
// indicating a UL DCI format 1bit
|
||
pos=1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos);
|
||
// Freq domain assignment max 16 bit
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
pos+=fsize;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos);
|
||
// Time domain assignment 4bit
|
||
pos += 4;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << 4) - 1)) << (dci_size - pos);
|
||
// Frequency hopping flag – 1 bit
|
||
pos++;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos);
|
||
// MCS 5 bit
|
||
pos+=5;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
|
||
// New data indicator 1bit
|
||
pos++;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos);
|
||
// Redundancy version 2bit
|
||
pos+=2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
|
||
// HARQ process number 4bit
|
||
pos+=4;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos);
|
||
// TPC command for scheduled PUSCH – 2 bits
|
||
pos+=2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos);
|
||
// Padding bits
|
||
for (int a = pos; a < 32; a++)
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++);
|
||
// UL/SUL indicator – 1 bit
|
||
/* commented for now (RK): need to get this from BWP descriptor
|
||
if (cfg->pucch_config.pucch_GroupHopping.value)
|
||
*dci_pdu |=
|
||
((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++);
|
||
*/
|
||
|
||
LOG_D(NR_MAC,"N_RB = %i\n", N_RB);
|
||
LOG_D(NR_MAC,"dci_size = %i\n", dci_size);
|
||
LOG_D(NR_MAC,"fsize = %i\n", fsize);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->frequency_hopping_flag.val = %i\n", dci_pdu_rel15->frequency_hopping_flag.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->ndi = %i\n", dci_pdu_rel15->ndi);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->padding = %i\n", dci_pdu_rel15->padding);
|
||
break;
|
||
|
||
case NFAPI_NR_RNTI_TC:
|
||
// indicating a UL DCI format 1bit
|
||
pos=1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos);
|
||
// Freq domain assignment max 16 bit
|
||
fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
|
||
pos+=fsize;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos);
|
||
// Time domain assignment 4bit
|
||
pos += 4;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << 4) - 1)) << (dci_size - pos);
|
||
// Frequency hopping flag – 1 bit
|
||
pos++;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos);
|
||
// MCS 5 bit
|
||
pos+=5;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
|
||
// New data indicator 1bit
|
||
pos++;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos);
|
||
// Redundancy version 2bit
|
||
pos+=2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
|
||
// HARQ process number 4bit
|
||
pos+=4;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos);
|
||
// Padding bits
|
||
for (int a = pos; a < dci_size; a++)
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++);
|
||
// UL/SUL indicator – 1 bit
|
||
/* commented for now (RK): need to get this from BWP descriptor
|
||
if (cfg->pucch_config.pucch_GroupHopping.value)
|
||
*dci_pdu |=
|
||
((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++);
|
||
*/
|
||
LOG_D(NR_MAC,"N_RB = %i\n", N_RB);
|
||
LOG_D(NR_MAC,"dci_size = %i\n", dci_size);
|
||
LOG_D(NR_MAC,"fsize = %i\n", fsize);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->frequency_hopping_flag.val = %i\n", dci_pdu_rel15->frequency_hopping_flag.val);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->ndi = %i\n", dci_pdu_rel15->ndi);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc);
|
||
LOG_D(NR_MAC,"dci_pdu_rel15->padding = %i\n", dci_pdu_rel15->padding);
|
||
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case NR_UL_DCI_FORMAT_0_1:
|
||
switch (rnti_type) {
|
||
case NR_RNTI_C:
|
||
LOG_D(NR_MAC,"Filling NR_UL_DCI_FORMAT_0_1 size %d format indicator %d\n",dci_size,dci_pdu_rel15->format_indicator);
|
||
// Indicating a DL DCI format 1bit
|
||
pos = 1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos);
|
||
// Carrier indicator
|
||
pos += dci_pdu_rel15->carrier_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// UL/SUL Indicator
|
||
pos += dci_pdu_rel15->ul_sul_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val & ((1 << dci_pdu_rel15->ul_sul_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// BWP indicator
|
||
pos += dci_pdu_rel15->bwp_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// Frequency domain resource assignment
|
||
pos += dci_pdu_rel15->frequency_domain_assignment.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos);
|
||
// Time domain resource assignment
|
||
pos += dci_pdu_rel15->time_domain_assignment.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos);
|
||
// Frequency hopping
|
||
pos += dci_pdu_rel15->frequency_hopping_flag.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & ((1 << dci_pdu_rel15->frequency_hopping_flag.nbits) - 1)) << (dci_size - pos);
|
||
// MCS 5bit
|
||
pos += 5;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
|
||
// New data indicator 1bit
|
||
pos += 1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos);
|
||
// Redundancy version 2bit
|
||
pos += 2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
|
||
// HARQ process number 4bit
|
||
pos += 4;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos);
|
||
// 1st Downlink assignment index
|
||
pos += dci_pdu_rel15->dai[0].nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos);
|
||
// 2nd Downlink assignment index
|
||
pos += dci_pdu_rel15->dai[1].nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val & ((1 << dci_pdu_rel15->dai[1].nbits) - 1)) << (dci_size - pos);
|
||
// TPC command for scheduled PUSCH 2bit
|
||
pos += 2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos);
|
||
// SRS resource indicator
|
||
pos += dci_pdu_rel15->srs_resource_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val & ((1 << dci_pdu_rel15->srs_resource_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// Precoding info and n. of layers
|
||
pos += dci_pdu_rel15->precoding_information.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val & ((1 << dci_pdu_rel15->precoding_information.nbits) - 1)) << (dci_size - pos);
|
||
// Antenna ports
|
||
pos += dci_pdu_rel15->antenna_ports.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos);
|
||
// SRS request
|
||
pos += dci_pdu_rel15->srs_request.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos);
|
||
// CSI request
|
||
pos += dci_pdu_rel15->csi_request.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val & ((1 << dci_pdu_rel15->csi_request.nbits) - 1)) << (dci_size - pos);
|
||
// CBG transmission information
|
||
pos += dci_pdu_rel15->cbgti.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos);
|
||
// PTRS DMRS association
|
||
pos += dci_pdu_rel15->ptrs_dmrs_association.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val & ((1 << dci_pdu_rel15->ptrs_dmrs_association.nbits) - 1)) << (dci_size - pos);
|
||
// Beta offset indicator
|
||
pos += dci_pdu_rel15->beta_offset_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val & ((1 << dci_pdu_rel15->beta_offset_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// DMRS sequence initialization
|
||
pos += dci_pdu_rel15->dmrs_sequence_initialization.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & ((1 << dci_pdu_rel15->dmrs_sequence_initialization.nbits) - 1)) << (dci_size - pos);
|
||
// UL-SCH indicator
|
||
pos += 1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator & 0x1) << (dci_size - pos);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case NR_DL_DCI_FORMAT_1_1:
|
||
// Indicating a DL DCI format 1bit
|
||
LOG_D(NR_MAC,"Filling Format 1_1 DCI of size %d\n",dci_size);
|
||
pos = 1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos);
|
||
// Carrier indicator
|
||
pos += dci_pdu_rel15->carrier_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// BWP indicator
|
||
pos += dci_pdu_rel15->bwp_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// Frequency domain resource assignment
|
||
pos += dci_pdu_rel15->frequency_domain_assignment.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos);
|
||
// Time domain resource assignment
|
||
pos += dci_pdu_rel15->time_domain_assignment.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos);
|
||
// VRB-to-PRB mapping
|
||
pos += dci_pdu_rel15->vrb_to_prb_mapping.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & ((1 << dci_pdu_rel15->vrb_to_prb_mapping.nbits) - 1)) << (dci_size - pos);
|
||
// PRB bundling size indicator
|
||
pos += dci_pdu_rel15->prb_bundling_size_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val & ((1 << dci_pdu_rel15->prb_bundling_size_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// Rate matching indicator
|
||
pos += dci_pdu_rel15->rate_matching_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val & ((1 << dci_pdu_rel15->rate_matching_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// ZP CSI-RS trigger
|
||
pos += dci_pdu_rel15->zp_csi_rs_trigger.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val & ((1 << dci_pdu_rel15->zp_csi_rs_trigger.nbits) - 1)) << (dci_size - pos);
|
||
// TB1
|
||
// MCS 5bit
|
||
pos += 5;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
|
||
// New data indicator 1bit
|
||
pos += 1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos);
|
||
// Redundancy version 2bit
|
||
pos += 2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
|
||
// TB2
|
||
// MCS 5bit
|
||
pos += dci_pdu_rel15->mcs2.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val & ((1 << dci_pdu_rel15->mcs2.nbits) - 1)) << (dci_size - pos);
|
||
// New data indicator 1bit
|
||
pos += dci_pdu_rel15->ndi2.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val & ((1 << dci_pdu_rel15->ndi2.nbits) - 1)) << (dci_size - pos);
|
||
// Redundancy version 2bit
|
||
pos += dci_pdu_rel15->rv2.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val & ((1 << dci_pdu_rel15->rv2.nbits) - 1)) << (dci_size - pos);
|
||
// HARQ process number 4bit
|
||
pos += 4;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos);
|
||
// Downlink assignment index
|
||
pos += dci_pdu_rel15->dai[0].nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos);
|
||
// TPC command for scheduled PUCCH 2bit
|
||
pos += 2;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos);
|
||
// PUCCH resource indicator 3bit
|
||
pos += 3;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos);
|
||
// PDSCH-to-HARQ_feedback timing indicator
|
||
pos += dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & ((1 << dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits) - 1)) << (dci_size - pos);
|
||
// Antenna ports
|
||
pos += dci_pdu_rel15->antenna_ports.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos);
|
||
// TCI
|
||
pos += dci_pdu_rel15->transmission_configuration_indication.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val & ((1 << dci_pdu_rel15->transmission_configuration_indication.nbits) - 1)) << (dci_size - pos);
|
||
// SRS request
|
||
pos += dci_pdu_rel15->srs_request.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos);
|
||
// CBG transmission information
|
||
pos += dci_pdu_rel15->cbgti.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos);
|
||
// CBG flushing out information
|
||
pos += dci_pdu_rel15->cbgfi.nbits;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val & ((1 << dci_pdu_rel15->cbgfi.nbits) - 1)) << (dci_size - pos);
|
||
// DMRS sequence init
|
||
pos += 1;
|
||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & 0x1) << (dci_size - pos);
|
||
}
|
||
LOG_D(NR_MAC, "DCI has %d bits and the payload is %lx\n", dci_size, *dci_pdu);
|
||
}
|
||
|
||
int get_spf(nfapi_nr_config_request_scf_t *cfg) {
|
||
|
||
int mu = cfg->ssb_config.scs_common.value;
|
||
AssertFatal(mu>=0&&mu<4,"Illegal scs %d\n",mu);
|
||
|
||
return(10 * (1<<mu));
|
||
}
|
||
|
||
int to_absslot(nfapi_nr_config_request_scf_t *cfg,int frame,int slot) {
|
||
|
||
return(get_spf(cfg)*frame) + slot;
|
||
|
||
}
|
||
|
||
int extract_startSymbol(int startSymbolAndLength) {
|
||
int tmp = startSymbolAndLength/14;
|
||
int tmp2 = startSymbolAndLength%14;
|
||
|
||
if (tmp > 0 && tmp < (14-tmp2)) return(tmp2);
|
||
else return(13-tmp2);
|
||
}
|
||
|
||
int extract_length(int startSymbolAndLength) {
|
||
int tmp = startSymbolAndLength/14;
|
||
int tmp2 = startSymbolAndLength%14;
|
||
|
||
if (tmp > 0 && tmp < (14-tmp2)) return(tmp);
|
||
else return(15-tmp2);
|
||
}
|
||
|
||
/*
|
||
* Dump the UL or DL UE_info into LOG_T(MAC)
|
||
*/
|
||
void dump_nr_list(NR_list_t *listP)
|
||
{
|
||
for (int j = listP->head; j >= 0; j = listP->next[j])
|
||
LOG_T(NR_MAC, "NR list node %d => %d\n", j, listP->next[j]);
|
||
}
|
||
|
||
/*
|
||
* Create a new NR_list
|
||
*/
|
||
void create_nr_list(NR_list_t *list, int len)
|
||
{
|
||
list->head = -1;
|
||
list->next = malloc(len * sizeof(*list->next));
|
||
AssertFatal(list->next, "cannot malloc() memory for NR_list_t->next\n");
|
||
for (int i = 0; i < len; ++i)
|
||
list->next[i] = -1;
|
||
list->tail = -1;
|
||
list->len = len;
|
||
}
|
||
|
||
/*
|
||
* Resize an NR_list
|
||
*/
|
||
void resize_nr_list(NR_list_t *list, int new_len)
|
||
{
|
||
if (new_len == list->len)
|
||
return;
|
||
if (new_len > list->len) {
|
||
/* list->head remains */
|
||
const int old_len = list->len;
|
||
int* n = realloc(list->next, new_len * sizeof(*list->next));
|
||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||
list->next = n;
|
||
for (int i = old_len; i < new_len; ++i)
|
||
list->next[i] = -1;
|
||
/* list->tail remains */
|
||
list->len = new_len;
|
||
} else { /* new_len < len */
|
||
AssertFatal(list->head < new_len, "shortened list head out of index %d (new len %d)\n", list->head, new_len);
|
||
AssertFatal(list->tail < new_len, "shortened list tail out of index %d (new len %d)\n", list->head, new_len);
|
||
for (int i = 0; i < list->len; ++i)
|
||
AssertFatal(list->next[i] < new_len, "shortened list entry out of index %d (new len %d)\n", list->next[i], new_len);
|
||
/* list->head remains */
|
||
int *n = realloc(list->next, new_len * sizeof(*list->next));
|
||
AssertFatal(n, "cannot realloc() memory for NR_list_t->next\n");
|
||
list->next = n;
|
||
/* list->tail remains */
|
||
list->len = new_len;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Destroy an NR_list
|
||
*/
|
||
void destroy_nr_list(NR_list_t *list)
|
||
{
|
||
free(list->next);
|
||
}
|
||
|
||
/*
|
||
* Add an ID to an NR_list at the end, traversing the whole list. Note:
|
||
* add_tail_nr_list() is a faster alternative, but this implementation ensures
|
||
* we do not add an existing ID.
|
||
*/
|
||
void add_nr_list(NR_list_t *listP, int id)
|
||
{
|
||
int *cur = &listP->head;
|
||
while (*cur >= 0) {
|
||
AssertFatal(*cur != id, "id %d already in NR_UE_list!\n", id);
|
||
cur = &listP->next[*cur];
|
||
}
|
||
*cur = id;
|
||
if (listP->next[id] < 0)
|
||
listP->tail = id;
|
||
}
|
||
|
||
/*
|
||
* Remove an ID from an NR_list
|
||
*/
|
||
void remove_nr_list(NR_list_t *listP, int id)
|
||
{
|
||
int *cur = &listP->head;
|
||
int *prev = &listP->head;
|
||
while (*cur != -1 && *cur != id) {
|
||
prev = cur;
|
||
cur = &listP->next[*cur];
|
||
}
|
||
AssertFatal(*cur != -1, "ID %d not found in UE_list\n", id);
|
||
int *next = &listP->next[*cur];
|
||
*cur = listP->next[*cur];
|
||
*next = -1;
|
||
listP->tail = *prev >= 0 && listP->next[*prev] >= 0 ? listP->tail : *prev;
|
||
}
|
||
|
||
/*
|
||
* Add an ID to the tail of the NR_list in O(1). Note that there is
|
||
* corresponding remove_tail_nr_list(), as we cannot set the tail backwards and
|
||
* therefore need to go through the whole list (use remove_nr_list())
|
||
*/
|
||
void add_tail_nr_list(NR_list_t *listP, int id)
|
||
{
|
||
int *last = listP->tail < 0 ? &listP->head : &listP->next[listP->tail];
|
||
*last = id;
|
||
listP->next[id] = -1;
|
||
listP->tail = id;
|
||
}
|
||
|
||
/*
|
||
* Add an ID to the front of the NR_list in O(1)
|
||
*/
|
||
void add_front_nr_list(NR_list_t *listP, int id)
|
||
{
|
||
const int ohead = listP->head;
|
||
listP->head = id;
|
||
listP->next[id] = ohead;
|
||
if (listP->tail < 0)
|
||
listP->tail = id;
|
||
}
|
||
|
||
/*
|
||
* Remove an ID from the front of the NR_list in O(1)
|
||
*/
|
||
void remove_front_nr_list(NR_list_t *listP)
|
||
{
|
||
AssertFatal(listP->head >= 0, "Nothing to remove\n");
|
||
const int ohead = listP->head;
|
||
listP->head = listP->next[ohead];
|
||
listP->next[ohead] = -1;
|
||
if (listP->head < 0)
|
||
listP->tail = -1;
|
||
}
|
||
|
||
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP)
|
||
//------------------------------------------------------------------------------
|
||
{
|
||
int UE_id;
|
||
NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info;
|
||
|
||
for (UE_id = 0; UE_id < MAX_MOBILES_PER_GNB; UE_id++) {
|
||
if (UE_info->active[UE_id]) {
|
||
if (UE_info->rnti[UE_id] == rntiP) {
|
||
return UE_id;
|
||
}
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) {
|
||
//------------------------------------------------------------------------------
|
||
int RA_id;
|
||
RA_t *ra = (RA_t *) &RC.nrmac[mod_idP]->common_channels[CC_idP].ra[0];
|
||
|
||
for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) {
|
||
LOG_D(NR_MAC, "Checking RA_id %d for %x : state %d\n",
|
||
RA_id,
|
||
rntiP,
|
||
ra[RA_id].state);
|
||
|
||
if (ra[RA_id].state != IDLE && ra[RA_id].rnti == rntiP)
|
||
return RA_id;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH n)
|
||
{
|
||
switch (n) {
|
||
case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n2:
|
||
return 2;
|
||
case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n4:
|
||
return 4;
|
||
case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n6:
|
||
return 6;
|
||
case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n10:
|
||
return 10;
|
||
case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n12:
|
||
return 12;
|
||
case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16:
|
||
return 16;
|
||
default:
|
||
return 8;
|
||
}
|
||
}
|
||
|
||
int get_dl_bwp_id(const NR_ServingCellConfig_t *servingCellConfig)
|
||
{
|
||
if (servingCellConfig->firstActiveDownlinkBWP_Id)
|
||
return *servingCellConfig->firstActiveDownlinkBWP_Id;
|
||
else if (servingCellConfig->defaultDownlinkBWP_Id)
|
||
return *servingCellConfig->defaultDownlinkBWP_Id;
|
||
else
|
||
return 1;
|
||
}
|
||
|
||
int get_ul_bwp_id(const NR_ServingCellConfig_t *servingCellConfig)
|
||
{
|
||
if (servingCellConfig->uplinkConfig && servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id)
|
||
return *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id;
|
||
else
|
||
return 1;
|
||
}
|
||
|
||
//------------------------------------------------------------------------------
|
||
int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
|
||
{
|
||
gNB_MAC_INST *nr_mac = RC.nrmac[mod_idP];
|
||
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
|
||
NR_UE_info_t *UE_info = &nr_mac->UE_info;
|
||
LOG_I(NR_MAC, "[gNB %d] Adding UE with rnti 0x%04x (num_UEs %d)\n",
|
||
mod_idP,
|
||
rntiP,
|
||
UE_info->num_UEs);
|
||
dump_nr_list(&UE_info->list);
|
||
|
||
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
|
||
if (UE_info->active[i]) {
|
||
LOG_D(NR_MAC,"UE %x is active, skipping\n",rntiP);
|
||
continue;
|
||
}
|
||
int UE_id = i;
|
||
UE_info->num_UEs++;
|
||
UE_info->active[UE_id] = true;
|
||
if (CellGroup) UE_info->Msg4_ACKed[UE_id] = true;
|
||
else UE_info->Msg4_ACKed[UE_id] = false;
|
||
UE_info->rnti[UE_id] = rntiP;
|
||
UE_info->CellGroup[UE_id] = CellGroup;
|
||
add_nr_list(&UE_info->list, UE_id);
|
||
memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t));
|
||
if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated)
|
||
compute_csi_bitlen (CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE_info, UE_id, mod_idP);
|
||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||
memset(sched_ctrl, 0, sizeof(*sched_ctrl));
|
||
sched_ctrl->set_mcs = true;
|
||
sched_ctrl->ta_frame = 0;
|
||
sched_ctrl->ta_update = 31;
|
||
sched_ctrl->ta_apply = false;
|
||
sched_ctrl->ul_rssi = 0;
|
||
sched_ctrl->pucch_consecutive_dtx_cnt = 0;
|
||
sched_ctrl->pusch_consecutive_dtx_cnt = 0;
|
||
sched_ctrl->ul_failure = 0;
|
||
|
||
sched_ctrl->sched_srs.frame = -1;
|
||
sched_ctrl->sched_srs.slot = -1;
|
||
sched_ctrl->sched_srs.srs_scheduled = false;
|
||
|
||
/* set illegal time domain allocation to force recomputation of all fields */
|
||
sched_ctrl->pdsch_semi_static.time_domain_allocation = -1;
|
||
sched_ctrl->pusch_semi_static.time_domain_allocation = -1;
|
||
const NR_ServingCellConfig_t *servingCellConfig = CellGroup && CellGroup->spCellConfig ? CellGroup->spCellConfig->spCellConfigDedicated : NULL;
|
||
|
||
/* Set default BWPs */
|
||
const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig ? servingCellConfig->downlinkBWP_ToAddModList : NULL;
|
||
if (bwpList) AssertFatal(bwpList->list.count == 1,
|
||
"downlinkBWP_ToAddModList has %d BWP!\n",
|
||
bwpList->list.count);
|
||
|
||
const int bwp_id = servingCellConfig ? *servingCellConfig->firstActiveDownlinkBWP_Id : 0;
|
||
sched_ctrl->active_bwp = bwpList && bwp_id > 0 ? bwpList->list.array[bwp_id - 1] : NULL;
|
||
NR_BWP_t *genericParameters = sched_ctrl->active_bwp ?
|
||
&sched_ctrl->active_bwp->bwp_Common->genericParameters:
|
||
&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||
const int target_ss = sched_ctrl->active_bwp ? NR_SearchSpace__searchSpaceType_PR_ue_Specific : NR_SearchSpace__searchSpaceType_PR_common;
|
||
const NR_SIB1_t *sib1 = nr_mac->common_channels[0].sib1 ? nr_mac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
|
||
sched_ctrl->search_space = get_searchspace(sib1,
|
||
scc,
|
||
sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Dedicated : NULL,
|
||
target_ss);
|
||
sched_ctrl->coreset = get_coreset(mod_idP, scc,
|
||
sched_ctrl->active_bwp ? (void*)sched_ctrl->active_bwp->bwp_Dedicated : NULL,
|
||
sched_ctrl->search_space, target_ss);
|
||
sched_ctrl->sched_pdcch = set_pdcch_structure(RC.nrmac[mod_idP],
|
||
sched_ctrl->search_space,
|
||
sched_ctrl->coreset,
|
||
scc,
|
||
genericParameters,
|
||
NULL);
|
||
const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig ? servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList : NULL;
|
||
if (ubwpList) AssertFatal(ubwpList->list.count == 1,
|
||
"uplinkBWP_ToAddModList has %d BWP!\n",
|
||
ubwpList->list.count);
|
||
const int ul_bwp_id = servingCellConfig ? *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id : 0;
|
||
sched_ctrl->active_ubwp = ubwpList && ul_bwp_id > 0 ? ubwpList->list.array[ul_bwp_id - 1] : NULL;
|
||
|
||
/* get Number of HARQ processes for this UE */
|
||
if (servingCellConfig) AssertFatal(servingCellConfig->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup,
|
||
"no pdsch-ServingCellConfig found for UE %d\n",
|
||
UE_id);
|
||
const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig ? servingCellConfig->pdsch_ServingCellConfig->choice.setup : NULL;
|
||
// pdsch == NULL in SA -> will create default (8) number of HARQ processes
|
||
create_dl_harq_list(sched_ctrl, pdsch);
|
||
// add all available UL HARQ processes for this UE
|
||
// nb of ul harq processes not configurable
|
||
create_nr_list(&sched_ctrl->available_ul_harq, 16);
|
||
for (int harq = 0; harq < 16; harq++)
|
||
add_tail_nr_list(&sched_ctrl->available_ul_harq, harq);
|
||
create_nr_list(&sched_ctrl->feedback_ul_harq, 16);
|
||
create_nr_list(&sched_ctrl->retrans_ul_harq, 16);
|
||
LOG_D(NR_MAC, "[gNB %d] Add NR UE_id %d : rnti %x\n",
|
||
mod_idP,
|
||
UE_id,
|
||
rntiP);
|
||
dump_nr_list(&UE_info->list);
|
||
return (UE_id);
|
||
}
|
||
|
||
// printf("MAC: cannot add new UE for rnti %x\n", rntiP);
|
||
LOG_E(NR_MAC, "error in add_new_ue(), could not find space in UE_info, Dumping UE list\n");
|
||
dump_nr_list(&UE_info->list);
|
||
return -1;
|
||
}
|
||
|
||
|
||
void create_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||
const NR_PDSCH_ServingCellConfig_t *pdsch) {
|
||
const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ?
|
||
get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8;
|
||
// add all available DL HARQ processes for this UE
|
||
AssertFatal(sched_ctrl->available_dl_harq.len == sched_ctrl->feedback_dl_harq.len
|
||
&& sched_ctrl->available_dl_harq.len == sched_ctrl->retrans_dl_harq.len,
|
||
"HARQ lists have different lengths (%d/%d/%d)\n",
|
||
sched_ctrl->available_dl_harq.len,
|
||
sched_ctrl->feedback_dl_harq.len,
|
||
sched_ctrl->retrans_dl_harq.len);
|
||
if (sched_ctrl->available_dl_harq.len == 0) {
|
||
create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ);
|
||
for (int harq = 0; harq < nrofHARQ; harq++)
|
||
add_tail_nr_list(&sched_ctrl->available_dl_harq, harq);
|
||
create_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ);
|
||
create_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ);
|
||
} else if (sched_ctrl->available_dl_harq.len == nrofHARQ) {
|
||
LOG_D(NR_MAC, "nrofHARQ %d already configured\n", nrofHARQ);
|
||
} else {
|
||
const int old_nrofHARQ = sched_ctrl->available_dl_harq.len;
|
||
AssertFatal(nrofHARQ > old_nrofHARQ,
|
||
"cannot resize HARQ list to be smaller (nrofHARQ %d, old_nrofHARQ %d)\n",
|
||
nrofHARQ, old_nrofHARQ);
|
||
resize_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ);
|
||
for (int harq = old_nrofHARQ; harq < nrofHARQ; harq++)
|
||
add_tail_nr_list(&sched_ctrl->available_dl_harq, harq);
|
||
resize_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ);
|
||
resize_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ);
|
||
}
|
||
}
|
||
|
||
/* hack data to remove UE in the phy */
|
||
int rnti_to_remove[10];
|
||
volatile int rnti_to_remove_count;
|
||
pthread_mutex_t rnti_to_remove_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||
|
||
void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
|
||
{
|
||
int UE_id;
|
||
int i;
|
||
int cc_id;
|
||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||
|
||
for (i = 0; i < MAX_MOBILES_PER_GNB; i++) {
|
||
|
||
if (UE_info->active[i] != TRUE)
|
||
continue;
|
||
if (UE_info->rnti[i] != rnti)
|
||
continue;
|
||
|
||
/* UE found, remove it */
|
||
UE_id = i;
|
||
|
||
UE_info->num_UEs--;
|
||
UE_info->active[UE_id] = FALSE;
|
||
UE_info->rnti[UE_id] = 0;
|
||
remove_nr_list(&UE_info->list, UE_id);
|
||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||
destroy_nr_list(&sched_ctrl->available_dl_harq);
|
||
destroy_nr_list(&sched_ctrl->feedback_dl_harq);
|
||
destroy_nr_list(&sched_ctrl->retrans_dl_harq);
|
||
destroy_nr_list(&sched_ctrl->available_ul_harq);
|
||
destroy_nr_list(&sched_ctrl->feedback_ul_harq);
|
||
destroy_nr_list(&sched_ctrl->retrans_ul_harq);
|
||
LOG_I(NR_MAC, "[gNB %d] Remove NR UE_id %d: rnti 0x%04x\n",
|
||
mod_id,
|
||
UE_id,
|
||
rnti);
|
||
|
||
/* hack to remove UE in the phy */
|
||
if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1);
|
||
if (rnti_to_remove_count == 10) exit(1);
|
||
rnti_to_remove[rnti_to_remove_count] = rnti;
|
||
LOG_W(NR_MAC, "to remove in mac rnti_to_remove[%d] = 0x%04x\n", rnti_to_remove_count, rnti);
|
||
rnti_to_remove_count++;
|
||
if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1);
|
||
}
|
||
|
||
/* clear RA process(es?) associated to the UE */
|
||
for (cc_id = 0; cc_id < NFAPI_CC_MAX; cc_id++) {
|
||
NR_COMMON_channels_t *cc = &RC.nrmac[mod_id]->common_channels[cc_id];
|
||
for (i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||
if (cc->ra[i].rnti == rnti) {
|
||
LOG_D(NR_MAC, "free RA process %d for rnti %d\n", i, rnti);
|
||
/* is it enough? */
|
||
cc->ra[i].cfra = false;
|
||
cc->ra[i].rnti = 0;
|
||
cc->ra[i].crnti = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void nr_mac_remove_ra_rnti(module_id_t mod_id, rnti_t rnti) {
|
||
// Hack to remove UE in the phy (following the same procedure as in function mac_remove_nr_ue)
|
||
if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1);
|
||
if (rnti_to_remove_count == 10) exit(1);
|
||
rnti_to_remove[rnti_to_remove_count] = rnti;
|
||
LOG_W(NR_MAC, "to remove in mac rnti_to_remove[%d] = 0x%04x\n", rnti_to_remove_count, rnti);
|
||
rnti_to_remove_count++;
|
||
if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1);
|
||
}
|
||
|
||
uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) {
|
||
// al values passed to this function are x10
|
||
int snrx10 = (cqi*5) - 640;
|
||
if (snrx10 > target + incr) return 0; // decrease 1dB
|
||
if (snrx10 < target - (3*incr)) return 3; // increase 3dB
|
||
if (snrx10 < target - incr) return 2; // increase 1dB
|
||
LOG_D(NR_MAC,"tpc : target %d, snrx10 %d\n",target,snrx10);
|
||
return 1; // no change
|
||
}
|
||
|
||
|
||
void get_pdsch_to_harq_feedback(int Mod_idP,
|
||
int UE_id,
|
||
int bwp_id,
|
||
NR_SearchSpace__searchSpaceType_PR ss_type,
|
||
int *max_fb_time,
|
||
uint8_t *pdsch_to_harq_feedback) {
|
||
|
||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||
NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id];
|
||
NR_BWP_DownlinkDedicated_t *bwpd=NULL;
|
||
NR_BWP_UplinkDedicated_t *ubwpd=NULL;
|
||
|
||
if (ss_type == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
|
||
AssertFatal(CellGroup!=NULL,"Cellgroup is not defined for UE_id %d\n",UE_id);
|
||
AssertFatal(CellGroup->spCellConfig!=NULL,"Cellgroup->spCellConfig is null\n");
|
||
AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated!=NULL,"CellGroup->spCellConfig->spCellConfigDedicated is null\n");
|
||
}
|
||
if (bwp_id>0) {
|
||
AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList!=NULL,
|
||
"CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList is null\n");
|
||
AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList!=NULL,
|
||
"CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList is null\n");
|
||
AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count >= bwp_id,
|
||
"CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count %d < bwp_id %d\n",
|
||
CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count,bwp_id);
|
||
AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count >= bwp_id,
|
||
"CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count %d < bwp_id %d\n",
|
||
CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count,bwp_id);
|
||
|
||
bwpd = CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||
ubwpd = CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated;
|
||
}
|
||
else if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) { // this is an initialBWP
|
||
AssertFatal((bwpd=CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)!=NULL,
|
||
"CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP is null\n");
|
||
AssertFatal((ubwpd=CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP)!=NULL,
|
||
"CellGroup->spCellConfig->spCellConfigDedicated->uplnikConfig->initialUplinkBWP is null\n");
|
||
}
|
||
NR_SearchSpace_t *ss=NULL;
|
||
|
||
// common search type uses DCI format 1_0
|
||
if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) {
|
||
for (int i=0; i<8; i++) {
|
||
pdsch_to_harq_feedback[i] = i+1;
|
||
if(pdsch_to_harq_feedback[i]>*max_fb_time)
|
||
*max_fb_time = pdsch_to_harq_feedback[i];
|
||
}
|
||
}
|
||
else {
|
||
|
||
// searching for a ue specific search space
|
||
int found=0;
|
||
AssertFatal(bwpd->pdcch_Config!=NULL,"bwpd->pdcch_Config is null\n");
|
||
AssertFatal(bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,
|
||
"bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList is null\n");
|
||
for (int i=0;i<bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) {
|
||
ss=bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i];
|
||
AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n");
|
||
AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n");
|
||
if (ss->searchSpaceType->present == ss_type) {
|
||
found=1;
|
||
break;
|
||
}
|
||
}
|
||
AssertFatal(found==1,"Couldn't find a ue specific searchspace\n");
|
||
|
||
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0) {
|
||
for (int i=0; i<8; i++) {
|
||
pdsch_to_harq_feedback[i] = i+1;
|
||
if(pdsch_to_harq_feedback[i]>*max_fb_time)
|
||
*max_fb_time = pdsch_to_harq_feedback[i];
|
||
|
||
}
|
||
}
|
||
else {
|
||
AssertFatal(ubwpd!=NULL,"ubwpd shouldn't be null here\n");
|
||
if(ubwpd->pucch_Config->choice.setup->dl_DataToUL_ACK != NULL) {
|
||
for (int i=0; i<8; i++) {
|
||
pdsch_to_harq_feedback[i] = *ubwpd->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[i];
|
||
if(pdsch_to_harq_feedback[i]>*max_fb_time)
|
||
*max_fb_time = pdsch_to_harq_feedback[i];
|
||
}
|
||
}
|
||
else
|
||
AssertFatal(0==1,"There is no allocated dl_DataToUL_ACK for pdsch to harq feedback\n");
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void nr_csirs_scheduling(int Mod_idP,
|
||
frame_t frame,
|
||
sub_frame_t slot,
|
||
int n_slots_frame){
|
||
|
||
int CC_id = 0;
|
||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||
NR_list_t *UE_list = &UE_info->list;
|
||
gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP];
|
||
uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map;
|
||
|
||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||
|
||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||
NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id];
|
||
|
||
if (!CellGroup || !CellGroup->spCellConfig || !CellGroup->spCellConfig->spCellConfigDedicated ||
|
||
!CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig) continue;
|
||
|
||
NR_CSI_MeasConfig_t *csi_measconfig = CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
|
||
|
||
if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList != NULL) {
|
||
|
||
NR_NZP_CSI_RS_Resource_t *nzpcsi;
|
||
int period, offset;
|
||
|
||
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
|
||
NR_BWP_Downlink_t *bwp=CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[sched_ctrl->active_bwp->bwp_Id-1];
|
||
|
||
for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){
|
||
nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id];
|
||
NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping;
|
||
csi_period_offset(NULL,nzpcsi->periodicityAndOffset,&period,&offset);
|
||
|
||
if((frame*n_slots_frame+slot-offset)%period == 0) {
|
||
|
||
LOG_D(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot);
|
||
|
||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||
memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||
dl_tti_csirs_pdu->PDUType = NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE;
|
||
dl_tti_csirs_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_csi_rs_pdu));
|
||
|
||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csirs_pdu_rel15 = &dl_tti_csirs_pdu->csi_rs_pdu.csi_rs_pdu_rel15;
|
||
|
||
csirs_pdu_rel15->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||
csirs_pdu_rel15->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||
csirs_pdu_rel15->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
|
||
if (bwp->bwp_Common->genericParameters.cyclicPrefix)
|
||
csirs_pdu_rel15->cyclic_prefix = *bwp->bwp_Common->genericParameters.cyclicPrefix;
|
||
else
|
||
csirs_pdu_rel15->cyclic_prefix = 0;
|
||
|
||
csirs_pdu_rel15->start_rb = resourceMapping.freqBand.startingRB;
|
||
csirs_pdu_rel15->nr_of_rbs = resourceMapping.freqBand.nrofRBs;
|
||
csirs_pdu_rel15->csi_type = 1; // NZP-CSI-RS
|
||
csirs_pdu_rel15->symb_l0 = resourceMapping.firstOFDMSymbolInTimeDomain;
|
||
if (resourceMapping.firstOFDMSymbolInTimeDomain2)
|
||
csirs_pdu_rel15->symb_l1 = *resourceMapping.firstOFDMSymbolInTimeDomain2;
|
||
csirs_pdu_rel15->cdm_type = resourceMapping.cdm_Type;
|
||
csirs_pdu_rel15->freq_density = resourceMapping.density.present;
|
||
if ((resourceMapping.density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5)
|
||
&& (resourceMapping.density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs))
|
||
csirs_pdu_rel15->freq_density--;
|
||
csirs_pdu_rel15->scramb_id = nzpcsi->scramblingID;
|
||
csirs_pdu_rel15->power_control_offset = nzpcsi->powerControlOffset + 8;
|
||
if (nzpcsi->powerControlOffsetSS)
|
||
csirs_pdu_rel15->power_control_offset_ss = *nzpcsi->powerControlOffsetSS;
|
||
else
|
||
csirs_pdu_rel15->power_control_offset_ss = 1; // 0 dB
|
||
switch(resourceMapping.frequencyDomainAllocation.present){
|
||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1:
|
||
csirs_pdu_rel15->row = 1;
|
||
csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row1.buf[0])>>4)&0x0f;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2:
|
||
csirs_pdu_rel15->row = 2;
|
||
csirs_pdu_rel15->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]>>4)&0x0f) |
|
||
((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<4)&0xff0));
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4:
|
||
csirs_pdu_rel15->row = 4;
|
||
csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row4.buf[0])>>5)&0x07;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other:
|
||
csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.other.buf[0])>>2)&0x3f;
|
||
// determining the row of table 7.4.1.5.3-1 in 38.211
|
||
switch(resourceMapping.nrofPorts){
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p1:
|
||
AssertFatal(1==0,"Resource with 1 CSI port shouldn't be within other rows\n");
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p2:
|
||
csirs_pdu_rel15->row = 3;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p4:
|
||
csirs_pdu_rel15->row = 5;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2);
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p8:
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) {
|
||
csirs_pdu_rel15->row = 8;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2);
|
||
}
|
||
else{
|
||
int num_k = 0;
|
||
for (int k=0; k<6; k++)
|
||
num_k+=(((csirs_pdu_rel15->freq_domain)>>k)&0x01);
|
||
if(num_k==4) {
|
||
csirs_pdu_rel15->row = 6;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||
}
|
||
else {
|
||
csirs_pdu_rel15->row = 7;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2);
|
||
}
|
||
}
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p12:
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) {
|
||
csirs_pdu_rel15->row = 10;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2);
|
||
}
|
||
else {
|
||
csirs_pdu_rel15->row = 9;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 1);
|
||
}
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p16:
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
|
||
csirs_pdu_rel15->row = 12;
|
||
else
|
||
csirs_pdu_rel15->row = 11;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2);
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p24:
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) {
|
||
csirs_pdu_rel15->row = 14;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2) | SL_to_bitmap(csirs_pdu_rel15->symb_l1, 2));
|
||
}
|
||
else{
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) {
|
||
csirs_pdu_rel15->row = 15;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 3);
|
||
}
|
||
else {
|
||
csirs_pdu_rel15->row = 13;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2) | SL_to_bitmap(csirs_pdu_rel15->symb_l1, 2));
|
||
}
|
||
}
|
||
break;
|
||
case NR_CSI_RS_ResourceMapping__nrofPorts_p32:
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) {
|
||
csirs_pdu_rel15->row = 17;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2) | SL_to_bitmap(csirs_pdu_rel15->symb_l1, 2));
|
||
}
|
||
else{
|
||
if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) {
|
||
csirs_pdu_rel15->row = 18;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= SL_to_bitmap(csirs_pdu_rel15->symb_l0, 3);
|
||
}
|
||
else {
|
||
csirs_pdu_rel15->row = 16;
|
||
for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++)
|
||
vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (SL_to_bitmap(csirs_pdu_rel15->symb_l0, 2) | SL_to_bitmap(csirs_pdu_rel15->symb_l1, 2));
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Invalid number of ports in CSI-RS resource\n");
|
||
}
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Invalid freqency domain allocation in CSI-RS resource\n");
|
||
}
|
||
dl_req->nPDUs++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*void fill_nfapi_coresets_and_searchspaces(NR_CellGroupConfig_t *cg,
|
||
nfapi_nr_coreset_t *coreset,
|
||
nfapi_nr_search_space_t *search_space) {
|
||
|
||
nfapi_nr_coreset_t *cs;
|
||
nfapi_nr_search_space_t *ss;
|
||
NR_ServingCellConfigCommon_t *scc=cg->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
|
||
AssertFatal(cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
|
||
"downlinkBWP_ToAddModList has %d BWP!\n",
|
||
cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
|
||
|
||
NR_BWP_Downlink_t *bwp=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
|
||
struct NR_PDCCH_Config__controlResourceSetToAddModList *coreset_list = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList;
|
||
AssertFatal(coreset_list->list.count>0,
|
||
"cs list has 0 elements\n");
|
||
for (int i=0;i<coreset_list->list.count;i++) {
|
||
NR_ControlResourceSet_t *coreset_i=coreset_list->list.array[i];
|
||
cs = coreset + coreset_i->controlResourceSetId;
|
||
|
||
cs->coreset_id = coreset_i->controlResourceSetId;
|
||
AssertFatal(coreset_i->frequencyDomainResources.size <=8 && coreset_i->frequencyDomainResources.size>0,
|
||
"coreset_i->frequencyDomainResources.size=%d\n",
|
||
(int)coreset_i->frequencyDomainResources.size);
|
||
|
||
for (int f=0;f<coreset_i->frequencyDomainResources.size;f++)
|
||
((uint8_t*)&cs->frequency_domain_resources)[coreset_i->frequencyDomainResources.size-1-f]=coreset_i->frequencyDomainResources.buf[f];
|
||
|
||
cs->frequency_domain_resources>>=coreset_i->frequencyDomainResources.bits_unused;
|
||
|
||
cs->duration = coreset_i->duration;
|
||
// Need to add information about TCI_StateIDs
|
||
|
||
if (coreset_i->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_nonInterleaved)
|
||
cs->cce_reg_mapping_type = NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED;
|
||
else {
|
||
cs->cce_reg_mapping_type = NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED;
|
||
|
||
if (coreset_i->cce_REG_MappingType.choice.interleaved->reg_BundleSize==NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6)
|
||
cs->reg_bundle_size = 6;
|
||
else cs->reg_bundle_size = 2+coreset_i->cce_REG_MappingType.choice.interleaved->reg_BundleSize;
|
||
|
||
if (coreset_i->cce_REG_MappingType.choice.interleaved->interleaverSize==NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6)
|
||
cs->interleaver_size = 6;
|
||
else cs->interleaver_size = 2+coreset_i->cce_REG_MappingType.choice.interleaved->interleaverSize;
|
||
|
||
if (coreset_i->cce_REG_MappingType.choice.interleaved->shiftIndex)
|
||
cs->shift_index = *coreset_i->cce_REG_MappingType.choice.interleaved->shiftIndex;
|
||
else cs->shift_index = 0;
|
||
}
|
||
|
||
if (coreset_i->precoderGranularity == NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle)
|
||
cs->precoder_granularity = NFAPI_NR_CSET_SAME_AS_REG_BUNDLE;
|
||
else cs->precoder_granularity = NFAPI_NR_CSET_ALL_CONTIGUOUS_RBS;
|
||
if (coreset_i->tci_PresentInDCI == NULL) cs->tci_present_in_dci = 0;
|
||
else cs->tci_present_in_dci = 1;
|
||
|
||
if (coreset_i->tci_PresentInDCI == NULL) cs->dmrs_scrambling_id = 0;
|
||
else cs->dmrs_scrambling_id = *coreset_i->tci_PresentInDCI;
|
||
}
|
||
|
||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||
AssertFatal(commonSearchSpaceList->list.count>0,
|
||
"common SearchSpace list has 0 elements\n");
|
||
// Common searchspace list
|
||
for (int i=0;i<commonSearchSpaceList->list.count;i++) {
|
||
NR_SearchSpace_t *searchSpace_i=commonSearchSpaceList->list.array[i];
|
||
ss=search_space + searchSpace_i->searchSpaceId;
|
||
if (searchSpace_i->controlResourceSetId) ss->coreset_id = *searchSpace_i->controlResourceSetId;
|
||
switch(searchSpace_i->monitoringSlotPeriodicityAndOffset->present) {
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL1;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL2;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl2;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL4;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl4;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL5;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl5;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL8;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl8;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL10;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl10;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL16;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl16;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL20;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl20;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL40;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl40;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL80;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl80;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL160;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl160;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL320;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl320;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL640;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl640;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL1280;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl1280;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL2560;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl2560;
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Shouldn't get here\n");
|
||
break;
|
||
}
|
||
if (searchSpace_i->duration) ss->duration = *searchSpace_i->duration;
|
||
else ss->duration = 1;
|
||
|
||
|
||
AssertFatal(searchSpace_i->monitoringSymbolsWithinSlot->size == 2,
|
||
"ss_i->monitoringSymbolsWithinSlot = %d != 2\n",
|
||
(int)searchSpace_i->monitoringSymbolsWithinSlot->size);
|
||
((uint8_t*)&ss->monitoring_symbols_in_slot)[1] = searchSpace_i->monitoringSymbolsWithinSlot->buf[0];
|
||
((uint8_t*)&ss->monitoring_symbols_in_slot)[0] = searchSpace_i->monitoringSymbolsWithinSlot->buf[1];
|
||
|
||
AssertFatal(searchSpace_i->nrofCandidates!=NULL,"searchSpace_%d->nrofCandidates is null\n",(int)searchSpace_i->searchSpaceId);
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel1 == NR_SearchSpace__nrofCandidates__aggregationLevel1_n8)
|
||
ss->number_of_candidates[0] = 8;
|
||
else ss->number_of_candidates[0] = searchSpace_i->nrofCandidates->aggregationLevel1;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel2 == NR_SearchSpace__nrofCandidates__aggregationLevel2_n8)
|
||
ss->number_of_candidates[1] = 8;
|
||
else ss->number_of_candidates[1] = searchSpace_i->nrofCandidates->aggregationLevel2;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel4 == NR_SearchSpace__nrofCandidates__aggregationLevel4_n8)
|
||
ss->number_of_candidates[2] = 8;
|
||
else ss->number_of_candidates[2] = searchSpace_i->nrofCandidates->aggregationLevel4;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel8 == NR_SearchSpace__nrofCandidates__aggregationLevel8_n8)
|
||
ss->number_of_candidates[3] = 8;
|
||
else ss->number_of_candidates[3] = searchSpace_i->nrofCandidates->aggregationLevel8;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel16 == NR_SearchSpace__nrofCandidates__aggregationLevel16_n8)
|
||
ss->number_of_candidates[4] = 8;
|
||
else ss->number_of_candidates[4] = searchSpace_i->nrofCandidates->aggregationLevel16;
|
||
|
||
AssertFatal(searchSpace_i->searchSpaceType->present==NR_SearchSpace__searchSpaceType_PR_common,
|
||
"searchspace %d is not common\n",(int)searchSpace_i->searchSpaceId);
|
||
AssertFatal(searchSpace_i->searchSpaceType->choice.common!=NULL,
|
||
"searchspace %d common is null\n",(int)searchSpace_i->searchSpaceId);
|
||
ss->search_space_type = NFAPI_NR_SEARCH_SPACE_TYPE_COMMON;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)
|
||
ss->css_formats_0_0_and_1_0 = 1;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_0) {
|
||
ss->css_format_2_0 = 1;
|
||
// add aggregation info
|
||
}
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_1)
|
||
ss->css_format_2_1 = 1;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_2)
|
||
ss->css_format_2_2 = 1;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_3)
|
||
ss->css_format_2_3 = 1;
|
||
}
|
||
|
||
struct NR_PDCCH_Config__searchSpacesToAddModList *dedicatedSearchSpaceList = bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList;
|
||
AssertFatal(dedicatedSearchSpaceList->list.count>0,
|
||
"Dedicated Search Space list has 0 elements\n");
|
||
// Dedicated searchspace list
|
||
for (int i=0;i<dedicatedSearchSpaceList->list.count;i++) {
|
||
NR_SearchSpace_t *searchSpace_i=dedicatedSearchSpaceList->list.array[i];
|
||
ss=search_space + searchSpace_i->searchSpaceId;
|
||
ss->search_space_id = searchSpace_i->searchSpaceId;
|
||
if (searchSpace_i->controlResourceSetId) ss->coreset_id = *searchSpace_i->controlResourceSetId;
|
||
switch(searchSpace_i->monitoringSlotPeriodicityAndOffset->present) {
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL1;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL2;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl2;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL4;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl4;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL5;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl5;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL8;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl8;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL10;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl10;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL16;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl16;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL20;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl20;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL40;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl40;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL80;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl80;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL160;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl160;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL320;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl320;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL640;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl640;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL1280;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl1280;
|
||
break;
|
||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
|
||
ss->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL2560;
|
||
ss->slot_monitoring_offset = searchSpace_i->monitoringSlotPeriodicityAndOffset->choice.sl2560;
|
||
break;
|
||
default:
|
||
AssertFatal(1==0,"Shouldn't get here\n");
|
||
break;
|
||
}
|
||
if (searchSpace_i->duration) ss->duration = *searchSpace_i->duration;
|
||
else ss->duration = 1;
|
||
|
||
|
||
AssertFatal(searchSpace_i->monitoringSymbolsWithinSlot->size == 2,
|
||
"ss_i->monitoringSymbolsWithinSlot = %d != 2\n",
|
||
(int)searchSpace_i->monitoringSymbolsWithinSlot->size);
|
||
((uint8_t*)&ss->monitoring_symbols_in_slot)[1] = searchSpace_i->monitoringSymbolsWithinSlot->buf[0];
|
||
((uint8_t*)&ss->monitoring_symbols_in_slot)[0] = searchSpace_i->monitoringSymbolsWithinSlot->buf[1];
|
||
|
||
AssertFatal(searchSpace_i->nrofCandidates!=NULL,"searchSpace_%d->nrofCandidates is null\n",(int)searchSpace_i->searchSpaceId);
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel1 == NR_SearchSpace__nrofCandidates__aggregationLevel1_n8)
|
||
ss->number_of_candidates[0] = 8;
|
||
else ss->number_of_candidates[0] = searchSpace_i->nrofCandidates->aggregationLevel1;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel2 == NR_SearchSpace__nrofCandidates__aggregationLevel2_n8)
|
||
ss->number_of_candidates[1] = 8;
|
||
else ss->number_of_candidates[1] = searchSpace_i->nrofCandidates->aggregationLevel2;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel4 == NR_SearchSpace__nrofCandidates__aggregationLevel4_n8)
|
||
ss->number_of_candidates[2] = 8;
|
||
else ss->number_of_candidates[2] = searchSpace_i->nrofCandidates->aggregationLevel4;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel8 == NR_SearchSpace__nrofCandidates__aggregationLevel8_n8)
|
||
ss->number_of_candidates[3] = 8;
|
||
else ss->number_of_candidates[3] = searchSpace_i->nrofCandidates->aggregationLevel8;
|
||
if (searchSpace_i->nrofCandidates->aggregationLevel16 == NR_SearchSpace__nrofCandidates__aggregationLevel16_n8)
|
||
ss->number_of_candidates[4] = 8;
|
||
else ss->number_of_candidates[4] = searchSpace_i->nrofCandidates->aggregationLevel16;
|
||
|
||
if (searchSpace_i->searchSpaceType->present==NR_SearchSpace__searchSpaceType_PR_ue_Specific && searchSpace_i->searchSpaceType->choice.ue_Specific!=NULL) {
|
||
|
||
ss->search_space_type = NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC;
|
||
|
||
ss->uss_dci_formats = searchSpace_i->searchSpaceType->choice.ue_Specific-> dci_Formats;
|
||
|
||
} else if (searchSpace_i->searchSpaceType->present==NR_SearchSpace__searchSpaceType_PR_common && searchSpace_i->searchSpaceType->choice.common!=NULL) {
|
||
ss->search_space_type = NFAPI_NR_SEARCH_SPACE_TYPE_COMMON;
|
||
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)
|
||
ss->css_formats_0_0_and_1_0 = 1;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_0) {
|
||
ss->css_format_2_0 = 1;
|
||
// add aggregation info
|
||
}
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_1)
|
||
ss->css_format_2_1 = 1;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_2)
|
||
ss->css_format_2_2 = 1;
|
||
if (searchSpace_i->searchSpaceType->choice.common->dci_Format2_3)
|
||
ss->css_format_2_3 = 1;
|
||
}
|
||
}
|
||
}
|
||
*/
|