code cleaning pss and sss detection, no functional change

This commit is contained in:
Laurent THOMAS
2026-03-16 09:49:30 +01:00
parent fdb6b44b05
commit 70711633bc
7 changed files with 113 additions and 434 deletions
-3
View File
@@ -90,9 +90,6 @@ static const c16_t phase_nr[PHASE_HYPOTHESIS_NUMBER] = {
void init_context_sss_nr(int amp);
void free_context_sss_nr(void);
void insert_sss_nr(int16_t *sss_time,
NR_DL_FRAME_PARMS *frame_parms);
bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
int nid2,
int target_Nid_cell,
+3 -10
View File
@@ -23,11 +23,7 @@
//#define NR_SSS_DEBUG
int nr_generate_sss( c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t* config,
NR_DL_FRAME_PARMS *frame_parms)
int nr_generate_sss(c16_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, int Nid, NR_DL_FRAME_PARMS *frame_parms)
{
int16_t x0[NR_SSS_LENGTH];
int16_t x1[NR_SSS_LENGTH];
@@ -35,7 +31,6 @@ int nr_generate_sss( c16_t *txdataF,
const int x1_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
/// Sequence generation
int Nid = config->cell_config.phy_cell_id.value;
int Nid2 = Nid % 3;
int Nid1 = (Nid - Nid2)/3;
@@ -59,13 +54,11 @@ int nr_generate_sss( c16_t *txdataF,
/// Resource mapping
// SSS occupies a predefined position (subcarriers 56-182, symbol 2) within the SSB block starting from
int k = frame_parms->ssb_start_subcarrier + 56;
int l = ssb_start_symbol + 2;
c16_t *tx = txdataF + (ssb_start_symbol + 2) * frame_parms->ofdm_symbol_size + frame_parms->ssb_start_subcarrier + 56;
for (int i = 0; i < NR_SSS_LENGTH; i++) {
int16_t d_sss = (1 - 2*x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2*x1[(i + m1) % NR_SSS_LENGTH] ) * 23170;
((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_sss) >> 15;
k++;
*tx++ = (c16_t){.r = (amp * d_sss) >> 15};
}
#ifdef NR_SSS_DEBUG
// write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
@@ -60,11 +60,7 @@ int nr_generate_pss(c16_t *txdataF,
@param
@returns 0 on success
*/
int nr_generate_sss(c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
int nr_generate_sss(c16_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, int nid, NR_DL_FRAME_PARMS *frame_parms);
/*!
\fn void nr_generate_pbch_dmrs
@@ -260,7 +260,7 @@ 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 < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
for (phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS
int32_t metric = 0, metric_re = 0;
+46 -142
View File
@@ -49,24 +49,12 @@
//#define DBG_PSS_NR
static time_stats_t generic_time[TIME_LAST];
int pss_search_time_nr(const c16_t **rxdata,
const NR_DL_FRAME_PARMS *frame_parms,
const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size],
bool fo_flag,
int is,
int target_Nid_cell,
int *nid2,
int *f_off,
int *pssPeak,
int *pssAvg,
int search_start,
int search_length);
static int16_t primary_synchro_nr2[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0};
static int16_t d_pss[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0};
static c16_t primary_synchro[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0};
int16_t *get_primary_synchro_nr2(const int nid2)
{
return primary_synchro_nr2[nid2];
return d_pss[nid2];
}
/*******************************************************************
@@ -86,12 +74,9 @@ int16_t *get_primary_synchro_nr2(const int nid2)
void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
{
AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size);
AssertFatal(N_ID_2>=0 && N_ID_2 <=2,"Illegal N_ID_2 %d\n",N_ID_2);
int16_t d_pss[LENGTH_PSS_NR];
AssertFatal(N_ID_2 >= 0 && N_ID_2 <= 2, "Illegal N_ID_2 %d\n", N_ID_2);
int16_t x[LENGTH_PSS_NR];
int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */
#define INITIAL_PSS_NR (7)
const int16_t x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1};
assert(N_ID_2 < NUMBER_PSS_SEQUENCE);
@@ -99,16 +84,15 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++)
x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2);
int16_t *pss = d_pss[N_ID_2];
for (int n=0; n < LENGTH_PSS_NR; n++) {
const int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR);
d_pss[n] = 1 - 2*x[m];
pss[n] = 1 - 2 * x[m];
}
/* PSS is directly mapped to subcarrier without modulation 38.211 */
for (int i=0; i < LENGTH_PSS_NR; i++) {
primary_synchro[N_ID_2][i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
primary_synchro2[i] = d_pss[i];
primary_synchro[N_ID_2][i].r = (pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
}
#ifdef DBG_PSS_NR
@@ -150,12 +134,13 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssbFirstSCS, c16_t pssTime[fp->ofdm_symbol_size])
{
unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL;
unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start;
if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size;
c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32)));
memset(synchroF_tmp, 0, sizeof(synchroF_tmp));
unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start;
for (int i=0; i < LENGTH_PSS_NR; i++) {
synchroF_tmp[k % fp->ofdm_symbol_size] = primary_synchro[N_ID_2][i];
if (k >= fp->ofdm_symbol_size)
k -= fp->ofdm_symbol_size;
synchroF_tmp[k] = primary_synchro[N_ID_2][i];
k++;
}
@@ -182,54 +167,6 @@ void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssb
}
#endif
#if 0
/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */
if ((N_ID_2 == 0) && (length == 256)) {
LOG_M("pss_f00.m","pss_f00",synchro_tmp,length,1,1);
bzero(synchroF_tmp, size);
/* get pss in the time domain by applying an inverse FFT */
dft((int16_t)get_dft(length),
synchro_tmp, /* complex input */
synchroF_tmp, /* complex output */
1); /* scaling factor */
if ((N_ID_2 == 0) && (length == 256)) {
LOG_M("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1);
}
/* check Pss */
k = length - (LENGTH_PSS_NR/2);
#define LIMIT_ERROR_FFT (10)
for (int i=0; i < LENGTH_PSS_NR; i++) {
if (abs(synchroF_tmp[2*k] - primary_synchro[i].r) > LIMIT_ERROR_FFT) {
printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[i].r);
}
if (abs(synchroF_tmp[2*k+1] - primary_synchro[i].i) > LIMIT_ERROR_FFT) {
printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[i].i);
}
k++;
if (k >= length) {
k-=length;
}
}
}
#endif
}
/*******************************************************************
@@ -391,50 +328,32 @@ int pss_synchro_nr(const c16_t **rxdata,
int *pssAvg)
{
#ifdef DBG_PSS_NR
LOG_M("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1);
#endif
#ifdef DBG_PSS_NR
LOG_M("rxdata0_des.m","rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame,1,1);
LOG_M("rxdata0_rand.m", "rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1);
LOG_M("rxdata0_des.m", "rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame, 1, 1);
#endif
start_meas(&generic_time[TIME_PSS]);
int synchro_position =
pss_search_time_nr(rxdata, frame_parms, pssTime, fo_flag, is, target_Nid_cell, nid2, f_off, pssPeak, pssAvg, -1, -1);
stop_meas(&generic_time[TIME_PSS]);
#if TEST_SYNCHRO_TIMING_PSS
stop_meas(&generic_time[TIME_PSS]);
int duration_ms = generic_time[TIME_PSS].p_time/(cpuf*1000.0);
#ifndef NR_UNIT_TEST
LOG_D(PHY,"PSS execution duration %4d microseconds \n", duration_ms);
#endif
int duration_ms = generic_time[TIME_PSS].p_time / (cpuf * 1000.0);
#ifndef NR_UNIT_TEST
LOG_D(PHY, "PSS execution duration %4d microseconds \n", duration_ms);
#endif
#endif
#ifdef SYNCHRO_DECIMAT
if (rate_change != 1) {
if (rxdata[0] != NULL) {
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
free(rxdata[aa]);
}
free(rxdata);
}
restore_frame_context_pss_nr(frame_parms, rate_change);
restore_frame_context_pss_nr(frame_parms, rate_change);
}
#endif
@@ -504,11 +423,6 @@ int pss_search_time_nr(const c16_t **rxdata,
int search_start,
int search_length)
{
unsigned int n, ar, peak_position, pss_source;
int64_t peak_value;
int64_t avg[NUMBER_PSS_SEQUENCE] = {0};
double ffo_est = 0;
// Determine search window
unsigned int start, length;
if (search_start >= 0 && search_length > 0) {
@@ -524,11 +438,7 @@ int pss_search_time_nr(const c16_t **rxdata,
length = frame_parms->samples_per_frame;
}
AssertFatal(length>0,"illegal length %d\n",length);
peak_value = 0;
peak_position = 0;
pss_source = 0;
AssertFatal(length > 0, "illegal length %d\n", length);
int maxval=0;
int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
for (int j = 0; j < max_size; j++)
@@ -542,53 +452,55 @@ int pss_search_time_nr(const c16_t **rxdata,
/* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */
/* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
uint16_t pss_index_start = 0;
uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
int pss_index_start;
int pss_index_end;
if (target_Nid_cell != -1) {
pss_index_start = GET_NID2(target_Nid_cell);
pss_index_end = pss_index_start + 1;
} else {
pss_index_start = 0;
pss_index_end = max_size;
}
int64_t avg[NUMBER_PSS_SEQUENCE] = {0};
int64_t peak_value = 0;
unsigned int peak_position = 0;
unsigned int pss_source = 0;
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) {
for (n = start; n < start + length; n += 4) { //
int64_t pss_corr_ue=0;
for (int n = start; n < start + length; n += 4) { //
int64_t pss_corr_ue = 0;
/* calculate dot product of primary_synchro_time_nr and rxdata[ar][n]
* (ar=0..nb_ant_rx) and store the sum in temp[n]; */
for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
for (int ar = 0; ar < frame_parms->nb_antennas_rx; ar++) {
/* perform correlation of rx data and pss sequence ie it is a dot product */
const c32_t result = dot_product(pssTime[pss_index],
&(rxdata[ar][n + is * frame_parms->samples_per_frame]),
&rxdata[ar][n + is * frame_parms->samples_per_frame],
frame_parms->ofdm_symbol_size,
shift);
const c64_t r64 = {.r = result.r, .i = result.i};
pss_corr_ue += squaredMod(r64);
//((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */
//((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
//((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */
//((short*)&synchro_out)[1] += ((int*) &result)[1]; /* imaginary part */
}
/* calculate the absolute value of sync_corr[n] */
avg[pss_index]+=pss_corr_ue;
avg[pss_index] += pss_corr_ue;
if (pss_corr_ue > peak_value) {
peak_value = pss_corr_ue;
peak_position = n;
pss_source = pss_index;
#ifdef DEBUG_PSS_NR
printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[n]);
#endif
}
}
avg[pss_index] /= (length / 4);
}
if (fo_flag){
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS
// Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012.
double ffo_est = 0;
if (fo_flag) {
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS
// Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th
// International Conference on Communications and Networking in China, 2012.
// Computing cross-correlation at peak on half the symbol size for first half of data
c32_t r1 = dot_product(pssTime[pss_source],
@@ -606,15 +518,11 @@ int pss_search_time_nr(const c16_t **rxdata,
ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI;
#ifdef DBG_PSS_NR
printf("ffo %lf\n",ffo_est);
printf("ffo %lf\n", ffo_est);
#endif
}
// computing absolute value of frequency offset
*f_off = ffo_est*frame_parms->subcarrier_spacing;
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++)
avg[pss_index] /= (length / 4);
*f_off = ffo_est * frame_parms->subcarrier_spacing;
*nid2 = pss_source;
*pssPeak = dB_fixed64(peak_value);
@@ -631,22 +539,18 @@ int pss_search_time_nr(const c16_t **rxdata,
ffo_est);
if ((search_start < 0 || search_length == 0) && peak_value < 5 * avg[pss_source])
return(-1);
return (-1);
#ifdef DBG_PSS_NR
static int debug_cnt = 0;
if (debug_cnt == 0) {
if (is)
LOG_M("rxdata1.m","rxd0",rxdata[frame_parms->samples_per_frame],length,1,1);
LOG_M("rxdata1.m", "rxd0", rxdata[frame_parms->samples_per_frame], length, 1, 1);
else
LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1);
LOG_M("rxdata0.m", "rxd0", rxdata[0], length, 1, 1);
} else {
debug_cnt++;
}
#endif
return peak_position;
+61 -272
View File
@@ -109,71 +109,8 @@ void init_context_sss_nr(int amp)
#endif
}
/*******************************************************************
*
* NAME : insert_sss_nr
*
* PARAMETERS : pointer to input buffer for which sss in inserted
* amp amplitude applied to input
* frame parameters for cell identity
*
* RETURN : none
*
* DESCRIPTION : Allow to generate a reference sss sequence according to cell identity
*
*********************************************************************/
//#define DEBUG_SSS_NR
//#define DEBUG_PLOT_SSS
void insert_sss_nr(int16_t *sss_time,
NR_DL_FRAME_PARMS *frame_parms)
{
const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
int Nid2 = GET_NID2(frame_parms->Nid_cell);
int Nid1 = GET_NID1(frame_parms->Nid_cell);
/* call of IDFT should be done with ordered input as below
*
* n input samples
* <------------------------------------------------>
* 0 n
* are written into input buffer for IFFT in this order
* -------------------------------------------------
* |xxxxxxx N/2 xxxxxxxx|
* --------------------------------------------------
* ^ ^ ^ ^ ^
* | | | | |
* n/2 end of n=0 start of n/2-1
* sss sss
*
* Frequencies
* positives negatives
* 0 (+N/2)(-N/2)
* |-----------------------><-------------------------|
*
* sample 0 is for continuous frequency which is not used here
*/
unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1);
c16_t synchroF_tmp[2048] __attribute__((aligned(32)));
c16_t synchro_tmp[2048] __attribute__((aligned(32)));
bzero(synchroF_tmp, sizeof(synchroF_tmp));
/* SSS is directly mapped to subcarrier */
for (int i=0; i<LENGTH_SSS_NR; i++) {
synchroF_tmp[k % ofdm_symbol_size].r = d_sss[Nid2][Nid1][i];
k++;
}
/* get sss in the frequency domain by applying an inverse FFT */
idft(IDFT_2048,
(int16_t *)synchroF_tmp, /* complex input */
(int16_t *)synchro_tmp, /* complex output */
1); /* scaling factor */
/* then get final sss in time */
memcpy(sss_time, synchro_tmp, ofdm_symbol_size * sizeof(c16_t));
}
// #define DEBUG_SSS_NR
// #define DEBUG_PLOT_SSS
/*******************************************************************
*
@@ -187,7 +124,7 @@ void insert_sss_nr(int16_t *sss_time,
*
*********************************************************************/
static int pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms,
static void pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms,
int nid2,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR])
@@ -199,148 +136,60 @@ static int pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t *pss_ext2 = pss_ext[aarx];
for (int i = 0; i < LENGTH_PSS_NR; i++) {
// This is H*(PSS) = R* \cdot PSS
const int tmp_re = pss_ext2[i].r * pss[i];
const int tmp_im = -pss_ext2[i].i * pss[i];
const int32_t amp = tmp_re * tmp_re + tmp_im * tmp_im;
const c16_t tmp = (c16_t){pss_ext2[i].r * pss[i], -pss_ext2[i].i * pss[i]};
const int32_t amp = squaredMod(tmp);
const int shift = log2_approx(amp) / 2;
// This is R(SSS) \cdot H*(PSS)
const c16_t tmp = {(tmp_re * sss_ext2[i].r - tmp_im * sss_ext2[i].i) >> shift,
(tmp_re * sss_ext2[i].i + tmp_im * sss_ext2[i].r) >> shift};
// printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]);
// printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2);
// MRC on RX antennas
if (aarx == 0) {
sss_ext2[i].r = tmp.r;
sss_ext2[i].i = tmp.i;
} else {
sss_ext2[i].r += tmp.r;
sss_ext2[i].i += tmp.i;
}
const c16_t new_sss = c16mulShift(tmp, sss_ext2[i], shift);
if (aarx == 0)
sss_ext2[i] = new_sss;
else
sss_ext2[i] = c16add(sss_ext2[i], new_sss);
}
}
#if 0
LOG_M("pssrx.m","pssrx",pss,LENGTH_PSS_NR,1,1);
LOG_M("pss_ext.m","pssext",pss_ext2,LENGTH_PSS_NR,1,1);
LOG_M("psschest.m","pssch",chest,LENGTH_PSS_NR,1,1);
#endif
#if 0
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
}
#endif
// sss_ext now contains the compensated SSS
return(0);
// sss_ext[0] now contains the compensated SSS
}
/*******************************************************************
*
* NAME : do_pss_sss_extract
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION : it allows extracting sss from samples buffer
*
*********************************************************************/
*
* NAME : pss_sss_extract_nr
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION : it allows extracting sss from samples buffer
*
*********************************************************************/
static int do_pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms,
static void pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR],
uint8_t doPss,
uint8_t doSss,
int ssb_start_subcarrier,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both
{
AssertFatal(frame_parms->nb_antennas_rx > 0, "UB as sss_ext is not set to any value\n");
AssertFatal(frame_parms->nb_antennas_rx > 0, "nb antennas as sss_ext is not set to any value\n");
const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
const int pss_symbol = 0;
const int sss_symbol =
get_softmodem_params()->sl_mode == 0 ? (SSS_SYMBOL_NB - PSS_SYMBOL_NB) : (SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB);
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
int pss_symbol = 0;
int sss_symbol = get_softmodem_params()->sl_mode == 0 ?
(SSS_SYMBOL_NB - PSS_SYMBOL_NB) :
(SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ;
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size;
c16_t *sss_rxF = rxdataF[aarx] + sss_symbol * ofdm_symbol_size;
c16_t *pss_rxF_ext = pss_ext[aarx];
c16_t *sss_rxF_ext = sss_ext[aarx];
unsigned int k = frame_parms->first_carrier_offset + ssb_start_subcarrier
+ ((get_softmodem_params()->sl_mode == 0) ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL);
if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
for (int i=0; i < LENGTH_PSS_NR; i++) {
if (doPss) {
pss_rxF_ext[i] = pss_rxF[k];
}
if (doSss) {
sss_rxF_ext[i] = sss_rxF[k];
}
if (k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
pss_rxF_ext[i] = pss_rxF[k];
sss_rxF_ext[i] = sss_rxF[k];
k++;
if (k == frame_parms->ofdm_symbol_size) k = 0;
}
}
#if 0
int16_t *p = (int16_t *)sss_rxF_ext;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
}
#endif
#if 0
int16_t *p2 = (int16_t *)pss_rxF_ext;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" pss_rxF_ext [%d] %d %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]);
}
#endif
return(0);
}
/*******************************************************************
*
* NAME : pss_sss_extract_nr
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION :
*
*********************************************************************/
static int pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR],
int ssb_start_subcarrier,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP])
{
return do_pss_sss_extract_nr(frame_parms,
pss_ext,
sss_ext,
1 /* doPss */,
1 /* doSss */,
ssb_start_subcarrier,
rxdataF);
}
/*******************************************************************
@@ -366,44 +215,22 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
int *freq_offset_sss,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP])
{
uint8_t i;
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR];
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR];
uint8_t Nid2 = GET_NID2(nid2);
uint16_t Nid1;
uint8_t phase;
int32_t metric, metric_re;
int16_t *d;
const int Nid2 = GET_NID2(nid2);
// pss sss extraction
pss_sss_extract_nr(frame_parms, pss_ext, sss_ext, ssb_start_subcarrier, rxdataF); /* subframe */
#ifdef DEBUG_PLOT_SSS
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1);
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
#endif
#if 0
int16_t *p = (int16_t *)sss_ext[0];
int16_t *p2 = (int16_t *)pss_ext[0];
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, p[2*i], p[2*i+1]);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, p2[2*i], p2[2*i+1]);
}
write_output("pss_ext.m", "pss_ext", pss_ext, LENGTH_PSS_NR, 1, 1);
#endif
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
// and do channel estimation and compensation based on PSS
pss_ch_est_nr(frame_parms, nid2, pss_ext, sss_ext);
// now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h
@@ -411,91 +238,49 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t *sss = sss_ext[0];
#ifdef DEBUG_PLOT_SSS
write_output("sss_ext.m","sss_ext",sss_ext[0],LENGTH_SSS_NR,1,1);
write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,1);
#endif
#if 0
/* simulate of a phase shift on the signal */
int phase_shift_index = 0;
phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
#endif
#if 0
int16_t *ps = (int16_t *)pss_ext;
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d \n", i, d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, sss[i].r, sss[i].i);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
}
#endif
/* for phase evaluation, one uses an array of possible phase shifts */
/* then a correlation is done between received signal with a shift pĥase and the reference signal */
/* Computation of signal with shift phase is based on below formula */
/* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
/* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
uint16_t Nid1_start = 0;
uint16_t Nid1_end = N_ID_1_NUMBER;
int Nid1_start = 0;
int Nid1_end = N_ID_1_NUMBER;
if (target_Nid_cell != -1) {
Nid1_start = GET_NID1(target_Nid_cell);
Nid1_end = Nid1_start + 1;
}
for (Nid1 = Nid1_start; Nid1 < Nid1_end; Nid1++) { // all possible Nid1 values
for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
metric = 0;
metric_re = 0;
d = (int16_t *)&d_sss[Nid2][Nid1];
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
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 (i=0; i < LENGTH_SSS_NR; i++) {
metric_re += d[i] * ((phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i) >> SCALING_METRIC_SSS_NR);
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 = metric_re;
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 * Nid1);
*Nid_cell = Nid2 + (3 * n1);
*phase_max = phase;
#ifdef DEBUG_SSS_NR
LOG_D(PHY,"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
LOG_D(PHY,
"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",
phase,
n1,
metric,
*tot_metric,
*phase_max);
#endif
}
}
}
//#ifdef DEBUG_SSS_NR
#define SSS_METRIC_FLOOR_NR (30000)
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
Nid2 = GET_NID2(*Nid_cell);
Nid1 = GET_NID1(*Nid_cell);
LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
}
// #endif
int re = 0;
int im = 0;
if (Nid1 == Nid1_end) {
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",
*tot_metric,
@@ -503,15 +288,19 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
*Nid_cell);
return false;
}
d = (int16_t *)&d_sss[Nid2][Nid1];
for(i = 0; i<LENGTH_SSS_NR; i++) {
re += d[i] * sss[i].r;
im += d[i] * sss[i].i;
int Nid1 = GET_NID1(*Nid_cell);
LOG_D(PHY, "Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
int16_t *d = d_sss[Nid2][Nid1];
c32_t sig_sum = {};
for (int i = 0; i < LENGTH_SSS_NR; i++) {
sig_sum.r += d[i] * sss[i].r;
sig_sum.i += d[i] * sss[i].i;
}
double ffo_sss = atan2(im,re)/M_PI/4.3;
double ffo_sss = atan2(sig_sum.i, sig_sum.r) / M_PI / 4.3;
*freq_offset_sss = (int)(ffo_sss*frame_parms->subcarrier_spacing);
double ffo_pss = ((double)freq_offset_pss) / frame_parms->subcarrier_spacing;
double ffo_pss = (double)freq_offset_pss / frame_parms->subcarrier_spacing;
LOG_D(NR_PHY,
"SSS detected, PCI: %d, ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz), nid1: %d, nid2: %d\n",
*Nid_cell,
+1 -1
View File
@@ -156,7 +156,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
bitmap);
nr_generate_pss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg->cell_config.phy_cell_id.value, fp);
uint16_t slots_per_hf = (fp->slots_per_frame) >> 1;
int n_hf = slot < slots_per_hf ? 0 : 1;