FFO estimation and compensation optional via command line
This commit is contained in:
@@ -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_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change);
|
||||||
int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||||
NR_DL_FRAME_PARMS *frame_parms,
|
NR_DL_FRAME_PARMS *frame_parms,
|
||||||
|
int fo_flag,
|
||||||
int *eNB_id,
|
int *eNB_id,
|
||||||
int *f_off);
|
int *f_off);
|
||||||
|
|
||||||
|
|||||||
@@ -203,18 +203,20 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// digital compensation of FFO for SSB symbols
|
// digital compensation of FFO for SSB symbols
|
||||||
double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time
|
if (ue->UE_fo_compensation){
|
||||||
double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample
|
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 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 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 n=start; n<end; n++){
|
||||||
for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
|
for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
|
||||||
re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]);
|
re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]);
|
||||||
im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]);
|
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] = (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)));
|
((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);
|
NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
|
||||||
int synchro_position;
|
int synchro_position;
|
||||||
int **rxdata = NULL;
|
int **rxdata = NULL;
|
||||||
|
int fo_flag = PHY_vars_UE->UE_fo_compensation; // flag to enable freq offset estimation and compensation
|
||||||
|
|
||||||
#ifdef DBG_PSS_NR
|
#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,
|
synchro_position = pss_search_time_nr(rxdata,
|
||||||
frame_parms,
|
frame_parms,
|
||||||
|
fo_flag,
|
||||||
(int *)&PHY_vars_UE->common_vars.eNb_id,
|
(int *)&PHY_vars_UE->common_vars.eNb_id,
|
||||||
(int *)&PHY_vars_UE->common_vars.freq_offset);
|
(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
|
int pss_search_time_nr(int **rxdata, ///rx data in time domain
|
||||||
NR_DL_FRAME_PARMS *frame_parms,
|
NR_DL_FRAME_PARMS *frame_parms,
|
||||||
|
int fo_flag,
|
||||||
int *eNB_id,
|
int *eNB_id,
|
||||||
int *f_off)
|
int *f_off)
|
||||||
{
|
{
|
||||||
unsigned int n, ar, peak_position, pss_source;
|
unsigned int n, ar, peak_position, pss_source;
|
||||||
int64_t peak_value;
|
int64_t peak_value;
|
||||||
int64_t result,result1,result2;
|
int64_t result;
|
||||||
int64_t avg[NUMBER_PSS_SEQUENCE];
|
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 */
|
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
// fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS
|
int64_t result1,result2;
|
||||||
// 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],
|
||||||
// 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]),
|
(short*) &(rxdata[0][peak_position]),
|
||||||
frame_parms->ofdm_symbol_size>>1,
|
frame_parms->ofdm_symbol_size>>1,
|
||||||
shift);
|
shift);
|
||||||
// Computing cross-correlation at peak on half the symbol size for data shifted by half 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
|
// 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),
|
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),
|
(short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size),
|
||||||
frame_parms->ofdm_symbol_size>>1,
|
frame_parms->ofdm_symbol_size>>1,
|
||||||
shift);
|
shift);
|
||||||
|
|
||||||
int64_t re1,re2,im1,im2;
|
int64_t re1,re2,im1,im2;
|
||||||
re1=((int*) &result1)[0];
|
re1=((int*) &result1)[0];
|
||||||
re2=((int*) &result2)[0];
|
re2=((int*) &result2)[0];
|
||||||
im1=((int*) &result1)[1];
|
im1=((int*) &result1)[1];
|
||||||
im2=((int*) &result2)[1];
|
im2=((int*) &result2)[1];
|
||||||
|
|
||||||
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
|
// estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
|
||||||
ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI;
|
ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI;
|
||||||
|
|
||||||
#ifdef DBG_PSS_NR
|
#ifdef DBG_PSS_NR
|
||||||
printf("ffo %lf\n",ffo_est);
|
printf("ffo %lf\n",ffo_est);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// computing absolute value of frequency offset
|
// computing absolute value of frequency offset
|
||||||
*f_off = ffo_est*frame_parms->subcarrier_spacing;
|
*f_off = ffo_est*frame_parms->subcarrier_spacing;
|
||||||
|
|||||||
@@ -983,6 +983,8 @@ typedef struct {
|
|||||||
int UE_scan;
|
int UE_scan;
|
||||||
/// \brief Indicator that UE should perform coarse scanning around carrier
|
/// \brief Indicator that UE should perform coarse scanning around carrier
|
||||||
int UE_scan_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
|
/// \brief Indicator that UE is synchronized to an eNB
|
||||||
int is_synchronized;
|
int is_synchronized;
|
||||||
/// Data structure for UE process scheduling
|
/// Data structure for UE process scheduling
|
||||||
|
|||||||
@@ -462,6 +462,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
UE->perfect_ce = 0;
|
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)
|
if (init_nr_ue_signal(UE, 1, 0) != 0)
|
||||||
{
|
{
|
||||||
printf("Error at UE NR initialisation\n");
|
printf("Error at UE NR initialisation\n");
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ static char *itti_dump_file = NULL;
|
|||||||
|
|
||||||
int UE_scan = 0;
|
int UE_scan = 0;
|
||||||
int UE_scan_carrier = 0;
|
int UE_scan_carrier = 0;
|
||||||
|
int UE_fo_compensation = 0;
|
||||||
runmode_t mode = normal_txrx;
|
runmode_t mode = normal_txrx;
|
||||||
|
|
||||||
FILE *input_fd=NULL;
|
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 = UE_scan;
|
||||||
UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
|
UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
|
||||||
|
UE[CC_id]->UE_fo_compensation = UE_fo_compensation;
|
||||||
UE[CC_id]->mode = mode;
|
UE[CC_id]->mode = mode;
|
||||||
printf("UE[%d]->mode = %d\n",CC_id,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_UENANTR "set UE number of rx antennas\n"
|
||||||
#define CONFIG_HLP_UENANTT "set UE number of tx 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_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_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_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"
|
#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-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-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-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}, \
|
{"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}, \
|
{"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}, \
|
{"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
|
||||||
|
|||||||
Reference in New Issue
Block a user