diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml index 4e209e09d1..3b5e7170ba 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -123,7 +123,7 @@ services: --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --rfsimulator.serveraddr 192.168.71.140 --time-sync-I 0.1 --ntn-initial-time-drift -46 - --autonomous-ta --initial-fo 57340 --cont-fo-comp 2 + --initial-fo 57340 --cont-fo-comp 2 --log_config.global_log_options level,nocolor,time --num-ul-actors 1 depends_on: diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index c703899c16..a29176ddd7 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -352,7 +352,9 @@ These modes of operation are supported: - Formats 0,1,2,3, A1-A3, B1-B3 * NTN - TA adjustemt based on ntn-Config-r17 information - - Autonomous TA adjustemt between SIB19 receptions based on DL time tracking + - Different TA adjustemt algorithms between SIB19 receptions: + - Autonomous TA adjustemt based on DL time tracking + - Standard compliant epoch time based TA adjustment including orbital propagation - UL Doppler pre-compensation based on continuous DL FO estimation * Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) * Highly efficient 3GPP compliant polar encoder and decoder diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index 6e46a361fe..57ec937470 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -356,7 +356,9 @@ sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be provided via command line, as the UE needs this value to compensate for the time drift during initial sync, before SIB19 was received. This parameter provides the drift rate of the complete DL timing (incl. feeder link and service link) in µs/s. -Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario. + +To perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` can be added. +If that parameter is omitted, the TA is continuously computed based on the SIB19 information. For LEO satellite scenario we assume the LO to be very accurate and the main FO contribution comes from Doppler shift. Therefore, we use the command line parameter `--cont-fo-comp 2` to continuously compensate the DL Doppler and pre-compensate the UL Doppler. @@ -367,7 +369,7 @@ For other information on optional NR UE command line options, please refer [here So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this: ``` cd cmake_targets -sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta --initial-fo 57340 --cont-fo-comp 2 +sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --initial-fo 57340 --cont-fo-comp 2 ``` # Specific OAI modes diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 5721b45f8d..de752f1513 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -434,8 +434,10 @@ void processSlotTX(void *arg) nr_sidelink_indication_t sl_indication = {.module_id = UE->Mod_id, .gNB_index = proc->gNB_id, .cc_id = UE->CC_id, + .hfn_tx = proc->hfn_tx, .frame_tx = proc->frame_tx, .slot_tx = proc->nr_slot_tx, + .hfn_rx = proc->hfn_rx, .frame_rx = proc->frame_rx, .slot_rx = proc->nr_slot_rx, .slot_type = SIDELINK_SLOT_TYPE_TX, @@ -669,8 +671,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r AssertFatal(read_block_size == tmp, ""); if (IS_SOFTMODEM_RFSIM) { - const openair0_timestamp writeTimestamp = - *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance; + const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) + - UE->N_TA_offset - UE->timing_advance - UE->timing_advance_ntn; dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp)); } } @@ -696,8 +698,8 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); DevAssert(unitTransfer == res); if (IS_SOFTMODEM_RFSIM) { - const openair0_timestamp writeTimestamp = - *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance; + const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) + - UE->N_TA_offset - UE->timing_advance - UE->timing_advance_ntn; dummyWrite(UE, writeTimestamp, unitTransfer); } slot = (slot + 1) % fp->slots_per_subframe; @@ -721,8 +723,61 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) { return rem_samples + next_slot_first_symbol; } +#define SPEED_OF_LIGHT 299792458 +static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx) +{ + const fapi_nr_dl_ntn_config_command_pdu *ntn_config_params = &UE->ntn_config_message->ntn_config_params; + + const int abs_subframe_epoch = ntn_config_params->epoch_subframe + + ntn_config_params->epoch_sfn * 10 + + ntn_config_params->epoch_hfn * 10240; + const int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch; + + const double omega = ntn_config_params->omega; + const double cos_wt = cos(omega * ms_since_epoch); + const double sin_wt = sin(omega * ms_since_epoch); + + const position_t pos_sat_0 = ntn_config_params->pos_sat_0; + const position_t pos_sat_90 = ntn_config_params->pos_sat_90; + const position_t pos_sat = {pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt, + pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt, + pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt}; + + position_t pos_ue = {0}; + get_position_coordinates(UE->Mod_id, &pos_ue); + + // calculate directional vector from SAT to UE + const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z}; + + // calculate distance between SAT and UE + const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z); + + // calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000) + const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT; + + const double N_common_ta_adj = ntn_config_params->N_common_ta_adj; + const double N_common_ta_drift = ntn_config_params->N_common_ta_drift; + const double N_common_ta_drift_variant = ntn_config_params->N_common_ta_drift_variant; + + UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj + + N_common_ta_drift * ms_since_epoch / 1e6 + + N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9) + * fp->samples_per_subframe; + + LOG_D(PHY, + "N_UE_TA_adj = %f ms, N_common_ta_adj = %f ms, N_common_ta_drift = %f µs/s, N_common_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, " + "computed timing_advance_ntn = %d samples\n", + N_UE_TA_adj, + N_common_ta_adj, + N_common_ta_drift, + N_common_ta_drift_variant, + ms_since_epoch, + UE->timing_advance_ntn); +} + static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, NR_DL_FRAME_PARMS *fp, + int hfn_rx, int frame_rx, int slot_rx, int *duration_rx_to_tx, @@ -742,34 +797,8 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, *timing_advance -= fp->get_samples_slot_timestamp(slot_rx, fp, (*ntn_koffset - koffset) << mu); *ntn_koffset = koffset; - const int abs_subframe_tx = 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu); - const int abs_subframe_epoch = - 10 * UE->ntn_config_message->ntn_config_params.epoch_sfn + UE->ntn_config_message->ntn_config_params.epoch_subframe; - int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch; - // cope with sfn wrap-around - // this currently limits us to epoch times that are not more than 5.12 seconds in the future (allowed are up to 10.24 seconds) - // and ntn-UlSyncValidityDuration < 5.12 seconds (allowed are up to 900 seconds) - // TODO: fix this limitation by introducing the hyper frame number HFN - if (ms_since_epoch < -5120) - ms_since_epoch += 10240; - else if (ms_since_epoch > 5120) - ms_since_epoch -= 10240; - - const double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; - const double total_ta_drift = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift; // µs/s - const double total_ta_drift_variant = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant; // µs/s² - UE->timing_advance = fp->samples_per_subframe * (total_ta_ms + (total_ta_drift / 1000.0) * (ms_since_epoch / 1000.0) + (total_ta_drift_variant / 1000.0) * (ms_since_epoch / 1000.0) * (ms_since_epoch / 1000.0)); - - LOG_I(PHY, - "k_offset = %d ms (%d slots), total_ta_ms = %f ms, total_ta_drift = %f µs/s, total_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, computed " - "timing_advance = %d samples\n", - *ntn_koffset, - *ntn_koffset << mu, - total_ta_ms, - total_ta_drift, - total_ta_drift_variant, - ms_since_epoch, - UE->timing_advance); + const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu); + apply_ntn_timing_advance(UE, fp, abs_subframe_tx); } } @@ -809,7 +838,7 @@ void *UE_thread(void *arg) int ntn_koffset = 0; int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; - int timing_advance = UE->timing_advance; + int timing_advance = UE->timing_advance + UE->timing_advance_ntn; UE->N_TA_offset = determine_N_TA_offset(UE); NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id); @@ -968,6 +997,8 @@ void *UE_thread(void *arg) curMsg.proc.nr_slot_tx = (absolute_slot + duration_rx_to_tx) % nb_slot_frame; curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER; curMsg.proc.frame_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER; + curMsg.proc.hfn_rx = (absolute_slot / nb_slot_frame) / MAX_FRAME_NUMBER; + curMsg.proc.hfn_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) / MAX_FRAME_NUMBER; if (UE->received_config_request) { if (UE->sl_mode) { curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD); @@ -990,12 +1021,18 @@ void *UE_thread(void *arg) if (slot_nr == nb_slot_frame - 1) { // we shift of half of measured drift, at each beginning of frame for both rx and tx iq_shift_to_apply = shiftForNextFrame; - // TODO: remove this autonomous TA and use up-to-date values of ta-Common, ta-CommonDrift and ta-CommonDriftVariant from received SIB19 instead - if (get_nrUE_params()->autonomous_ta) - UE->timing_advance -= 2 * shiftForNextFrame; + // autonomous timing advance calculation, which does not use SIB19 information + if (ntn_koffset && get_nrUE_params()->autonomous_ta) + UE->timing_advance_ntn -= 2 * shiftForNextFrame; shiftForNextFrame = -round(UE->max_pos_acc * get_nrUE_params()->time_sync_I); } + // Calculate new TA based on SIB19 information for each subframe in NTN mode, if "autonomous_ta" is not enabled + if (ntn_koffset && !get_nrUE_params()->autonomous_ta && (absolute_slot + duration_rx_to_tx) % fp->slots_per_subframe == 0) { + const int abs_subframe_tx = (absolute_slot + duration_rx_to_tx) / fp->slots_per_subframe; + apply_ntn_timing_advance(UE, fp, abs_subframe_tx); + } + const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; openair0_timestamp rx_timestamp; int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx); @@ -1035,7 +1072,7 @@ void *UE_thread(void *arg) // but use current UE->timing_advance value to compute writeBlockSize int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; - int new_timing_advance = UE->timing_advance; + int new_timing_advance = UE->timing_advance + UE->timing_advance_ntn; if (new_timing_advance != timing_advance) { writeBlockSize -= new_timing_advance - timing_advance; timing_advance = new_timing_advance; @@ -1048,7 +1085,7 @@ void *UE_thread(void *arg) } if (curMsg.proc.nr_slot_rx == 0) - nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_rx, curMsg.proc.gNB_id); + nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.gNB_id); // RX slot processing. We launch and forget. notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, UE_dl_processing); @@ -1064,7 +1101,7 @@ void *UE_thread(void *arg) } // apply new NTN timing information - apply_ntn_config(UE, fp, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset); + apply_ntn_config(UE, fp, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset); // Start TX slot processing here. It runs in parallel with RX slot processing // in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot diff --git a/executables/position_interface.c b/executables/position_interface.c index be37515096..fa28e7e884 100644 --- a/executables/position_interface.c +++ b/executables/position_interface.c @@ -20,6 +20,7 @@ */ #include "position_interface.h" +#include "executables/nr-uesoftmodem.h" static void read_position_coordinates(char *sectionName, position_t *position) { diff --git a/executables/position_interface.h b/executables/position_interface.h index 8ef0b3144b..af8c581712 100644 --- a/executables/position_interface.h +++ b/executables/position_interface.h @@ -22,11 +22,6 @@ #ifndef __POSITION_INTERFACE__H__ #define __POSITION_INTERFACE__H__ -#include -#include -#include "PHY/defs_nr_UE.h" -#include "executables/nr-uesoftmodem.h" - /* position configuration parameters name */ #define CONFIG_STRING_POSITION_X "x" #define CONFIG_STRING_POSITION_Y "y" diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index faebaffc6f..62e514cf3f 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -24,6 +24,7 @@ #include "PHY/impl_defs_top.h" #include "PHY/impl_defs_nr.h" #include "common/utils/nr/nr_common.h" +#include "executables/position_interface.h" #define NFAPI_UE_MAX_NUM_CB 8 #define NFAPI_MAX_NUM_UL_PDU 255 @@ -562,18 +563,26 @@ typedef struct { } fapi_nr_ta_command_pdu; typedef struct { + int epoch_hfn; int epoch_sfn; int epoch_subframe; + // orbital angular velocity in rad/ms + double omega; + // satellite position at epoch time + position_t pos_sat_0; + // satellite position at 90° orbit + position_t pos_sat_90; + + // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) + double N_common_ta_adj; + // drift rate of common ta in µs/s + double N_common_ta_drift; + // change rate of common ta drift in µs/s² + double N_common_ta_drift_variant; + // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; - - // ntn_total_time_advance_ms represents the complete round-trip-time between gNB and UE via SAT - double ntn_total_time_advance_ms; - // drift rate of ntn_total_time_advance_ms in µs/s - double ntn_total_time_advance_drift; - // change rate of ntn_total_time_advance_ms drift in µs/s² - double ntn_total_time_advance_drift_variant; } fapi_nr_dl_ntn_config_command_pdu; typedef struct { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index f9047aedd0..619262c746 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -324,7 +324,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int32_t sync_pos = -1; // sync_pos_frame = -1; int32_t metric_tdd_ncp = 0; - uint8_t phase_tdd_ncp; + uint8_t phase_tdd_ncp = 0; double im, re; int ret = -1; uint16_t rx_slss_id = 65535; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 935226b238..f266d7aad5 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -467,7 +467,8 @@ typedef struct PHY_VARS_NR_UE_s { /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB - int timing_advance; + int timing_advance; /// corresponds to N_TA + int timing_advance_ntn; /// corresponds to N_common_TA_adj + N_UE_TA_adj int N_TA_offset; ///timing offset used in TDD int ta_frame; int ta_slot; @@ -538,11 +539,14 @@ typedef struct { /// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_rx; int tx_slot_type; - //#endif /// frame to act upon for transmission int frame_tx; /// frame to act upon for reception int frame_rx; + /// hyper frame number to act upon for transmission + int hfn_tx; + /// hyper frame number to act upon for reception + int hfn_rx; } UE_nr_rxtx_proc_t; typedef struct { diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index a3e86ce433..5c679630f4 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -95,12 +95,20 @@ static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_comma ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message)); } + ue->ntn_config_message->ntn_config_params.epoch_hfn = ntn_params_message->epoch_hfn; ue->ntn_config_message->ntn_config_params.epoch_sfn = ntn_params_message->epoch_sfn; ue->ntn_config_message->ntn_config_params.epoch_subframe = ntn_params_message->epoch_subframe; + + ue->ntn_config_message->ntn_config_params.omega = ntn_params_message->omega; + ue->ntn_config_message->ntn_config_params.pos_sat_0 = ntn_params_message->pos_sat_0; + ue->ntn_config_message->ntn_config_params.pos_sat_90 = ntn_params_message->pos_sat_90; + + ue->ntn_config_message->ntn_config_params.N_common_ta_adj = ntn_params_message->N_common_ta_adj; + ue->ntn_config_message->ntn_config_params.N_common_ta_drift = ntn_params_message->N_common_ta_drift; + ue->ntn_config_message->ntn_config_params.N_common_ta_drift_variant = ntn_params_message->N_common_ta_drift_variant; + ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset; - ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms = ntn_params_message->ntn_total_time_advance_ms; - ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift = ntn_params_message->ntn_total_time_advance_drift; - ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant = ntn_params_message->ntn_total_time_advance_drift_variant; + ue->ntn_config_message->update = true; } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 43fef06ef7..d018630357 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -95,6 +95,7 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, dl_ind->gNB_index = proc->gNB_id; dl_ind->module_id = ue->Mod_id; dl_ind->cc_id = ue->CC_id; + dl_ind->hfn = proc->hfn_rx; dl_ind->frame = proc->frame_rx; dl_ind->slot = proc->nr_slot_rx; dl_ind->phy_data = phy_data; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index e03c0a1fae..d1bbb7ae99 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -44,8 +44,10 @@ void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind, sl_ind->gNB_index = proc->gNB_id; sl_ind->module_id = ue->Mod_id; sl_ind->cc_id = ue->CC_id; + sl_ind->hfn_rx = proc->hfn_rx; sl_ind->frame_rx = proc->frame_rx; sl_ind->slot_rx = proc->nr_slot_rx; + sl_ind->hfn_tx = proc->hfn_tx; sl_ind->frame_tx = proc->frame_tx; sl_ind->slot_tx = proc->nr_slot_tx; sl_ind->phy_data = phy_data; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index a8926e7a44..6b656e5242 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -965,7 +965,7 @@ int main(int argc, char **argv) //Configure UE NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc); nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false, false); - nr_rrc_mac_config_req_cg(0, 0, UE_CellGroup, UE_Capability_nr); + nr_rrc_mac_config_req_cg(0, 0, 0, 0, UE_CellGroup, UE_Capability_nr); asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, UE_CellGroup); diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 604e7a8c2a..ba9712391c 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -163,6 +163,7 @@ typedef uint32_t channel_t; int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, + const int hfn, const frame_t frame, const int slot, const rnti_t rnti, diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index c5c18a12f2..d0d38c5938 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -121,6 +121,7 @@ typedef struct RrcMacBcchDataInd_s { } RrcMacBcchDataInd; typedef struct NRRrcMacBcchDataInd_s { + uint32_t hfn; uint32_t frame; uint8_t slot; uint32_t sdu_size; @@ -134,6 +135,7 @@ typedef struct NRRrcMacBcchDataInd_s { } NRRrcMacBcchDataInd; typedef struct NRRrcMacSBcchDataInd_s { + uint32_t hfn; uint32_t frame; uint8_t slot; uint32_t sdu_size; diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 255da9f189..ab8f93763e 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -438,6 +438,7 @@ typedef struct rrc_subframe_process_s { } RrcSubframeProcess; typedef struct nrrrc_frame_process_s { + int hfn; int frame; int gnb_id; } NRRrcFrameProcess; @@ -475,6 +476,8 @@ typedef struct { typedef struct { NR_CellGroupConfig_t *cellGroupConfig; NR_UE_NR_Capability_t *UE_NR_Capability; + int hfn; + int frame; } nr_mac_rrc_config_cg_t; typedef struct { NR_BCCH_BCH_Message_t *bcch; @@ -487,6 +490,8 @@ typedef struct { } nr_mac_rrc_config_sib1_t; typedef struct { NR_SIB19_r17_t *sib19; + int hfn; + int frame; bool can_start_ra; } nr_mac_rrc_config_other_sib_t; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index f592423c5a..997d0b6c23 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -31,7 +31,6 @@ */ #define _GNU_SOURCE -#define SPEED_OF_LIGHT 299792458 #include "mac_defs.h" #include "NR_MAC_UE/mac_proto.h" @@ -41,7 +40,6 @@ #include "executables/softmodem-common.h" #include "SCHED_NR/phy_frame_config_nr.h" #include "oai_asn1.h" -#include "executables/position_interface.h" #define ASIGN_P_VAL(dst, src) \ do { \ @@ -266,56 +264,61 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo } -// computes round-trip-time between ue and sat based on SIB19 ephemeris data -static void calculate_ue_sat_ta(const position_t *position_params, - const NR_PositionVelocity_r17_t *sat_pos, - ntn_timing_advance_componets_t *ntn_ta) +// prepare data for orbit propagation based on SIB19 ephemeris data to be able to compute the round-trip-time between ue and sat +static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, ntn_timing_advance_componets_t *ntn_ta) { - // get UE position coordinates - const position_t pos_ue = *position_params; - // get sat position coordinates const position_t pos_sat = {sat_pos->positionX_r17 * 1.3, sat_pos->positionY_r17 * 1.3, sat_pos->positionZ_r17 * 1.3}; - // calculate directional vector from SAT to UE - const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z}; - - // calculate distance between SAT and UE - double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z); - // get sat velocity vector const position_t vel_sat = {sat_pos->velocityVX_r17 * 0.06, sat_pos->velocityVY_r17 * 0.06, sat_pos->velocityVZ_r17 * 0.06}; - // calculate SAT velocity towards UE - double velocity = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance; - - // calculate SAT acceleration towards UE + // calculate orbital radius const double radius_2 = pos_sat.X * pos_sat.X + pos_sat.Y * pos_sat.Y + pos_sat.Z * pos_sat.Z; + const double radius = sqrt(radius_2); + + // calculate sat velocity magnitude const double vel_sat_2 = vel_sat.X * vel_sat.X + vel_sat.Y * vel_sat.Y + vel_sat.Z * vel_sat.Z; - const double acceleration = - -(pos_sat.X * dir_sat_ue.X + pos_sat.Y * dir_sat_ue.Y + pos_sat.Z * dir_sat_ue.Z) * vel_sat_2 / (radius_2 * distance); + const double vel_mag = sqrt(vel_sat_2); - LOG_D(NR_MAC, "Satellite velocity towards UE: %f m/s, acceleration towards UE: %f m/s²\n", velocity, acceleration); + // calculate angular velocity in rad/ms + const double omega = vel_mag / (radius * 1000); - ntn_ta->N_UE_TA_adj = (2 * distance / SPEED_OF_LIGHT) * 1e3; // in ms - ntn_ta->N_UE_TA_drift = (2 * -velocity / SPEED_OF_LIGHT) * 1e6; // in µs/s - ntn_ta->N_UE_TA_drift_variant = (2 * acceleration / SPEED_OF_LIGHT) * 1e6; // in µs/s² + // calculate sat position in 90° orbit + position_t pos_sat_90 = pos_sat; + if (vel_mag) { + const double scaling = radius / vel_mag; + pos_sat_90 = (position_t){vel_sat.X * scaling, vel_sat.Y * scaling, vel_sat.Z * scaling}; + } + + LOG_I(NR_MAC, + "Satellite angular velocity = %e rad/ms, sat_pos = {%f, %f, %f}, sat_pos_90 = {%f, %f, %f}\n", + omega, + pos_sat.X, + pos_sat.Y, + pos_sat.Z, + pos_sat_90.X, + pos_sat_90.Y, + pos_sat_90.Z); + + ntn_ta->omega = omega; + ntn_ta->pos_sat_0 = pos_sat; + ntn_ta->pos_sat_90 = pos_sat_90; } // populate ntn_ta structure from mac -static void configure_ntn_ta(module_id_t module_id, - ntn_timing_advance_componets_t *ntn_ta, - const NR_NTN_Config_r17_t *ntn_Config_r17) +static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NTN_Config_r17_t *ntn_Config_r17, int hfn, int frame) { if (!ntn_Config_r17) return; - position_t position_params = {0}; - get_position_coordinates(module_id, &position_params); - // epochTime_r17 must be present (this is assured by function `eval_epoch_time()`) const NR_EpochTime_r17_t *epoch_time_r17 = ntn_Config_r17->epochTime_r17; AssertFatal(epoch_time_r17, "epoch_time_r17 should not be NULL here\n"); + if (epoch_time_r17->sfn_r17 >= frame) + ntn_ta->epoch_hfn = hfn; + else + ntn_ta->epoch_hfn = hfn + 1; ntn_ta->epoch_sfn = epoch_time_r17->sfn_r17; ntn_ta->epoch_subframe = epoch_time_r17->subFrameNR_r17; @@ -325,17 +328,17 @@ static void configure_ntn_ta(module_id_t module_id, if (ephemeris_info->present == NR_EphemerisInfo_r17_PR_positionVelocity_r17) { const NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17; AssertFatal(position_velocity, "position_velocity should not be NULL here\n"); - calculate_ue_sat_ta(&position_params, position_velocity, ntn_ta); + prepare_ue_sat_ta(position_velocity, ntn_ta); } else { LOG_W(NR_MAC, "NR UE currently supports only ephemerisInfo_r17 of type positionVelocity_r17\n"); - ntn_ta->N_UE_TA_adj = 0; - ntn_ta->N_UE_TA_drift = 0; - ntn_ta->N_UE_TA_drift_variant = 0; + ntn_ta->omega = 0; + ntn_ta->pos_sat_0 = (position_t){0, 0, 0}; + ntn_ta->pos_sat_90 = (position_t){0, 0, 0}; } } else { // Need R - Release if not present - ntn_ta->N_UE_TA_adj = 0; - ntn_ta->N_UE_TA_drift = 0; - ntn_ta->N_UE_TA_drift_variant = 0; + ntn_ta->omega = 0; + ntn_ta->pos_sat_0 = (position_t){0, 0, 0}; + ntn_ta->pos_sat_90 = (position_t){0, 0, 0}; } // handle cellSpecificKoffset_r17 @@ -366,21 +369,19 @@ static void configure_ntn_ta(module_id_t module_id, ntn_ta->ntn_params_changed = true; - LOG_D(NR_MAC, - "SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s², " - "N_UE_TA: %fms, drift: %fµs/s, variant %fµs/s²\n", + LOG_I(NR_MAC, + "SIB19 Rxd. Epoch HFN: %d, Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, " + "N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s²\n", + ntn_ta->epoch_hfn, ntn_ta->epoch_sfn, ntn_ta->epoch_subframe, ntn_ta->cell_specific_k_offset, ntn_ta->N_common_ta_adj, ntn_ta->N_common_ta_drift, - ntn_ta->N_common_ta_drift_variant, - ntn_ta->N_UE_TA_adj, - ntn_ta->N_UE_TA_drift, - ntn_ta->N_UE_TA_drift_variant); + ntn_ta->N_common_ta_drift_variant); } -static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP) +static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP, int hfn, int frame) { fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; @@ -555,7 +556,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t // NTN Config if (scc->ext2) { UPDATE_IE(mac->sc_info.ntn_Config_r17, scc->ext2->ntn_Config_r17, NR_NTN_Config_r17_t); - configure_ntn_ta(mac->ue_id, &mac->ntn_ta, mac->sc_info.ntn_Config_r17); + configure_ntn_ta(&mac->ntn_ta, mac->sc_info.ntn_Config_r17, hfn, frame); } else { asn1cFreeStruc(asn_DEF_NR_NTN_Config_r17, mac->sc_info.ntn_Config_r17); } @@ -1947,7 +1948,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si AssertFatal(!ret, "mutex failed %d\n", ret); } -void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, bool can_start_ra) +void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, int hfn, int frame, bool can_start_ra) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -1956,7 +1957,7 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, b if (sib19) { // update ntn_Config_r17 with received values UPDATE_IE(mac->sc_info.ntn_Config_r17, sib19->ntn_Config_r17, NR_NTN_Config_r17_t); - configure_ntn_ta(mac->ue_id, &mac->ntn_ta, mac->sc_info.ntn_Config_r17); + configure_ntn_ta(&mac->ntn_ta, mac->sc_info.ntn_Config_r17, hfn, frame); } if (mac->state == UE_RECEIVING_SIB && can_start_ra) mac->state = UE_PERFORMING_RA; @@ -1966,6 +1967,8 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, b static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, int cc_idP, + int hfn, + int frame, const NR_ReconfigurationWithSync_t *reconfWithSync) { reset_mac_inst(mac); @@ -1985,7 +1988,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, mac->physCellId = *scc->physCellId; mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t); - config_common_ue(mac, scc, cc_idP); + config_common_ue(mac, scc, cc_idP, hfn, frame); // Build the list of all the valid/transmitted SSBs according to the config LOG_D(NR_MAC,"Build SSB list\n"); build_ssb_list(mac); @@ -2754,6 +2757,8 @@ static void handle_mac_uecap_info(NR_UE_MAC_INST_t *mac, NR_UE_NR_Capability_t * void nr_rrc_mac_config_req_cg(module_id_t module_id, int cc_idP, + int hfn, + int frame, NR_CellGroupConfig_t *cell_group_config, NR_UE_NR_Capability_t *ue_Capability) { @@ -2772,7 +2777,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, mac->servCellIndex = spCellConfig->servCellIndex ? *spCellConfig->servCellIndex : 0; if (spCellConfig->reconfigurationWithSync) { LOG_A(NR_MAC, "Received reconfigurationWithSync\n"); - handle_reconfiguration_with_sync(mac, cc_idP, spCellConfig->reconfigurationWithSync); + handle_reconfiguration_with_sync(mac, cc_idP, hfn, frame, spCellConfig->reconfigurationWithSync); } if (scd) { mac->tag_Id = scd->tag_Id; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b43937d362..8a8d9e4ebb 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -62,6 +62,8 @@ #include "NR_MeasConfig.h" #include "NR_ServingCellConfigCommonSIB.h" +/* position_t */ +#include "executables/position_interface.h" // ========== // NR UE defs @@ -543,21 +545,24 @@ typedef struct { } si_schedInfo_t; typedef struct ntn_timing_advance_components { + int epoch_hfn; int epoch_sfn; int epoch_subframe; + // orbital angular velocity in rad/ms + double omega; + // satellite position at epoch time + position_t pos_sat_0; + // satellite position at 90° orbit + position_t pos_sat_90; + // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; // drift rate of common ta in µs/s double N_common_ta_drift; // change rate of common ta drift in µs/s² double N_common_ta_drift_variant; - // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) - double N_UE_TA_adj; - // drift rate of N_UE_TA in µs/s - double N_UE_TA_drift; - // change rate of N_UE_TA drift in µs/s² - double N_UE_TA_drift_variant; + // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; @@ -678,20 +683,5 @@ static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *n return NR_UE_CAPABILITY_SLOT_RX_TO_TX + (ntn_ta->cell_specific_k_offset << scs); } -static inline double get_total_TA_ms(const ntn_timing_advance_componets_t *ntn_ta) -{ - return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj; -} - -static inline double get_total_TA_drift(const ntn_timing_advance_componets_t *ntn_ta) -{ - return ntn_ta->N_common_ta_drift + ntn_ta->N_UE_TA_drift; -} - -static inline double get_total_TA_drift_variant(const ntn_timing_advance_componets_t *ntn_ta) -{ - return ntn_ta->N_common_ta_drift_variant + ntn_ta->N_UE_TA_drift_variant; -} - /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 4897a8fab8..52cb38e4de 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -73,6 +73,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len, + int hfn, int frame, int slot); @@ -82,6 +83,8 @@ void nr_release_mac_config_logicalChannelBearer(NR_UE_MAC_INST_t *mac, long chan void nr_rrc_mac_config_req_cg(module_id_t module_id, int cc_idP, + int hfn, + int frame, NR_CellGroupConfig_t *cell_group_config, NR_UE_NR_Capability_t *ue_Capability); @@ -90,7 +93,7 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra); struct position; /* forward declaration */ -void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, bool can_start_ra); +void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, int hfn, int frame, bool can_start_ra); void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id); void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 0dae34eda7..b5eeedca3f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -777,13 +777,12 @@ static int nr_get_RA_window_4Step(long ra_ResponseWindow) return 0; } -static void setup_ra_response_window(RA_config_t *ra, - int slots_per_frame, - NR_NTN_Config_r17_t *ntn_Config_r17, +static void setup_ra_response_window(NR_UE_MAC_INST_t *mac, + RA_config_t *ra, NR_RACH_ConfigGeneric_t *configGeneric, - NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep, - ntn_timing_advance_componets_t *ntn_ta) + NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep) { + const int slots_per_frame = mac->frame_structure.numb_slots_frame; int respwind_value = 0; if (ra->ra_type == RA_2_STEP) { long *msgB_ResponseWindow = twostep->msgB_ResponseWindow_r16; @@ -816,13 +815,8 @@ static void setup_ra_response_window(RA_config_t *ra, LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n"); } - int ta_Common_slots = 0; - if (ntn_Config_r17) { - const double ta_Common_ms = get_total_TA_ms(ntn_ta); - ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10); - } - - ra->response_window_setup_time = respwind_value + ta_Common_slots; + const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs); + ra->response_window_setup_time = respwind_value + ntn_ue_koffset; } // Random Access procedure initialization as per 5.1.1 and initialization of variables specific @@ -1026,12 +1020,8 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) else ra->num_fd_occasions = 1 << rach_ConfigGeneric->msg1_FDM; - setup_ra_response_window(ra, - mac->frame_structure.numb_slots_frame, - mac->sc_info.ntn_Config_r17, - rach_ConfigGeneric, - twostep_generic, - &mac->ntn_ta); + setup_ra_response_window(mac, ra, rach_ConfigGeneric, twostep_generic); + return true; } @@ -1039,16 +1029,15 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s { RA_config_t *ra = &mac->ra; NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - const double ta_Common_ms = get_total_TA_ms(&mac->ntn_ta); + const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs); const int slots_per_ms = mac->frame_structure.numb_slots_frame / 10; // start contention resolution timer const int RA_contention_resolution_timer_ms = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3; const int RA_contention_resolution_timer_slots = RA_contention_resolution_timer_ms * slots_per_ms; - 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_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_slots + ntn_ue_koffset, 1); nr_timer_start(&ra->contention_resolution_timer); ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index aeb15fe864..86d7b9254f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -361,12 +361,13 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len, + int hfn, int frame, int slot) { if(ack_nack) { LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, hfn, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); if (mac->get_sib1) mac->get_sib1 = false; for (int i = 0; i < MAX_SI_GROUPS; i++) { @@ -383,7 +384,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, } else { LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, hfn, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index e566f3db9e..6387d9b516 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2848,12 +2848,19 @@ static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, { fapi_nr_dl_ntn_config_command_pdu *ntn_config_command_pdu = &dl_config->dl_config_list[dl_config->number_pdus].ntn_config_command_pdu; + ntn_config_command_pdu->epoch_hfn = mac->ntn_ta.epoch_hfn; ntn_config_command_pdu->epoch_sfn = mac->ntn_ta.epoch_sfn; ntn_config_command_pdu->epoch_subframe = mac->ntn_ta.epoch_subframe; + + ntn_config_command_pdu->omega = mac->ntn_ta.omega; + ntn_config_command_pdu->pos_sat_0 = mac->ntn_ta.pos_sat_0; + ntn_config_command_pdu->pos_sat_90 = mac->ntn_ta.pos_sat_90; + + ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj; + ntn_config_command_pdu->N_common_ta_drift = mac->ntn_ta.N_common_ta_drift; + ntn_config_command_pdu->N_common_ta_drift_variant = mac->ntn_ta.N_common_ta_drift_variant; + ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; - ntn_config_command_pdu->ntn_total_time_advance_ms = get_total_TA_ms(&mac->ntn_ta); - ntn_config_command_pdu->ntn_total_time_advance_drift = get_total_TA_drift(&mac->ntn_ta); - ntn_config_command_pdu->ntn_total_time_advance_drift_variant = get_total_TA_drift_variant(&mac->ntn_ta); dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS; dl_config->number_pdus += 1; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 0939b52c7a..09f3218f1e 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -123,7 +123,7 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac, else mac->frequency_range = FR1; // fixed 3 bytes MIB PDU - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, cell_id, ssb_arfcn, NR_BCCH_BCH, (uint8_t *) pduP, 3); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, 0, cell_id, ssb_arfcn, NR_BCCH_BCH, (uint8_t *) pduP, 3); return 0; } @@ -134,10 +134,11 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len, + int hfn, int frame, int slot) { - nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len, frame, slot); + nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len, hfn, frame, slot); return 0; } @@ -301,6 +302,7 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio rx_indication_body.pdsch_pdu.ack_nack, rx_indication_body.pdsch_pdu.pdu, rx_indication_body.pdsch_pdu.pdu_length, + dl_info->hfn, dl_info->frame, dl_info->slot)) << FAPI_NR_RX_PDU_TYPE_SIB; break; @@ -389,6 +391,7 @@ static void handle_sl_bch(int ue_id, sl_nr_ue_mac_params_t *sl_mac, uint8_t *const sl_mib, const uint8_t len, + int hfn_rx, uint16_t frame_rx, uint16_t slot_rx, uint16_t rx_slss_id) @@ -421,7 +424,7 @@ static void handle_sl_bch(int ue_id, sl_mac->decoded_DFN = frame; sl_mac->decoded_slot = slot; - nr_mac_rrc_data_ind_ue(ue_id, 0, 0, frame_rx, slot_rx, 0, rx_slss_id, 0, NR_SBCCH_SL_BCH, (uint8_t *)sl_mib, len); + nr_mac_rrc_data_ind_ue(ue_id, 0, 0, hfn_rx, frame_rx, slot_rx, 0, rx_slss_id, 0, NR_SBCCH_SL_BCH, (uint8_t *)sl_mib, len); return; } @@ -433,6 +436,7 @@ if PSBCH rx - handle_psbch() if PSSCH DATa rx - handle slsch() */ void sl_nr_process_rx_ind(int ue_id, + int hfn, uint32_t frame, uint32_t slot, sl_nr_ue_mac_params_t *sl_mac, @@ -456,6 +460,7 @@ void sl_nr_process_rx_ind(int ue_id, sl_mac, rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.psbch_payload, 4, + hfn, frame, slot, rx_ind->rx_indication_body[num_pdus - 1].ssb_pdu.rx_slss_id); @@ -488,11 +493,12 @@ void nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication) uint16_t slot = sl_indication->slot_rx; uint16_t frame = sl_indication->frame_rx; + int hfn = sl_indication->hfn_rx; sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS; if (sl_indication->rx_ind) { - sl_nr_process_rx_ind(ue_id, frame, slot, sl_mac, sl_indication->rx_ind); + sl_nr_process_rx_ind(ue_id, hfn, frame, slot, sl_mac, sl_indication->rx_ind); } else { nr_ue_sidelink_scheduler(sl_indication, mac); } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index a1175282f0..66afa266f8 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -56,6 +56,8 @@ typedef struct { uint32_t gNB_index; /// component carrier id int cc_id; + /// hyper frame number + int hfn; /// frame frame_t frame; /// slot @@ -101,10 +103,14 @@ typedef struct { uint32_t gNB_index; /// component carrier id int cc_id; + /// hyper frame number rx + int hfn_rx; /// frame rx frame_t frame_rx; /// slot rx uint32_t slot_rx; + /// hyper frame number tx + int hfn_tx; /// frame tx frame_t frame_tx; /// slot tx diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index bae8915916..12ed0953dd 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -59,6 +59,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const void nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, + const int hfn, const frame_t frame, const int slot, const rnti_t rnti, @@ -97,6 +98,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, else { NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = 0; } + NR_RRC_MAC_BCCH_DATA_IND (message_p).hfn = hfn; NR_RRC_MAC_BCCH_DATA_IND (message_p).frame = frame; //frameP NR_RRC_MAC_BCCH_DATA_IND (message_p).slot = slot; NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index; @@ -120,6 +122,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SBCCH_DATA_IND); memset(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); memcpy(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, pduP, sdu_size); + NR_RRC_MAC_SBCCH_DATA_IND (message_p).hfn = hfn; NR_RRC_MAC_SBCCH_DATA_IND (message_p).frame = frame; //frameP NR_RRC_MAC_SBCCH_DATA_IND (message_p).slot = slot; NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu_size = sdu_size; @@ -139,7 +142,12 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) nr_rrc_mac_config_req_reset(instance_id, msg->payload.config_reset.cause); break; case NR_MAC_RRC_CONFIG_CG: - nr_rrc_mac_config_req_cg(instance_id, 0, msg->payload.config_cg.cellGroupConfig, msg->payload.config_cg.UE_NR_Capability); + nr_rrc_mac_config_req_cg(instance_id, + 0, + msg->payload.config_cg.hfn, + msg->payload.config_cg.frame, + msg->payload.config_cg.cellGroupConfig, + msg->payload.config_cg.UE_NR_Capability); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, msg->payload.config_cg.cellGroupConfig); break; case NR_MAC_RRC_CONFIG_MIB: @@ -157,8 +165,11 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) SEQUENCE_free(&asn_DEF_NR_SIB1, msg->payload.config_sib1.sib1, ASFM_FREE_EVERYTHING); } break; case NR_MAC_RRC_CONFIG_OTHER_SIB: { - bool can_start_ra = msg->payload.config_other_sib.can_start_ra; - nr_rrc_mac_config_other_sib(instance_id, msg->payload.config_other_sib.sib19, can_start_ra); + nr_rrc_mac_config_other_sib(instance_id, + msg->payload.config_other_sib.sib19, + msg->payload.config_other_sib.hfn, + msg->payload.config_other_sib.frame, + msg->payload.config_other_sib.can_start_ra); } break; case NR_MAC_RRC_RESUME_RB: nr_rrc_mac_resume_rb(instance_id, msg->payload.resume_rb.is_srb, msg->payload.resume_rb.rb_id); @@ -183,10 +194,11 @@ void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_ itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p); } -void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id) +void nr_ue_rrc_timer_trigger(int instance, int hfn, int frame, int gnb_id) { MessageDef *message_p; message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NRRRC_FRAME_PROCESS); + NRRRC_FRAME_PROCESS(message_p).hfn = hfn; NRRRC_FRAME_PROCESS(message_p).frame = frame; NRRRC_FRAME_PROCESS(message_p).gnb_id = gnb_id; LOG_D(NR_RRC, "RRC timer trigger: frame %d\n", frame); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index 5c7a4c16af..9a5e5ee2a8 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -29,6 +29,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const void nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, + const int hfn, const frame_t frame, const int slot, const rnti_t rnti, @@ -45,7 +46,7 @@ void nr_mac_rrc_meas_ind_ue(module_id_t module_id, int rsrp_dBm); void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload); -void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); +void nr_ue_rrc_timer_trigger(int instance, int hfn, int frame, int gnb_id); void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success); void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id); #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 27e1dc0bb1..bc2efb84b0 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -292,7 +292,7 @@ static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *S nr_timer_start(&SI_info->SInfo_r17.sib19_timer); } -static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int frame) +static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int hfn, int frame) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN); @@ -381,6 +381,8 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, rrc_msg.payload_type = NR_MAC_RRC_CONFIG_OTHER_SIB; nr_mac_rrc_config_other_sib_t *sib19_msg = &rrc_msg.payload.config_other_sib; asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&sib19_msg->sib19, sib19); + sib19_msg->hfn = hfn; + sib19_msg->frame = frame; sib19_msg->can_start_ra = rrc->is_NTN_UE; nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } @@ -776,6 +778,8 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, nr_mac_rrc_config_cg_t *mac_msg = &rrc_msg.payload.config_cg; mac_msg->cellGroupConfig = cellGroupConfig; mac_msg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + mac_msg->hfn = rrc->current_hfn; + mac_msg->frame = rrc->current_frame; nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } @@ -824,7 +828,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe SEQUENCE_free(&asn_DEF_NR_SystemInformation, si, 1); } else { LOG_I(NR_RRC, "[UE %ld] Decoding dedicatedSystemInformationDelivery\n", rrc->ue_id); - nr_decode_SI(SI_info, si, rrc, rrc->current_frame); + nr_decode_SI(SI_info, si, rrc, rrc->current_hfn, rrc->current_frame); } } if (rec_1530->otherConfig) { @@ -1182,6 +1186,8 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; config_cg->cellGroupConfig = cellGroupConfig; config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + config_cg->hfn = rrc->current_hfn; + config_cg->frame = rrc->current_frame; nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } } @@ -1611,6 +1617,7 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, const uint8_t Sdu_len, const uint8_t rsrq, const uint8_t rsrp, + int hfn, int frame, int slot) { @@ -1650,7 +1657,7 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: LOG_I(NR_RRC, "[UE %ld] %d:%d Decoding SI\n", rrc->ue_id, frame, slot); NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation; - nr_decode_SI(SI_info, si, rrc, frame); + nr_decode_SI(SI_info, si, rrc, hfn, frame); break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: default: @@ -2640,6 +2647,7 @@ void *rrc_nrue(void *notUsed) } break; case NRRRC_FRAME_PROCESS: + rrc->current_hfn = NRRRC_FRAME_PROCESS(msg_p).hfn; rrc->current_frame = NRRRC_FRAME_PROCESS(msg_p).frame; LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), rrc->current_frame); // increase the timers every 10ms (every new frame) @@ -2698,6 +2706,7 @@ void *rrc_nrue(void *notUsed) bcch->sdu_size, bcch->rsrq, bcch->rsrp, + bcch->hfn, bcch->frame, bcch->slot); break; diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 0672af7741..e7f9cec43b 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -262,6 +262,7 @@ typedef struct NR_UE_RRC_INST_s { // 5G-S-TMSI uint64_t fiveG_S_TMSI; // Frame timing received from MAC + int current_hfn; int current_frame; //Sidelink params diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 1ebb728884..28bdeb6e51 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -73,7 +73,7 @@ int get_from_lte_ue_fd(); void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo); void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo); -void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id); +void nr_ue_rrc_timer_trigger(int module_id, int hfn, int frame, int gnb_id); void handle_t300_expiry(NR_UE_RRC_INST_t *rrc); void handle_t430_expiry(NR_UE_RRC_INST_t *rrc); diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index a976c63264..aca8a6b030 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -99,21 +99,54 @@ void rxAddInput(const c16_t *input_sig, double vel_sat_gnb = 0; double acc_sat_gnb = 0; if (channelDesc->modelid == SAT_LEO_TRANS) { - const double acc_sat_x = 0; - const double acc_sat_y = -w_sat * w_sat * radius_sat * sin(w_sat * t); - const double acc_sat_z = -w_sat * w_sat * radius_sat * cos(w_sat * t); + const double t5 = t + 5; + const double t10 = t + 10; const double pos_gnb_x = 0; const double pos_gnb_y = 0; const double pos_gnb_z = radius_earth; + const double pos_sat_x5 = 0; + const double pos_sat_y5 = radius_sat * sin(w_sat * t5); + const double pos_sat_z5 = radius_sat * cos(w_sat * t5); + + const double pos_sat_x10 = 0; + const double pos_sat_y10 = radius_sat * sin(w_sat * t10); + const double pos_sat_z10 = radius_sat * cos(w_sat * t10); + const double dir_sat_gnb_x = pos_gnb_x - pos_sat_x; const double dir_sat_gnb_y = pos_gnb_y - pos_sat_y; const double dir_sat_gnb_z = pos_gnb_z - pos_sat_z; + const double dir_sat_gnb_x5 = pos_gnb_x - pos_sat_x5; + const double dir_sat_gnb_y5 = pos_gnb_y - pos_sat_y5; + const double dir_sat_gnb_z5 = pos_gnb_z - pos_sat_z5; + + const double dir_sat_gnb_x10 = pos_gnb_x - pos_sat_x10; + const double dir_sat_gnb_y10 = pos_gnb_y - pos_sat_y10; + const double dir_sat_gnb_z10 = pos_gnb_z - pos_sat_z10; + dist_sat_gnb = sqrt(dir_sat_gnb_x * dir_sat_gnb_x + dir_sat_gnb_y * dir_sat_gnb_y + dir_sat_gnb_z * dir_sat_gnb_z); - vel_sat_gnb = (vel_sat_x * dir_sat_gnb_x + vel_sat_y * dir_sat_gnb_y + vel_sat_z * dir_sat_gnb_z) / dist_sat_gnb; - acc_sat_gnb = (acc_sat_x * dir_sat_gnb_x + acc_sat_y * dir_sat_gnb_y + acc_sat_z * dir_sat_gnb_z) / dist_sat_gnb; + const double dist_sat_gnb5 = sqrt(dir_sat_gnb_x5 * dir_sat_gnb_x5 + dir_sat_gnb_y5 * dir_sat_gnb_y5 + dir_sat_gnb_z5 * dir_sat_gnb_z5); + const double dist_sat_gnb10 = sqrt(dir_sat_gnb_x10 * dir_sat_gnb_x10 + dir_sat_gnb_y10 * dir_sat_gnb_y10 + dir_sat_gnb_z10 * dir_sat_gnb_z10); + + // calculate vel_sat_gnb and acc_sat_gnb, so the delay is correct for epoch_time, epoch_time + 5 seconds and epoch_time + 10 seconds + // + // dist_sat_gnb = dist_sat_gnb + 0 * vel_sat_gnb + 0 * acc_sat_gnb; + // dist_sat_gnb5 = dist_sat_gnb + 5 * vel_sat_gnb + 25 * acc_sat_gnb; + // dist_sat_gnb10 = dist_sat_gnb + 10 * vel_sat_gnb + 100 * acc_sat_gnb; + // + // vel_sat_gnb = (dist_sat_gnb5 - dist_sat_gnb) / 5 - 5 * acc_sat_gnb; + // acc_sat_gnb = (dist_sat_gnb10 - dist_sat_gnb) / 100 - vel_sat_gnb / 10; + // + // vel_sat_gnb = (dist_sat_gnb5 - dist_sat_gnb) / 5 - 5 * ((dist_sat_gnb10 - dist_sat_gnb) / 100 - vel_sat_gnb / 10); + + vel_sat_gnb = 2 * (dist_sat_gnb5 - dist_sat_gnb) / 5 - (dist_sat_gnb10 - dist_sat_gnb) / 10; + acc_sat_gnb = (dist_sat_gnb10 - dist_sat_gnb) / 50 - (dist_sat_gnb5 - dist_sat_gnb) / 25; + + // in the moment when the satellite disappears behind the horizon acc_sat_gnb might become negative, what is invalid + if (acc_sat_gnb < 0) + acc_sat_gnb = 0; } const double prop_delay = (dist_ue_sat + dist_sat_gnb) / c; @@ -128,7 +161,7 @@ void rxAddInput(const c16_t *input_sig, last_TS = TS; LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); LOG_I(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000); - LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", vel_sat_gnb, acc_sat_gnb); + LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", -vel_sat_gnb, acc_sat_gnb); } const int samples_per_subframe = channelDesc->sampling_rate / 1000; @@ -138,7 +171,7 @@ void rxAddInput(const c16_t *input_sig, .sfn = (abs_subframe / 10 + 1) % 1024, .subframe = 0, .delay = 2 * dist_sat_gnb / (c * 4.072e-9), - .drift = 2 * -vel_sat_gnb / (c * 0.2e-9), + .drift = 2 * vel_sat_gnb / (c * 0.2e-9), .accel = 2 * acc_sat_gnb / (c * 0.2e-10), .position.X = pos_sat_x / 1.3, .position.Y = pos_sat_y / 1.3,