Commit 9c741e9c authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/NR_fix_ssbpos_ho' into integration_2026_w10 (!3929)

UE: Fix if target cell during handover has SSB at a different offset as in source cell

These changes fixed these observed issues:
- If target cell has a different SSB position compared to source cell during
  ho - sync was not successful.
- RAR does not get decoded if SSB position has changed on the target cell
  compared to source cell.
parents 352188fb dafabe38
......@@ -486,12 +486,13 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
UE->UE_scan_carrier = false;
UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell;
const fapi_nr_ue_carrier_config_t *cfg = &UE->nrUE_config.carrier_config;
const fapi_nr_config_request_t *config = &UE->nrUE_config;
const fapi_nr_ue_carrier_config_t *cfg = &config->carrier_config;
uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency);
uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency);
if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) {
LOG_I(NR_PHY,
"[UE %d] RF frequency change: dl %lu->%lu Hz, ul %lu->%lu Hz (from dl_frequency=%u kHz, target_Nid_cell=%d)\n",
"[UE %d] SYNC REQ: RF frequency change: dl %lu->%lu Hz, ul %lu->%lu Hz (from dl_frequency=%u kHz, target_Nid_cell=%d)\n",
UE->Mod_id,
fp->dl_CarrierFreq,
dl_CarrierFreq,
......@@ -505,6 +506,16 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
init_symbol_rotation(fp);
}
int ssb_start_subcarrier = nr_get_ssb_start_sc(fp->numerology_index,
config->ssb_table.ssb_offset_point_a,
config->ssb_table.ssb_subcarrier_offset,
fp->freq_range);
// SSB location can change during for ex: handover on the target cell
if (ssb_start_subcarrier != fp->ssb_start_subcarrier) {
fp->ssb_start_subcarrier = ssb_start_subcarrier;
LOG_I(NR_PHY, "SYNC REQ: SSB location changed:%d\n", fp->ssb_start_subcarrier);
}
// Apply Doppler based on NTN-Config for target cell
if (UE->nrUE_config.ntn_config.is_targetcell)
apply_ntn_timing_advance_and_doppler(UE, fp, -1);
......
......@@ -24,6 +24,7 @@
#include "common/utils/LOG/log.h"
#include "executables/softmodem-common.h"
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
/// Subcarrier spacings in Hz indexed by numerology index
static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3};
......@@ -421,16 +422,11 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fapi_nr_config_request_t* conf
fp->samples_per_frame = 10 * fp->samples_per_subframe;
fp->freq_range = get_freq_range_from_freq(fp->dl_CarrierFreq);
uint8_t sco = 0;
if (((fp->freq_range == FR1) && (config->ssb_table.ssb_subcarrier_offset < 24)) ||
((fp->freq_range == FR2) && (config->ssb_table.ssb_subcarrier_offset < 12))) {
if (fp->freq_range == FR1)
sco = config->ssb_table.ssb_subcarrier_offset>>config->ssb_config.scs_common;
else
sco = config->ssb_table.ssb_subcarrier_offset;
}
fp->ssb_start_subcarrier = nr_get_ssb_start_sc(config->ssb_config.scs_common,
config->ssb_table.ssb_offset_point_a,
config->ssb_table.ssb_subcarrier_offset,
fp->freq_range);
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
set_Lmax(fp);
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
......
......@@ -389,4 +389,9 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
const uint8_t cdm_type,
c16_t **dataF);
int nr_get_ssb_start_sc(int scs,
int ssb_offset_point_a,
int ssb_sco,
frequency_range_t freq_range);
#endif
......@@ -481,3 +481,26 @@ void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, con
mult_complex_vectors(rxdata_in, rot, rxdata_out, size, 14);
#endif
}
/*!
* Setting the first subcarrier
* 3GPP TS 38.211 sections 7.4.3.1 and 4.4.4.2
* for FR1 offsetToPointA and k_SSB are expressed in terms of 15 kHz SCS
* for FR2 offsetToPointA is expressed in terms of 60 kHz SCS and k_SSB expressed in terms of the SCS provided
* by the higher-layer parameter subCarrierSpacingCommon
*/
int nr_get_ssb_start_sc(int scs, int ssb_offset_point_a, int ssb_sco, frequency_range_t freq_range)
{
const int prb_offset =
(freq_range == FR1) ? ssb_offset_point_a >> scs : ssb_offset_point_a >> (scs - 2);
const int sc_offset =
(freq_range == FR1) ? ssb_sco >> scs : ssb_sco;
int ssb_start_subcarrier = (12 * prb_offset + sc_offset);
LOG_D(NR_PHY, "prb_offset:%d, ssb_subcarrier_offset:%d,scs :%d, Fr:%d, ssb_start_subcarrier:%d\n",
prb_offset, ssb_sco, scs, freq_range, ssb_start_subcarrier);
return ssb_start_subcarrier;
}
......@@ -118,9 +118,10 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
// by the higher-layer parameter subCarrierSpacingCommon
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
const int scs = cfg->ssb_config.scs_common.value;
const int prb_offset = (fp->freq_range == FR1) ? pdu->ssbOffsetPointA >> scs : pdu->ssbOffsetPointA >> (scs - 2);
const int sc_offset = (fp->freq_range == FR1) ? pdu->SsbSubcarrierOffset >> scs : pdu->SsbSubcarrierOffset;
fp->ssb_start_subcarrier = (12 * prb_offset + sc_offset);
fp->ssb_start_subcarrier = nr_get_ssb_start_sc(scs,
pdu->ssbOffsetPointA,
pdu->SsbSubcarrierOffset,
fp->freq_range);
if (fp->print_ue_help_cmdline_log && IS_SA_MODE(get_softmodem_params())) {
fp->print_ue_help_cmdline_log = false;
......@@ -142,15 +143,6 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
fp->ssb_start_subcarrier,
fp->threequarter_fs ? "-E" : "");
}
LOG_D(PHY,
"ssbOffsetPointA %d SSB SsbSubcarrierOffset %d prb_offset %d sc_offset %d scs %d ssb_start_subcarrier %d\n",
pdu->ssbOffsetPointA,
pdu->SsbSubcarrierOffset,
prb_offset,
sc_offset,
scs,
fp->ssb_start_subcarrier);
LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n", frame, slot, ssb_start_symbol);
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming;
c16_t ***txdataF = gNB->common_vars.txdataF;
......
......@@ -537,16 +537,15 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
// SSB Table config
if (frequencyInfoDL && frequencyInfoDL->absoluteFrequencySSB) {
int scs_scaling = 1 << (cfg->ssb_config.scs_common);
if (frequencyInfoDL->absoluteFrequencyPointA < 600000)
scs_scaling = scs_scaling * 3;
if (frequencyInfoDL->absoluteFrequencyPointA > 2016666)
scs_scaling = scs_scaling >> 2;
uint32_t absolute_diff = (*frequencyInfoDL->absoluteFrequencySSB - frequencyInfoDL->absoluteFrequencyPointA);
cfg->ssb_table.ssb_offset_point_a = absolute_diff / (12 * scs_scaling) - 10;
cfg->ssb_table.ssb_offset_point_a = get_ssb_offset_to_pointA(*frequencyInfoDL->absoluteFrequencySSB,
frequencyInfoDL->absoluteFrequencyPointA,
cfg->ssb_config.scs_common,
mac->frequency_range);
cfg->ssb_table.ssb_period = *scc->ssb_periodicityServingCell;
// NSA -> take ssb offset from SCS
cfg->ssb_table.ssb_subcarrier_offset = absolute_diff % (12 * scs_scaling);
cfg->ssb_table.ssb_subcarrier_offset = get_ssb_subcarrier_offset(*frequencyInfoDL->absoluteFrequencySSB,
frequencyInfoDL->absoluteFrequencyPointA,
cfg->ssb_config.scs_common);
cfg->ssb_table.ssb_case = set_ssb_case(*scc->ssbSubcarrierSpacing, mac->nr_band);
}
......@@ -2107,18 +2106,24 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
configure_common_BWP_dl(mac, bwp_id, scc->downlinkConfigCommon->initialDownlinkBWP);
if (scc->uplinkConfigCommon)
configure_common_BWP_ul(mac, bwp_id, scc->uplinkConfigCommon->initialUplinkBWP);
// Update PDCCH config as MAC configuration has changed
if (IS_SA_MODE(get_softmodem_params()))
update_pdcch_config(mac);
}
mac->state = UE_NOT_SYNC_RECONF;
ra->ra_state = nrRA_UE_IDLE;
nr_ue_mac_default_configs(mac);
// PHY CONFIG request should be sent, ahead of SYNC request
// As SYNC request processes the new config
mac->if_module->phy_config_request(&mac->phy_config);
mac->phy_config.config_req.ntn_config.params_changed = false;
mac->synch_request.Mod_id = mac->ue_id;
mac->synch_request.CC_id = cc_idP;
mac->synch_request.synch_req.target_Nid_cell = mac->physCellId;
mac->if_module->synch_request(&mac->synch_request);
mac->if_module->phy_config_request(&mac->phy_config);
mac->phy_config.config_req.ntn_config.params_changed = false;
}
static void configure_physicalcellgroup(NR_UE_MAC_INST_t *mac,
......
......@@ -377,4 +377,5 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t
NR_SearchSpace_t *get_common_search_space(const NR_UE_MAC_INST_t *mac, const NR_SearchSpaceId_t ss_id);
ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config);
void update_pdcch_config(NR_UE_MAC_INST_t *mac);
#endif
......@@ -422,6 +422,38 @@ static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
return false;
}
void update_pdcch_config(NR_UE_MAC_INST_t *mac)
{
int scs = mac->current_DL_BWP ? mac->current_DL_BWP->scs : mac->numerology;
const int slots_per_frame = get_slots_per_frame_from_scs(scs);
int ssb_sc_offset_norm;
if (mac->ssb_subcarrier_offset < 24 && mac->frequency_range == FR1)
ssb_sc_offset_norm = mac->ssb_subcarrier_offset >> scs;
else
ssb_sc_offset_norm = mac->ssb_subcarrier_offset;
uint16_t ssb_offset_point_a = (mac->ssb_start_subcarrier - ssb_sc_offset_norm) / 12;
int ssb_start_symbol = get_ssb_start_symbol(mac->nr_band, scs, mac->mib_ssb);
get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config,
mac->mib_frame,
mac->mib,
slots_per_frame,
ssb_sc_offset_norm,
ssb_start_symbol,
scs,
mac->frequency_range,
mac->nr_band,
273, // at this point UE in principle doesn't know the grid size (we assume the largest)
mac->mib_ssb,
1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame
ssb_offset_point_a);
if (mac->search_space_zero == NULL)
mac->search_space_zero = calloc(1, sizeof(*mac->search_space_zero));
if (mac->coreset0 == NULL)
mac->coreset0 = calloc(1, sizeof(*mac->coreset0));
fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config);
fill_searchSpaceZero(mac->search_space_zero, slots_per_frame, &mac->type0_PDCCH_CSS_config);
}
void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot)
{
const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
......@@ -430,37 +462,14 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
int scs = current_DL_BWP ? current_DL_BWP->scs : mac->numerology;
const int slots_per_frame = get_slots_per_frame_from_scs(scs);
if (mac->get_sib1) {
int ssb_sc_offset_norm;
if (mac->ssb_subcarrier_offset < 24 && mac->frequency_range == FR1)
ssb_sc_offset_norm = mac->ssb_subcarrier_offset >> scs;
else
ssb_sc_offset_norm = mac->ssb_subcarrier_offset;
uint16_t ssb_offset_point_a = (mac->ssb_start_subcarrier - ssb_sc_offset_norm) / 12;
int ssb_start_symbol = get_ssb_start_symbol(mac->nr_band, scs, mac->mib_ssb);
get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config,
mac->mib_frame,
mac->mib,
slots_per_frame,
ssb_sc_offset_norm,
ssb_start_symbol,
scs,
mac->frequency_range,
mac->nr_band,
273, // at this point UE in principle doesn't know the grid size (we assume the largest)
mac->mib_ssb,
1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame
ssb_offset_point_a);
if (mac->search_space_zero == NULL)
mac->search_space_zero = calloc(1, sizeof(*mac->search_space_zero));
if (mac->coreset0 == NULL)
mac->coreset0 = calloc(1, sizeof(*mac->coreset0));
fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config);
fill_searchSpaceZero(mac->search_space_zero, slots_per_frame, &mac->type0_PDCCH_CSS_config);
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, mac->search_space_zero)) {
update_pdcch_config(mac);
bool is_occasion = is_ss_monitor_occasion(frame, slot, slots_per_frame, mac->search_space_zero);
if (is_occasion) {
LOG_D(NR_MAC_DCI, "Monitoring DCI for SIB1 in frame %d slot %d\n", frame, slot);
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, mac->search_space_zero);
}
}
for (int i = 0; i < MAX_SI_GROUPS; i++) {
if (!mac->get_otherSI[i])
continue;
......
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