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
This commit is contained in:
Laurent THOMAS
2026-03-16 09:49:32 +01:00
parent 70711633bc
commit e151366bea
3 changed files with 17 additions and 36 deletions
-26
View File
@@ -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);
@@ -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;
+13 -6
View File
@@ -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",