mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
make all functions for pss detection independant of global context such as frame_parms
Signed-off-by: Laurent THOMAS <laurent.thomas@open-cells.com>
This commit is contained in:
committed by
Robert Schmidt
parent
ad44ee75f6
commit
8eeb1b125f
@@ -54,20 +54,24 @@
|
||||
#endif
|
||||
|
||||
int pss_synchro_nr(const c16_t **rxdata,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size],
|
||||
int is,
|
||||
int nb_ant,
|
||||
int ofdm_symbol_size,
|
||||
int rxdata_size,
|
||||
int subcarrier_spacing,
|
||||
const c16_t pssTime[NUMBER_PSS_SEQUENCE][ofdm_symbol_size],
|
||||
bool fo_flag,
|
||||
int target_Nid_cell,
|
||||
int *nid2,
|
||||
int *f_off,
|
||||
int *pssPeak,
|
||||
int *pssAvg);
|
||||
|
||||
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],
|
||||
int ofdm_symbol_size,
|
||||
int nb_antennas_rx,
|
||||
int subcarrier_spacing,
|
||||
const c16_t pssTime[NUMBER_PSS_SEQUENCE][ofdm_symbol_size],
|
||||
bool fo_flag,
|
||||
int is,
|
||||
int target_Nid_cell,
|
||||
int *nid2,
|
||||
int *f_off,
|
||||
@@ -75,7 +79,11 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
int *pssAvg,
|
||||
int search_start,
|
||||
int search_length);
|
||||
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]);
|
||||
void generate_pss_nr_time(int ofdm_symbol_size,
|
||||
int first_carrier_offset,
|
||||
const int N_ID_2,
|
||||
int ssbFirstSCS,
|
||||
c16_t pssTime[ofdm_symbol_size]);
|
||||
void generate_pss_nr(const int N_ID_2, int16_t *pss);
|
||||
#endif /* PSS_NR_H */
|
||||
|
||||
|
||||
@@ -237,14 +237,27 @@ static bool search_neighboring_cell(NR_DL_FRAME_PARMS *frame_parms,
|
||||
int freq_offset_sss = 0;
|
||||
|
||||
nr_ssb_search_params_t search_params = {
|
||||
.frame_parms = frame_parms,
|
||||
.rxdata = rxdata,
|
||||
.dl_CarrierFreq = frame_parms->dl_CarrierFreq,
|
||||
.sampling_rate = frame_parms->samples_per_subframe * 1000,
|
||||
.slots_per_frame = frame_parms->slots_per_frame,
|
||||
.slots_per_subframe = frame_parms->slots_per_subframe,
|
||||
.numerology_index = frame_parms->numerology_index,
|
||||
.ofdm_symbol_size = frame_parms->ofdm_symbol_size,
|
||||
.ofdm_offset_divisor = frame_parms->ofdm_offset_divisor,
|
||||
.nb_antennas_rx = frame_parms->nb_antennas_rx,
|
||||
.symbols_per_slot = frame_parms->symbols_per_slot,
|
||||
.first_carrier_offset = frame_parms->first_carrier_offset,
|
||||
.N_RB_DL = frame_parms->N_RB_DL,
|
||||
.rxdata_size = rxdata_size,
|
||||
.rxdata = rxdata,
|
||||
.nb_prefix_samples = frame_parms->nb_prefix_samples,
|
||||
.nb_prefix_samples0 = frame_parms->nb_prefix_samples0,
|
||||
.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier,
|
||||
.subcarrier_spacing = frame_parms->subcarrier_spacing,
|
||||
.samples_per_slot_wCP = frame_parms->samples_per_slot_wCP,
|
||||
.target_nid_cell = -1, // Blind search
|
||||
.exclude_nid_cell = frame_parms->Nid_cell, // Exclude serving cell
|
||||
.apply_freq_offset = false,
|
||||
.search_frame_id = 0, // Search in first frame of buffer
|
||||
.fo_flag = false,
|
||||
.rxdataF = rxdataF,
|
||||
.pssTime = pssTime,
|
||||
@@ -295,10 +308,11 @@ static bool validate_known_pci(NR_DL_FRAME_PARMS *frame_parms,
|
||||
int length = neighboring_cell_info->pss_search_length;
|
||||
|
||||
int peak_position = pss_search_time_nr((const c16_t **)rxdata,
|
||||
frame_parms,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
frame_parms->nb_antennas_rx,
|
||||
frame_parms->subcarrier_spacing,
|
||||
pssTime,
|
||||
false, // no frequency offset estimation for tracking
|
||||
0, // first frame
|
||||
known_pci,
|
||||
&pss_index,
|
||||
&f_off,
|
||||
@@ -378,7 +392,11 @@ void do_neighboring_cell_measurements(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *u
|
||||
// Generate PSS time-domain sequences once for all neighbor cells
|
||||
__attribute__((aligned(32))) c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size];
|
||||
for (int nid2_idx = 0; nid2_idx < NUMBER_PSS_SEQUENCE; nid2_idx++) {
|
||||
generate_pss_nr_time(frame_parms, nid2_idx, frame_parms->ssb_start_subcarrier, pssTime[nid2_idx]);
|
||||
generate_pss_nr_time(frame_parms->ofdm_symbol_size,
|
||||
frame_parms->first_carrier_offset,
|
||||
nid2_idx,
|
||||
frame_parms->ssb_start_subcarrier,
|
||||
pssTime[nid2_idx]);
|
||||
}
|
||||
|
||||
__attribute__((aligned(32))) c16_t rxdataF[NR_N_SYMBOLS_SSB][frame_parms->nb_antennas_rx][rxdataF_sz];
|
||||
|
||||
@@ -130,13 +130,13 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void compensate_freq_offset(c16_t **x, const NR_DL_FRAME_PARMS *fp, const int offset, const int sn)
|
||||
static void compensate_freq_offset(c16_t **x, const int nb_antennas_rx, const int x_len, const int offset, const int sampling_rate)
|
||||
{
|
||||
double s_time = 1 / (1.0e3 * fp->samples_per_subframe); // sampling time
|
||||
double s_time = 1.0 / sampling_rate; // sampling time
|
||||
double off_angle = -2 * M_PI * s_time * (offset); // offset rotation angle compensation per sample
|
||||
|
||||
for (int n = sn * fp->samples_per_frame; n < (sn + 1) * fp->samples_per_frame; n++) {
|
||||
for (int ar = 0; ar < fp->nb_antennas_rx; ar++) {
|
||||
for (int n = 0; n < x_len; n++) {
|
||||
for (int ar = 0; ar < nb_antennas_rx; ar++) {
|
||||
const double re = x[ar][n].r;
|
||||
const double im = x[ar][n].i;
|
||||
x[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle)));
|
||||
@@ -145,14 +145,59 @@ static void compensate_freq_offset(c16_t **x, const NR_DL_FRAME_PARMS *fp, const
|
||||
}
|
||||
}
|
||||
|
||||
/* rxdataF should be 16 bytes aligned */
|
||||
static void generate_table(nr_ssb_search_params_t *params,
|
||||
c16_t timeshift_symbol_rotation[params->ofdm_symbol_size],
|
||||
c16_t symbol_rotation[224])
|
||||
{
|
||||
init_timeshift_rotation(params->ofdm_symbol_size,
|
||||
params->nb_prefix_samples,
|
||||
params->ofdm_offset_divisor,
|
||||
timeshift_symbol_rotation);
|
||||
perform_symbol_rotation(params->symbols_per_slot * params->slots_per_frame / 10,
|
||||
params->numerology_index,
|
||||
params->dl_CarrierFreq,
|
||||
symbol_rotation);
|
||||
}
|
||||
|
||||
static void do_time_to_freq(nr_ssb_search_params_t *params, uint32_t sample_offset)
|
||||
{
|
||||
c16_t timeshift_symbol_rotation[params->ofdm_symbol_size];
|
||||
c16_t symbol_rotation[224];
|
||||
generate_table(params, timeshift_symbol_rotation, symbol_rotation);
|
||||
|
||||
c16_t(*rxdataF)[params->nb_antennas_rx][params->ofdm_symbol_size] =
|
||||
(c16_t(*)[params->nb_antennas_rx][params->ofdm_symbol_size])params->rxdataF;
|
||||
dft_size_idx_t dftsize = get_dft(params->ofdm_symbol_size);
|
||||
|
||||
for (int symb = 0; symb < NR_N_SYMBOLS_SSB; symb++) {
|
||||
// For Sidelink 16 frames worth of samples is processed to find SSB, for 5G-NR 2.
|
||||
unsigned int rx_offset = sample_offset + params->nb_prefix_samples;
|
||||
rx_offset += symb * (params->nb_prefix_samples + params->ofdm_symbol_size);
|
||||
// use OFDM symbol from within 1/8th of the CP to avoid ISI
|
||||
rx_offset -= params->nb_prefix_samples / params->ofdm_offset_divisor;
|
||||
for (unsigned char aa = 0; aa < params->nb_antennas_rx; aa++) {
|
||||
c16_t *rxF = rxdataF[symb][aa];
|
||||
dft(dftsize, (int16_t *)¶ms->rxdata[aa][rx_offset], (int16_t *)rxF, 1);
|
||||
apply_nr_rotation_symbol_RX(params->symbols_per_slot,
|
||||
params->slots_per_subframe,
|
||||
timeshift_symbol_rotation,
|
||||
params->first_carrier_offset,
|
||||
rxF,
|
||||
symbol_rotation,
|
||||
params->N_RB_DL,
|
||||
0,
|
||||
symb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Common SSB search function used by both initial sync and neighbor cell search
|
||||
*/
|
||||
bool nr_search_ssb_common(nr_ssb_search_params_t *params)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = params->frame_parms;
|
||||
|
||||
const uint32_t pssTime_sz = fp->ofdm_symbol_size;
|
||||
const uint32_t pssTime_sz = params->ofdm_symbol_size;
|
||||
c16_t(*pssTime)[pssTime_sz] = (c16_t(*)[pssTime_sz])params->pssTime;
|
||||
|
||||
// Perform PSS search
|
||||
@@ -161,9 +206,11 @@ bool nr_search_ssb_common(nr_ssb_search_params_t *params)
|
||||
int pss_peak = 0;
|
||||
int pss_avg = 0;
|
||||
const int sync_pos = pss_synchro_nr((const c16_t **)params->rxdata,
|
||||
fp,
|
||||
params->nb_antennas_rx,
|
||||
params->ofdm_symbol_size,
|
||||
params->rxdata_size,
|
||||
params->subcarrier_spacing,
|
||||
pssTime,
|
||||
params->search_frame_id,
|
||||
params->fo_flag,
|
||||
params->target_nid_cell,
|
||||
&nid2,
|
||||
@@ -178,11 +225,11 @@ bool nr_search_ssb_common(nr_ssb_search_params_t *params)
|
||||
if (params->freq_offset_pss)
|
||||
*params->freq_offset_pss = freq_offset_pss;
|
||||
|
||||
if (sync_pos < fp->nb_prefix_samples || nid2 < 0) {
|
||||
if (sync_pos < params->nb_prefix_samples || nid2 < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int ssb_offset = sync_pos - fp->nb_prefix_samples;
|
||||
const int ssb_offset = sync_pos - params->nb_prefix_samples;
|
||||
if (params->ssb_offset)
|
||||
*params->ssb_offset = ssb_offset;
|
||||
|
||||
@@ -191,7 +238,7 @@ bool nr_search_ssb_common(nr_ssb_search_params_t *params)
|
||||
#endif
|
||||
|
||||
// Check that SSB fits within buffer
|
||||
if (ssb_offset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) >= params->rxdata_size) {
|
||||
if (ssb_offset + NR_N_SYMBOLS_SSB * (params->ofdm_symbol_size + params->nb_prefix_samples) >= params->rxdata_size) {
|
||||
LOG_D(PHY,
|
||||
"SSB extends beyond buffer boundary (sync_pos %d, ssb_offset %d, buffer_size %d)\n",
|
||||
sync_pos,
|
||||
@@ -202,35 +249,27 @@ bool nr_search_ssb_common(nr_ssb_search_params_t *params)
|
||||
|
||||
// Apply frequency offset compensation if requested
|
||||
if (params->apply_freq_offset && freq_offset_pss != 0) {
|
||||
compensate_freq_offset(params->rxdata, fp, freq_offset_pss, params->search_frame_id);
|
||||
compensate_freq_offset(params->rxdata, params->nb_antennas_rx, params->rxdata_size, freq_offset_pss, params->sampling_rate);
|
||||
}
|
||||
|
||||
// Extract SSB symbols to frequency domain
|
||||
// Symbol ordering: 0=PSS, 1=PBCH, 2=SSS, 3=PBCH
|
||||
c16_t(*rxdataF)[fp->nb_antennas_rx][fp->ofdm_symbol_size] = (c16_t(*)[fp->nb_antennas_rx][fp->ofdm_symbol_size])params->rxdataF;
|
||||
|
||||
__attribute__((aligned(32))) c16_t rxdataF_tmp[fp->nb_antennas_rx][fp->samples_per_slot_wCP];
|
||||
|
||||
for (int i = 0; i < NR_N_SYMBOLS_SSB; i++) {
|
||||
const int sample_offset = params->search_frame_id * fp->samples_per_frame + ssb_offset;
|
||||
nr_slot_fep(NULL, fp, 0, i, rxdataF_tmp, link_type_dl, sample_offset, (c16_t **)params->rxdata);
|
||||
// TODO: In later commit, call the modified symbol demod function and remove the following memcpy.
|
||||
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++)
|
||||
memcpy(rxdataF[i][aarx], &rxdataF_tmp[aarx][i * fp->ofdm_symbol_size], sizeof(c16_t) * fp->ofdm_symbol_size);
|
||||
}
|
||||
do_time_to_freq(params, ssb_offset);
|
||||
|
||||
// Perform SSS detection
|
||||
int detected_nid_cell = -1;
|
||||
int32_t sss_metric = 0;
|
||||
uint8_t sss_phase = 0;
|
||||
int freq_offset_sss = 0;
|
||||
nr_sss_params_t p = (nr_sss_params_t){.nb_antennas_rx = fp->nb_antennas_rx,
|
||||
.samples_per_slot_wCP = fp->samples_per_slot_wCP,
|
||||
.ofdm_symbol_size = fp->ofdm_symbol_size,
|
||||
.first_carrier_offset = fp->first_carrier_offset,
|
||||
.ssb_start_subcarrier = fp->ssb_start_subcarrier,
|
||||
.subcarrier_spacing = fp->subcarrier_spacing};
|
||||
nr_sss_params_t p = (nr_sss_params_t){.nb_antennas_rx = params->nb_antennas_rx,
|
||||
.samples_per_slot_wCP = params->samples_per_slot_wCP,
|
||||
.ofdm_symbol_size = params->ofdm_symbol_size,
|
||||
.first_carrier_offset = params->first_carrier_offset,
|
||||
.ssb_start_subcarrier = params->ssb_start_subcarrier,
|
||||
.subcarrier_spacing = params->subcarrier_spacing};
|
||||
|
||||
c16_t(*rxdataF)[params->nb_antennas_rx][params->ofdm_symbol_size] =
|
||||
(c16_t(*)[params->nb_antennas_rx][params->ofdm_symbol_size])params->rxdataF;
|
||||
bool sss_detected =
|
||||
rx_sss_nr(&p, nid2, -1, freq_offset_pss, &detected_nid_cell, &sss_metric, &sss_phase, &freq_offset_sss, rxdataF);
|
||||
|
||||
@@ -279,16 +318,16 @@ void nr_scan_ssb(void *arg)
|
||||
__attribute__((aligned(32))) c16_t pssTime[NUMBER_PSS_SEQUENCE][fp->ofdm_symbol_size];
|
||||
const int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
|
||||
for (int nid2 = 0; nid2 < pss_sequence; nid2++)
|
||||
generate_pss_nr_time(fp, nid2, ssbInfo->gscnInfo.ssbFirstSC, pssTime[nid2]);
|
||||
generate_pss_nr_time(fp->ofdm_symbol_size, fp->first_carrier_offset, nid2, ssbInfo->gscnInfo.ssbFirstSC, pssTime[nid2]);
|
||||
|
||||
__attribute__((aligned(32))) c16_t rxdataF[NR_N_SYMBOLS_SSB][fp->nb_antennas_rx][fp->ofdm_symbol_size];
|
||||
|
||||
// initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame
|
||||
// only one frame is used for simulation tools
|
||||
for (int frame_id = 0; frame_id < ssbInfo->nFrames && !ssbInfo->syncRes.cell_detected; frame_id++) {
|
||||
if (ssbInfo->freqOffset)
|
||||
compensate_freq_offset(rxdata, fp, ssbInfo->freqOffset, frame_id);
|
||||
if (ssbInfo->freqOffset)
|
||||
compensate_freq_offset(rxdata, fp->nb_antennas_rx, ssbInfo->rxdata_sz, ssbInfo->freqOffset, fp->samples_per_subframe * 1000);
|
||||
|
||||
for (int frame_id = 0; frame_id < ssbInfo->nFrames && !ssbInfo->syncRes.cell_detected; frame_id++) {
|
||||
int detected_nid_cell = -1;
|
||||
int ssb_offset = 0;
|
||||
int freq_offset_pss = 0;
|
||||
@@ -296,15 +335,32 @@ void nr_scan_ssb(void *arg)
|
||||
int32_t sss_metric = 0;
|
||||
uint8_t sss_phase = 0;
|
||||
|
||||
c16_t *rxdataShift[fp->nb_antennas_rx];
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxdataShift[i] = rxdata[i] + fp->samples_per_frame * frame_id;
|
||||
|
||||
nr_ssb_search_params_t search_params = {
|
||||
.frame_parms = fp,
|
||||
.rxdata = rxdata,
|
||||
.dl_CarrierFreq = fp->dl_CarrierFreq,
|
||||
.sampling_rate = fp->samples_per_subframe * 1000,
|
||||
.slots_per_frame = fp->slots_per_frame,
|
||||
.slots_per_subframe = fp->slots_per_subframe,
|
||||
.numerology_index = fp->numerology_index,
|
||||
.ofdm_symbol_size = fp->ofdm_symbol_size,
|
||||
.ofdm_offset_divisor = fp->ofdm_offset_divisor,
|
||||
.nb_antennas_rx = fp->nb_antennas_rx,
|
||||
.symbols_per_slot = fp->symbols_per_slot,
|
||||
.first_carrier_offset = fp->first_carrier_offset,
|
||||
.N_RB_DL = fp->N_RB_DL,
|
||||
.rxdata_size = fp->samples_per_frame,
|
||||
.rxdata = rxdataShift,
|
||||
.nb_prefix_samples = fp->nb_prefix_samples,
|
||||
.nb_prefix_samples0 = fp->nb_prefix_samples0,
|
||||
.ssb_start_subcarrier = ssbInfo->gscnInfo.ssbFirstSC,
|
||||
.subcarrier_spacing = fp->subcarrier_spacing,
|
||||
.samples_per_slot_wCP = fp->samples_per_slot_wCP,
|
||||
.target_nid_cell = ssbInfo->targetNidCell,
|
||||
.exclude_nid_cell = -1, // No exclusion for initial sync
|
||||
.apply_freq_offset = ssbInfo->foFlag,
|
||||
.search_frame_id = frame_id,
|
||||
.fo_flag = ssbInfo->foFlag,
|
||||
.rxdataF = rxdataF,
|
||||
.pssTime = pssTime,
|
||||
@@ -392,9 +448,10 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
.targetNidCell = ue->target_Nid_cell};
|
||||
ssbInfo->rxdata = malloc16_clear(fp->nb_antennas_rx * sizeof(c16_t *));
|
||||
for (int ant = 0; ant < fp->nb_antennas_rx; ant++) {
|
||||
ssbInfo->rxdata[ant] = malloc16(sizeof(c16_t) * (fp->samples_per_frame * 2 + fp->ofdm_symbol_size));
|
||||
memcpy(ssbInfo->rxdata[ant], ue->common_vars.rxdata[ant], sizeof(c16_t) * fp->samples_per_frame * 2);
|
||||
memset(ssbInfo->rxdata[ant] + fp->samples_per_frame * 2, 0, fp->ofdm_symbol_size * sizeof(c16_t));
|
||||
ssbInfo->rxdata[ant] = malloc16(sizeof(c16_t) * (fp->samples_per_frame * n_frames + fp->ofdm_symbol_size));
|
||||
memcpy(ssbInfo->rxdata[ant], ue->common_vars.rxdata[ant], sizeof(c16_t) * fp->samples_per_frame * n_frames);
|
||||
memset(ssbInfo->rxdata[ant] + fp->samples_per_frame * n_frames, 0, fp->ofdm_symbol_size * sizeof(c16_t));
|
||||
ssbInfo->rxdata_sz = fp->samples_per_frame * n_frames + fp->ofdm_symbol_size;
|
||||
}
|
||||
LOG_I(NR_PHY,
|
||||
"Scanning GSCN: %d, with SSB offset: %d, SSB Freq: %lf\n",
|
||||
@@ -467,7 +524,11 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
if (res->freqOffset && ue->UE_fo_compensation) {
|
||||
// In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1
|
||||
// and we do not know yet in which slot it goes.
|
||||
compensate_freq_offset(ue->common_vars.rxdata, fp, res->freqOffset, res->syncRes.frame_id);
|
||||
compensate_freq_offset(ue->common_vars.rxdata,
|
||||
fp->nb_antennas_rx,
|
||||
fp->samples_per_frame,
|
||||
res->freqOffset,
|
||||
fp->samples_per_subframe * 1000);
|
||||
}
|
||||
// sync at symbol ue->symbol_offset
|
||||
// computing the offset wrt the beginning of the frame
|
||||
|
||||
@@ -84,23 +84,27 @@ void generate_pss_nr(const int N_ID_2, int16_t *pss)
|
||||
*
|
||||
* sample 0 is for continuous frequency which is used here
|
||||
*/
|
||||
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])
|
||||
void generate_pss_nr_time(int ofdm_symbol_size,
|
||||
int first_carrier_offset,
|
||||
const int N_ID_2,
|
||||
int ssbFirstSCS,
|
||||
c16_t pssTime[ofdm_symbol_size])
|
||||
{
|
||||
unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL;
|
||||
c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
c16_t synchroF_tmp[ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
memset(synchroF_tmp, 0, sizeof(synchroF_tmp));
|
||||
unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start;
|
||||
unsigned int k = first_carrier_offset + ssbFirstSCS + subcarrier_start;
|
||||
int16_t pss[LENGTH_PSS_NR];
|
||||
generate_pss_nr(N_ID_2, pss);
|
||||
for (int i=0; i < LENGTH_PSS_NR; i++) {
|
||||
if (k >= fp->ofdm_symbol_size)
|
||||
k -= fp->ofdm_symbol_size;
|
||||
if (k >= ofdm_symbol_size)
|
||||
k -= ofdm_symbol_size;
|
||||
synchroF_tmp[k] = (c16_t){.r = (pss[i] * SHRT_MAX) >> SCALING_PSS_NR}; /* Maximum value for type short int ie int16_t */
|
||||
k++;
|
||||
}
|
||||
|
||||
/* IFFT will give temporal signal of Pss */
|
||||
idft((int16_t)get_idft(fp->ofdm_symbol_size),
|
||||
idft((int16_t)get_idft(ofdm_symbol_size),
|
||||
(int16_t *)synchroF_tmp, /* complex input but legacy type is wrong*/
|
||||
(int16_t *)pssTime, /* complex output */
|
||||
1); /* scaling factor */
|
||||
@@ -119,9 +123,11 @@ void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssb
|
||||
*********************************************************************/
|
||||
|
||||
int pss_synchro_nr(const c16_t **rxdata,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size],
|
||||
int is,
|
||||
int nb_ant,
|
||||
int ofdm_symbol_size,
|
||||
int rxdata_size,
|
||||
int subcarrier_spacing,
|
||||
const c16_t pssTime[NUMBER_PSS_SEQUENCE][ofdm_symbol_size],
|
||||
bool fo_flag,
|
||||
int target_Nid_cell,
|
||||
int *nid2,
|
||||
@@ -130,8 +136,19 @@ int pss_synchro_nr(const c16_t **rxdata,
|
||||
int *pssAvg)
|
||||
{
|
||||
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);
|
||||
int synchro_position = pss_search_time_nr(rxdata,
|
||||
ofdm_symbol_size,
|
||||
nb_ant,
|
||||
subcarrier_spacing,
|
||||
pssTime,
|
||||
fo_flag,
|
||||
target_Nid_cell,
|
||||
nid2,
|
||||
f_off,
|
||||
pssPeak,
|
||||
pssAvg,
|
||||
0,
|
||||
rxdata_size - ofdm_symbol_size);
|
||||
stop_meas(&generic_time[TIME_PSS]);
|
||||
|
||||
#if TEST_SYNCHRO_TIMING_PSS
|
||||
@@ -196,10 +213,11 @@ int pss_synchro_nr(const c16_t **rxdata,
|
||||
*********************************************************************/
|
||||
|
||||
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],
|
||||
int ofdm_symbol_size,
|
||||
int nb_antennas_rx,
|
||||
int subcarrier_spacing,
|
||||
const c16_t pssTime[NUMBER_PSS_SEQUENCE][ofdm_symbol_size],
|
||||
bool fo_flag,
|
||||
int is,
|
||||
int target_Nid_cell,
|
||||
int *nid2,
|
||||
int *f_off,
|
||||
@@ -210,24 +228,13 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
{
|
||||
// Determine search window
|
||||
unsigned int start, length;
|
||||
if (search_start >= 0 && search_length > 0) {
|
||||
// Use provided search window for known neighboring cells
|
||||
start = search_start;
|
||||
length = search_length;
|
||||
} else {
|
||||
// For initial cell search
|
||||
start = 0;
|
||||
if (is == 0)
|
||||
length = frame_parms->samples_per_frame + (2 * frame_parms->ofdm_symbol_size);
|
||||
else
|
||||
length = frame_parms->samples_per_frame;
|
||||
}
|
||||
|
||||
AssertFatal(length > 0, "illegal length %d\n", length);
|
||||
// Use provided search window for known neighboring cells
|
||||
start = search_start;
|
||||
length = search_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++)
|
||||
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
|
||||
for (int i = 0; i < ofdm_symbol_size; i++) {
|
||||
maxval = max(maxval, abs(pssTime[j][i].r));
|
||||
maxval = max(maxval, abs(pssTime[j][i].i));
|
||||
}
|
||||
@@ -256,12 +263,9 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
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 (int ar = 0; ar < frame_parms->nb_antennas_rx; ar++) {
|
||||
for (int ar = 0; ar < 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],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
shift);
|
||||
const c32_t result = dot_product(pssTime[pss_index], &rxdata[ar][n], ofdm_symbol_size, shift);
|
||||
const c64_t r64 = {.r = result.r, .i = result.i};
|
||||
pss_corr_ue += squaredMod(r64);
|
||||
}
|
||||
@@ -274,7 +278,7 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
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]);
|
||||
printf("pss_index %d: n %6u peak_value %lu\n", pss_index, n, pss_corr_ue);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -288,15 +292,12 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
// 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],
|
||||
&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]),
|
||||
frame_parms->ofdm_symbol_size >> 1,
|
||||
shift);
|
||||
c32_t r1 = dot_product(pssTime[pss_source], &(rxdata[0][peak_position]), ofdm_symbol_size >> 1, shift);
|
||||
// Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size
|
||||
// as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift
|
||||
c32_t r2 = dot_product(pssTime[pss_source] + (frame_parms->ofdm_symbol_size >> 1),
|
||||
&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]) + (frame_parms->ofdm_symbol_size >> 1),
|
||||
frame_parms->ofdm_symbol_size >> 1,
|
||||
c32_t r2 = dot_product(pssTime[pss_source] + (ofdm_symbol_size >> 1),
|
||||
&(rxdata[0][peak_position]) + (ofdm_symbol_size >> 1),
|
||||
ofdm_symbol_size >> 1,
|
||||
shift);
|
||||
cd_t r1d = {r1.r, r1.i}, r2d = {r2.r, r2.i};
|
||||
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
|
||||
@@ -307,7 +308,7 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
#endif
|
||||
}
|
||||
// computing absolute value of frequency offset
|
||||
*f_off = ffo_est * frame_parms->subcarrier_spacing;
|
||||
*f_off = ffo_est * subcarrier_spacing;
|
||||
|
||||
*nid2 = pss_source;
|
||||
*pssPeak = dB_fixed64(peak_value);
|
||||
@@ -329,10 +330,7 @@ int pss_search_time_nr(const c16_t **rxdata,
|
||||
#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);
|
||||
else
|
||||
LOG_M("rxdata0.m", "rxd0", rxdata[0], length, 1, 1);
|
||||
LOG_M("rxdata0.m", "rxd0", rxdata[0], length, 1, 1);
|
||||
} else {
|
||||
debug_cnt++;
|
||||
}
|
||||
|
||||
@@ -468,6 +468,7 @@ typedef struct {
|
||||
int foFlag;
|
||||
int targetNidCell;
|
||||
c16_t **rxdata;
|
||||
int rxdata_sz;
|
||||
NR_DL_FRAME_PARMS *fp;
|
||||
UE_nr_rxtx_proc_t *proc;
|
||||
int nFrames;
|
||||
@@ -487,14 +488,27 @@ typedef struct {
|
||||
|
||||
// Common SSB search parameters - used by both initial sync and neighbor cell search
|
||||
typedef struct {
|
||||
const NR_DL_FRAME_PARMS *frame_parms;
|
||||
c16_t **rxdata;
|
||||
uint64_t dl_CarrierFreq;
|
||||
uint sampling_rate;
|
||||
int slots_per_frame;
|
||||
int slots_per_subframe;
|
||||
int numerology_index;
|
||||
int ofdm_symbol_size;
|
||||
uint ofdm_offset_divisor;
|
||||
int nb_antennas_rx;
|
||||
int symbols_per_slot;
|
||||
int first_carrier_offset;
|
||||
int N_RB_DL;
|
||||
uint32_t rxdata_size;
|
||||
c16_t **rxdata;
|
||||
int nb_prefix_samples;
|
||||
int nb_prefix_samples0;
|
||||
int ssb_start_subcarrier;
|
||||
int subcarrier_spacing;
|
||||
int samples_per_slot_wCP;
|
||||
int target_nid_cell; // -1 for blind search, specific PCI for targeted search
|
||||
int exclude_nid_cell; // -1 for no exclusion, or serving cell PCI to exclude
|
||||
bool apply_freq_offset; // whether to compensate frequency offset
|
||||
int search_frame_id; // Frame index to search (0, 1, 2...) within rxdata buffer
|
||||
bool fo_flag; // frequency offset estimation flag for pss_synchro_nr()
|
||||
void *rxdataF; // Pre-allocated rxdataF buffer
|
||||
void *pssTime; // Pre-generated PSS time sequences
|
||||
|
||||
Reference in New Issue
Block a user