Commit 09204798 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/initial_gNB_NTN_support' into integration_2024_w22

parents 5b53f4ee f7c27328
......@@ -141,6 +141,53 @@ You can see all options by typing
./nr-uesoftmodem --help
```
## How to run a NTN configuration
### NTN channel
A 5G NR NTN configuration only works in a non-terrestrial setup.
Therefore either SDR boards and a dedicated NTN channel emulator are required, or RFsimulator has to be configured to simulate a NTN channel.
As shown on the [rfsimulator page](../radio/rfsimulator/README.md), RFsimulator provides different possibilities.
E.g. to perform a simple simulation of a satellite in geostationary orbit (GEO), these parameters should be added to both gNB and UE command lines:
```
--rfsimulator.prop_delay 238.74
```
### gNB
The main parameter to cope with the large NTN propagation delay is the cellSpecificKoffset.
This parameter is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213).
The unit of the field Koffset is number of slots for a given subcarrier spacing of 15 kHz.
This parameter can be provided to the gNB in the conf file as `cellSpecificKoffset_r17` in the section `servingCellConfigCommon`.
```
...
cellSpecificKoffset_r17 = 478;
...
```
Besides this, some timers, e.g. `sr_ProhibitTimer_v1700`, `t300`, `t301` and `t319`, in the conf file section `gNBs.[0].TIMERS` might need to be extended.
```
...
TIMERS :
{
sr_ProhibitTimer = 0;
sr_TransMax = 64;
sr_ProhibitTimer_v1700 = 512;
t300 = 2000;
t301 = 2000;
t319 = 2000;
};
...
```
So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, GEO satellite 5G NR NTN is this:
```
cd cmake_targets
sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --sa --rfsim --rfsimulator.prop_delay 238.74
```
# Specific OAI modes
## phy-test setup with OAI UE
......
......@@ -643,7 +643,17 @@ int main(int argc, char **argv)
.minRXTXTIME = 6,
.do_CSIRS = 0,
.do_SRS = 0,
.force_256qam_off = false};
.force_256qam_off = false,
.timer_config.sr_ProhibitTimer = 0,
.timer_config.sr_TransMax = 64,
.timer_config.sr_ProhibitTimer_v1700 = 0,
.timer_config.t300 = 400,
.timer_config.t301 = 400,
.timer_config.t310 = 2000,
.timer_config.n310 = 10,
.timer_config.t311 = 3000,
.timer_config.n311 = 1,
.timer_config.t319 = 400};
RC.nb_nr_macrlc_inst = 1;
RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
......
......@@ -607,7 +607,17 @@ int main(int argc, char *argv[])
.minRXTXTIME = 0,
.do_CSIRS = 0,
.do_SRS = 0,
.force_256qam_off = false};
.force_256qam_off = false,
.timer_config.sr_ProhibitTimer = 0,
.timer_config.sr_TransMax = 64,
.timer_config.sr_ProhibitTimer_v1700 = 0,
.timer_config.t300 = 400,
.timer_config.t301 = 400,
.timer_config.t310 = 2000,
.timer_config.n310 = 10,
.timer_config.t311 = 3000,
.timer_config.n311 = 1,
.timer_config.t319 = 400};
RC.nb_nr_macrlc_inst = 1;
RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
......
......@@ -109,6 +109,7 @@
#define GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2 "nrofUplinkSymbols2"
#define GNB_CONFIG_STRING_SSPBCHBLOCKPOWER "ssPBCH_BlockPower"
#define GNB_CONFIG_STRING_CELLSPECIFICKOFFSET "cellSpecificKoffset_r17"
#define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273}
......@@ -232,6 +233,7 @@
{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\
{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0},\
{GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,.i64ptr=&scc->ss_PBCH_BlockPower,.defint64val=20,TYPE_INT64,0}, \
{GNB_CONFIG_STRING_CELLSPECIFICKOFFSET,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17,.defint64val=0,TYPE_INT64,0}, \
{GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,.defintval=-1,TYPE_INT64,0}}
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
......
......@@ -214,7 +214,10 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) {
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n40.buf = MALLOC(5);
//ratematchpattern->subcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t));
//ratematchpatternid = CALLOC(1,sizeof(NR_RateMatchPatternId_t));
scc->ext2 = CALLOC(1, sizeof(*scc->ext2));
scc->ext2->ntn_Config_r17 = CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17));
scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17));
}
void fill_scc_sim(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL,int N_RB_UL,int mu_dl,int mu_ul) {
......@@ -406,6 +409,13 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) {
// check pucch_ResourceConfig
AssertFatal(*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon < 2,
"pucch_ResourceConfig should be 0 or 1 for now\n");
if(*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 == 0) {
free(scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17);
free(scc->ext2->ntn_Config_r17);
free(scc->ext2);
scc->ext2 = NULL;
}
}
/* Function to allocate dedicated serving cell config strutures */
......@@ -1249,6 +1259,35 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
int tot_ant = config.pdsch_AntennaPorts.N1 * config.pdsch_AntennaPorts.N2 * config.pdsch_AntennaPorts.XP;
AssertFatal(config.maxMIMO_layers != 0 && config.maxMIMO_layers <= tot_ant, "Invalid maxMIMO_layers %d\n", config.maxMIMO_layers);
paramdef_t Timers_Params[] = GNB_TIMERS_PARAMS_DESC;
char aprefix[MAX_OPTNAME_SIZE * 2 + 8];
sprintf(aprefix, "%s.[0].%s", GNB_CONFIG_STRING_GNB_LIST, GNB_CONFIG_STRING_TIMERS_CONFIG);
config_get(config_get_if(), Timers_Params, sizeofArray(Timers_Params), aprefix);
config.timer_config.sr_ProhibitTimer = *Timers_Params[GNB_TIMERS_SR_PROHIBIT_TIMER_IDX].iptr;
config.timer_config.sr_TransMax = *Timers_Params[GNB_TIMERS_SR_TRANS_MAX_IDX].iptr;
config.timer_config.sr_ProhibitTimer_v1700 = *Timers_Params[GNB_TIMERS_SR_PROHIBIT_TIMER_V1700_IDX].iptr;
config.timer_config.t300 = *Timers_Params[GNB_TIMERS_T300_IDX].iptr;
config.timer_config.t301 = *Timers_Params[GNB_TIMERS_T301_IDX].iptr;
config.timer_config.t310 = *Timers_Params[GNB_TIMERS_T310_IDX].iptr;
config.timer_config.n310 = *Timers_Params[GNB_TIMERS_N310_IDX].iptr;
config.timer_config.t311 = *Timers_Params[GNB_TIMERS_T311_IDX].iptr;
config.timer_config.n311 = *Timers_Params[GNB_TIMERS_N311_IDX].iptr;
config.timer_config.t319 = *Timers_Params[GNB_TIMERS_T319_IDX].iptr;
LOG_I(GNB_APP,
"sr_ProhibitTimer %d, sr_TransMax %d, sr_ProhibitTimer_v1700 %d, "
"t300 %d, t301 %d, t310 %d, n310 %d, t311 %d, n311 %d, t319 %d\n",
config.timer_config.sr_ProhibitTimer,
config.timer_config.sr_TransMax,
config.timer_config.sr_ProhibitTimer_v1700,
config.timer_config.t300,
config.timer_config.t301,
config.timer_config.t310,
config.timer_config.n310,
config.timer_config.t311,
config.timer_config.n311,
config.timer_config.t319);
NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME);
//xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc);
NR_ServingCellConfig_t *scd = get_scd_config(cfg);
......
......@@ -327,6 +327,51 @@ typedef enum {
#define GNB_AMF_IPV4_ADDRESS_IDX 0
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* TIMERS configuration parameters section name */
#define GNB_CONFIG_STRING_TIMERS_CONFIG "TIMERS"
/* TIMERS configuration parameters names */
#define GNB_CONFIG_STRING_TIMERS_SR_PROHIBIT_TIMER "sr_ProhibitTimer"
#define GNB_CONFIG_STRING_TIMERS_SR_TRANS_MAX "sr_TransMax"
#define GNB_CONFIG_STRING_TIMERS_SR_PROHIBIT_TIMER_V1700 "sr_ProhibitTimer_v1700"
#define GNB_CONFIG_STRING_TIMERS_T300 "t300"
#define GNB_CONFIG_STRING_TIMERS_T301 "t301"
#define GNB_CONFIG_STRING_TIMERS_T310 "t310"
#define GNB_CONFIG_STRING_TIMERS_N310 "n310"
#define GNB_CONFIG_STRING_TIMERS_T311 "t311"
#define GNB_CONFIG_STRING_TIMERS_N311 "n311"
#define GNB_CONFIG_STRING_TIMERS_T319 "t319"
/*-------------------------------------------------------------------------------------------------------------------------------------*/
/* TIMERS configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------*/
#define GNB_TIMERS_PARAMS_DESC { \
{GNB_CONFIG_STRING_TIMERS_SR_PROHIBIT_TIMER, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_SR_TRANS_MAX, NULL, 0, .iptr=NULL, .defintval=64, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_SR_PROHIBIT_TIMER_V1700, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_T300, NULL, 0, .iptr=NULL, .defintval=400, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_T301, NULL, 0, .iptr=NULL, .defintval=400, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_T310, NULL, 0, .iptr=NULL, .defintval=2000, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_N310, NULL, 0, .iptr=NULL, .defintval=10, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_T311, NULL, 0, .iptr=NULL, .defintval=3000, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_N311, NULL, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_TIMERS_T319, NULL, 0, .iptr=NULL, .defintval=400, TYPE_INT, 0}, \
}
#define GNB_TIMERS_SR_PROHIBIT_TIMER_IDX 0
#define GNB_TIMERS_SR_TRANS_MAX_IDX 1
#define GNB_TIMERS_SR_PROHIBIT_TIMER_V1700_IDX 2
#define GNB_TIMERS_T300_IDX 3
#define GNB_TIMERS_T301_IDX 4
#define GNB_TIMERS_T310_IDX 5
#define GNB_TIMERS_N310_IDX 6
#define GNB_TIMERS_T311_IDX 7
#define GNB_TIMERS_N311_IDX 8
#define GNB_TIMERS_T319_IDX 9
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* SCTP configuration parameters section name */
......
......@@ -97,6 +97,13 @@ void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers)
}
}
int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc)
{
if (scc->ext2 && scc->ext2->ntn_Config_r17 && scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17)
return *scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 << *scc->ssbSubcarrierSpacing;
return 0;
}
int precoding_weigths_generation(nfapi_nr_pm_list_t *mat,
int pmiq,
int L,
......@@ -602,14 +609,19 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
"SSB Bitmap type %d is not valid\n",
scc->ssb_PositionsInBurst->present);
int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
if (*scc->ssbSubcarrierSpacing == 0)
n <<= 1; // to have enough room for feedback possibly beyond the frame we need a larger array at 15kHz SCS
nrmac->common_channels[0].vrb_map_UL = calloc(n * MAX_BWP_SIZE, sizeof(uint16_t));
nrmac->vrb_map_UL_size = n;
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
const int size = n << (int)ceil(log2((NTN_gNB_Koffset + 13) / n + 1)); // 13 is upper limit for max_fb_time
nrmac->vrb_map_UL_size = size;
nrmac->common_channels[0].vrb_map_UL = calloc(size * MAX_BWP_SIZE, sizeof(uint16_t));
AssertFatal(nrmac->common_channels[0].vrb_map_UL,
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
nrmac->UL_tti_req_ahead_size = size;
nrmac->UL_tti_req_ahead[0] = calloc(size, sizeof(nfapi_nr_ul_tti_request_t));
AssertFatal(nrmac->UL_tti_req_ahead[0], "could not allocate memory for nrmac->UL_tti_req_ahead[0]\n");
LOG_I(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
config_common(nrmac, config->pdsch_AntennaPorts, config->pusch_AntennaPorts, scc);
......@@ -677,7 +689,7 @@ void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac);
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac, &nrmac->radio_config.timer_config);
cc->sib1 = sib1;
cc->sib1_bcch_length = encode_SIB1_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n");
......
......@@ -68,7 +68,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon;
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
UL_tti_req_ahead_initialization(gNB, scc, num_slots, CC_idP, frameP, slotP, *scc->ssbSubcarrierSpacing);
UL_tti_req_ahead_initialization(gNB, num_slots, CC_idP, frameP, slotP);
nfapi_nr_dl_tti_pdcch_pdu_rel15_t **pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t **)gNB->pdcch_pdu_idx[CC_idP];
......
......@@ -542,10 +542,10 @@ static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_Cont
// ra-ContentionResolutionTimer ENUMERATED {sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64}
// The initial value for the contention resolution timer.
// Value sf8 corresponds to 8 subframes, value sf16 corresponds to 16 subframes, and so on.
// We add K2 because we start the timer in the DL slot that schedules Msg3/Msg3 retransmission
ra->contention_resolution_timer = ((((int)ra_ContentionResolutionTimer + 1) * 8) << scs) + K2;
LOG_D(NR_MAC,
"Starting RA Contention Resolution timer with %d ms + %d K2 (%d slots) duration\n",
// We add 2 * K2 because the timer runs from Msg2 transmission till Msg4 ACK reception
ra->contention_resolution_timer = ((((int)ra_ContentionResolutionTimer + 1) * 8) << scs) + 2 * K2;
LOG_I(NR_MAC,
"Starting RA Contention Resolution timer with %d ms + 2 * %d K2 (%d slots) duration\n",
((int)ra_ContentionResolutionTimer + 1) * 8,
K2,
ra->contention_resolution_timer);
......@@ -580,8 +580,8 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common;
int mu = ul_bwp->scs;
uint8_t K2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2;
const int sched_frame = (frame + (slot + K2 >= nr_slots_per_frame[mu])) % 1024;
uint16_t K2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc);
const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER;
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) {
......@@ -747,6 +747,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
}
static int get_feasible_msg3_tda(frame_type_t frame_type,
const NR_ServingCellConfigCommon_t *scc,
int mu_delta,
uint64_t ulsch_slot_bitmap[3],
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list,
......@@ -761,12 +762,14 @@ static int get_feasible_msg3_tda(frame_type_t frame_type,
return tda;
}
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
// TDD
DevAssert(tdd != NULL);
uint8_t tdd_period_slot = slots_per_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
for (int i = 0; i < tda_list->list.count; i++) {
// check if it is UL
long k2 = *tda_list->list.array[i]->k2;
long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset;
int temp_slot = (slot + k2 + mu_delta) % slots_per_frame; // msg3 slot according to 8.3 in 38.213
if (!is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot))
continue;
......@@ -820,10 +823,10 @@ static void nr_get_Msg3alloc(module_id_t module_id,
int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
SLIV2SL(startSymbolAndLength, &ra->msg3_startsymb, &ra->msg3_nbSymb);
long k2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2;
long k2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc);
int abs_slot = current_slot + k2 + DELTA[mu];
ra->Msg3_slot = abs_slot % n_slots_frame;
ra->Msg3_frame = (current_frame + (abs_slot / n_slots_frame)) % 1024;
ra->Msg3_frame = (current_frame + (abs_slot / n_slots_frame)) % MAX_FRAME_NUMBER;
LOG_I(NR_MAC,
"UE %04x: Msg3 scheduled at %d.%d (%d.%d k2 %ld TDA %u)\n",
......@@ -1224,6 +1227,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
}
ra->Msg3_tda_id = get_feasible_msg3_tda(cc->frame_type,
scc,
DELTA[ul_bwp->scs],
nr_mac->ulsch_slot_bitmap,
ul_bwp->tdaList_Common,
......@@ -1464,7 +1468,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
start_ra_contention_resolution_timer(
ra,
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,
*ra->UL_BWP.tdaList_Common->list.array[ra->Msg3_tda_id]->k2,
*ra->UL_BWP.tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc),
ra->UL_BWP.scs);
if (ra->cfra) {
......
......@@ -660,7 +660,7 @@ static void pf_dl(module_id_t module_id,
}
/* Check DL buffer and skip this UE if no bytes and no TA necessary */
if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024)
if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 100) % 1024)
continue;
/* Calculate coeff */
......@@ -805,8 +805,8 @@ static void pf_dl(module_id_t module_id,
// awaiting. Therefore, for the time being, we put a fixed overhead of 12
// (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of
// PDUs, we replace with 3 * numPDUs
const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
//const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 100) % 1024);
//const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 100) % 1024);
nr_find_nb_rb(sched_pdsch->Qm,
sched_pdsch->R,
1, // no transform precoding for DL
......@@ -958,7 +958,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
* Possible improvement: take the periodicity from input file.
* If such UE is not scheduled now, it will be by the preprocessor later.
* If we add the CE, ta_apply will be reset */
if (frame == (sched_ctrl->ta_frame + 10) % 1024) {
if (frame == (sched_ctrl->ta_frame + 100) % 1024) {
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
LOG_D(NR_MAC, "[UE %04x][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE->rnti, frame, slot);
}
......
......@@ -60,6 +60,12 @@ void nr_preprocessor_phytest(module_id_t module_id,
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
const int CC_id = 0;
/* return if all DL HARQ processes wait for feedback */
if (sched_ctrl->retrans_dl_harq.head == -1 && sched_ctrl->available_dl_harq.head == -1) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free DL HARQ process, skipping\n", UE->rnti, frame, slot);
return;
}
const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot);
NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp,
sched_ctrl->search_space->searchSpaceType->present,
......@@ -216,6 +222,12 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const int mu = ul_bwp->scs;
/* return if all UL HARQ processes wait for feedback */
if (sched_ctrl->retrans_ul_harq.head == -1 && sched_ctrl->available_ul_harq.head == -1) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free UL HARQ process, skipping\n", UE->rnti, frame, slot);
return false;
}
NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = get_ul_tdalist(ul_bwp,
sched_ctrl->coreset->controlResourceSetId,
sched_ctrl->search_space->searchSpaceType->present,
......@@ -227,8 +239,8 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
"time domain assignment %d >= %d\n",
temp_tda,
tdaList->list.count);
int K2 = get_K2(tdaList, temp_tda, mu);
const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
int K2 = get_K2(tdaList, temp_tda, mu, scc);
const int sched_frame = frame + (slot + K2) / nr_slots_per_frame[mu];
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
const int tda = get_ul_tda(nr_mac, scc, sched_frame, sched_slot);
if (tda < 0)
......
......@@ -2546,15 +2546,16 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
const NR_UE_UL_BWP_t *ul_bwp,
const NR_ServingCellConfigCommon_t *scc) {
const NR_ServingCellConfigCommon_t *scc)
{
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame;
// PUCCH list size is given by the number of UL slots in the PUCCH period
// the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead
const int list_size = n_ul_slots_period << (ul_bwp->max_fb_time/nr_slots_period);
const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / nr_slots_period + 1));
if(!sched_ctrl->sched_pucch) {
sched_ctrl->sched_pucch = calloc(list_size, sizeof(*sched_ctrl->sched_pucch));
sched_ctrl->sched_pucch_size = list_size;
......@@ -3075,26 +3076,19 @@ int ul_buffer_index(int frame, int slot, int scs, int size)
return abs_slot % size;
}
void UL_tti_req_ahead_initialization(gNB_MAC_INST * gNB, NR_ServingCellConfigCommon_t *scc, int n, int CCid, frame_t frameP, int slotP, int scs)
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP)
{
if(gNB->UL_tti_req_ahead[CCid])
if(gNB->UL_tti_req_ahead[CCid][1].Slot == 1)
return;
int size = n;
if (scs == 0)
size <<= 1; // to have enough room for feedback possibly beyond the frame we need a larger array at 15kHz SCS
gNB->UL_tti_req_ahead_size = size;
gNB->UL_tti_req_ahead[CCid] = calloc(size, sizeof(nfapi_nr_ul_tti_request_t));
AssertFatal(gNB->UL_tti_req_ahead[CCid], "could not allocate memory for RC.nrmac[]->UL_tti_req_ahead[]\n");
/* fill in slot/frame numbers: slot is fixed, frame will be updated by scheduler
* consider that scheduler runs sl_ahead: the first sl_ahead slots are
* already "in the past" and thus we put frame 1 instead of 0! */
for (int i = 0; i < size; ++i) {
for (int i = 0; i < gNB->UL_tti_req_ahead_size; ++i) {
int abs_slot = frameP * n + slotP + i;
nfapi_nr_ul_tti_request_t *req = &gNB->UL_tti_req_ahead[CCid][abs_slot % size];
req->SFN = abs_slot / n;
nfapi_nr_ul_tti_request_t *req = &gNB->UL_tti_req_ahead[CCid][abs_slot % gNB->UL_tti_req_ahead_size];
req->SFN = (abs_slot / n) % MAX_FRAME_NUMBER;
req->Slot = abs_slot % n;
}
}
......
......@@ -512,8 +512,11 @@ static void nr_fill_nfapi_srs(int module_id,
*********************************************************************/
void nr_schedule_srs(int module_id, frame_t frame, int slot)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
const int CC_id = 0;
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
NR_UEs_t *UE_info = &nrmac->UE_info;
......@@ -571,14 +574,14 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
int max_k2 = 0;
// avoid last one in the list (for msg3)
for (int i = 0; i < num_tda - 1; i++) {
int k2 = get_K2(tdaList, i, current_BWP->scs);
int k2 = get_K2(tdaList, i, current_BWP->scs, scc);
max_k2 = k2 > max_k2 ? k2 : max_k2;
}
// we are sheduling SRS max_k2 slot in advance for the presence of SRS to be taken into account when scheduling PUSCH
const int n_slots_frame = nr_slots_per_frame[current_BWP->scs];
const int sched_slot = (slot + max_k2) % n_slots_frame;
const int sched_frame = (frame + ((slot + max_k2) / n_slots_frame)) % 1024;
const int sched_frame = (frame + (slot + max_k2) / n_slots_frame) % MAX_FRAME_NUMBER;
const uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
const uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
......
......@@ -211,8 +211,12 @@ void nr_csi_meas_reporting(int Mod_idP,
frame_t frame,
sub_frame_t slot)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
const int CC_id = 0;
gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP];
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
UE_iterator(nrmac->UE_info.list, UE ) {
......@@ -242,8 +246,8 @@ void nr_csi_meas_reporting(int Mod_idP,
// we schedule CSI reporting max_fb_time slots in advance
int period, offset;
csi_period_offset(csirep, NULL, &period, &offset);
const int sched_slot = (slot + ul_bwp->max_fb_time) % n_slots_frame;
const int sched_frame = (frame + ((slot + ul_bwp->max_fb_time) / n_slots_frame)) % 1024;
const int sched_slot = (slot + ul_bwp->max_fb_time + NTN_gNB_Koffset) % n_slots_frame;
const int sched_frame = (frame + ((slot + ul_bwp->max_fb_time + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
continue;
......@@ -260,7 +264,6 @@ void nr_csi_meas_reporting(int Mod_idP,
AssertFatal(res_index < n,
"CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource);
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon;
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n");
const int pucch_index = get_pucch_index(sched_frame, sched_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
......@@ -974,7 +977,7 @@ static NR_UE_harq_t *find_harq(frame_t frame, sub_frame_t slot, NR_UE_info_t * U
return NULL;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
/* old feedbacks we missed: mark for retransmission */
while (harq->feedback_frame != frame
while ((harq->feedback_frame - frame + 1024 ) % 1024 > 512 // harq->feedback_frame < frame, distance of 512 is boundary to decide if feedback_frame is in the past or future
|| (harq->feedback_frame == frame && harq->feedback_slot < slot)) {
LOG_W(NR_MAC,
"UE %04x expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the past)\n",
......@@ -992,7 +995,9 @@ static NR_UE_harq_t *find_harq(frame_t frame, sub_frame_t slot, NR_UE_info_t * U
harq = &sched_ctrl->harq_processes[pid];
}
/* feedbacks that we wait for in the future: don't do anything */
if (harq->feedback_slot > slot) {
if ((frame - harq->feedback_frame + 1024 ) % 1024 > 512 // harq->feedback_frame > frame, distance of 512 is boundary to decide if feedback_frame is in the past or future
|| (harq->feedback_frame == frame && harq->feedback_slot > slot)) {
LOG_W(NR_MAC,
"UE %04x expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the future)\n",
UE->rnti,
......@@ -1237,8 +1242,10 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
* called often, don't try to lock every time */
const int CC_id = 0;
const int minfbtime = mac->radio_config.minRXTXTIME;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset;
const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
......@@ -1261,13 +1268,13 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
for (int f = 0; f < fb_size; f++) {
// can't schedule ACKNACK before minimum feedback time
if(pdsch_to_harq_feedback[f] < minfbtime)
if((pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) < minfbtime)
continue;
const int pucch_slot = (slot + pdsch_to_harq_feedback[f]) % n_slots_frame;
const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame;
// check if the slot is UL
if(pucch_slot%nr_slots_period < first_ul_slot_period)
continue;
const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f]) / n_slots_frame)) & 1023;
const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
// we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures
const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
......@@ -1346,7 +1353,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
return pucch_index; // index of current PUCCH structure
}
}
LOG_D(NR_MAC, "DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", frame, slot);
LOG_W(NR_MAC, "DL %4d.%2d, Couldn't find scheduling occasion for this HARQ process\n", frame, slot);
return -1;
}
......
......@@ -1433,19 +1433,21 @@ void handle_nr_srs_measurements(const module_id_t module_id,
long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
int time_domain_assignment,
int mu) {
int mu,
const NR_ServingCellConfigCommon_t *scc)
{
/* we assume that this function is mutex-protected from outside */
NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdaList->list.array[time_domain_assignment];
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
if (tda->k2)
return *tda->k2;
return *tda->k2 + NTN_gNB_Koffset;
else if (mu < 2)
return 1;
return 1 + NTN_gNB_Koffset;
else if (mu == 2)
return 2;
return 2 + NTN_gNB_Koffset;
else
return 3;
return 3 + NTN_gNB_Koffset;
}
static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, int CC_id, NR_UE_info_t* UE, frame_t frame, sub_frame_t slot, uint32_t ulsch_max_frame_inactivity)
......@@ -2084,13 +2086,13 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_
sched_ctrl->coreset->controlResourceSetId,
sched_ctrl->search_space->searchSpaceType->present,
TYPE_C_RNTI_);
int K2 = get_K2(tdaList, temp_tda, mu);
const int sched_frame = (frame + (slot + K2 >= nr_slots_per_frame[mu])) & 1023;
int K2 = get_K2(tdaList, temp_tda, mu, scc);
const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER;
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
const int tda = get_ul_tda(nr_mac, scc, sched_frame, sched_slot);
if (tda < 0)
return false;
DevAssert(K2 == get_K2(tdaList, tda, mu));
DevAssert(K2 == get_K2(tdaList, tda, mu, scc));
if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot))
return false;
......@@ -2099,9 +2101,9 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_
sched_ctrl->sched_pusch.frame = sched_frame;
UE_iterator(nr_mac->UE_info.list, UE2) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE2->UE_sched_ctrl;
AssertFatal(K2 == get_K2(tdaList, tda, mu),
AssertFatal(K2 == get_K2(tdaList, tda, mu, scc),
"Different K2, %d(UE%d) != %ld(UE%04x)\n",
K2, 0, get_K2(tdaList, tda, mu), UE2->rnti);
K2, 0, get_K2(tdaList, tda, mu, scc), UE2->rnti);
sched_ctrl->sched_pusch.slot = sched_slot;
sched_ctrl->sched_pusch.frame = sched_frame;
}
......
......@@ -37,6 +37,7 @@
void set_cset_offset(uint16_t);
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers);
int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc);
void mac_top_init_gNB(ngran_node_t node_type,
NR_ServingCellConfigCommon_t *scc,
......@@ -264,7 +265,8 @@ NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
int time_domain_assignment,
int mu);
int mu,
const NR_ServingCellConfigCommon_t *scc);
const NR_DMRS_UplinkConfig_t *get_DMRS_UplinkConfig(const NR_PUSCH_Config_t *pusch_Config, const NR_tda_info_t *tda_info);
......@@ -418,7 +420,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
int ul_buffer_index(int frame, int slot, int scs, int size);
void UL_tti_req_ahead_initialization(gNB_MAC_INST * gNB, NR_ServingCellConfigCommon_t *scc, int n, int CCid, frame_t frameP, int slotP, int scs);
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP);
......
......@@ -128,6 +128,19 @@ typedef struct nr_pdsch_AntennaPorts_t {
int XP;
} nr_pdsch_AntennaPorts_t;
typedef struct nr_mac_timers {
int sr_ProhibitTimer;
int sr_TransMax;
int sr_ProhibitTimer_v1700;
int t300;
int t301;
int t310;
int n310;
int t311;
int n311;
int t319;
} nr_mac_timers_t;
typedef struct nr_mac_config_t {
int sib1_tda;
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts;
......@@ -141,6 +154,7 @@ typedef struct nr_mac_config_t {
int maxMIMO_layers;
//int pusch_TargetSNRx10;
//int pucch_TargetSNRx10;
nr_mac_timers_t timer_config;
} nr_mac_config_t;
typedef struct NR_preamble_ue {
......@@ -422,7 +436,7 @@ typedef struct NR_sched_pdsch {
int8_t dl_harq_pid;
// pucch format allocation
uint8_t pucch_allocation;
uint16_t pucch_allocation;
uint16_t pm_index;
uint8_t nrOfLayers;
......
This diff is collapsed.
......@@ -38,6 +38,9 @@
struct nr_mac_config_t;
typedef struct nr_mac_config_t nr_mac_config_t;
struct nr_mac_timers;
typedef struct nr_mac_timers nr_mac_timers_t;
void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList,
frame_type_t frame_type,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
......@@ -63,7 +66,11 @@ int encode_MeasurementTimingConfiguration(const struct NR_MeasurementTimingConfi
void free_MeasurementTimingConfiguration(struct NR_MeasurementTimingConfiguration *mtc);
#define NR_MAX_SIB_LENGTH 2976 // 3GPP TS 38.331 section 5.2.1
NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac);
NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc,
const f1ap_plmn_t *plmn,
uint64_t cellID,
int tac,
const nr_mac_timers_t *timer_config);
void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1);
int encode_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1, uint8_t *buffer, int max_buffer_size);
......
......@@ -161,10 +161,23 @@ gNBs =
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
#ext2
#ntn_Config_r17
# cellSpecificKoffset_r17 = 478;
}
);
TIMERS :
{
sr_ProhibitTimer = 0;
sr_TransMax = 64;
# sr_ProhibitTimer_v1700 = 512;
# t300 = 2000;
# t301 = 2000;
# t319 = 2000;
};
# ------- SCTP definitions
SCTP :
......
......@@ -161,10 +161,23 @@ gNBs =
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
#ext2
#ntn_Config_r17
# cellSpecificKoffset_r17 = 478;
}
);
TIMERS :
{
sr_ProhibitTimer = 0;
sr_TransMax = 64;
# sr_ProhibitTimer_v1700 = 512;
# t300 = 2000;
# t301 = 2000;
# t319 = 2000;
};
# ------- SCTP definitions
SCTP :
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment