diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index 4245ec9ae560d2755971b8fab9d767767652de1d..753efdadaf5a67f2264bd12c99a02665cfa13b45 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -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 diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 9928d25557d3e97107cf6a4f651f4c6cd1a37a00..6f48f80ce98b7e8418b1bda384d7af899836b122 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -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)); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index ae2abbdc3d7b1c3d71728bb6f3bb4d81f1fa9fbe..0efdc9be39bd07708644f1921600f98869660ff4 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -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)); diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 14e8cb13defc1c0b2a1e29da545c8087bd6e93e7..16a5939fc5a0e66c8410733444594fb4d6a1cb02 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -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}} /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 4a244fe34845fa72b3a2254af55c1305639f883c..1363e68aaa305fd47bac9ac966dac6193d15af21 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -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); diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 6491ddb755b138eb4c0c851deef202ea765939fe..94e854e301226b99752a44d96668c03e8669b80f 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -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 */ diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index e313cdb19093189be4052f44b064224767561b9b..e165a717f74ba58a09b71329fe047c87ba244136 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -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"); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 34a372247c0c2f2d1b9a7abed97073b33ae8bf65..dbd64f524ed9811995977f5214d6e2f153ba3ea3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -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]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 7507207ac8ea9b2a7e55965dd2076efb92152aac..3f752dae232bfd5f6933de7984475f838d08c801 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -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) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index ca6d44d5b0e8d95b447b7061f574aa44a970b5a5..29b5fbe7137c6a443e552b35404812b6e431cd74 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -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); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 3eb9a9ce7b1bbdf4671f949c949a05ec11b16c02..6d6c6a20478854ab9b9a8b221e6b4ff2db72d0fb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -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) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 1aeba91026536300b3244d61dd5c66344253b176..8ae9c3dcc57f41033700f1b56db73e0c349675ea 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -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; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 2e5fb0c7a19187b40625e9a33a143469797f0159..b4492ffa44cd5888b6c314b2516e84bf1b48d8c4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -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); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index ac067044eb108ec7068b45ee2ba420321a185dde..b2a6827d04098e59efd1269f589b6385da84374c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -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; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index ecb28907769e9c1abd19208945b5dc92dfa280a3..820eba2b5bb66717a2ff3d1444c9d3f1c3a7024b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -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; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 0fc1071c5fe307c854eec5118fa32d56c3681b64..a23e588a492427d48d52602460c7f2d8fa3922d3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -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); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 59a33556913db67c68646ba9ce92e32a74626dce..7fe0c8994eab147b58a73ac4af35161ea4e97cd3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -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; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 3b1791ad55c2582a4de42d6e56a4c32e6042797a..9bbd4f38b7f42385774683916b148a9ca6d1170c 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -1974,7 +1974,175 @@ void free_MeasurementTimingConfiguration(NR_MeasurementTimingConfiguration_t *mt ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); } -NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac) +static long get_NR_UE_TimersAndConstants_t300(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->t300) { + case 100: + return NR_UE_TimersAndConstants__t300_ms100; + case 200: + return NR_UE_TimersAndConstants__t300_ms200; + case 300: + return NR_UE_TimersAndConstants__t300_ms300; + case 400: + return NR_UE_TimersAndConstants__t300_ms400; + case 600: + return NR_UE_TimersAndConstants__t300_ms600; + case 1000: + return NR_UE_TimersAndConstants__t300_ms1000; + case 1500: + return NR_UE_TimersAndConstants__t300_ms1500; + case 2000: + return NR_UE_TimersAndConstants__t300_ms2000; + default: + AssertFatal(1 == 0, "Invalid value configured for t300!\n"); + } +} + +static long get_NR_UE_TimersAndConstants_t301(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->t301) { + case 100: + return NR_UE_TimersAndConstants__t301_ms100; + case 200: + return NR_UE_TimersAndConstants__t301_ms200; + case 300: + return NR_UE_TimersAndConstants__t301_ms300; + case 400: + return NR_UE_TimersAndConstants__t301_ms400; + case 600: + return NR_UE_TimersAndConstants__t301_ms600; + case 1000: + return NR_UE_TimersAndConstants__t301_ms1000; + case 1500: + return NR_UE_TimersAndConstants__t301_ms1500; + case 2000: + return NR_UE_TimersAndConstants__t301_ms2000; + default: + AssertFatal(1 == 0, "Invalid value configured for t301!\n"); + } +} + +static long get_NR_UE_TimersAndConstants_t310(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->t310) { + case 0: + return NR_UE_TimersAndConstants__t310_ms0; + case 50: + return NR_UE_TimersAndConstants__t310_ms50; + case 100: + return NR_UE_TimersAndConstants__t310_ms100; + case 200: + return NR_UE_TimersAndConstants__t310_ms200; + case 500: + return NR_UE_TimersAndConstants__t310_ms500; + case 1000: + return NR_UE_TimersAndConstants__t310_ms1000; + case 2000: + return NR_UE_TimersAndConstants__t310_ms2000; + default: + AssertFatal(1 == 0, "Invalid value configured for t310!\n"); + } +} + +static long get_NR_UE_TimersAndConstants_n310(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->n310) { + case 1: + return NR_UE_TimersAndConstants__n310_n1; + case 2: + return NR_UE_TimersAndConstants__n310_n2; + case 3: + return NR_UE_TimersAndConstants__n310_n3; + case 4: + return NR_UE_TimersAndConstants__n310_n4; + case 6: + return NR_UE_TimersAndConstants__n310_n6; + case 8: + return NR_UE_TimersAndConstants__n310_n8; + case 10: + return NR_UE_TimersAndConstants__n310_n10; + case 20: + return NR_UE_TimersAndConstants__n310_n20; + default: + AssertFatal(1 == 0, "Invalid value configured for n310!\n"); + } +} + +static long get_NR_UE_TimersAndConstants_t311(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->t311) { + case 1000: + return NR_UE_TimersAndConstants__t311_ms1000; + case 3000: + return NR_UE_TimersAndConstants__t311_ms3000; + case 5000: + return NR_UE_TimersAndConstants__t311_ms5000; + case 10000: + return NR_UE_TimersAndConstants__t311_ms10000; + case 15000: + return NR_UE_TimersAndConstants__t311_ms15000; + case 20000: + return NR_UE_TimersAndConstants__t311_ms20000; + case 30000: + return NR_UE_TimersAndConstants__t311_ms30000; + default: + AssertFatal(1 == 0, "Invalid value configured for t311!\n"); + } +} + +static long get_NR_UE_TimersAndConstants_n311(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->n311) { + case 1: + return NR_UE_TimersAndConstants__n311_n1; + case 2: + return NR_UE_TimersAndConstants__n311_n2; + case 3: + return NR_UE_TimersAndConstants__n311_n3; + case 4: + return NR_UE_TimersAndConstants__n311_n4; + case 5: + return NR_UE_TimersAndConstants__n311_n5; + case 6: + return NR_UE_TimersAndConstants__n311_n6; + case 8: + return NR_UE_TimersAndConstants__n311_n8; + case 10: + return NR_UE_TimersAndConstants__n311_n10; + default: + AssertFatal(1 == 0, "Invalid value configured for n311!\n"); + } +} + +static long get_NR_UE_TimersAndConstants_t319(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->t319) { + case 100: + return NR_UE_TimersAndConstants__t319_ms100; + case 200: + return NR_UE_TimersAndConstants__t319_ms200; + case 300: + return NR_UE_TimersAndConstants__t319_ms300; + case 400: + return NR_UE_TimersAndConstants__t319_ms400; + case 600: + return NR_UE_TimersAndConstants__t319_ms600; + case 1000: + return NR_UE_TimersAndConstants__t319_ms1000; + case 1500: + return NR_UE_TimersAndConstants__t319_ms1500; + case 2000: + return NR_UE_TimersAndConstants__t319_ms2000; + default: + AssertFatal(1 == 0, "Invalid value configured for t319!\n"); + } +} + +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) { AssertFatal(cellID < (1l << 36), "cellID must fit within 36 bits, but is %lu\n", cellID); @@ -2230,13 +2398,13 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c // ue-TimersAndConstants sib1->ue_TimersAndConstants = CALLOC(1,sizeof(struct NR_UE_TimersAndConstants)); AssertFatal(sib1->ue_TimersAndConstants != NULL, "out of memory\n"); - sib1->ue_TimersAndConstants->t300 = NR_UE_TimersAndConstants__t300_ms400; - sib1->ue_TimersAndConstants->t301 = NR_UE_TimersAndConstants__t301_ms400; - sib1->ue_TimersAndConstants->t310 = NR_UE_TimersAndConstants__t310_ms2000; - sib1->ue_TimersAndConstants->n310 = NR_UE_TimersAndConstants__n310_n10; - sib1->ue_TimersAndConstants->t311 = NR_UE_TimersAndConstants__t311_ms3000; - sib1->ue_TimersAndConstants->n311 = NR_UE_TimersAndConstants__n311_n1; - sib1->ue_TimersAndConstants->t319 = NR_UE_TimersAndConstants__t319_ms400; + sib1->ue_TimersAndConstants->t300 = get_NR_UE_TimersAndConstants_t300(timer_config); + sib1->ue_TimersAndConstants->t301 = get_NR_UE_TimersAndConstants_t301(timer_config); + sib1->ue_TimersAndConstants->t310 = get_NR_UE_TimersAndConstants_t310(timer_config); + sib1->ue_TimersAndConstants->n310 = get_NR_UE_TimersAndConstants_n310(timer_config); + sib1->ue_TimersAndConstants->t311 = get_NR_UE_TimersAndConstants_t311(timer_config); + sib1->ue_TimersAndConstants->n311 = get_NR_UE_TimersAndConstants_n311(timer_config); + sib1->ue_TimersAndConstants->t319 = get_NR_UE_TimersAndConstants_t319(timer_config); // uac-BarringInfo /*sib1->uac_BarringInfo = CALLOC(1, sizeof(struct NR_SIB1__uac_BarringInfo)); @@ -2286,7 +2454,102 @@ static NR_PhysicalCellGroupConfig_t *configure_phy_cellgroup(void) return physicalCellGroupConfig; } -static NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(void) +static long *get_sr_ProhibitTimer(const nr_mac_timers_t *timer_config) +{ + if (timer_config->sr_ProhibitTimer == 0) + return NULL; + + long *ret = calloc(1, sizeof(*ret)); + switch (timer_config->sr_ProhibitTimer) { + case 1: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms1; + break; + case 2: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms2; + break; + case 4: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms4; + break; + case 8: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms8; + break; + case 16: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms16; + break; + case 32: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms32; + break; + case 64: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms64; + break; + case 128: + *ret = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms128; + break; + default: + AssertFatal(1 == 0, "Invalid value configured for sr_ProhibitTimer!\n"); + } + return ret; +} + +static long get_sr_TransMax(const nr_mac_timers_t *timer_config) +{ + switch (timer_config->sr_TransMax) { + case 4: + return NR_SchedulingRequestToAddMod__sr_TransMax_n4; + case 8: + return NR_SchedulingRequestToAddMod__sr_TransMax_n8; + case 16: + return NR_SchedulingRequestToAddMod__sr_TransMax_n16; + case 32: + return NR_SchedulingRequestToAddMod__sr_TransMax_n32; + case 64: + return NR_SchedulingRequestToAddMod__sr_TransMax_n64; + default: + AssertFatal(1 == 0, "Invalid value configured for sr_TransMax!\n"); + } +} + +static long *get_sr_ProhibitTimer_v1700(const nr_mac_timers_t *timer_config) +{ + if (timer_config->sr_ProhibitTimer_v1700 == 0) + return NULL; + + long *ret = calloc(1, sizeof(*ret)); + switch (timer_config->sr_ProhibitTimer_v1700) { + case 192: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms192; + break; + case 256: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms256; + break; + case 320: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms320; + break; + case 384: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms384; + break; + case 448: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms448; + break; + case 512: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms512; + break; + case 576: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms576; + break; + case 640: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms640; + break; + case 1082: + *ret = NR_SchedulingRequestToAddModExt_v1700__sr_ProhibitTimer_v1700_ms1082; + break; + default: + AssertFatal(1 == 0, "Invalid value configured for sr_ProhibitTimer_v1700!\n"); + } + return ret; +} + +static NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(const nr_mac_timers_t *timer_config) { NR_MAC_CellGroupConfig_t * mac_CellGroupConfig = calloc(1, sizeof(*mac_CellGroupConfig)); AssertFatal(mac_CellGroupConfig != NULL, "Couldn't allocate mac-CellGroupConfig. Out of memory!\n"); @@ -2307,10 +2570,22 @@ static NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(void) mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList = CALLOC(1,sizeof(*mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList)); struct NR_SchedulingRequestToAddMod *schedulingrequestlist = CALLOC(1,sizeof(*schedulingrequestlist)); schedulingrequestlist->schedulingRequestId = 0; - schedulingrequestlist->sr_ProhibitTimer = NULL; - schedulingrequestlist->sr_TransMax = NR_SchedulingRequestToAddMod__sr_TransMax_n64; + schedulingrequestlist->sr_ProhibitTimer = get_sr_ProhibitTimer(timer_config); + schedulingrequestlist->sr_TransMax = get_sr_TransMax(timer_config); asn1cSeqAdd(&(mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList->list),schedulingrequestlist); + if (timer_config->sr_ProhibitTimer_v1700 != 0) { + mac_CellGroupConfig->ext4 = calloc(1, sizeof(*mac_CellGroupConfig->ext4)); + mac_CellGroupConfig->ext4->schedulingRequestConfig_v1700 = + calloc(1, sizeof(*mac_CellGroupConfig->ext4->schedulingRequestConfig_v1700)); + mac_CellGroupConfig->ext4->schedulingRequestConfig_v1700->schedulingRequestToAddModListExt_v1700 = + calloc(1, sizeof(*mac_CellGroupConfig->ext4->schedulingRequestConfig_v1700->schedulingRequestToAddModListExt_v1700)); + struct NR_SchedulingRequestToAddModExt_v1700 *schedulingrequestlist_v1700 = calloc(1, sizeof(*schedulingrequestlist_v1700)); + schedulingrequestlist_v1700->sr_ProhibitTimer_v1700 = get_sr_ProhibitTimer_v1700(timer_config); + asn1cSeqAdd(&(mac_CellGroupConfig->ext4->schedulingRequestConfig_v1700->schedulingRequestToAddModListExt_v1700->list), + schedulingrequestlist_v1700); + } + mac_CellGroupConfig->skipUplinkTxDynamic=false; mac_CellGroupConfig->ext1 = NULL; return mac_CellGroupConfig; @@ -2577,8 +2852,8 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, cellGroupConfig->rlc_BearerToReleaseList = NULL; /* mac CellGroup Config */ - cellGroupConfig->mac_CellGroupConfig = configure_mac_cellgroup(); - + cellGroupConfig->mac_CellGroupConfig = configure_mac_cellgroup(&configuration->timer_config); + cellGroupConfig->physicalCellGroupConfig = configure_phy_cellgroup(); cellGroupConfig->spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration); @@ -2791,7 +3066,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC secondaryCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*secondaryCellGroup->rlc_BearerToAddModList)); asn1cSeqAdd(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig); - secondaryCellGroup->mac_CellGroupConfig = configure_mac_cellgroup(); + secondaryCellGroup->mac_CellGroupConfig = configure_mac_cellgroup(&configuration->timer_config); secondaryCellGroup->physicalCellGroupConfig = configure_phy_cellgroup(); secondaryCellGroup->spCellConfig = calloc(1, sizeof(*secondaryCellGroup->spCellConfig)); secondaryCellGroup->spCellConfig->servCellIndex = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->servCellIndex)); diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index d469638fcf932d4ce3db111e9bb2a54e33cd7dea..d46363c7073641a4ea9a7327a02d64ee6697c01d 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -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); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf index 8273a3a82a23b50cdcc8ddd26efd974d5fdf3bbf..0ad01d6e939acd7a2bf59d8949309a8279331c04 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf @@ -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 : diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf index 4e27d924deda05cd18cfec40662fc222eb1e59a7..f29bbf9cf66f3a8e3b2aa18ef7f03ce66dbf245b 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf @@ -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 :