From e151366beaa5d6a082c2624a455263ff8c7b28c2 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 27 Oct 2025 21:42:56 +0100 Subject: [PATCH] SSS detection used PSS phase, but when signal is noisy, use the PSS phase can make a SSS slightly rotated the code use a precomputed table of rotations: 16 steaps between -PI/3 and +PI/3 This commit replaces the precomputed table by in code computation. This version improves code understanding, while it won't make any significant difference --- openair1/PHY/NR_REFSIG/sss_nr.h | 26 ------------------- .../PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c | 8 +++--- openair1/PHY/NR_UE_TRANSPORT/sss_nr.c | 19 +++++++++----- 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/sss_nr.h b/openair1/PHY/NR_REFSIG/sss_nr.h index 7bd37a7dc0..ae99a8e3d4 100644 --- a/openair1/PHY/NR_REFSIG/sss_nr.h +++ b/openair1/PHY/NR_REFSIG/sss_nr.h @@ -61,32 +61,6 @@ #define SSS_METRIC_FLOOR_NR (30000) -/************** VARIABLES *****************************************/ - -#define PHASE_HYPOTHESIS_NUMBER (16) -#define INDEX_NO_PHASE_DIFFERENCE (3) /* this is for no phase shift case */ - -/************** FUNCTION ******************************************/ - -static const c16_t phase_nr[PHASE_HYPOTHESIS_NUMBER] = { - // {pi/3 ---- pi/3, -pi/3 ---- pi/3} - {16384, -28377}, - {20173, -25821}, - {23571, -22762}, - {26509, -19260}, - {28932, -15383}, - {30791, -11207}, - {32051, -6813}, - {32687, -2286}, - {32687, 2286}, - {32051, 6813}, - {30791, 11207}, - {28932, 15383}, - {26509, 19260}, - {23571, 22762}, - {20173, 25821}, - {16384, 28377}}; - void init_context_sss_nr(int amp); void free_context_sss_nr(void); 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 0636c9d7d9..00506ef419 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -161,7 +161,6 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *sl_fp = &ue->SL_UE_PHY_PARAMS.sl_frame_params; int16_t *d; uint16_t Nid1 = 0; - uint8_t phase; c16_t *rxF_ext; for (int aarx = 0; aarx < sl_fp->nb_antennas_rx; aarx++) { @@ -260,15 +259,16 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, c16_t *sss = &sss_ext[0][0][0]; for (uint16_t id1 = 0; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values - for (phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS + for (int phase = -15; phase < 16; phase += 2) { // phase offset between PSS and SSS int32_t metric = 0, metric_re = 0; - + const c64_t rot = (c64_t){round(cos(M_PI / 3 / 15 * (phase)) * 32767), round(sin(M_PI / 3 / 15 * (phase)) * 32767)}; d = (int16_t *)&ue->SL_UE_PHY_PARAMS.init_params.sl_sss_for_sync[Nid2 * SL_NR_NUM_IDs_IN_SSS + id1]; // This is the inner product using one particular value of each unknown parameter for (int i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH; i++) { - metric_re += d[i] * (((int64_t)phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i) >> 15); + // metric is only real part because sss is a pure real signal (imaginary is 0) + metric_re += d[i] * ((rot.r * sss[i].r - rot.i * sss[i].i) >> 15); } metric = metric_re; diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 8e9c3ad510..d400369bb1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -251,20 +251,23 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, Nid1_end = Nid1_start + 1; } - for (int n1 = Nid1_start; n1 < Nid1_end; n1++) { // all possible Nid1 values - for (int phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS + const int phase_to_try[] = {0, 2, -2, 4, -4, 6, -6, 8, -8, 10, -10, 12, -12, 14, -14}; + for (int idx = 0; idx < sizeofArray(phase_to_try); idx++) { // phase offset between PSS and SSS + const c64_t rot = + (c64_t){round(cos(M_PI / 3 / 15 * (phase_to_try[idx])) * 32767), round(sin(M_PI / 3 / 15 * (phase_to_try[idx])) * 32767)}; + for (int n1 = Nid1_start; n1 < Nid1_end; n1++) { // all possible Nid1 values int64_t metric = 0; int16_t *d = d_sss[Nid2][n1]; - // This is the inner product using one particular value of each unknown parameter for (int i = 0; i < LENGTH_SSS_NR; i++) { - metric += d[i] * (phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i); + // metric is only real part because sss is a pure real signal (imaginary is 0) + metric += d[i] * (rot.r * sss[i].r - rot.i * sss[i].i); } metric >>= SCALING_METRIC_SSS_NR; // if the current metric is better than the last save it if (metric > *tot_metric) { *tot_metric = metric; *Nid_cell = Nid2 + (3 * n1); - *phase_max = phase; + *phase_max = idx; #ifdef DEBUG_SSS_NR LOG_D(PHY, @@ -277,9 +280,13 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, #endif } } + // we try progressively rotation between pss and sss + // but pss and sss are in phase at emission + // rotation means doppler variation, or very noisy pss detection + if (*tot_metric >= SSS_METRIC_FLOOR_NR) + break; } -#define SSS_METRIC_FLOOR_NR (30000) if (*tot_metric < SSS_METRIC_FLOOR_NR) { LOG_D(PHY, "Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n",