working version of FFO estimation
This commit is contained in:
@@ -137,7 +137,8 @@ int set_pss_nr(int ofdm_symbol_size);
|
||||
int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change);
|
||||
int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int *eNB_id);
|
||||
int *eNB_id,
|
||||
int *f_off);
|
||||
|
||||
#endif
|
||||
#undef EXTERN
|
||||
|
||||
@@ -244,7 +244,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Consider this is a false detection if the offset is > 1000 Hz */
|
||||
/* Consider this is a false detection if the offset is > 1000 Hz
|
||||
Not to be used now that offest estimation is in place
|
||||
if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
|
||||
{
|
||||
ret=-1;
|
||||
@@ -253,7 +254,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
|
||||
#else
|
||||
LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
|
||||
if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters
|
||||
|
||||
|
||||
@@ -706,7 +706,9 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
|
||||
|
||||
synchro_position = pss_search_time_nr(rxdata,
|
||||
frame_parms,
|
||||
(int *)&PHY_vars_UE->common_vars.eNb_id);
|
||||
(int *)&PHY_vars_UE->common_vars.eNb_id,
|
||||
(int *)&PHY_vars_UE->common_vars.freq_offset);
|
||||
|
||||
|
||||
#if TEST_SYNCHRO_TIMING_PSS
|
||||
|
||||
@@ -815,11 +817,12 @@ static inline double angle64(int64_t x)
|
||||
|
||||
int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int *eNB_id)
|
||||
int *eNB_id,
|
||||
int *f_off)
|
||||
{
|
||||
unsigned int n, ar, peak_position, pss_source;
|
||||
int64_t peak_value;
|
||||
int64_t result;
|
||||
int64_t result,result1,result2;
|
||||
int64_t avg[NUMBER_PSS_SEQUENCE];
|
||||
double ffo_est;
|
||||
|
||||
@@ -842,7 +845,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||
maxval = max(maxval,-primary_synchro_time_nr[1][i]);
|
||||
maxval = max(maxval,primary_synchro_time_nr[2][i]);
|
||||
maxval = max(maxval,-primary_synchro_time_nr[2][i]);
|
||||
|
||||
}
|
||||
int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2);
|
||||
|
||||
@@ -877,27 +879,58 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* calculate the absolute value of sync_corr[n] */
|
||||
avg[pss_index]+=pss_corr_ue[pss_index][n];
|
||||
if (pss_corr_ue[pss_index][n] > peak_value) {
|
||||
peak_value = pss_corr_ue[pss_index][n];
|
||||
peak_position = n;
|
||||
pss_source = pss_index;
|
||||
ffo_est = angle64(result)/M_PI;
|
||||
|
||||
//#ifdef DEBUG_PSS_NR
|
||||
printf("pss_index %d: n %6d peak_value %15llu ffo %lf\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n],ffo_est);
|
||||
//#endif
|
||||
#ifdef DEBUG_PSS_NR
|
||||
printf("pss_index %d: n %6d peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fractional frequency offser 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
|
||||
result1 = dot_product64((short*)primary_synchro_time_nr[pss_source],
|
||||
(short*) &(rxdata[0][peak_position]),
|
||||
frame_parms->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
|
||||
result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size),
|
||||
(short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size),
|
||||
frame_parms->ofdm_symbol_size>>1,
|
||||
shift);
|
||||
|
||||
int64_t re1,re2,im1,im2;
|
||||
re1=((int*) &result1)[0];
|
||||
re2=((int*) &result2)[0];
|
||||
im1=((int*) &result1)[1];
|
||||
im2=((int*) &result2)[1];
|
||||
|
||||
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
|
||||
ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI;
|
||||
|
||||
#ifdef DBG_PSS_NR
|
||||
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 = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) avg[pss_index]/=(length/4);
|
||||
|
||||
*eNB_id = pss_source;
|
||||
|
||||
LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]));
|
||||
LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est);
|
||||
|
||||
if (peak_value < 5*avg[pss_source])
|
||||
return(-1);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "tools_defs.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
|
||||
|
||||
@@ -139,20 +139,20 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) {
|
||||
LOG_D(PHY,"SS TX: frame %d, subframe %d, start_symbol %d\n",frame,subframe, ssb_start_symbol);
|
||||
|
||||
nr_generate_pss(gNB->d_pss, txdataF, AMP, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_sss(gNB->d_sss, txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_sss(gNB->d_sss, txdataF, AMP, ssb_start_symbol, cfg, fp);
|
||||
|
||||
if (!(frame&7)){
|
||||
LOG_D(PHY,"%d.%d : pbch_configured %d\n",frame,subframe,gNB->pbch_configured);
|
||||
if (gNB->pbch_configured != 1)return;
|
||||
gNB->pbch_configured = 0;
|
||||
}
|
||||
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_pbch(&gNB->pbch,
|
||||
gNB->nrPolar_params,
|
||||
pbch_pdu,
|
||||
gNB->nr_pbch_interleaver,
|
||||
txdataF,
|
||||
AMP_OVER_2,
|
||||
AMP,
|
||||
ssb_start_symbol,
|
||||
n_hf,Lmax,ssb_index,
|
||||
frame, cfg, fp);
|
||||
|
||||
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
|
||||
|
||||
double pbch_sinr;
|
||||
int pbch_tx_ant;
|
||||
int N_RB_DL=106,mu=1;
|
||||
int N_RB_DL=273,mu=1;
|
||||
|
||||
unsigned char frame_type = 0;
|
||||
unsigned char pbch_phase = 0;
|
||||
@@ -538,7 +538,6 @@ int main(int argc, char **argv)
|
||||
sigma2_dB = 10*log10((double)txlev)-SNR;
|
||||
sigma2 = pow(10,sigma2_dB/10);
|
||||
// printf("sigma2 %f (%f dB)\n",sigma2,sigma2_dB);
|
||||
|
||||
if(eps!=0.0)
|
||||
rf_rx(r_re, // real part of txdata
|
||||
r_im, // imag part of txdata
|
||||
|
||||
@@ -444,6 +444,7 @@ static void *UE_thread_synch(void *arg) {
|
||||
|
||||
//write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_subframe), 1, 1);
|
||||
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe;
|
||||
printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
|
||||
hw_slot_offset,
|
||||
@@ -459,13 +460,13 @@ static void *UE_thread_synch(void *arg) {
|
||||
openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
if (freq_offset >= 0)
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset);
|
||||
else
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset);
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
|
||||
downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
|
||||
freq_offset=0;
|
||||
//freq_offset=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user