diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 28de10154d..c95a6dc98c 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -12,6 +12,7 @@ #define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" #define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" #define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n" +#define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument @@ -63,7 +64,8 @@ {"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \ {"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \ - {"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT,0}, \ + {"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \ + {"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \ } // clang-format on @@ -84,6 +86,7 @@ typedef struct { int N_RB_DL; int ssb_start_subcarrier; int ldpc_offload_flag; + unsigned int ntn_koffset; } nrUE_params_t; extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 6973f06103..46ef4050e9 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -597,6 +597,7 @@ typedef struct { int n_ul_bwp; int dl_bw_tbslbrm; int ul_bw_tbslbrm; + NR_NTN_Config_r17_t *ntn_Config_r17; } NR_UE_ServingCell_Info_t; typedef enum { diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index d8b1ac158d..ccff0020c3 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -409,6 +409,13 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, // prach_fd_occasion->num_unused_root_sequences = ??? } } + + // NTN Config + if (scc->ext2) { + UPDATE_IE(mac->sc_info.ntn_Config_r17, scc->ext2->ntn_Config_r17, NR_NTN_Config_r17_t); + } else { + asn1cFreeStruc(asn_DEF_NR_NTN_Config_r17, mac->sc_info.ntn_Config_r17); + } } void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch) @@ -1585,6 +1592,17 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, mac->phy_config_request_sent = true; } +void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id, + NR_SIB19_r17_t *sib19_r17) +{ + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + + // ntn-Config-r17 + UPDATE_IE(mac->sc_info.ntn_Config_r17, sib19_r17->ntn_Config_r17, NR_NTN_Config_r17_t); + + // TODO handle other SIB19 elements +} + static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, int cc_idP, const NR_ReconfigurationWithSync_t *reconfigurationWithSync) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 6b849415f8..79a367de4c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -90,6 +90,9 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_ServingCellConfigCommonSIB_t *scc); +void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id, + NR_SIB19_r17_t *sib19_r17); + void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause); /**\brief initialization NR UE MAC instance(s)*/ @@ -196,7 +199,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, uint8_t pucch_id, uint8_t harq_id, int8_t delta_pucch, - uint8_t data_toul_fb, + uint16_t data_toul_fb, uint8_t dai, int n_CCE, int N_CCE, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 4d8b79a2ab..2230d92729 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -35,7 +35,7 @@ #include "radio/COMMON/common_lib.h" //#undef MALLOC #include "assertions.h" -#include "executables/softmodem-common.h" +#include "executables/nr-uesoftmodem.h" #include "nr_rlc/nr_rlc_oai_api.h" #include "RRC/NR_UE/rrc_proto.h" #include @@ -84,6 +84,21 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) memset(&mac->scheduling_info.sr_info[i], 0, sizeof(mac->scheduling_info.sr_info[i])); mac->pucch_power_control_initialized = false; + + // Fake SIB19 reception for NTN + // TODO: remove this and implement the actual SIB19 reception instead! + if (get_nrUE_params()->ntn_koffset) { + NR_SIB19_r17_t *sib19_r17 = calloc(1, sizeof(*sib19_r17)); + sib19_r17->ntn_Config_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17)); + + // NTN cellSpecificKoffset-r17 + if (get_nrUE_params()->ntn_koffset) { + asn1cCallocOne(sib19_r17->ntn_Config_r17->cellSpecificKoffset_r17, get_nrUE_params()->ntn_koffset); + } + + nr_rrc_mac_config_req_sib19_r17(mac->ue_id, sib19_r17); + asn1cFreeStruc(asn_DEF_NR_SIB19_r17, sib19_r17); + } } void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) @@ -246,6 +261,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, asn1cFreeStruc(asn_DEF_NR_PUSCH_CodeBlockGroupTransmission, sc->pusch_CGB_Transmission); asn1cFreeStruc(asn_DEF_NR_CSI_MeasConfig, sc->csi_MeasConfig); asn1cFreeStruc(asn_DEF_NR_CSI_AperiodicTriggerStateList, sc->aperiodicTriggerStateList); + asn1cFreeStruc(asn_DEF_NR_NTN_Config_r17, sc->ntn_Config_r17); free(sc->xOverhead_PDSCH); free(sc->nrofHARQ_ProcessesForPDSCH); free(sc->rateMatching_PUSCH); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 2954cf246b..af148e6bd5 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -148,6 +148,13 @@ static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, const uint8_t *dci_pdu, const int slot); +static int get_NTN_UE_Koffset(NR_NTN_Config_r17_t *ntn_Config_r17, int scs) +{ + if (ntn_Config_r17 && ntn_Config_r17->cellSpecificKoffset_r17) + return *ntn_Config_r17->cellSpecificKoffset_r17 << scs; + return 0; +} + int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti) { const RA_config_t *ra = &mac->ra; @@ -492,7 +499,8 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac, frame_t frame_tx; int slot_tx; - if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2)) { + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset)) { LOG_E(MAC, "Cannot schedule PUSCH\n"); return -1; } @@ -589,7 +597,8 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac, tda_info.k2 = csi_K2; } - if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2)) { + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset)) { LOG_E(MAC, "Cannot schedule PUSCH\n"); return -1; } @@ -903,10 +912,15 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, return -1; } + /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ + // according to TS 38.213 9.2.3 + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, dlsch_pdu->SubcarrierSpacing); + const uint16_t feedback_ti = 1 + dci->pdsch_to_harq_feedback_timing_indicator.val + ntn_ue_koffset; + if (rnti_type != TYPE_RA_RNTI_ && rnti_type != TYPE_SI_RNTI_) { - AssertFatal(1 + dci->pdsch_to_harq_feedback_timing_indicator.val > DURATION_RX_TO_TX, + AssertFatal(feedback_ti > DURATION_RX_TO_TX, "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d).\n", - 1 + dci->pdsch_to_harq_feedback_timing_indicator.val, + feedback_ti, DURATION_RX_TO_TX); // set the harq status at MAC for feedback const int tpc[] = {-1, 0, 1, 3}; @@ -914,7 +928,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dci->pucch_resource_indicator, dci->harq_pid, tpc[dci->tpc], - 1 + dci->pdsch_to_harq_feedback_timing_indicator.val, + feedback_ti, dci->dai[0].val, dci_ind->n_CCE, dci_ind->N_CCE, @@ -948,9 +962,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->scaling_factor_S, dci->tpc, dci->pucch_resource_indicator, - 1 + dci->pdsch_to_harq_feedback_timing_indicator.val); + feedback_ti); - dlsch_pdu->k1_feedback = 1 + dci->pdsch_to_harq_feedback_timing_indicator.val; + dlsch_pdu->k1_feedback = feedback_ti; LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n\n", dl_conf_req->pdu_type); @@ -1239,7 +1253,8 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ // according to TS 38.213 Table 9.2.3-1 - uint8_t feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, dlsch_pdu->SubcarrierSpacing); + const uint16_t feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset; AssertFatal(feedback_ti > DURATION_RX_TO_TX, "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d). Min feedback time set in config " @@ -1436,7 +1451,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, uint8_t pucch_id, uint8_t harq_id, int8_t delta_pucch, - uint8_t data_toul_fb, + uint16_t data_toul_fb, uint8_t dai, int n_CCE, int N_CCE, @@ -1457,7 +1472,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, current_harq->ul_frame = frame; current_harq->ul_slot = slot + data_toul_fb; if (current_harq->ul_slot >= slots_per_frame) { - current_harq->ul_frame = (frame + 1) % 1024; + current_harq->ul_frame = (frame + current_harq->ul_slot / slots_per_frame) % MAX_FRAME_NUMBER; current_harq->ul_slot %= slots_per_frame; } // counter DAI in DCI ranges from 0 to 3 @@ -3544,9 +3559,13 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; ul_time_alignment->tag_id = tag; ul_time_alignment->ta_command = ta; - ul_time_alignment->frame = frameP; - ul_time_alignment->slot = slot; ul_time_alignment->ta_apply = adjustment_ta; + + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs]; + ul_time_alignment->frame = (frameP + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; + ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame; + /* #ifdef DEBUG_HEADER_PARSING LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); @@ -4023,9 +4042,12 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n"); return; } - ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2); - ul_time_alignment->frame = frame_tx; - ul_time_alignment->slot = slot_tx; + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset); + + const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; + ul_time_alignment->frame = (frame_tx + (slot_tx + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; + ul_time_alignment->slot = (slot_tx + ntn_ue_koffset) % n_slots_frame; if (ret != -1) { uint16_t rnti = mac->crnti; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b88ca7e5f3..a5c7982ddf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1112,7 +1112,7 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger LOG_E(NR_MAC, "Slot for scheduling aperiodic SRS %d is not an UL slot\n", sched_slot); return; } - int sched_frame = frame + (slot + slot_offset >= n_slots_frame) % 1024; + int sched_frame = frame + (slot + slot_offset / n_slots_frame) % MAX_FRAME_NUMBER; fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_SRS); if (!pdu) return; @@ -1571,11 +1571,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, DURATION_RX_TO_TX); *slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; - if (current_slot + k2 + delta >= nr_slots_per_frame[mu]){ - *frame_tx = (current_frame + 1) % 1024; - } else { - *frame_tx = current_frame; - } + *frame_tx = (current_frame + (current_slot + k2 + delta) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER; } else { @@ -1593,7 +1589,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, // Calculate TX slot and frame *slot_tx = (current_slot + k2) % nr_slots_per_frame[mu]; - *frame_tx = ((current_slot + k2) > (nr_slots_per_frame[mu]-1)) ? (current_frame + 1) % 1024 : current_frame; + *frame_tx = (current_frame + (current_slot + k2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER; }