Commit bc81662c authored by Thomas Schlichter's avatar Thomas Schlichter

NR UE: consider computed DL/UL Doppler shift in continuous FO compensation

parent b59bcaf4
...@@ -258,7 +258,7 @@ static void UE_synch(void *arg) { ...@@ -258,7 +258,7 @@ static void UE_synch(void *arg) {
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0); + round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
if (get_nrUE_params()->cont_fo_comp) { if (get_nrUE_params()->cont_fo_comp) {
UE->freq_offset = freq_offset; UE->freq_offset = freq_offset - UE->dl_Doppler_shift;
} else { } else {
// rerun with new cell parameters and frequency-offset // rerun with new cell parameters and frequency-offset
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset); nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
...@@ -400,7 +400,12 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx ...@@ -400,7 +400,12 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative
ul_freq_offset = -ul_freq_offset; ul_freq_offset = -ul_freq_offset;
for (int i = 0; i < fp->nb_antennas_tx; i++) for (int i = 0; i < fp->nb_antennas_tx; i++)
nr_fo_compensation(ul_freq_offset, fp->samples_per_subframe, writeTimestamp, txp[i], txp[i], writeBlockSize); nr_fo_compensation(UE->ul_Doppler_shift + ul_freq_offset,
fp->samples_per_subframe,
writeTimestamp,
txp[i],
txp[i],
writeBlockSize);
} }
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags); int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags);
...@@ -723,10 +728,18 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) { ...@@ -723,10 +728,18 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
} }
#define SPEED_OF_LIGHT 299792458 #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) static void apply_ntn_timing_advance_and_doppler(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 fapi_nr_dl_ntn_config_command_pdu *ntn_config_params = &UE->ntn_config_message->ntn_config_params;
// Handle terrestrial networks
if (ntn_config_params->cell_specific_k_offset == 0) {
UE->timing_advance_ntn = 0;
UE->dl_Doppler_shift = 0;
UE->ul_Doppler_shift = 0;
return;
}
const int abs_subframe_epoch = ntn_config_params->epoch_subframe const int abs_subframe_epoch = ntn_config_params->epoch_subframe
+ ntn_config_params->epoch_sfn * 10 + ntn_config_params->epoch_sfn * 10
+ ntn_config_params->epoch_hfn * 10240; + ntn_config_params->epoch_hfn * 10240;
...@@ -771,6 +784,12 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM ...@@ -771,6 +784,12 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM
// calculate projected velocity from SAT towards UE // calculate projected velocity from SAT towards UE
const double vel_sat_ue = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance; const double vel_sat_ue = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance;
// calculate DL Doppler shift (moving source)
const double dl_Doppler_shift = (vel_sat_ue / (SPEED_OF_LIGHT - vel_sat_ue)) * fp->dl_CarrierFreq;
// calculate UL Doppler shift (moving target)
const double ul_Doppler_shift = (vel_sat_ue / SPEED_OF_LIGHT) * fp->ul_CarrierFreq;
// calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000) // 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_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT;
...@@ -783,32 +802,33 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM ...@@ -783,32 +802,33 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM
+ N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9) + N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
* fp->samples_per_subframe; * fp->samples_per_subframe;
UE->freq_offset -= dl_Doppler_shift - UE->dl_Doppler_shift;
UE->dl_Doppler_shift = dl_Doppler_shift;
UE->ul_Doppler_shift = ul_Doppler_shift;
LOG_D(PHY, 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², " "satellite velocity towards UE = %f m/s, DL Doppler shift = %f kHz, UL Doppler shift = %f kHz\n",
"ms_since_epoch = %d ms, computed timing_advance_ntn = %d samples, satellite velocity towards UE = %f m/s\n", vel_sat_ue,
N_UE_TA_adj, dl_Doppler_shift / 1000,
N_common_ta_adj, ul_Doppler_shift / 1000);
N_common_ta_drift,
N_common_ta_drift_variant,
ms_since_epoch,
UE->timing_advance_ntn,
vel_sat_ue);
} }
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, static void apply_ntn_config(PHY_VARS_NR_UE *UE,
NR_DL_FRAME_PARMS *fp, NR_DL_FRAME_PARMS *fp,
int hfn_rx, int hfn_rx,
int frame_rx, int frame_rx,
int slot_rx, int slot_rx,
int *duration_rx_to_tx, int *duration_rx_to_tx,
int *timing_advance, int *timing_advance,
int *ntn_koffset) int *ntn_koffset)
{ {
if (UE->ntn_config_message->update) { if (UE->ntn_config_message->update) {
UE->ntn_config_message->update = false; UE->ntn_config_message->update = false;
const fapi_nr_dl_ntn_config_command_pdu *ntn_config_params = &UE->ntn_config_message->ntn_config_params;
const int mu = fp->numerology_index; const int mu = fp->numerology_index;
const int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; const int koffset = ntn_config_params->cell_specific_k_offset;
*duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu); *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
if (koffset > *ntn_koffset) if (koffset > *ntn_koffset)
...@@ -818,7 +838,18 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, ...@@ -818,7 +838,18 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
*ntn_koffset = koffset; *ntn_koffset = koffset;
const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu); 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); apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
LOG_I(PHY,
"k_offset: %dms, N_Common_Ta: %fms, drift: %fµs/s, variant: %fµs/s², "
"timing_advance_ntn: %d samples, DL Doppler shift: %fkHz, UL Doppler shift: %fkHz\n",
koffset << mu,
ntn_config_params->N_common_ta_adj,
ntn_config_params->N_common_ta_drift,
ntn_config_params->N_common_ta_drift_variant,
UE->timing_advance_ntn,
UE->dl_Doppler_shift / 1000,
UE->ul_Doppler_shift / 1000);
} }
} }
...@@ -1050,7 +1081,7 @@ void *UE_thread(void *arg) ...@@ -1050,7 +1081,7 @@ void *UE_thread(void *arg)
// Calculate new TA based on SIB19 information for each subframe in NTN mode, if "autonomous_ta" is not enabled // 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) { 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; const int abs_subframe_tx = (absolute_slot + duration_rx_to_tx) / fp->slots_per_subframe;
apply_ntn_timing_advance(UE, fp, abs_subframe_tx); apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
} }
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
......
...@@ -119,7 +119,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, ...@@ -119,7 +119,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
if (ue && ue->cont_fo_comp) { if (ue && ue->cont_fo_comp) {
start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
nr_fo_compensation(ue->freq_offset, nr_fo_compensation(ue->dl_Doppler_shift + ue->freq_offset,
frame_parms->samples_per_subframe, frame_parms->samples_per_subframe,
rx_offset, rx_offset,
rxdata_symb_ptr[aa], rxdata_symb_ptr[aa],
......
...@@ -462,8 +462,10 @@ typedef struct PHY_VARS_NR_UE_s { ...@@ -462,8 +462,10 @@ typedef struct PHY_VARS_NR_UE_s {
double initial_fo; /// initial frequency offset provided by the user double initial_fo; /// initial frequency offset provided by the user
int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation
double freq_offset; /// currently compensated frequency offset double freq_offset; /// currently compensated DL frequency offset (without dl_Doppler_shift)
double freq_off_acc; /// accumulated frequency error (for PI controller) double freq_off_acc; /// accumulated DL frequency error (for PI controller)
double dl_Doppler_shift; /// calculated DL Doppler shift
double ul_Doppler_shift; /// calculated UL Doppler shift
/// Timing Advance updates variables /// Timing Advance updates variables
/// Timing advance update computed from the TA command signalled from gNB /// Timing advance update computed from the TA command signalled from gNB
......
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