Commit 43c62ecb authored by Francesco Mani's avatar Francesco Mani

FFO estimation and compensation optional via command line

parent 1592738a
......@@ -137,6 +137,7 @@ 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 fo_flag,
int *eNB_id,
int *f_off);
......
......@@ -202,19 +202,21 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot);
#endif
// digital compensation of FFO for SSB symbols
double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time
double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample
// digital compensation of FFO for SSB symbols
if (ue->UE_fo_compensation){
double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time
double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample
int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position)
int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix
int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position)
int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix
for(int n=start; n<end; n++){
for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
for(int n=start; n<end; n++){
for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]);
im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]);
((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle)));
((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle)));
}
}
}
......
......@@ -663,6 +663,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
int synchro_position;
int **rxdata = NULL;
int fo_flag = PHY_vars_UE->UE_fo_compensation; // flag to enable freq offset estimation and compensation
#ifdef DBG_PSS_NR
......@@ -706,6 +707,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
synchro_position = pss_search_time_nr(rxdata,
frame_parms,
fo_flag,
(int *)&PHY_vars_UE->common_vars.eNb_id,
(int *)&PHY_vars_UE->common_vars.freq_offset);
......@@ -817,14 +819,15 @@ 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 fo_flag,
int *eNB_id,
int *f_off)
{
unsigned int n, ar, peak_position, pss_source;
int64_t peak_value;
int64_t result,result1,result2;
int64_t result;
int64_t avg[NUMBER_PSS_SEQUENCE];
double ffo_est;
double ffo_est=0;
unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); /* 1 frame for now, it should be 2 TODO_NR */
......@@ -894,34 +897,36 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
}
}
// 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.
if (fo_flag){
// 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],
int64_t result1,result2;
// 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),
// 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];
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;
// 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);
printf("ffo %lf\n",ffo_est);
#endif
}
// computing absolute value of frequency offset
*f_off = ffo_est*frame_parms->subcarrier_spacing;
......
......@@ -983,6 +983,8 @@ typedef struct {
int UE_scan;
/// \brief Indicator that UE should perform coarse scanning around carrier
int UE_scan_carrier;
/// \brief Indicator that UE should enable estimation and compensation of frequency offset
int UE_fo_compensation;
/// \brief Indicator that UE is synchronized to an eNB
int is_synchronized;
/// Data structure for UE process scheduling
......
......@@ -462,6 +462,9 @@ int main(int argc, char **argv)
UE->perfect_ce = 0;
if(eps!=0.0)
UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation
if (init_nr_ue_signal(UE, 1, 0) != 0)
{
printf("Error at UE NR initialisation\n");
......
......@@ -130,6 +130,7 @@ static char *itti_dump_file = NULL;
int UE_scan = 0;
int UE_scan_carrier = 0;
int UE_fo_compensation = 0;
runmode_t mode = normal_txrx;
FILE *input_fd=NULL;
......@@ -978,6 +979,7 @@ int main( int argc, char **argv ) {
UE[CC_id]->UE_scan = UE_scan;
UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
UE[CC_id]->UE_fo_compensation = UE_fo_compensation;
UE[CC_id]->mode = mode;
printf("UE[%d]->mode = %d\n",CC_id,mode);
......
......@@ -55,6 +55,7 @@
#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n"
#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n"
#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n"
#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n"
#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n"
#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n"
#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n"
......@@ -135,6 +136,7 @@
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \
{"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \
{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \
{"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \
{"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \
{"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment