NR UE: correctly apply Doppler and TA for NTN target cell
Make sure to apply Doppler and TA not directly when receiving the target cell ntn_config, but apply Doppler just before the initial sync, and the TA after the initial sync when we have tha actuel cell frame and slot numbers.
This commit is contained in:
+50
-29
@@ -523,7 +523,7 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
}
|
||||
|
||||
// Apply Doppler based on NTN-Config for target cell
|
||||
if (UE->target_Nid_cell != fp->Nid_cell)
|
||||
if (UE->nrUE_config.ntn_config.is_targetcell)
|
||||
apply_ntn_timing_advance_and_doppler(UE, fp, -1);
|
||||
// Apply NTN DL Doppler as initial FO
|
||||
UE->initial_fo = UE->dl_Doppler_shift;
|
||||
@@ -857,37 +857,46 @@ static void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
int slot_rx,
|
||||
int *duration_rx_to_tx,
|
||||
int *timing_advance,
|
||||
int *ntn_koffset)
|
||||
int *ntn_koffset,
|
||||
bool *ntn_targetcell)
|
||||
{
|
||||
if (UE->nrUE_config.ntn_config.params_changed) {
|
||||
UE->nrUE_config.ntn_config.params_changed = false;
|
||||
// return if there is no pending update
|
||||
if (!UE->nrUE_config.ntn_config.params_changed)
|
||||
return;
|
||||
|
||||
const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
|
||||
*ntn_targetcell = UE->nrUE_config.ntn_config.is_targetcell;
|
||||
|
||||
const int mu = fp->numerology_index;
|
||||
const int koffset = ntn_config_params->cell_specific_k_offset;
|
||||
// skip update if it is for the target cell
|
||||
if (UE->nrUE_config.ntn_config.is_targetcell)
|
||||
return;
|
||||
|
||||
*duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
|
||||
if (koffset > *ntn_koffset)
|
||||
*timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
|
||||
else if (koffset < *ntn_koffset)
|
||||
*timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
|
||||
*ntn_koffset = koffset;
|
||||
UE->nrUE_config.ntn_config.params_changed = false;
|
||||
|
||||
const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
|
||||
apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
|
||||
const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
|
||||
|
||||
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);
|
||||
}
|
||||
const int mu = fp->numerology_index;
|
||||
const int koffset = ntn_config_params->cell_specific_k_offset;
|
||||
|
||||
*duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
|
||||
if (koffset > *ntn_koffset)
|
||||
*timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
|
||||
else if (koffset < *ntn_koffset)
|
||||
*timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
|
||||
*ntn_koffset = koffset;
|
||||
|
||||
const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
|
||||
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);
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg)
|
||||
@@ -929,6 +938,7 @@ void *UE_thread(void *arg)
|
||||
else
|
||||
UE->max_pos_acc = 0;
|
||||
|
||||
bool ntn_targetcell = false;
|
||||
int ntn_koffset = 0;
|
||||
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
|
||||
int timing_advance = UE->timing_advance + UE->timing_advance_ntn;
|
||||
@@ -1057,12 +1067,14 @@ void *UE_thread(void *arg)
|
||||
const int frame_rx = (absolute_slot / nb_slot_frame) % 1024;
|
||||
const int hfn_rx = (absolute_slot / nb_slot_frame) / 1024;
|
||||
fix_ntn_epoch_hfn(UE, hfn_rx, frame_rx);
|
||||
UE->nrUE_config.ntn_config.is_targetcell = false;
|
||||
if (UE->nrUE_config.ntn_config.params_changed) {
|
||||
apply_ntn_config(UE, fp, hfn_rx, frame_rx, 0, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
|
||||
apply_ntn_config(UE, fp, hfn_rx, frame_rx, 0, &duration_rx_to_tx, &timing_advance, &ntn_koffset, &ntn_targetcell);
|
||||
} else {
|
||||
const int mu = fp->numerology_index;
|
||||
const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + (duration_rx_to_tx >> mu);
|
||||
apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
|
||||
ntn_targetcell = false;
|
||||
}
|
||||
UE->timing_advance = 0;
|
||||
// We have resynchronized, maybe after RF loss so we need to purge any existing context
|
||||
@@ -1124,7 +1136,8 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// 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 && !ntn_targetcell && !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_and_doppler(UE, fp, abs_subframe_tx);
|
||||
}
|
||||
@@ -1202,7 +1215,15 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// apply new NTN timing information
|
||||
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);
|
||||
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,
|
||||
&ntn_targetcell);
|
||||
|
||||
// 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
|
||||
|
||||
@@ -588,6 +588,7 @@ typedef struct {
|
||||
// cell scheduling offset expressed in terms of 15kHz SCS
|
||||
long cell_specific_k_offset;
|
||||
|
||||
bool is_targetcell;
|
||||
bool params_changed;
|
||||
} fapi_nr_ntn_config_t;
|
||||
|
||||
|
||||
@@ -327,7 +327,11 @@ static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, fapi_nr_
|
||||
}
|
||||
|
||||
// populate ntn_ta structure from mac
|
||||
static void configure_ntn_ta(fapi_nr_ntn_config_t *ntn_ta, const NR_NTN_Config_r17_t *ntn_Config_r17, int hfn, int frame)
|
||||
static void configure_ntn_ta(fapi_nr_ntn_config_t *ntn_ta,
|
||||
const NR_NTN_Config_r17_t *ntn_Config_r17,
|
||||
int hfn,
|
||||
int frame,
|
||||
bool is_targetcell)
|
||||
{
|
||||
if (!ntn_Config_r17)
|
||||
return;
|
||||
@@ -402,6 +406,7 @@ static void configure_ntn_ta(fapi_nr_ntn_config_t *ntn_ta, const NR_NTN_Config_r
|
||||
ntn_ta->vel_sat_90 = (position_t){0, 0, 0};
|
||||
}
|
||||
|
||||
ntn_ta->is_targetcell = is_targetcell;
|
||||
ntn_ta->params_changed = true;
|
||||
}
|
||||
|
||||
@@ -579,7 +584,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->phy_config.config_req.ntn_config, mac->sc_info.ntn_Config_r17, hfn, frame);
|
||||
configure_ntn_ta(&mac->phy_config.config_req.ntn_config, mac->sc_info.ntn_Config_r17, hfn, frame, true);
|
||||
} else {
|
||||
asn1cFreeStruc(asn_DEF_NR_NTN_Config_r17, mac->sc_info.ntn_Config_r17);
|
||||
}
|
||||
@@ -1991,7 +1996,7 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, i
|
||||
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->phy_config.config_req.ntn_config, mac->sc_info.ntn_Config_r17, hfn, frame);
|
||||
configure_ntn_ta(&mac->phy_config.config_req.ntn_config, mac->sc_info.ntn_Config_r17, hfn, frame, false);
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
mac->phy_config.config_req.ntn_config.params_changed = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user