Commit 38284919 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/initial_NR_UE_NTN_support' into integration_2024_w28

parents 62cb46fe 359880fa
...@@ -188,6 +188,18 @@ cd cmake_targets ...@@ -188,6 +188,18 @@ 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 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
``` ```
### NR UE
At UE side, there are two main parameters to cope with the large NTN propagation delay, cellSpecificKoffset and ta-Common.
`cellSpecificKoffset` is the same as for gNB and can be provided to the UE via command line parameter `--ntn-koffset`.
`ta-Common` is a common timong advance and can be provided to the UE via command line parameter `--ntn-ta-common` in milliseconds.
So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, GEO satellite 5G NR NTN is this:
```
cd cmake_targets
sudo ./ran_build/build/nr-uesoftmodem --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --sa --rfsim --rfsimulator.prop_delay 238.74 --ntn-koffset 478 --ntn-ta-common 477.48
```
# Specific OAI modes # Specific OAI modes
## phy-test setup with OAI UE ## phy-test setup with OAI UE
......
...@@ -149,6 +149,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, ...@@ -149,6 +149,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
ue->if_inst = nr_ue_if_module_init(UE_id); ue->if_inst = nr_ue_if_module_init(UE_id);
ue->dci_thres = 0; ue->dci_thres = 0;
ue->target_Nid_cell = -1; ue->target_Nid_cell = -1;
ue->timing_advance = ue->frame_parms.samples_per_subframe * get_nrUE_params()->ntn_ta_common;
// initialize all signal buffers // initialize all signal buffers
init_nr_ue_signal(ue, nb_connected_gNB); init_nr_ue_signal(ue, nb_connected_gNB);
......
...@@ -159,6 +159,9 @@ int oaisim_flag = 0; ...@@ -159,6 +159,9 @@ int oaisim_flag = 0;
int emulate_rf = 0; int emulate_rf = 0;
uint32_t N_RB_DL = 106; uint32_t N_RB_DL = 106;
// NTN cellSpecificKoffset-r17, but in slots for DL SCS
unsigned int NTN_UE_Koffset = 0;
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed /* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
* this is very hackish - find a proper solution * this is very hackish - find a proper solution
*/ */
...@@ -591,6 +594,9 @@ int main(int argc, char **argv) ...@@ -591,6 +594,9 @@ int main(int argc, char **argv)
} }
} }
// NTN cellSpecificKoffset-r17, but in slots for DL SCS
NTN_UE_Koffset = nrUE_params.ntn_koffset << PHY_vars_UE_g[0][0]->frame_parms.numerology_index;
init_openair0(); init_openair0();
lock_memory_to_ram(); lock_memory_to_ram();
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" #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/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" #define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). 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_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"
#define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n"
/***************************************************************************************************************************************/ /***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
...@@ -63,7 +65,9 @@ ...@@ -63,7 +65,9 @@
{"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \ {"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}, \ {"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}, \ {"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}, \
{"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \
} }
// clang-format on // clang-format on
...@@ -84,6 +88,8 @@ typedef struct { ...@@ -84,6 +88,8 @@ typedef struct {
int N_RB_DL; int N_RB_DL;
int ssb_start_subcarrier; int ssb_start_subcarrier;
int ldpc_offload_flag; int ldpc_offload_flag;
unsigned int ntn_koffset;
double ntn_ta_common;
} nrUE_params_t; } nrUE_params_t;
extern uint64_t get_nrUE_optmask(void); extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask); extern uint64_t set_nrUE_optmask(uint64_t bitmask);
......
...@@ -262,15 +262,15 @@ uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, const NR_DL_FR ...@@ -262,15 +262,15 @@ uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, const NR_DL_FR
return slot_idx; return slot_idx;
} }
uint32_t get_samples_slot_timestamp(int slot, const NR_DL_FRAME_PARMS *fp, uint8_t sl_ahead) uint32_t get_samples_slot_timestamp(int slot, const NR_DL_FRAME_PARMS *fp, unsigned int sl_ahead)
{ {
uint32_t samp_count = 0; uint32_t samp_count = 0;
if(!sl_ahead) { if(!sl_ahead) {
for(uint8_t idx_slot = 0; idx_slot < slot; idx_slot++) for(unsigned int idx_slot = 0; idx_slot < slot; idx_slot++)
samp_count += fp->get_samples_per_slot(idx_slot, fp); samp_count += fp->get_samples_per_slot(idx_slot, fp);
} else { } else {
for(uint8_t idx_slot = slot; idx_slot < slot+sl_ahead; idx_slot++) for(unsigned int idx_slot = slot; idx_slot < slot+sl_ahead; idx_slot++)
samp_count += fp->get_samples_per_slot(idx_slot, fp); samp_count += fp->get_samples_per_slot(idx_slot, fp);
} }
return samp_count; return samp_count;
......
...@@ -560,7 +560,7 @@ static int pss_search_time_nr(const c16_t **rxdata, ...@@ -560,7 +560,7 @@ static int pss_search_time_nr(const c16_t **rxdata,
} }
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) { for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) {
for (n = 0; n < length; n += 8) { // for (n = 0; n < length; n += 4) { //
int64_t pss_corr_ue=0; int64_t pss_corr_ue=0;
/* calculate dot product of primary_synchro_time_nr and rxdata[ar][n] /* calculate dot product of primary_synchro_time_nr and rxdata[ar][n]
......
...@@ -135,7 +135,7 @@ typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS; ...@@ -135,7 +135,7 @@ typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS;
typedef uint32_t (*get_samples_per_slot_t)(int slot, const NR_DL_FRAME_PARMS *fp); typedef uint32_t (*get_samples_per_slot_t)(int slot, const NR_DL_FRAME_PARMS *fp);
typedef uint32_t (*get_slot_from_timestamp_t)(openair0_timestamp timestamp_rx, const NR_DL_FRAME_PARMS *fp); typedef uint32_t (*get_slot_from_timestamp_t)(openair0_timestamp timestamp_rx, const NR_DL_FRAME_PARMS *fp);
typedef uint32_t (*get_samples_slot_timestamp_t)(int slot, const NR_DL_FRAME_PARMS *fp, uint8_t sl_ahead); typedef uint32_t (*get_samples_slot_timestamp_t)(int slot, const NR_DL_FRAME_PARMS *fp, unsigned int sl_ahead);
struct NR_DL_FRAME_PARMS { struct NR_DL_FRAME_PARMS {
/// frequency range /// frequency range
......
...@@ -268,13 +268,24 @@ ...@@ -268,13 +268,24 @@
#define TDD_CONFIG_NB_FRAMES (2) #define TDD_CONFIG_NB_FRAMES (2)
#define NR_MAX_SLOTS_PER_FRAME (160) /* number of slots per frame */ #define NR_MAX_SLOTS_PER_FRAME (160) /* number of slots per frame */
/* FFS_NR_TODO it defines ue capability which is the number of slots */ /* FFS_NR_TODO it defines ue capability which is the number of slots */
/* - between reception of pdsch and tarnsmission of its acknowlegment */ /* - between reception of pdsch and transmission of its acknowlegment (k1) */
/* - between reception of un uplink grant and its related transmission */ /* - between reception of un uplink grant and its related transmission (k2) */
// should be 2 as per NR standard, but current UE is not able to perform this value
#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3) #define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3)
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* When the OAI UE receives RX slot N, it starts sending TX slot N+DURATION_RX_TO_TX.
* Therefore DURATION_RX_TO_TX must not be larger than the minimum k1 and k2 values (NR_UE_CAPABILITY_SLOT_RX_TO_TX).
* In case of NTN, the propagation delay is so large, that the TX slot needs to be transmitted far in advance.
* Therefore, the NTN_UE_Koffset is added to DURATION_RX_TO_TX.
*
* Note: currently, the UE requires this to be a constant.
* But in case of NTN, Koffset is only known after receiving SIB19.
* Therefore, support should be added to allow changing DURATION_RX_TO_TX on reception of SIB19 (via FAPI-like interface).
* E.g. no transmission before successful reception of SIB19, and re-sync with disabled transmission if Koffset changes.
* When this has been implemented, the global variable NTN_UE_Koffset should be removed, too.
*/
extern unsigned int NTN_UE_Koffset;
#define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX + NTN_UE_Koffset)
#define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */ #define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */
#define NR_MAX_DLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 5.1 UE procedure for receiving the physical downlink shared channel */ #define NR_MAX_DLSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 5.1 UE procedure for receiving the physical downlink shared channel */
......
...@@ -373,7 +373,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_ ...@@ -373,7 +373,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_
if (ta_command_pdu->is_rar) { if (ta_command_pdu->is_rar) {
ue->ta_slot = ta_command_pdu->ta_slot; ue->ta_slot = ta_command_pdu->ta_slot;
ue->ta_frame = ta_command_pdu->ta_frame; ue->ta_frame = ta_command_pdu->ta_frame;
ue->timing_advance = 0;
ue->ta_command = ta_command_pdu->ta_command + 31; // To use TA adjustment algo in ue_ta_procedures() ue->ta_command = ta_command_pdu->ta_command + 31; // To use TA adjustment algo in ue_ta_procedures()
} else { } else {
ue->ta_slot = (ta_command_pdu->ta_slot + ul_tx_timing_adjustment) % slots_per_frame; ue->ta_slot = (ta_command_pdu->ta_slot + ul_tx_timing_adjustment) % slots_per_frame;
......
...@@ -95,6 +95,9 @@ nfapi_ue_release_request_body_t release_rntis; ...@@ -95,6 +95,9 @@ nfapi_ue_release_request_body_t release_rntis;
instance_t DUuniqInstance=0; instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0; instance_t CUuniqInstance=0;
// NTN cellSpecificKoffset-r17, but in slots for DL SCS
unsigned int NTN_UE_Koffset = 0;
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star) void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{ {
} }
......
...@@ -93,6 +93,9 @@ nfapi_ue_release_request_body_t release_rntis; ...@@ -93,6 +93,9 @@ nfapi_ue_release_request_body_t release_rntis;
instance_t DUuniqInstance=0; instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0; instance_t CUuniqInstance=0;
// NTN cellSpecificKoffset-r17, but in slots for DL SCS
unsigned int NTN_UE_Koffset = 0;
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star) void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{ {
} }
......
...@@ -597,6 +597,7 @@ typedef struct { ...@@ -597,6 +597,7 @@ typedef struct {
int n_ul_bwp; int n_ul_bwp;
int dl_bw_tbslbrm; int dl_bw_tbslbrm;
int ul_bw_tbslbrm; int ul_bw_tbslbrm;
NR_NTN_Config_r17_t *ntn_Config_r17;
} NR_UE_ServingCell_Info_t; } NR_UE_ServingCell_Info_t;
typedef enum { typedef enum {
......
...@@ -409,6 +409,13 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, ...@@ -409,6 +409,13 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac,
// prach_fd_occasion->num_unused_root_sequences = ??? // 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) void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch)
...@@ -1593,6 +1600,17 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, ...@@ -1593,6 +1600,17 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
mac->phy_config_request_sent = true; 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, static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
int cc_idP, int cc_idP,
const NR_ReconfigurationWithSync_t *reconfigurationWithSync) const NR_ReconfigurationWithSync_t *reconfigurationWithSync)
...@@ -1810,6 +1828,17 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup ...@@ -1810,6 +1828,17 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup
int target_ms = 0; int target_ms = 0;
if (sr->sr_ProhibitTimer) if (sr->sr_ProhibitTimer)
target_ms = 1 << *sr->sr_ProhibitTimer; target_ms = 1 << *sr->sr_ProhibitTimer;
if (mcg->ext4 && mcg->ext4->schedulingRequestConfig_v1700) {
const NR_SchedulingRequestConfig_v1700_t *src_v1700 = mcg->ext4->schedulingRequestConfig_v1700;
if (src_v1700->schedulingRequestToAddModListExt_v1700) {
if (i < src_v1700->schedulingRequestToAddModListExt_v1700->list.count) {
const NR_SchedulingRequestToAddModExt_v1700_t *sr_v1700 = src_v1700->schedulingRequestToAddModListExt_v1700->list.array[i];
if (sr_v1700->sr_ProhibitTimer_v1700) {
target_ms = 192 + 64 * *sr_v1700->sr_ProhibitTimer_v1700;
}
}
}
}
// length of slot is (1/2^scs)ms // length of slot is (1/2^scs)ms
nr_timer_setup(&sr_info->prohibitTimer, target_ms << scs, 1); // 1 slot update rate nr_timer_setup(&sr_info->prohibitTimer, target_ms << scs, 1); // 1 slot update rate
} }
......
...@@ -90,6 +90,9 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, ...@@ -90,6 +90,9 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_SI_SchedulingInfo_t *si_SchedulingInfo,
NR_ServingCellConfigCommonSIB_t *scc); 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); 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)*/ /**\brief initialization NR UE MAC instance(s)*/
...@@ -196,7 +199,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, ...@@ -196,7 +199,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
uint8_t pucch_id, uint8_t pucch_id,
uint8_t harq_id, uint8_t harq_id,
int8_t delta_pucch, int8_t delta_pucch,
uint8_t data_toul_fb, uint16_t data_toul_fb,
uint8_t dai, uint8_t dai,
int n_CCE, int n_CCE,
int N_CCE, int N_CCE,
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "radio/COMMON/common_lib.h" #include "radio/COMMON/common_lib.h"
//#undef MALLOC //#undef MALLOC
#include "assertions.h" #include "assertions.h"
#include "executables/softmodem-common.h" #include "executables/nr-uesoftmodem.h"
#include "nr_rlc/nr_rlc_oai_api.h" #include "nr_rlc/nr_rlc_oai_api.h"
#include "RRC/NR_UE/rrc_proto.h" #include "RRC/NR_UE/rrc_proto.h"
#include <pthread.h> #include <pthread.h>
...@@ -85,6 +85,27 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) ...@@ -85,6 +85,27 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->pucch_power_control_initialized = false; mac->pucch_power_control_initialized = false;
mac->pusch_power_control_initialized = false; mac->pusch_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 || get_nrUE_params()->ntn_ta_common) {
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);
}
// NTN ta-Common-r17
if (get_nrUE_params()->ntn_ta_common) {
sib19_r17->ntn_Config_r17->ta_Info_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17->ta_Info_r17));
sib19_r17->ntn_Config_r17->ta_Info_r17->ta_Common_r17 = get_nrUE_params()->ntn_ta_common / 4.072e-6; // ta-Common-r17 is in units of 4.072e-3 µs, ntn_ta_common is in ms
}
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) void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
...@@ -247,6 +268,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, ...@@ -247,6 +268,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_PUSCH_CodeBlockGroupTransmission, sc->pusch_CGB_Transmission);
asn1cFreeStruc(asn_DEF_NR_CSI_MeasConfig, sc->csi_MeasConfig); asn1cFreeStruc(asn_DEF_NR_CSI_MeasConfig, sc->csi_MeasConfig);
asn1cFreeStruc(asn_DEF_NR_CSI_AperiodicTriggerStateList, sc->aperiodicTriggerStateList); 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->xOverhead_PDSCH);
free(sc->nrofHARQ_ProcessesForPDSCH); free(sc->nrofHARQ_ProcessesForPDSCH);
free(sc->rateMatching_PUSCH); free(sc->rateMatching_PUSCH);
......
...@@ -41,6 +41,13 @@ ...@@ -41,6 +41,13 @@
#include <executables/softmodem-common.h> #include <executables/softmodem-common.h>
#include "openair2/LAYER2/RLC/rlc.h" #include "openair2/LAYER2/RLC/rlc.h"
static double get_ta_Common_ms(NR_NTN_Config_r17_t *ntn_Config_r17)
{
if (ntn_Config_r17 && ntn_Config_r17->ta_Info_r17)
return ntn_Config_r17->ta_Info_r17->ta_Common_r17 * 4.072e-6; // ta_Common_r17 is in units of 4.072e-3 µs
return 0.0;
}
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac)
{ {
RA_config_t *ra = &mac->ra; RA_config_t *ra = &mac->ra;
...@@ -581,13 +588,17 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s ...@@ -581,13 +588,17 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s
{ {
RA_config_t *ra = &mac->ra; RA_config_t *ra = &mac->ra;
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
long mu = mac->current_UL_BWP->scs; const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17);
int subframes_per_slot = nr_slots_per_frame[mu] / 10; const int mu = mac->current_UL_BWP->scs;
const int slots_per_ms = nr_slots_per_frame[mu] / 10;
// start contention resolution timer // start contention resolution timer
int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3; const int RA_contention_resolution_timer_ms = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3;
// timer step 1 slot and timer target given by ra_ContentionResolutionTimer const int RA_contention_resolution_timer_slots = RA_contention_resolution_timer_ms * slots_per_ms;
nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_subframes * subframes_per_slot, 1); const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms);
// timer step 1 slot and timer target given by ra_ContentionResolutionTimer + ta-Common-r17
nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_slots + ta_Common_slots, 1);
nr_timer_start(&ra->contention_resolution_timer); nr_timer_start(&ra->contention_resolution_timer);
ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION; ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION;
...@@ -789,11 +800,16 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac) ...@@ -789,11 +800,16 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac)
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__);
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17);
const int mu = mac->current_DL_BWP->scs;
const int slots_per_ms = nr_slots_per_frame[mu] / 10;
int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; const int ra_Offset_slots = ra->RA_offset * nr_slots_per_frame[mu];
int mu = mac->current_DL_BWP->scs; const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms);
ra->RA_window_cnt = ra_Offset_slots + ta_Common_slots; // taking into account the 2 frames gap introduced by OAI gNB
ra->RA_window_cnt = ra->RA_offset * nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow;
switch (ra_ResponseWindow) { switch (ra_ResponseWindow) {
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
......
...@@ -148,6 +148,13 @@ static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, ...@@ -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 uint8_t *dci_pdu,
const int slot); 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) int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti)
{ {
const RA_config_t *ra = &mac->ra; 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, ...@@ -492,7 +499,8 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
frame_t frame_tx; frame_t frame_tx;
int slot_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"); LOG_E(MAC, "Cannot schedule PUSCH\n");
return -1; return -1;
} }
...@@ -589,7 +597,8 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac, ...@@ -589,7 +597,8 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
tda_info.k2 = csi_K2; 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"); LOG_E(MAC, "Cannot schedule PUSCH\n");
return -1; return -1;
} }
...@@ -903,10 +912,15 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, ...@@ -903,10 +912,15 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
return -1; 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_) { 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", "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); DURATION_RX_TO_TX);
// set the harq status at MAC for feedback // set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3}; 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, ...@@ -914,7 +928,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
dci->pucch_resource_indicator, dci->pucch_resource_indicator,
dci->harq_pid, dci->harq_pid,
tpc[dci->tpc], tpc[dci->tpc],
1 + dci->pdsch_to_harq_feedback_timing_indicator.val, feedback_ti,
dci->dai[0].val, dci->dai[0].val,
dci_ind->n_CCE, dci_ind->n_CCE,
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, ...@@ -948,9 +962,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
dlsch_pdu->scaling_factor_S, dlsch_pdu->scaling_factor_S,
dci->tpc, dci->tpc,
dci->pucch_resource_indicator, 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); 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, ...@@ -1239,7 +1253,8 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 Table 9.2.3-1 // 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, 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 " "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, ...@@ -1436,7 +1451,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
uint8_t pucch_id, uint8_t pucch_id,
uint8_t harq_id, uint8_t harq_id,
int8_t delta_pucch, int8_t delta_pucch,
uint8_t data_toul_fb, uint16_t data_toul_fb,
uint8_t dai, uint8_t dai,
int n_CCE, int n_CCE,
int N_CCE, int N_CCE,
...@@ -1457,7 +1472,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, ...@@ -1457,7 +1472,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
current_harq->ul_frame = frame; current_harq->ul_frame = frame;
current_harq->ul_slot = slot + data_toul_fb; current_harq->ul_slot = slot + data_toul_fb;
if (current_harq->ul_slot >= slots_per_frame) { 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; current_harq->ul_slot %= slots_per_frame;
} }
// counter DAI in DCI ranges from 0 to 3 // 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 ...@@ -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; NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
ul_time_alignment->tag_id = tag; ul_time_alignment->tag_id = tag;
ul_time_alignment->ta_command = ta; ul_time_alignment->ta_command = ta;
ul_time_alignment->frame = frameP;
ul_time_alignment->slot = slot;
ul_time_alignment->ta_apply = adjustment_ta; 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 #ifdef DEBUG_HEADER_PARSING
LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); 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 ...@@ -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"); LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n");
return; return;
} }
ret = nr_ue_pusch_scheduler(mac, is_Msg3, 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);
ul_time_alignment->frame = frame_tx; ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset);
ul_time_alignment->slot = slot_tx;
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) { if (ret != -1) {
uint16_t rnti = mac->crnti; uint16_t rnti = mac->crnti;
......
...@@ -1114,7 +1114,7 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger ...@@ -1114,7 +1114,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); LOG_E(NR_MAC, "Slot for scheduling aperiodic SRS %d is not an UL slot\n", sched_slot);
return; 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); fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_SRS);
if (!pdu) if (!pdu)
return; return;
...@@ -1573,11 +1573,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, ...@@ -1573,11 +1573,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
DURATION_RX_TO_TX); DURATION_RX_TO_TX);
*slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; *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 + (current_slot + k2 + delta) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER;
*frame_tx = (current_frame + 1) % 1024;
} else {
*frame_tx = current_frame;
}
} else { } else {
...@@ -1595,7 +1591,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, ...@@ -1595,7 +1591,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
// Calculate TX slot and frame // Calculate TX slot and frame
*slot_tx = (current_slot + k2) % nr_slots_per_frame[mu]; *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;
} }
......
...@@ -983,7 +983,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { ...@@ -983,7 +983,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
rfsimulator->tx_bw=openair0_cfg->tx_bw; rfsimulator->tx_bw=openair0_cfg->tx_bw;
rfsimulator_readconfig(rfsimulator); rfsimulator_readconfig(rfsimulator);
if (rfsimulator->prop_delay_ms > 0.0) if (rfsimulator->prop_delay_ms > 0.0)
rfsimulator->chan_offset = rfsimulator->sample_rate * rfsimulator->prop_delay_ms / 1000; rfsimulator->chan_offset = ceil(rfsimulator->sample_rate * rfsimulator->prop_delay_ms / 1000);
if (rfsimulator->chan_offset != 0) { if (rfsimulator->chan_offset != 0) {
if (CirSize < minCirSize + rfsimulator->chan_offset) { if (CirSize < minCirSize + rfsimulator->chan_offset) {
CirSize = minCirSize + rfsimulator->chan_offset; CirSize = minCirSize + rfsimulator->chan_offset;
......
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