Commit d74b2bd1 authored by laurent's avatar laurent

improve dot_product function

parent 8773e423
...@@ -35,8 +35,7 @@ int32x4_t avg128F; ...@@ -35,8 +35,7 @@ int32x4_t avg128F;
#endif #endif
//compute average channel_level on each (TX,RX) antenna pair //compute average channel_level on each (TX,RX) antenna pair
int dl_channel_level(int16_t *dl_ch, int dl_channel_level(c16_t *dl_ch, LTE_DL_FRAME_PARMS *frame_parms)
LTE_DL_FRAME_PARMS *frame_parms)
{ {
int16_t rb; int16_t rb;
...@@ -100,13 +99,9 @@ int lte_est_freq_offset(int **dl_ch_estimates, ...@@ -100,13 +99,9 @@ int lte_est_freq_offset(int **dl_ch_estimates,
int* freq_offset, int* freq_offset,
int reset) int reset)
{ {
int ch_offset;
int ch_offset, omega, dl_ch_shift;
c16_t omega_cpx;
double phase_offset; double phase_offset;
int freq_offset_est; int freq_offset_est;
unsigned char aa;
int16_t *dl_ch,*dl_ch_prev;
static int first_run = 1; static int first_run = 1;
int coef = 1<<10; int coef = 1<<10;
int ncoef = 32767 - coef; int ncoef = 32767 - coef;
...@@ -124,49 +119,40 @@ int lte_est_freq_offset(int **dl_ch_estimates, ...@@ -124,49 +119,40 @@ int lte_est_freq_offset(int **dl_ch_estimates,
phase_offset = 0.0; phase_offset = 0.0;
// for (aa=0;aa<frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx;aa++) { // Warning: only one antenna used
for (aa=0; aa<1; aa++) { for (int aa = 0; aa < 1; aa++) {
c16_t *dl_ch = (c16_t *)&dl_ch_estimates[aa][12 + ch_offset];
dl_ch = (int16_t *)&dl_ch_estimates[aa][12+ch_offset];
dl_ch_shift = 6+(log2_approx(dl_channel_level(dl_ch,frame_parms))/2); int dl_ch_shift = 6 + (log2_approx(dl_channel_level(dl_ch, frame_parms)) / 2);
// printf("dl_ch_shift: %d\n",dl_ch_shift);
c16_t *dl_ch_prev;
if (ch_offset == 0) if (ch_offset == 0)
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][12+(4-frame_parms->Ncp)*(frame_parms->ofdm_symbol_size)]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][12 + (4 - frame_parms->Ncp) * (frame_parms->ofdm_symbol_size)];
else else
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][12+0]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][12 + 0];
// calculate omega = angle(conj(dl_ch)*dl_ch_prev)) // calculate omega = angle(conj(dl_ch)*dl_ch_prev))
// printf("Computing freq_offset\n"); // printf("Computing freq_offset\n");
omega = dot_product(dl_ch,dl_ch_prev,(frame_parms->N_RB_DL/2 - 1)*12,dl_ch_shift); c32_t omega_tmp = dot_product(dl_ch, dl_ch_prev, (frame_parms->N_RB_DL / 2 - 1) * 12, dl_ch_shift);
//omega = dot_product(dl_ch,dl_ch_prev,frame_parms->ofdm_symbol_size,15); cd_t omega_cpx = {omega_tmp.r, omega_tmp.i};
omega_cpx.r = ((c16_t*) &omega)->r; // omega = dot_product(dl_ch,dl_ch_prev,frame_parms->ofdm_symbol_size,15);
omega_cpx.i = ((c16_t*) &omega)->i;
dl_ch = (int16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL/2) + 1)*12) + ch_offset]; dl_ch = (c16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL / 2) + 1) * 12) + ch_offset];
if (ch_offset == 0) if (ch_offset == 0)
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL/2) + 1)*12)+(4-frame_parms->Ncp)*(frame_parms->ofdm_symbol_size)]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL / 2) + 1) * 12) + (4 - frame_parms->Ncp) * (frame_parms->ofdm_symbol_size)];
else else
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][((frame_parms->N_RB_DL/2) + 1)*12]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][((frame_parms->N_RB_DL / 2) + 1) * 12];
// calculate omega = angle(conj(dl_ch)*dl_ch_prev)) // calculate omega = angle(conj(dl_ch)*dl_ch_prev))
omega = dot_product(dl_ch,dl_ch_prev,((frame_parms->N_RB_DL/2) - 1)*12,dl_ch_shift); c32_t omega = dot_product(dl_ch, dl_ch_prev, ((frame_parms->N_RB_DL / 2) - 1) * 12, dl_ch_shift);
omega_cpx.r += ((c16_t*) &omega)->r;
omega_cpx.i += ((c16_t*) &omega)->i;
// phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r); omega_cpx.r += omega.r;
phase_offset += atan2((double)omega_cpx.i,(double)omega_cpx.r); omega_cpx.i += omega.i;
// LOG_I(PHY,"omega (%d,%d) -> %f\n",omega_cpx->r,omega_cpx->i,phase_offset); phase_offset += atan2(omega_cpx.i, omega_cpx.r);
} }
// phase_offset /= (frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx);
freq_offset_est = (int) (phase_offset/(2*M_PI)/(frame_parms->Ncp==NORMAL ? (285.8e-6):(2.5e-4))); //2.5e-4 is the time between pilot symbols freq_offset_est = (int) (phase_offset/(2*M_PI)/(frame_parms->Ncp==NORMAL ? (285.8e-6):(2.5e-4))); //2.5e-4 is the time between pilot symbols
// LOG_I(PHY,"symbol %d : freq_offset_est %d\n",l,freq_offset_est);
// update freq_offset with phase_offset using a moving average filter // update freq_offset with phase_offset using a moving average filter
if (first_run == 1) { if (first_run == 1) {
...@@ -175,14 +161,6 @@ int lte_est_freq_offset(int **dl_ch_estimates, ...@@ -175,14 +161,6 @@ int lte_est_freq_offset(int **dl_ch_estimates,
} else } else
*freq_offset = ((freq_offset_est * coef) + (*freq_offset * ncoef)) >> 15; *freq_offset = ((freq_offset_est * coef) + (*freq_offset * ncoef)) >> 15;
//#ifdef DEBUG_PHY
// msg("l=%d, phase_offset = %f (%d,%d), freq_offset_est = %d Hz, freq_offset_filt = %d \n",l,phase_offset,omega_cpx->r,omega_cpx->i,freq_offset_est,*freq_offset);
/*
for (i=0;i<150;i++)
msg("i %d : %d,%d <=> %d,%d\n",i,dl_ch[2*i],dl_ch[(2*i)+1],dl_ch_prev[2*i],dl_ch_prev[(2*i)+1]);
*/
//#endif
return(0); return(0);
} }
//****************************************************************************************************** //******************************************************************************************************
...@@ -193,13 +171,9 @@ int lte_mbsfn_est_freq_offset(int **dl_ch_estimates, ...@@ -193,13 +171,9 @@ int lte_mbsfn_est_freq_offset(int **dl_ch_estimates,
int l, int l,
int* freq_offset) int* freq_offset)
{ {
int ch_offset;
int ch_offset, omega, dl_ch_shift;
c16_t *omega_cpx;
double phase_offset; double phase_offset;
int freq_offset_est; int freq_offset_est;
unsigned char aa;
int16_t *dl_ch,*dl_ch_prev;
static int first_run = 1; static int first_run = 1;
int coef = 1<<10; int coef = 1<<10;
int ncoef = 32767 - coef; int ncoef = 32767 - coef;
...@@ -214,51 +188,37 @@ int lte_mbsfn_est_freq_offset(int **dl_ch_estimates, ...@@ -214,51 +188,37 @@ int lte_mbsfn_est_freq_offset(int **dl_ch_estimates,
phase_offset = 0.0; phase_offset = 0.0;
// for (aa=0;aa<frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx;aa++) { // Warning: only one antenna used
for (aa=0; aa<1; aa++) { for (int aa = 0; aa < 1; aa++) {
c16_t *dl_ch_prev;
c16_t *dl_ch = (c16_t *)&dl_ch_estimates[aa][12 + ch_offset];
dl_ch = (int16_t *)&dl_ch_estimates[aa][12+ch_offset]; int dl_ch_shift = 4 + (log2_approx(dl_channel_level(dl_ch, frame_parms)) / 2);
dl_ch_shift = 4+(log2_approx(dl_channel_level(dl_ch,frame_parms))/2);
// printf("dl_ch_shift: %d\n",dl_ch_shift); // printf("dl_ch_shift: %d\n",dl_ch_shift);
if (ch_offset == 0) if (ch_offset == 0)
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][12+(10*(frame_parms->ofdm_symbol_size))]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][12 + (10 * (frame_parms->ofdm_symbol_size))];
else else
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][12+6]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][12 + 6];
//else if
// dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][12+0];
// calculate omega = angle(conj(dl_ch)*dl_ch_prev))
// printf("Computing freq_offset\n");
omega = dot_product(dl_ch,dl_ch_prev,(frame_parms->N_RB_DL/2 - 1)*12,dl_ch_shift);
//omega = dot_product(dl_ch,dl_ch_prev,frame_parms->ofdm_symbol_size,15);
omega_cpx = (c16_t*) &omega;
// printf("omega (%d,%d)\n",omega_cpx->r,omega_cpx->i); const c32_t omega_tmp = dot_product(dl_ch, dl_ch_prev, (frame_parms->N_RB_DL / 2 - 1) * 12, dl_ch_shift);
cd_t omega_cpx = {omega_tmp.r, omega_tmp.i};
dl_ch = (int16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL/2) + 1)*12) + ch_offset]; dl_ch = (c16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL / 2) + 1) * 12) + ch_offset];
if (ch_offset == 0) if (ch_offset == 0)
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL/2) + 1)*12)+10*(frame_parms->ofdm_symbol_size)]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL / 2) + 1) * 12) + 10 * (frame_parms->ofdm_symbol_size)];
else else
dl_ch_prev = (int16_t *)&dl_ch_estimates[aa][((frame_parms->N_RB_DL/2) + 1)*12+6]; dl_ch_prev = (c16_t *)&dl_ch_estimates[aa][((frame_parms->N_RB_DL / 2) + 1) * 12 + 6];
// calculate omega = angle(conj(dl_ch)*dl_ch_prev)) // calculate omega = angle(conj(dl_ch)*dl_ch_prev))
omega = dot_product(dl_ch,dl_ch_prev,((frame_parms->N_RB_DL/2) - 1)*12,dl_ch_shift); c32_t omega2 = dot_product(dl_ch, dl_ch_prev, ((frame_parms->N_RB_DL / 2) - 1) * 12, dl_ch_shift);
omega_cpx->r += ((c16_t*) &omega)->r; omega_cpx.r += omega2.r;
omega_cpx->i += ((c16_t*) &omega)->i; omega_cpx.i += omega2.i;
// phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r); phase_offset += atan2(omega_cpx.i, omega_cpx.r);
phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r);
// printf("omega (%d,%d) -> %f\n",omega_cpx->r,omega_cpx->i,phase_offset);
} }
// phase_offset /= (frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx);
freq_offset_est = (int) (phase_offset/(2*M_PI)/2.5e-4); //2.5e-4 is the time between pilot symbols freq_offset_est = (int) (phase_offset/(2*M_PI)/2.5e-4); //2.5e-4 is the time between pilot symbols
// printf("symbol %d : freq_offset_est %d\n",l,freq_offset_est);
// update freq_offset with phase_offset using a moving average filter // update freq_offset with phase_offset using a moving average filter
if (first_run == 1) { if (first_run == 1) {
*freq_offset = freq_offset_est; *freq_offset = freq_offset_est;
...@@ -266,13 +226,5 @@ int lte_mbsfn_est_freq_offset(int **dl_ch_estimates, ...@@ -266,13 +226,5 @@ int lte_mbsfn_est_freq_offset(int **dl_ch_estimates,
} else } else
*freq_offset = ((freq_offset_est * coef) + (*freq_offset * ncoef)) >> 15; *freq_offset = ((freq_offset_est * coef) + (*freq_offset * ncoef)) >> 15;
//#ifdef DEBUG_PHY
// msg("l=%d, phase_offset = %f (%d,%d), freq_offset_est = %d Hz, freq_offset_filt = %d \n",l,phase_offset,omega_cpx->r,omega_cpx->i,freq_offset_est,*freq_offset);
/*
for (i=0;i<150;i++)
msg("i %d : %d,%d <=> %d,%d\n",i,dl_ch[2*i],dl_ch[(2*i)+1],dl_ch_prev[2*i],dl_ch_prev[(2*i)+1]);
*/
//#endif
return(0); return(0);
} }
...@@ -75,28 +75,6 @@ void lte_sync_timefreq(PHY_VARS_UE *ue, ...@@ -75,28 +75,6 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,
int band, int band,
unsigned int DL_freq); unsigned int DL_freq);
/*!
\brief This function performs detection of the PRACH (=SRS) at the eNb to estimate the timing advance
The algorithm uses a time domain correlation with a downsampled version of the received signal.
\param rxdata Received time domain data for all rx antennas
\param frame_parms LTE DL frame parameter structure
\param length Length for correlation
\param peak_val pointer to value of returned peak
\param sync_corr_eNb pointer to correlation buffer
\return sync_pos Position of the sync within the frame (downsampled) if successfull and -1 if there was an error or no peak was detected.
*/
int lte_sync_time_eNB(int32_t **rxdata,
LTE_DL_FRAME_PARMS *frame_parms,
uint32_t length,
uint32_t *peak_val,
uint32_t *sync_corr_eNb);
int lte_sync_time_eNB_emul(PHY_VARS_eNB *phy_vars_eNb,
uint8_t sect_id,
int32_t *sync_val);
int ru_sync_time_init(RU_t *ru); int ru_sync_time_init(RU_t *ru);
int ru_sync_time(RU_t *ru, int ru_sync_time(RU_t *ru,
......
This diff is collapsed.
...@@ -651,7 +651,6 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) ...@@ -651,7 +651,6 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change)
* *
*********************************************************************/ *********************************************************************/
#define DOT_PRODUCT_SCALING_SHIFT (17)
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 fo_flag,
...@@ -694,8 +693,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain ...@@ -694,8 +693,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
/* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */ /* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) { for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) {
for (n = 0; n < length; n += 8) { //
for (n=0; n < length; n+=4) { //
int64_t pss_corr_ue=0; int64_t pss_corr_ue=0;
/* calculate dot product of primary_synchro_time_nr and rxdata[ar][n] /* calculate dot product of primary_synchro_time_nr and rxdata[ar][n]
...@@ -703,12 +701,8 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain ...@@ -703,12 +701,8 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) { for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
/* perform correlation of rx data and pss sequence ie it is a dot product */ /* perform correlation of rx data and pss sequence ie it is a dot product */
const int64_t result = dot_product64((short *)primary_synchro_time_nr[pss_index], const c32_t result = dot_product((c16_t *)primary_synchro_time_nr[pss_index], (c16_t *)&(rxdata[ar][n + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size, shift);
(short *)&(rxdata[ar][n + is * frame_parms->samples_per_frame]), const c64_t r64 = {.r = result.r, .i = result.i};
frame_parms->ofdm_symbol_size,
shift);
const c32_t r32 = *(c32_t*)&result;
const c64_t r64 = {.r = r32.r, .i = r32.i};
pss_corr_ue += squaredMod(r64); 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] += ((short*) &result)[0]; /* real part */
//((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */ //((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
...@@ -736,27 +730,17 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain ...@@ -736,27 +730,17 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS // 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. // 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.
int64_t result1,result2;
// Computing cross-correlation at peak on half the symbol size for first half of data // 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], c32_t r1 = dot_product((c16_t *)primary_synchro_time_nr[pss_source], (c16_t *)&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size >> 1, shift);
(short*) &(rxdata[0][peak_position+is*frame_parms->samples_per_frame]),
frame_parms->ofdm_symbol_size>>1,
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), c32_t r2 = dot_product((c16_t *)primary_synchro_time_nr[pss_source] + (frame_parms->ofdm_symbol_size >> 1),
(short*) &(rxdata[0][peak_position+is*frame_parms->samples_per_frame])+frame_parms->ofdm_symbol_size, (c16_t *)&(rxdata[0][peak_position + is * frame_parms->samples_per_frame]) + (frame_parms->ofdm_symbol_size >> 1),
frame_parms->ofdm_symbol_size>>1, frame_parms->ofdm_symbol_size >> 1,
shift); shift);
cd_t r1d = {r1.r, r1.i}, r2d = {r2.r, r2.i};
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 // 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(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI;
#ifdef DBG_PSS_NR #ifdef DBG_PSS_NR
printf("ffo %lf\n",ffo_est); printf("ffo %lf\n",ffo_est);
......
This diff is collapsed.
...@@ -742,16 +742,10 @@ int32_t phy_phase_compensation_top(uint32_t pilot_type, ...@@ -742,16 +742,10 @@ int32_t phy_phase_compensation_top(uint32_t pilot_type,
uint32_t last_pilot, uint32_t last_pilot,
int32_t ignore_prefix); int32_t ignore_prefix);
int32_t dot_product(int16_t *x, c32_t dot_product(const c16_t *x,
int16_t *y, const c16_t *y,
uint32_t N, //must be a multiple of 8 const uint32_t N, // must be a multiple of 8
uint8_t output_shift); const int output_shift);
int64_t dot_product64(int16_t *x,
int16_t *y,
uint32_t N, //must be a multiple of 8
uint8_t output_shift);
/** @} */ /** @} */
......
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