git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7885 818b1a75-f10b-46b9-bf7c-635c3b92a50f
743 lines
29 KiB
C
743 lines
29 KiB
C
/*******************************************************************************
|
|
OpenAirInterface
|
|
Copyright(c) 1999 - 2014 Eurecom
|
|
|
|
OpenAirInterface is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
|
|
OpenAirInterface is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenAirInterface.The full GNU General Public License is
|
|
included in this distribution in the file called "COPYING". If not,
|
|
see <http://www.gnu.org/licenses/>.
|
|
|
|
Contact Information
|
|
OpenAirInterface Admin: openair_admin@eurecom.fr
|
|
OpenAirInterface Tech : openair_tech@eurecom.fr
|
|
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
|
|
|
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
|
|
|
*******************************************************************************/
|
|
#ifdef USER_MODE
|
|
#include <string.h>
|
|
#endif
|
|
#include "defs.h"
|
|
#include "PHY/defs.h"
|
|
#include "filt96_32.h"
|
|
//#define DEBUG_CH
|
|
|
|
int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue,
|
|
uint8_t eNB_id,
|
|
uint8_t eNB_offset,
|
|
unsigned char Ns,
|
|
unsigned char p,
|
|
unsigned char l,
|
|
unsigned char symbol)
|
|
{
|
|
|
|
|
|
|
|
int pilot[2][200] __attribute__((aligned(16)));
|
|
unsigned char nu,aarx;
|
|
unsigned short k;
|
|
unsigned int rb,pilot_cnt;
|
|
int16_t ch[2],*pil,*rxF,*dl_ch,*dl_ch_prev,*f,*f2,*fl,*f2l2,*fr,*f2r2,*f2_dc,*f_dc;
|
|
int ch_offset,symbol_offset;
|
|
// unsigned int n;
|
|
// int i;
|
|
|
|
uint16_t Nid_cell = (eNB_offset == 0) ? phy_vars_ue->lte_frame_parms.Nid_cell : phy_vars_ue->PHY_measurements.adj_cell_id[eNB_offset-1];
|
|
|
|
uint8_t nushift,pilot1,pilot2,pilot3;
|
|
int **dl_ch_estimates=phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset];
|
|
int **rxdataF=phy_vars_ue->lte_ue_common_vars.rxdataF;
|
|
|
|
if (phy_vars_ue->lte_frame_parms.Ncp == 0) { // normal prefix
|
|
pilot1 = 4;
|
|
pilot2 = 7;
|
|
pilot3 = 11;
|
|
} else { // extended prefix
|
|
pilot1 = 3;
|
|
pilot2 = 6;
|
|
pilot3 = 9;
|
|
}
|
|
|
|
// recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
|
|
nushift = Nid_cell%6;
|
|
|
|
if ((p==0) && (l==0) )
|
|
nu = 0;
|
|
else if ((p==0) && (l>0))
|
|
nu = 3;
|
|
else if ((p==1) && (l==0))
|
|
nu = 3;
|
|
else if ((p==1) && (l>0))
|
|
nu = 0;
|
|
else {
|
|
msg("lte_dl_channel_estimation: p %d, l %d -> ERROR\n",p,l);
|
|
return(-1);
|
|
}
|
|
|
|
|
|
//ch_offset = (l*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size));
|
|
if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage
|
|
ch_offset = phy_vars_ue->lte_frame_parms.ofdm_symbol_size ;
|
|
else
|
|
ch_offset = phy_vars_ue->lte_frame_parms.ofdm_symbol_size*symbol;
|
|
|
|
symbol_offset = phy_vars_ue->lte_frame_parms.ofdm_symbol_size*symbol;
|
|
|
|
k = (nu + nushift)%6;
|
|
|
|
#ifdef DEBUG_CH
|
|
printf("Channel Estimation : eNB_offset %d cell_id %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d\n",eNB_offset,Nid_cell,ch_offset,phy_vars_ue->lte_frame_parms.ofdm_symbol_size,
|
|
phy_vars_ue->lte_frame_parms.Ncp,l,Ns,k);
|
|
#endif
|
|
|
|
switch (k) {
|
|
case 0 :
|
|
f=filt24_0; //for first pilot of RB, first half
|
|
f2=filt24_2; //for second pilot of RB, first half
|
|
fl=filt24_0; //for first pilot of leftmost RB
|
|
f2l2=filt24_2;
|
|
// fr=filt24_2r; //for first pilot of rightmost RB
|
|
fr=filt24_0r2; //for first pilot of rightmost RB
|
|
// f2r2=filt24_0r2;
|
|
f2r2=filt24_2r;
|
|
|
|
f_dc=filt24_0_dcr;
|
|
f2_dc=filt24_2_dcl;
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
f=filt24_1;
|
|
f2=filt24_3;
|
|
fl=filt24_1l;
|
|
f2l2=filt24_3l2;
|
|
fr=filt24_1r2;
|
|
f2r2=filt24_3r;
|
|
f_dc=filt24_1_dcr; //for first pilot of RB, first half
|
|
f2_dc=filt24_3_dcl; //for first pilot of RB, first half
|
|
break;
|
|
|
|
case 2 :
|
|
f=filt24_2;
|
|
f2=filt24_4;
|
|
fl=filt24_2l;
|
|
f2l2=filt24_4l2;
|
|
fr=filt24_2r2;
|
|
f2r2=filt24_4r;
|
|
f_dc=filt24_2_dcr; //for first pilot of RB, first half
|
|
f2_dc=filt24_4_dcl; //for first pilot of RB, first half
|
|
break;
|
|
|
|
case 3 :
|
|
f=filt24_3;
|
|
f2=filt24_5;
|
|
fl=filt24_3l;
|
|
f2l2=filt24_5l2;
|
|
fr=filt24_3r2;
|
|
f2r2=filt24_5r;
|
|
f_dc=filt24_3_dcr; //for first pilot of RB, first half
|
|
f2_dc=filt24_5_dcl; //for first pilot of RB, first half
|
|
break;
|
|
|
|
case 4 :
|
|
f=filt24_4;
|
|
f2=filt24_6;
|
|
fl=filt24_4l;
|
|
f2l2=filt24_6l2;
|
|
fr=filt24_4r2;
|
|
f2r2=filt24_6r;
|
|
f_dc=filt24_4_dcr; //for first pilot of RB, first half
|
|
f2_dc=filt24_6_dcl; //for first pilot of RB, first half
|
|
break;
|
|
|
|
case 5 :
|
|
f=filt24_5;
|
|
f2=filt24_7;
|
|
fl=filt24_5l;
|
|
f2l2=filt24_7l2;
|
|
fr=filt24_5r2;
|
|
f2r2=filt24_7r;
|
|
f_dc=filt24_5_dcr; //for first pilot of RB, first half
|
|
f2_dc=filt24_7_dcl; //for first pilot of RB, first half
|
|
break;
|
|
|
|
default:
|
|
msg("lte_dl_channel_estimation: k=%d -> ERROR\n",k);
|
|
return(-1);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
// generate pilot
|
|
lte_dl_cell_spec_rx(phy_vars_ue,
|
|
eNB_offset,
|
|
&pilot[p][0],
|
|
Ns,
|
|
(l==0)?0:1,
|
|
p);
|
|
|
|
|
|
for (aarx=0; aarx<phy_vars_ue->lte_frame_parms.nb_antennas_rx; aarx++) {
|
|
|
|
pil = (int16_t *)&pilot[p][0];
|
|
rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+k+phy_vars_ue->lte_frame_parms.first_carrier_offset))];
|
|
dl_ch = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset];
|
|
|
|
|
|
// if (eNb_id==0)
|
|
memset(dl_ch,0,4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size));
|
|
if (phy_vars_ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha
|
|
multadd_complex_vector_real_scalar(dl_ch-(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1),
|
|
phy_vars_ue->ch_est_alpha,dl_ch-(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1),
|
|
1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
|
|
if ((phy_vars_ue->lte_frame_parms.N_RB_DL==6) ||
|
|
(phy_vars_ue->lte_frame_parms.N_RB_DL==50) ||
|
|
(phy_vars_ue->lte_frame_parms.N_RB_DL==100)) {
|
|
|
|
//First half of pilots
|
|
// Treat first 2 pilots specially (left edge)
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
// printf("pilot 0 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
multadd_real_vector_complex_scalar(fl,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
// printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
multadd_real_vector_complex_scalar(f2l2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
for (pilot_cnt=2; pilot_cnt<((phy_vars_ue->lte_frame_parms.N_RB_DL)-1); pilot_cnt+=2) {
|
|
|
|
// printf("%d\n",dl_ch-(int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]);
|
|
|
|
// printf("pilot[%d][%d] (%d,%d)\n",p,pilot_cnt,pil[0],pil[1]);
|
|
// printf("rx[%d] -> (%d,%d)\n", k, rxF[0], rxF[1]);
|
|
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); //Re
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); //Im
|
|
// printf("**rb %d %d\n",rb,dl_ch-(int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]);
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
|
|
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
// printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]);
|
|
// printf("rx[%d] -> (%d,%d)\n", k+6, rxF[0], rxF[1]);
|
|
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
// printf("**rb %d %d\n",rb,dl_ch-(int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]);
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
}
|
|
|
|
// printf("Second half\n");
|
|
// Second half of RBs
|
|
|
|
k = (nu + nushift)%6;
|
|
|
|
if (k > 6)
|
|
k -=6;
|
|
|
|
rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+1+k))];
|
|
|
|
for (pilot_cnt=0; pilot_cnt<((phy_vars_ue->lte_frame_parms.N_RB_DL)-3); pilot_cnt+=2) {
|
|
// printf("pilot[%d][%d] (%d,%d)\n",p,pilot_cnt,pil[0],pil[1]);
|
|
// printf("rx[%d] -> (%d,%d)\n", k+6, rxF[0], rxF[1]);
|
|
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
// printf("**rb %d %d\n",rb,dl_ch-(int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]);
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
// printf("**rb %d %d\n",rb,dl_ch-(int16_T *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]);
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
}
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
// printf("pilot 49: rxF -> (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
multadd_real_vector_complex_scalar(fr,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
// printf("pilot 50: rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
multadd_real_vector_complex_scalar(f2r2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
|
|
|
|
}
|
|
|
|
else if (phy_vars_ue->lte_frame_parms.N_RB_DL==25) {
|
|
//printf("Channel estimation\n");
|
|
|
|
// Treat first 2 pilots specially (left edge)
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
#ifdef DEBUG_CH
|
|
printf("pilot 0 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
multadd_real_vector_complex_scalar(fl,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
#ifdef DEBUG_CH
|
|
printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
multadd_real_vector_complex_scalar(f2l2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
for (pilot_cnt=2; pilot_cnt<24; pilot_cnt+=2) {
|
|
|
|
// printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]);
|
|
// printf("rx[%d][%d] -> (%d,%d)\n",p,phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p),rxF[0],rxF[1]);
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
#ifdef DEBUG_CH
|
|
printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
#ifdef DEBUG_CH
|
|
printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
}
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
#ifdef DEBUG_CH
|
|
printf("pilot 24: rxF -> (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
|
|
multadd_real_vector_complex_scalar(f_dc,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
dl_ch+=8;
|
|
|
|
// printf("Second half\n");
|
|
// Second half of RBs
|
|
rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+1+k))];
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
#ifdef DEBUG_CH
|
|
printf("pilot 25: rxF -> (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
multadd_real_vector_complex_scalar(f2_dc,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
for (pilot_cnt=0; pilot_cnt<22; pilot_cnt+=2) {
|
|
|
|
// printf("* pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]);
|
|
// printf("rx[%d][%d] -> (%d,%d)\n",p,phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p),rxF[0],rxF[1]);
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
#ifdef DEBUG_CH
|
|
printf("pilot %d rxF -> (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",26+pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
#ifdef DEBUG_CH
|
|
printf("pilot %d : rxF -> (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",27+pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
}
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
#ifdef DEBUG_CH
|
|
printf("pilot 49: rxF -> (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
|
|
multadd_real_vector_complex_scalar(fr,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
#ifdef DEBUG_CH
|
|
|
|
printf("pilot 50: rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
|
|
|
|
// ch[0] = 1024;
|
|
// ch[1] = -128;
|
|
#endif
|
|
|
|
multadd_real_vector_complex_scalar(f2r2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
|
|
} else if (phy_vars_ue->lte_frame_parms.N_RB_DL==15) {
|
|
|
|
//printf("First Half\n");
|
|
for (rb=0; rb<28; rb+=4) {
|
|
|
|
//printf("aarx=%d\n",aarx);
|
|
//printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]);
|
|
//printf("rx[%d][%d] -> (%d,%d)\n",p,
|
|
// phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p),
|
|
// rxF[0],
|
|
// rxF[1]);
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
//printf("ch -> (%d,%d)\n",ch[0],ch[1]);
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
//printf("ch -> (%d,%d)\n",ch[0],ch[1]);
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
}
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
// printf("ch -> (%d,%d)\n",ch[0],ch[1]);
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2; // Re Im
|
|
dl_ch+=8;
|
|
|
|
//printf("Second half\n");
|
|
//Second half of RBs
|
|
rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+1+nushift + (3*p)))];
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
for (rb=0; rb<28; rb+=4) {
|
|
//printf("aarx=%d\n",aarx);
|
|
//printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]);
|
|
//printf("rx[%d][%d] -> (%d,%d)\n",p,
|
|
// phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p),
|
|
// rxF[0],
|
|
// rxF[1]);
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
multadd_real_vector_complex_scalar(f,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=8;
|
|
|
|
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
|
ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
|
|
|
|
multadd_real_vector_complex_scalar(f2,
|
|
ch,
|
|
dl_ch,
|
|
24);
|
|
pil+=2;
|
|
rxF+=12;
|
|
dl_ch+=16;
|
|
|
|
}
|
|
} else {
|
|
msg("channel estimation not implemented for phy_vars_ue->lte_frame_parms.N_RB_DL = %d\n",phy_vars_ue->lte_frame_parms.N_RB_DL);
|
|
}
|
|
|
|
|
|
if (phy_vars_ue->perfect_ce == 0) {
|
|
// Temporal Interpolation
|
|
// printf("ch_offset %d\n",ch_offset);
|
|
|
|
dl_ch = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset];
|
|
|
|
if (phy_vars_ue->high_speed_flag == 0) {
|
|
multadd_complex_vector_real_scalar(dl_ch,
|
|
32767-phy_vars_ue->ch_est_alpha,
|
|
dl_ch-(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} else { // high_speed_flag == 1
|
|
if (symbol == 0) {
|
|
// printf("Interpolating %d->0\n",4-phy_vars_ue->lte_frame_parms.Ncp);
|
|
// dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][(4-phy_vars_ue->lte_frame_parms.Ncp)*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)];
|
|
dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot3*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)];
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} // this is 1/3,2/3 combination for pilots spaced by 3 symbols
|
|
else if (symbol == pilot1) {
|
|
dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][0];
|
|
|
|
if (phy_vars_ue->lte_frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination)
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} else {
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} // pilot spacing 3 symbols (1/3,2/3 combination)
|
|
} else if (symbol == pilot2) {
|
|
dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot1*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)];
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} else { // symbol == pilot3
|
|
// printf("Interpolating 0->%d\n",4-phy_vars_ue->lte_frame_parms.Ncp);
|
|
dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)];
|
|
|
|
if (phy_vars_ue->lte_frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination)
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} else {
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
|
|
multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
|
|
} // pilot spacing 3 symbols (1/3,2/3 combination)
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void (*idft)(int16_t *,int16_t *, int);
|
|
|
|
switch (phy_vars_ue->lte_frame_parms.log2_symbol_size) {
|
|
case 7:
|
|
idft = idft128;
|
|
break;
|
|
|
|
case 8:
|
|
idft = idft256;
|
|
break;
|
|
|
|
case 9:
|
|
idft = idft512;
|
|
break;
|
|
|
|
case 10:
|
|
idft = idft1024;
|
|
break;
|
|
|
|
case 11:
|
|
idft = idft2048;
|
|
break;
|
|
|
|
default:
|
|
idft = idft512;
|
|
break;
|
|
}
|
|
|
|
// do ifft of channel estimate
|
|
for (aarx=0; aarx<phy_vars_ue->lte_frame_parms.nb_antennas_rx; aarx++)
|
|
for (p=0; p<phy_vars_ue->lte_frame_parms.nb_antennas_tx_eNB; p++) {
|
|
if (phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx])
|
|
idft((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx][8],
|
|
(int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|