astyle --recursive --indent=spaces=2 --style=kr --indent-col1-comments --break-blocks --convert-tabs --max-code-length=200
This is done for better merging branch/LG_PRE_RELEASE_0.3 into trunk (same process is applied on this branch) git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7073 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -45,7 +45,8 @@ double **cos_lut=NULL,**sin_lut=NULL;
|
||||
|
||||
|
||||
|
||||
void init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) {
|
||||
void init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples)
|
||||
{
|
||||
|
||||
|
||||
double delta_f,freq; // 90 kHz spacing
|
||||
@@ -56,33 +57,34 @@ void init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) {
|
||||
|
||||
cos_lut = (double **)malloc(n_samples*sizeof(double*));
|
||||
sin_lut = (double **)malloc(n_samples*sizeof(double*));
|
||||
|
||||
|
||||
|
||||
|
||||
delta_f = nb_rb*180000/(n_samples-1);
|
||||
|
||||
for (f=-(n_samples>>1);f<(n_samples>>1);f++) {
|
||||
for (f=-(n_samples>>1); f<(n_samples>>1); f++) {
|
||||
freq=delta_f*(double)f*1e-6;// due to the fact that delays is in mus
|
||||
|
||||
cos_lut[f+(n_samples>>1)] = (double *)malloc((int)desc->nb_taps*sizeof(double));
|
||||
sin_lut[f+(n_samples>>1)] = (double *)malloc((int)desc->nb_taps*sizeof(double));
|
||||
|
||||
|
||||
for (l=0;l<(int)desc->nb_taps;l++) {
|
||||
if (desc->nb_taps==1)
|
||||
delay = desc->delays[l];
|
||||
for (l=0; l<(int)desc->nb_taps; l++) {
|
||||
if (desc->nb_taps==1)
|
||||
delay = desc->delays[l];
|
||||
else
|
||||
delay = desc->delays[l]+NB_SAMPLES_CHANNEL_OFFSET/desc->BW;
|
||||
delay = desc->delays[l]+NB_SAMPLES_CHANNEL_OFFSET/desc->BW;
|
||||
|
||||
cos_lut[f+(n_samples>>1)][l] = cos(2*M_PI*freq*delay);
|
||||
sin_lut[f+(n_samples>>1)][l] = sin(2*M_PI*freq*delay);
|
||||
//printf("values cos:%d, sin:%d\n", cos_lut[f][l], sin_lut[f][l]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) {
|
||||
void freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples)
|
||||
{
|
||||
|
||||
|
||||
int16_t f,f2,d;
|
||||
@@ -91,46 +93,51 @@ void freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) {
|
||||
static int freq_channel_init=0;
|
||||
static int n_samples_max=0;
|
||||
|
||||
// printf("no of samples:%d,",n_samples);
|
||||
// printf("no of taps:%d,",(int)desc->nb_taps);
|
||||
// printf("no of samples:%d,",n_samples);
|
||||
// printf("no of taps:%d,",(int)desc->nb_taps);
|
||||
|
||||
if (freq_channel_init == 0) {
|
||||
// we are initializing the lut for the largets possible n_samples=12*nb_rb+1
|
||||
// we are initializing the lut for the largets possible n_samples=12*nb_rb+1
|
||||
// if called with n_samples<12*nb_rb+1, we decimate the lut
|
||||
n_samples_max=12*nb_rb+1;
|
||||
init_freq_channel(desc,nb_rb,n_samples_max);
|
||||
freq_channel_init=1;
|
||||
}
|
||||
|
||||
d=n_samples_max/n_samples;
|
||||
|
||||
|
||||
start_meas(&desc->interp_freq);
|
||||
for (f=-n_samples_max/2,f2=-n_samples/2;f<n_samples_max/2;f+=d,f2++) {
|
||||
clut = cos_lut[n_samples_max/2+f];
|
||||
slut = sin_lut[n_samples_max/2+f];
|
||||
|
||||
for (aarx=0;aarx<desc->nb_rx;aarx++) {
|
||||
for (aatx=0;aatx<desc->nb_tx;aatx++) {
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x=0.0;
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y=0.0;
|
||||
for (l=0;l<(int)desc->nb_taps;l++) {
|
||||
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x+=(desc->a[l][aarx+(aatx*desc->nb_rx)].x*clut[l]+
|
||||
desc->a[l][aarx+(aatx*desc->nb_rx)].y*slut[l]);
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y+=(-desc->a[l][aarx+(aatx*desc->nb_rx)].x*slut[l]+
|
||||
desc->a[l][aarx+(aatx*desc->nb_rx)].y*clut[l]);
|
||||
}
|
||||
}
|
||||
|
||||
for (f=-n_samples_max/2,f2=-n_samples/2; f<n_samples_max/2; f+=d,f2++) {
|
||||
clut = cos_lut[n_samples_max/2+f];
|
||||
slut = sin_lut[n_samples_max/2+f];
|
||||
|
||||
for (aarx=0; aarx<desc->nb_rx; aarx++) {
|
||||
for (aatx=0; aatx<desc->nb_tx; aatx++) {
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x=0.0;
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y=0.0;
|
||||
|
||||
for (l=0; l<(int)desc->nb_taps; l++) {
|
||||
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x+=(desc->a[l][aarx+(aatx*desc->nb_rx)].x*clut[l]+
|
||||
desc->a[l][aarx+(aatx*desc->nb_rx)].y*slut[l]);
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y+=(-desc->a[l][aarx+(aatx*desc->nb_rx)].x*slut[l]+
|
||||
desc->a[l][aarx+(aatx*desc->nb_rx)].y*clut[l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stop_meas(&desc->interp_freq);
|
||||
}
|
||||
|
||||
double compute_pbch_sinr(channel_desc_t *desc,
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb) {
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb)
|
||||
{
|
||||
|
||||
double avg_sinr,snr=pow(10.0,.1*snr_dB),snr_i1=pow(10.0,.1*snr_i1_dB),snr_i2=pow(10.0,.1*snr_i2_dB);
|
||||
uint16_t f;
|
||||
@@ -140,47 +147,53 @@ double compute_pbch_sinr(channel_desc_t *desc,
|
||||
struct complex S_i2;
|
||||
|
||||
avg_sinr=0.0;
|
||||
|
||||
// printf("nb_rb %d\n",nb_rb);
|
||||
for (f=(nb_rb-6);f<(nb_rb+6);f++) {
|
||||
for (f=(nb_rb-6); f<(nb_rb+6); f++) {
|
||||
S = 0.0;
|
||||
S_i1.x =0.0;
|
||||
S_i1.y =0.0;
|
||||
S_i2.x =0.0;
|
||||
S_i2.y =0.0;
|
||||
for (aarx=0;aarx<desc->nb_rx;aarx++) {
|
||||
for (aatx=0;aatx<desc->nb_tx;aatx++) {
|
||||
S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
// printf("%d %d chF[%d] => (%f,%f)\n",aarx,aatx,f,desc->chF[aarx+(aatx*desc->nb_rx)][f].x,desc->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
|
||||
if (desc_i1) {
|
||||
S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
if (desc_i2) {
|
||||
S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
|
||||
for (aarx=0; aarx<desc->nb_rx; aarx++) {
|
||||
for (aatx=0; aatx<desc->nb_tx; aatx++) {
|
||||
S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
// printf("%d %d chF[%d] => (%f,%f)\n",aarx,aatx,f,desc->chF[aarx+(aatx*desc->nb_rx)][f].x,desc->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
|
||||
if (desc_i1) {
|
||||
S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
|
||||
if (desc_i2) {
|
||||
S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printf("snr %f f %d : S %f, S_i1 %f, S_i2 %f\n",snr,f-nb_rb,S,snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y),snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y));
|
||||
avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y)+snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y)));
|
||||
}
|
||||
|
||||
// printf("avg_sinr %f (%f,%f,%f)\n",avg_sinr/12.0,snr,snr_i1,snr_i2);
|
||||
return(10*log10(avg_sinr/12.0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
double compute_sinr(channel_desc_t *desc,
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb) {
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb)
|
||||
{
|
||||
|
||||
double avg_sinr,snr=pow(10.0,.1*snr_dB),snr_i1=pow(10.0,.1*snr_i1_dB),snr_i2=pow(10.0,.1*snr_i2_dB);
|
||||
uint16_t f;
|
||||
@@ -190,53 +203,62 @@ double compute_sinr(channel_desc_t *desc,
|
||||
struct complex S_i2;
|
||||
|
||||
DevAssert( nb_rb > 0 );
|
||||
|
||||
|
||||
avg_sinr=0.0;
|
||||
|
||||
// printf("nb_rb %d\n",nb_rb);
|
||||
for (f=0;f<2*nb_rb;f++) {
|
||||
for (f=0; f<2*nb_rb; f++) {
|
||||
S = 0.0;
|
||||
S_i1.x =0.0;
|
||||
S_i1.y =0.0;
|
||||
S_i2.x =0.0;
|
||||
S_i2.y =0.0;
|
||||
for (aarx=0;aarx<desc->nb_rx;aarx++) {
|
||||
for (aatx=0;aatx<desc->nb_tx;aatx++) {
|
||||
S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
if (desc_i1) {
|
||||
S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
if (desc_i2) {
|
||||
S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
|
||||
for (aarx=0; aarx<desc->nb_rx; aarx++) {
|
||||
for (aatx=0; aatx<desc->nb_tx; aatx++) {
|
||||
S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
|
||||
if (desc_i1) {
|
||||
S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
|
||||
if (desc_i2) {
|
||||
S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x +
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y);
|
||||
S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y -
|
||||
desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printf("f %d : S %f, S_i1 %f, S_i2 %f\n",f-nb_rb,snr*S,snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y),snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y));
|
||||
avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y)+snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y)));
|
||||
}
|
||||
|
||||
// printf("avg_sinr %f (%f,%f,%f)\n",avg_sinr/12.0,snr,snr_i1,snr_i2);
|
||||
return(10*log10(avg_sinr/(nb_rb*2)));
|
||||
}
|
||||
|
||||
int pbch_polynomial_degree=6;
|
||||
double pbch_awgn_polynomial[7]={-7.2926e-05, -2.8749e-03, -4.5064e-02, -3.5301e-01, -1.4655e+00, -3.6282e+00, -6.6907e+00};
|
||||
double pbch_awgn_polynomial[7]= {-7.2926e-05, -2.8749e-03, -4.5064e-02, -3.5301e-01, -1.4655e+00, -3.6282e+00, -6.6907e+00};
|
||||
|
||||
void load_pbch_desc(FILE *pbch_file_fd) {
|
||||
void load_pbch_desc(FILE *pbch_file_fd)
|
||||
{
|
||||
|
||||
int i, ret;
|
||||
char dummy[25];
|
||||
|
||||
ret = fscanf(pbch_file_fd,"%d",&pbch_polynomial_degree);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("fscanf failed: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pbch_polynomial_degree>6) {
|
||||
printf("Illegal degree for pbch interpolation polynomial %d\n",pbch_polynomial_degree);
|
||||
exit(-1);
|
||||
@@ -244,38 +266,45 @@ void load_pbch_desc(FILE *pbch_file_fd) {
|
||||
|
||||
printf("PBCH polynomial : ");
|
||||
|
||||
for (i=0;i<=pbch_polynomial_degree;i++) {
|
||||
for (i=0; i<=pbch_polynomial_degree; i++) {
|
||||
ret = fscanf(pbch_file_fd,"%s",dummy);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("fscanf failed: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pbch_awgn_polynomial[i] = strtod(dummy,NULL);
|
||||
printf("%f ",pbch_awgn_polynomial[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
double pbch_bler(double sinr) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
double pbch_bler(double sinr)
|
||||
{
|
||||
|
||||
int i;
|
||||
double log10_bler=pbch_awgn_polynomial[pbch_polynomial_degree];
|
||||
double sinrpow=sinr;
|
||||
double bler=0.0;
|
||||
|
||||
// printf("log10bler %f\n",log10_bler);
|
||||
if (sinr<-10.0)
|
||||
bler= 1.0;
|
||||
else if (sinr>=0.0)
|
||||
bler=0.0;
|
||||
else {
|
||||
for (i=1;i<=pbch_polynomial_degree;i++) {
|
||||
for (i=1; i<=pbch_polynomial_degree; i++) {
|
||||
// printf("sinrpow %f\n",sinrpow);
|
||||
log10_bler += (pbch_awgn_polynomial[pbch_polynomial_degree-i]*sinrpow);
|
||||
sinrpow *= sinr;
|
||||
// printf("log10bler %f\n",log10_bler);
|
||||
}
|
||||
|
||||
bler = pow(10.0,log10_bler);
|
||||
}
|
||||
|
||||
//printf ("sinr %f bler %f\n",sinr,bler);
|
||||
return(bler);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -38,25 +38,27 @@
|
||||
enum sector {SEC1, SEC2, SEC3};
|
||||
scenario_desc_t scenario;
|
||||
|
||||
void get_chan_desc(node_desc_t* node_tx, node_desc_t* node_rx, channel_desc_t *ch_desc, scenario_desc_t* scenario) {
|
||||
double dist;
|
||||
void get_chan_desc(node_desc_t* node_tx, node_desc_t* node_rx, channel_desc_t *ch_desc, scenario_desc_t* scenario)
|
||||
{
|
||||
double dist;
|
||||
dist = sqrt(pow((node_tx->x - node_rx->x), 2) + pow((node_tx->y - node_rx->y), 2));
|
||||
|
||||
|
||||
/* conversion of distance into KM 3gpp (36-942)*/
|
||||
ch_desc->path_loss_dB = (128.1 + 37.6 * log10(dist/1000));
|
||||
ch_desc->path_loss_dB = (128.1 + 37.6 * log10(dist/1000));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main()
|
||||
{
|
||||
int enb_count = 16;
|
||||
int ue_count = 50;
|
||||
double sect_angle[3]={0,2*PI/3,4*PI/3};
|
||||
double sect_angle[3]= {0,2*PI/3,4*PI/3};
|
||||
double gain_max;
|
||||
double theta;
|
||||
double min_path_loss = 0;
|
||||
int att_enb_index;
|
||||
node_desc_t *enb_data[enb_count];
|
||||
node_desc_t *enb_data[enb_count];
|
||||
node_desc_t *ue_data[ue_count];
|
||||
channel_desc_t *ul_channel[ue_count][enb_count];
|
||||
channel_desc_t *ul_channel[ue_count][enb_count];
|
||||
channel_desc_t *dl_channel[ue_count][enb_count];
|
||||
int count;
|
||||
int mcs;
|
||||
@@ -77,30 +79,34 @@ int main() {
|
||||
double tlu_bler;
|
||||
int line_num;
|
||||
char *file_name[]= {"bler_1.csv", "bler_2.csv", "bler_3.csv", "bler_4.csv", "bler_5.csv", "bler_6.csv", "bler_7.csv", "bler_8.csv",
|
||||
"bler_9.csv", "bler_10.csv", "bler_11.csv", "bler_12.csv", "bler_13.csv", "bler_14.csv", "bler_15.csv", "bler_16.csv",
|
||||
"bler_17.csv", "bler_18.csv", "bler_19.csv", "bler_20.csv", "bler_21.csv", "bler_22.csv"};
|
||||
"bler_9.csv", "bler_10.csv", "bler_11.csv", "bler_12.csv", "bler_13.csv", "bler_14.csv", "bler_15.csv", "bler_16.csv",
|
||||
"bler_17.csv", "bler_18.csv", "bler_19.csv", "bler_20.csv", "bler_21.csv", "bler_22.csv"
|
||||
};
|
||||
|
||||
double beta[MCS_COUNT] = {0, 0, 0, 0, 0.9459960937499999, 1.2912109374999994, 1.0133789062499998, 1.000390625,
|
||||
double beta[MCS_COUNT] = {0, 0, 0, 0, 0.9459960937499999, 1.2912109374999994, 1.0133789062499998, 1.000390625,
|
||||
1.02392578125, 1.8595703124999998, 2.424389648437498, 2.3946533203124982, 2.5790039062499988,
|
||||
2.4084960937499984, 2.782617187499999, 2.7868652343749996, 3.92099609375, 4.0392578125,
|
||||
4.56109619140625, 5.03338623046875, 5.810888671875, 6.449108886718749};
|
||||
|
||||
4.56109619140625, 5.03338623046875, 5.810888671875, 6.449108886718749
|
||||
};
|
||||
|
||||
double enb_position[][2] = {{1100,1100},{1100,2100},{1100,3100},{1100,4100},
|
||||
{2100,1100},{2100,2100},{2100,3100},{2100,4100},
|
||||
{3100,1100},{3100,2100},{3100,3100},{3100,4100},
|
||||
{4100,1100},{4100,2100},{4100,3100},{4100,4100}};
|
||||
{2100,1100},{2100,2100},{2100,3100},{2100,4100},
|
||||
{3100,1100},{3100,2100},{3100,3100},{3100,4100},
|
||||
{4100,1100},{4100,2100},{4100,3100},{4100,4100}
|
||||
};
|
||||
|
||||
double ue_position[][2] = {{3340,4740},{1500,620},{1780,4220},{1300,3540},{780,3100},
|
||||
{1140,540},{1340,3660},{860,1220},{2700,2140},{3860,3060},
|
||||
{3740,1060},{1700,3060},{2180,1620},{4420,1060},{1300,3340},
|
||||
{3700,3180},{3780,540},{1700,4380},{4140,4740},{820,4380},
|
||||
{3300,1540},{2100,1780},{1780,2260},{1940,2620},{1580,1700},
|
||||
{1460,1940},{940,1340},{2100,3540},{1260,4340},{2940,4060},
|
||||
{3980,940},{540,2220},{3060,2140},{4620,3940},{4260,2820},
|
||||
{3860,3500},{4140,4140},{3900,3500},{1500,2140},{2620,3820},
|
||||
{3420,2820},{1580,3940},{660,2100},{2740,1180},{2500,2500},
|
||||
{3580,3580},{3740,3140},{3020,3020},{4340,4140},{980,4300}};
|
||||
|
||||
{1140,540},{1340,3660},{860,1220},{2700,2140},{3860,3060},
|
||||
{3740,1060},{1700,3060},{2180,1620},{4420,1060},{1300,3340},
|
||||
{3700,3180},{3780,540},{1700,4380},{4140,4740},{820,4380},
|
||||
{3300,1540},{2100,1780},{1780,2260},{1940,2620},{1580,1700},
|
||||
{1460,1940},{940,1340},{2100,3540},{1260,4340},{2940,4060},
|
||||
{3980,940},{540,2220},{3060,2140},{4620,3940},{4260,2820},
|
||||
{3860,3500},{4140,4140},{3900,3500},{1500,2140},{2620,3820},
|
||||
{3420,2820},{1580,3940},{660,2100},{2740,1180},{2500,2500},
|
||||
{3580,3580},{3740,3140},{3020,3020},{4340,4140},{980,4300}
|
||||
};
|
||||
|
||||
randominit(0);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -110,25 +116,29 @@ int main() {
|
||||
for (mcs = 5; mcs <= MCS_COUNT; mcs++) {
|
||||
|
||||
fp = fopen(file_name[mcs - 1],"r");
|
||||
|
||||
if (fp == NULL) {
|
||||
printf("ERROR: Unable to open the file\n");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fgets(buffer, 100, fp);
|
||||
tabl_len=0;
|
||||
|
||||
while (!feof(fp)) {
|
||||
|
||||
sinr_bler = strtok(buffer, ";");
|
||||
local_table[mcs-1][0][tabl_len] = atof(sinr_bler);
|
||||
sinr_bler = strtok(NULL,";");
|
||||
local_table[mcs-1][1][tabl_len] = atof(sinr_bler);
|
||||
tabl_len++;
|
||||
fgets(buffer, 100, fp);
|
||||
|
||||
sinr_bler = strtok(buffer, ";");
|
||||
local_table[mcs-1][0][tabl_len] = atof(sinr_bler);
|
||||
sinr_bler = strtok(NULL,";");
|
||||
local_table[mcs-1][1][tabl_len] = atof(sinr_bler);
|
||||
tabl_len++;
|
||||
fgets(buffer, 100, fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
printf("\n table for mcs %d\n",mcs);
|
||||
for (tabl_len=0;tabl_len<9;tabl_len++)
|
||||
|
||||
for (tabl_len=0; tabl_len<9; tabl_len++)
|
||||
printf("%lf %lf \n ",local_table[mcs-1][0][tabl_len],local_table[mcs-1][1][tabl_len]);
|
||||
|
||||
|
||||
@@ -138,13 +148,13 @@ int main() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
for (enb_index = 0; enb_index < enb_count; enb_index++)
|
||||
for (enb_index = 0; enb_index < enb_count; enb_index++)
|
||||
enb_data[enb_index] = (node_desc_t *)(malloc(sizeof(node_desc_t)));
|
||||
|
||||
for (ue_index = 0; ue_index < ue_count; ue_index++)
|
||||
ue_data[ue_index] = (node_desc_t *)(malloc(sizeof(node_desc_t)));
|
||||
|
||||
for (enb_index = 0; enb_index < enb_count; enb_index++) {
|
||||
for (ue_index = 0; ue_index < ue_count; ue_index++)
|
||||
ue_data[ue_index] = (node_desc_t *)(malloc(sizeof(node_desc_t)));
|
||||
|
||||
for (enb_index = 0; enb_index < enb_count; enb_index++) {
|
||||
enb_data[enb_index]->x = enb_position[enb_index][0];
|
||||
enb_data[enb_index]->y = enb_position[enb_index][1];
|
||||
enb_data[enb_index]->tx_power_dBm = 40;
|
||||
@@ -161,82 +171,90 @@ int main() {
|
||||
ue_data[ue_index]->ant_gain_dBi = 0;
|
||||
ue_data[ue_index]->rx_noise_level = 9; //value in db
|
||||
}
|
||||
|
||||
for (ue_index = 0; ue_index < ue_count; ue_index++) {
|
||||
min_path_loss = 10000;
|
||||
|
||||
for (enb_index = 0; enb_index < enb_count; enb_index++) {
|
||||
ul_channel[ue_index][enb_index] = new_channel_desc_scm(1, 1, SCM_C, 7.68, 0, 0, 0);
|
||||
dl_channel[ue_index][enb_index] = new_channel_desc_scm(1, 1, SCM_C, 7.68, 0, 0, 0);
|
||||
//printf("ue %d enb %d\n", ue_index, enb_index);
|
||||
|
||||
//printf("ue %d enb %d\n", ue_index, enb_index);
|
||||
|
||||
/* Calculating the angle in the range -pi to pi from the slope */
|
||||
//(ue_data[ue_index])->alpha_rad[enb_index] = (double)(atan2((ue_data[ue_index]->x - enb_data[enb_index]->x), (ue_data[ue_index]->y - enb_data[enb_index]->y)));
|
||||
ue_data[ue_index]->alpha_rad[enb_index] = atan2((ue_data[ue_index]->x - enb_data[enb_index]->x), (ue_data[ue_index]->y - enb_data[enb_index]->y));
|
||||
//printf("angle is tan %lf\n", ue_data[ue_index]->alpha_rad[enb_index]);
|
||||
|
||||
|
||||
if ((ue_data[ue_index]->alpha_rad[enb_index]) < 0) {
|
||||
ue_data[ue_index]->alpha_rad[enb_index] = 2*PI + ue_data[ue_index]->alpha_rad[enb_index];
|
||||
ue_data[ue_index]->alpha_rad[enb_index] = 2*PI + ue_data[ue_index]->alpha_rad[enb_index];
|
||||
//printf("angle in radians is %lf\n", ue_data[ue_index]->alpha_rad[enb_index]);
|
||||
}
|
||||
|
||||
|
||||
for(count = 0; count < enb_data[enb_index]->n_sectors; count++) {
|
||||
theta = sect_angle[count] - ue_data[ue_index]->alpha_rad[enb_index];
|
||||
gain_sec[count] = -(Am < (12 * pow((theta/theta_3dB),2)) ? Am : (12 * pow((theta/theta_3dB),2)));
|
||||
theta = sect_angle[count] - ue_data[ue_index]->alpha_rad[enb_index];
|
||||
gain_sec[count] = -(Am < (12 * pow((theta/theta_3dB),2)) ? Am : (12 * pow((theta/theta_3dB),2)));
|
||||
}
|
||||
|
||||
|
||||
/* gain = -min(Am , 12 * (theta/theta_3dB)^2) */
|
||||
gain_max = (gain_sec[SEC1] > gain_sec[SEC2]) ? ((gain_sec[SEC1] > gain_sec[SEC3]) ? gain_sec[SEC1]:gain_sec[SEC3]) :
|
||||
((gain_sec[SEC2] > gain_sec[SEC3]) ? gain_sec[SEC2]:gain_sec[SEC3]);
|
||||
gain_max = (gain_sec[SEC1] > gain_sec[SEC2]) ? ((gain_sec[SEC1] > gain_sec[SEC3]) ? gain_sec[SEC1]:gain_sec[SEC3]) :
|
||||
((gain_sec[SEC2] > gain_sec[SEC3]) ? gain_sec[SEC2]:gain_sec[SEC3]);
|
||||
|
||||
get_chan_desc(enb_data[enb_index], ue_data[ue_index], ul_channel[ue_index][enb_index], &scenario);
|
||||
get_chan_desc(enb_data[enb_index], ue_data[ue_index], dl_channel[ue_index][enb_index], &scenario);
|
||||
|
||||
//printf("Path loss for link between ue %d and enb %d is %lf and gain is %lf \n", ue_index, enb_index, dl_channel[ue_index][enb_index]->path_loss_dB, gain_max);
|
||||
|
||||
|
||||
//printf("Path loss for link between ue %d and enb %d is %lf and gain is %lf \n", ue_index, enb_index, dl_channel[ue_index][enb_index]->path_loss_dB, gain_max);
|
||||
|
||||
if (dl_channel[ue_index][enb_index]->path_loss_dB < min_path_loss) {
|
||||
min_path_loss = dl_channel[ue_index][enb_index]->path_loss_dB;
|
||||
att_enb_index = enb_index;
|
||||
}
|
||||
|
||||
//return_value = random_channel(ul_channel[ue_index][enb_index]);
|
||||
return_value = random_channel(dl_channel[ue_index][enb_index]);
|
||||
|
||||
|
||||
/* Thermal noise is calculated using 10log10(K*T*B) K = Boltzmann´s constant T = room temperature B = bandwidth */
|
||||
/* Taken as constant for the time being since the BW is not changing */
|
||||
thermal_noise = -105; //value in dBm
|
||||
|
||||
thermal_noise = -105; //value in dBm
|
||||
|
||||
if (0 == return_value) {
|
||||
//freq_channel(ul_channel[ue_index][enb_index], nb_rb);
|
||||
freq_channel(dl_channel[ue_index][enb_index], nb_rb);
|
||||
coupling = MCL > (dl_channel[ue_index][enb_index]->path_loss_dB-(enb_data[enb_index]->ant_gain_dBi + gain_max)) ?
|
||||
MCL : (dl_channel[ue_index][enb_index]->path_loss_dB-(enb_data[enb_index]->ant_gain_dBi + gain_max));
|
||||
//printf ("coupling factor is %lf\n", coupling);
|
||||
MCL : (dl_channel[ue_index][enb_index]->path_loss_dB-(enb_data[enb_index]->ant_gain_dBi + gain_max));
|
||||
|
||||
//printf ("coupling factor is %lf\n", coupling);
|
||||
for (count = 0; count < (2 * nb_rb); count++) {
|
||||
sinr[enb_index][count] = enb_data[enb_index]->tx_power_dBm
|
||||
- coupling
|
||||
- (thermal_noise + ue_data[ue_index]->rx_noise_level)
|
||||
+ 10 * log10 (pow(dl_channel[ue_index][enb_index]->chF[0][count].r, 2)
|
||||
+ pow(dl_channel[ue_index][enb_index]->chF[0][count].i, 2));
|
||||
|
||||
sinr[enb_index][count] = enb_data[enb_index]->tx_power_dBm
|
||||
- coupling
|
||||
- (thermal_noise + ue_data[ue_index]->rx_noise_level)
|
||||
+ 10 * log10 (pow(dl_channel[ue_index][enb_index]->chF[0][count].r, 2)
|
||||
+ pow(dl_channel[ue_index][enb_index]->chF[0][count].i, 2));
|
||||
|
||||
//printf("Dl_link SNR for res. block %d is %lf\n", count, sinr[enb_index][count]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (count = 0; count < 2 * nb_rb; count++) {
|
||||
interference = 0;
|
||||
|
||||
for (enb_index = 0; enb_index < enb_count; enb_index++) {
|
||||
if (att_enb_index != enb_index) {
|
||||
interference += pow(10, 0.1 * sinr[enb_index][count]);
|
||||
}
|
||||
}
|
||||
|
||||
sinr[att_enb_index][count] -= 10*log10(1 + interference);
|
||||
|
||||
|
||||
//printf("***Dl_link SINR for res. block %d is %lf\n", count, sinr[att_enb_index][count]);
|
||||
|
||||
|
||||
for (mcs = 5; mcs <= MCS_COUNT; mcs++) {
|
||||
sinr_eff[ue_index][mcs-1] += exp(-(pow(10, (sinr[att_enb_index][count])/10))/beta[mcs-1]);
|
||||
//printf("Effective snr %lf\n",sinr_eff[ue_index][mcs-1]);
|
||||
//printf("Effective snr %lf\n",sinr_eff[ue_index][mcs-1]);
|
||||
//sinr_eff[ue_index][mcs] += exp(-(sinr[att_enb_index][count])/beta[mcs]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (mcs = 5; mcs <= MCS_COUNT; mcs++) {
|
||||
//printf("mcs value %d \n",mcs);
|
||||
//printf("beta value %lf \n",-beta[mcs-1]);
|
||||
@@ -247,74 +265,78 @@ int main() {
|
||||
sinr_eff[ue_index][mcs-1] = 10 * log10(sinr_eff[ue_index][mcs-1]);
|
||||
sinr_eff[ue_index][mcs-1] *= 10;
|
||||
sinr_eff[ue_index][mcs-1] = floor(sinr_eff[ue_index][mcs-1]);
|
||||
|
||||
if ((int)sinr_eff[ue_index][mcs-1]%2) {
|
||||
sinr_eff[ue_index][mcs-1] += 1;
|
||||
}
|
||||
|
||||
sinr_eff[ue_index][mcs-1] /= 10;
|
||||
|
||||
//printf("Effective snr %lf \n",sinr_eff[ue_index][mcs-1]);
|
||||
|
||||
bler[ue_index][mcs-1] = 0;
|
||||
|
||||
/*line_num = 0;
|
||||
fp = fopen(file_name[mcs - 1],"r");
|
||||
if (fp == NULL) {
|
||||
fp = fopen(file_name[mcs - 1],"r");
|
||||
if (fp == NULL) {
|
||||
printf("ERROR: Unable to open the file\n");
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
fgets(buffer, 100, fp);
|
||||
while (!feof(fp)) {
|
||||
line_num++;
|
||||
sinr_bler = strtok(buffer, ";");
|
||||
tlu_sinr = atof(sinr_bler);
|
||||
sinr_bler = strtok(NULL,";");
|
||||
tlu_bler = atof(sinr_bler);
|
||||
if (1 == line_num) {
|
||||
if (sinr_eff[ue_index][mcs-1] < tlu_sinr) {
|
||||
bler[ue_index][mcs-1] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sinr_eff[ue_index][mcs-1] == tlu_sinr) {
|
||||
bler[ue_index][mcs-1] = tlu_bler;
|
||||
}
|
||||
fgets(buffer, 100, fp);
|
||||
line_num++;
|
||||
sinr_bler = strtok(buffer, ";");
|
||||
tlu_sinr = atof(sinr_bler);
|
||||
sinr_bler = strtok(NULL,";");
|
||||
tlu_bler = atof(sinr_bler);
|
||||
if (1 == line_num) {
|
||||
if (sinr_eff[ue_index][mcs-1] < tlu_sinr) {
|
||||
bler[ue_index][mcs-1] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sinr_eff[ue_index][mcs-1] == tlu_sinr) {
|
||||
bler[ue_index][mcs-1] = tlu_bler;
|
||||
}
|
||||
fgets(buffer, 100, fp);
|
||||
}
|
||||
fclose(fp);*/
|
||||
for (tabl_len=0;tabl_len<9;tabl_len++) {
|
||||
for (tabl_len=0; tabl_len<9; tabl_len++) {
|
||||
|
||||
if(tabl_len==0)
|
||||
if (sinr_eff[ue_index][mcs-1] < local_table[mcs-1][0][tabl_len]) {
|
||||
bler[ue_index][mcs-1] = 1;
|
||||
break;
|
||||
}
|
||||
if(tabl_len==0)
|
||||
if (sinr_eff[ue_index][mcs-1] < local_table[mcs-1][0][tabl_len]) {
|
||||
bler[ue_index][mcs-1] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (sinr_eff[ue_index][mcs-1] == local_table[mcs-1][0][tabl_len]) {
|
||||
bler[ue_index][mcs-1] = local_table[mcs-1][1][tabl_len];
|
||||
}
|
||||
if (sinr_eff[ue_index][mcs-1] == local_table[mcs-1][0][tabl_len]) {
|
||||
bler[ue_index][mcs-1] = local_table[mcs-1][1][tabl_len];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//printf("\n###Dl_link UE %d attached to eNB %d \n MCS %d effective SNR %lf BLER %lf", ue_index, att_enb_index, mcs,sinr_eff[ue_index][mcs-1],bler[ue_index][mcs-1]);
|
||||
}
|
||||
}
|
||||
|
||||
//printf("\n\n");
|
||||
|
||||
printf("\n Ue_ix enb_ix mcs5 mcs6 mcs7 mcs8 mcs9 mcs10 mcs11 mcs12 mcs13\
|
||||
mcs14 mcs15 mcs16 mcs17 mcs18 mcs19 mcs20 mcs21 mcs22\n");
|
||||
mcs14 mcs15 mcs16 mcs17 mcs18 mcs19 mcs20 mcs21 mcs22\n");
|
||||
|
||||
printf("SINR %4d %4d %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f\
|
||||
%+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f\n",
|
||||
ue_index, att_enb_index, sinr_eff[ue_index][4], sinr_eff[ue_index][5], sinr_eff[ue_index][6], sinr_eff[ue_index][7],
|
||||
sinr_eff[ue_index][8], sinr_eff[ue_index][9], sinr_eff[ue_index][10], sinr_eff[ue_index][11], sinr_eff[ue_index][12],
|
||||
sinr_eff[ue_index][13], sinr_eff[ue_index][14], sinr_eff[ue_index][15], sinr_eff[ue_index][16], sinr_eff[ue_index][17],
|
||||
sinr_eff[ue_index][18], sinr_eff[ue_index][19], sinr_eff[ue_index][20], sinr_eff[ue_index][21], sinr_eff[ue_index][22]);
|
||||
ue_index, att_enb_index, sinr_eff[ue_index][4], sinr_eff[ue_index][5], sinr_eff[ue_index][6], sinr_eff[ue_index][7],
|
||||
sinr_eff[ue_index][8], sinr_eff[ue_index][9], sinr_eff[ue_index][10], sinr_eff[ue_index][11], sinr_eff[ue_index][12],
|
||||
sinr_eff[ue_index][13], sinr_eff[ue_index][14], sinr_eff[ue_index][15], sinr_eff[ue_index][16], sinr_eff[ue_index][17],
|
||||
sinr_eff[ue_index][18], sinr_eff[ue_index][19], sinr_eff[ue_index][20], sinr_eff[ue_index][21], sinr_eff[ue_index][22]);
|
||||
|
||||
printf("BLER %4d %4d %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f\
|
||||
%+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f\n",
|
||||
ue_index, att_enb_index, bler[ue_index][4], bler[ue_index][5], bler[ue_index][6], bler[ue_index][7],
|
||||
bler[ue_index][8], bler[ue_index][9], bler[ue_index][10], bler[ue_index][11], bler[ue_index][12],
|
||||
bler[ue_index][13], bler[ue_index][14], bler[ue_index][15], bler[ue_index][16], bler[ue_index][17],
|
||||
bler[ue_index][18], bler[ue_index][19], bler[ue_index][20], bler[ue_index][21], bler[ue_index][22]);
|
||||
ue_index, att_enb_index, bler[ue_index][4], bler[ue_index][5], bler[ue_index][6], bler[ue_index][7],
|
||||
bler[ue_index][8], bler[ue_index][9], bler[ue_index][10], bler[ue_index][11], bler[ue_index][12],
|
||||
bler[ue_index][13], bler[ue_index][14], bler[ue_index][15], bler[ue_index][16], bler[ue_index][17],
|
||||
bler[ue_index][18], bler[ue_index][19], bler[ue_index][20], bler[ue_index][21], bler[ue_index][22]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+105
-105
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -40,7 +40,7 @@ The present clause specifies several numerical functions for testing of digital
|
||||
-# Generic Multipath Channel Generator
|
||||
|
||||
* @defgroup _channel_ Multipath channel generator
|
||||
* @ingroup _numerical_
|
||||
* @ingroup _numerical_
|
||||
* @{
|
||||
|
||||
*/
|
||||
@@ -49,49 +49,49 @@ The present clause specifies several numerical functions for testing of digital
|
||||
|
||||
typedef struct {
|
||||
///Number of tx antennas
|
||||
uint8_t nb_tx;
|
||||
uint8_t nb_tx;
|
||||
///Number of rx antennas
|
||||
uint8_t nb_rx;
|
||||
///number of taps
|
||||
uint8_t nb_taps;
|
||||
uint8_t nb_taps;
|
||||
///linear amplitudes of taps
|
||||
double *amps;
|
||||
///Delays of the taps in mus. length(delays)=nb_taps. Has to be between 0 and Td.
|
||||
double *delays;
|
||||
///length of impulse response. should be set to 11+2*bw*t_max
|
||||
uint8_t channel_length;
|
||||
double *amps;
|
||||
///Delays of the taps in mus. length(delays)=nb_taps. Has to be between 0 and Td.
|
||||
double *delays;
|
||||
///length of impulse response. should be set to 11+2*bw*t_max
|
||||
uint8_t channel_length;
|
||||
///channel state vector. size(state) = nb_taps * (n_tx * n_rx);
|
||||
struct complex **a;
|
||||
struct complex **a;
|
||||
///interpolated (sample-spaced) channel impulse response. size(ch) = (n_tx * n_rx) * channel_length. ATTENTION: the dimensions of ch are the transposed ones of a. This is to allow the use of BLAS when applying the correlation matrices to the state.
|
||||
struct complex **ch;
|
||||
struct complex **ch;
|
||||
///Sampled frequency response (90 kHz resolution)
|
||||
struct complex **chF;
|
||||
struct complex **chF;
|
||||
///Maximum path delay in mus.
|
||||
double Td;
|
||||
double Td;
|
||||
///Channel bandwidth in MHz.
|
||||
double BW;
|
||||
double BW;
|
||||
///Ricean factor of first tap wrt other taps (0..1, where 0 means AWGN and 1 means Rayleigh channel).
|
||||
double ricean_factor;
|
||||
///Angle of arrival of wavefront (in radians). For Ricean channel only. This assumes that both RX and TX have linear antenna arrays with lambda/2 antenna spacing. Furhter it is assumed that the arrays are parallel to each other and that they are far enough apart so that we can safely assume plane wave propagation.
|
||||
double aoa;
|
||||
///If set to 1, aoa is randomized according to a uniform random distribution
|
||||
double ricean_factor;
|
||||
///Angle of arrival of wavefront (in radians). For Ricean channel only. This assumes that both RX and TX have linear antenna arrays with lambda/2 antenna spacing. Furhter it is assumed that the arrays are parallel to each other and that they are far enough apart so that we can safely assume plane wave propagation.
|
||||
double aoa;
|
||||
///If set to 1, aoa is randomized according to a uniform random distribution
|
||||
int8_t random_aoa;
|
||||
///in Hz. if >0 generate a channel with a Clarke's Doppler profile with a maximum Doppler bandwidth max_Doppler. CURRENTLY NOT IMPLEMENTED!
|
||||
double max_Doppler;
|
||||
double max_Doppler;
|
||||
///Square root of the full correlation matrix size(R_tx) = nb_taps * (n_tx * n_rx) * (n_tx * n_rx).
|
||||
struct complex **R_sqrt;
|
||||
///path loss including shadow fading in dB
|
||||
struct complex **R_sqrt;
|
||||
///path loss including shadow fading in dB
|
||||
double path_loss_dB;
|
||||
///additional delay of channel in samples.
|
||||
int32_t channel_offset;
|
||||
///additional delay of channel in samples.
|
||||
int32_t channel_offset;
|
||||
///This parameter (0...1) allows for simple 1st order temporal variation. 0 means a new channel every call, 1 means keep channel constant all the time
|
||||
double forgetting_factor;
|
||||
///needs to be set to 1 for the first call, 0 otherwise.
|
||||
uint8_t first_run;
|
||||
/// initial phase for frequency offset simulation
|
||||
/// initial phase for frequency offset simulation
|
||||
double ip;
|
||||
/// number of paths taken by transmit signal
|
||||
uint16_t nb_paths;
|
||||
uint16_t nb_paths;
|
||||
/// timing measurements
|
||||
time_stats_t random_channel;
|
||||
time_stats_t interp_time;
|
||||
@@ -104,7 +104,7 @@ typedef struct {
|
||||
uint8_t n_sectors;
|
||||
/// Antenna orientation for each sector (for non-omnidirectional antennas) in radians wrt north
|
||||
double alpha_rad[3];
|
||||
/// Antenna 3dB beam width (in radians)
|
||||
/// Antenna 3dB beam width (in radians)
|
||||
double phi_rad;
|
||||
/// Antenna gain (dBi)
|
||||
double ant_gain_dBi;
|
||||
@@ -113,9 +113,9 @@ typedef struct {
|
||||
/// Rx noise level (dB)
|
||||
double rx_noise_level;
|
||||
///x coordinate (cartesian, in m)
|
||||
double x;
|
||||
double x;
|
||||
///y coordinate (cartesian, in m)
|
||||
double y;
|
||||
double y;
|
||||
///z coordinate (antenna height, in m)
|
||||
double z;
|
||||
/// direction of travel in radians wrt north
|
||||
@@ -129,7 +129,7 @@ typedef enum {
|
||||
urban,
|
||||
indoor
|
||||
} scenario_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// Scenario classifcation
|
||||
scenario_t scenario;
|
||||
@@ -139,11 +139,11 @@ typedef struct {
|
||||
double bandwidth;
|
||||
/// path loss at 0m distance in dB
|
||||
double path_loss_0;
|
||||
/// path loss exponent
|
||||
/// path loss exponent
|
||||
double path_loss_exponent;
|
||||
/// shadow fading standard deviation [dB] (assuming log-normal shadow fading with 0 mean)
|
||||
double shadow_fading_std;
|
||||
/// correlation distance of shadow fading
|
||||
/// correlation distance of shadow fading
|
||||
double shadow_fading_correlation_distance;
|
||||
/// Shadowing correlation between cells
|
||||
double shadow_fading_correlation_cells;
|
||||
@@ -156,7 +156,7 @@ typedef struct {
|
||||
} scenario_desc_t;
|
||||
|
||||
typedef enum {
|
||||
custom=0,
|
||||
custom=0,
|
||||
SCM_A,
|
||||
SCM_B,
|
||||
SCM_C,
|
||||
@@ -177,14 +177,14 @@ typedef enum {
|
||||
AWGN
|
||||
} SCM_t;
|
||||
|
||||
/**
|
||||
/**
|
||||
\brief This routine initializes a new channel descriptor
|
||||
\param nb_tx Number of TX antennas
|
||||
\param nb_rx Number of RX antennas
|
||||
\param nb_taps Number of taps
|
||||
\param channel_length Length of the interpolated channel impulse response
|
||||
\param amps Linear amplitudes of the taps (length(amps)=channel_length). The values should sum up to 1.
|
||||
\param delays Delays of the taps. If delays==NULL the taps are assumed to be spaced equidistantly between 0 and t_max.
|
||||
\param delays Delays of the taps. If delays==NULL the taps are assumed to be spaced equidistantly between 0 and t_max.
|
||||
\param R_sqrt Channel correlation matrix. If R_sqrt==NULL, no channel correlation is applied.
|
||||
\param Td Maximum path delay in mus.
|
||||
\param BW Channel bandwidth in MHz.
|
||||
@@ -200,33 +200,33 @@ typedef enum {
|
||||
//channel_desc_t *new_channel_desc(uint8_t nb_tx,uint8_t nb_rx, uint8_t nb_taps, uint8_t channel_length, double *amps, double* delays, struct complex** R_sqrt, double Td, double BW, double ricean_factor, double aoa, double forgetting_factor, double max_Doppler, int32_t channel_offset, double path_loss_dB,uint8_t random_aoa);
|
||||
|
||||
channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
uint8_t nb_rx,
|
||||
SCM_t channel_model,
|
||||
double BW,
|
||||
double forgetting_factor,
|
||||
int32_t channel_offset,
|
||||
double path_loss_dB);
|
||||
uint8_t nb_rx,
|
||||
SCM_t channel_model,
|
||||
double BW,
|
||||
double forgetting_factor,
|
||||
int32_t channel_offset,
|
||||
double path_loss_dB);
|
||||
|
||||
|
||||
|
||||
/** \fn void random_channel(channel_desc_t *desc)
|
||||
\brief This routine generates a random channel response (time domain) according to a tapped delay line model.
|
||||
\brief This routine generates a random channel response (time domain) according to a tapped delay line model.
|
||||
\param desc Pointer to the channel descriptor
|
||||
*/
|
||||
int random_channel(channel_desc_t *desc, uint8_t abstraction_flag);
|
||||
|
||||
/**\fn void multipath_channel(channel_desc_t *desc,
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel)
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel)
|
||||
|
||||
\brief This function generates and applys a random frequency selective random channel model.
|
||||
@param desc Pointer to channel descriptor
|
||||
@param tx_sig_re input signal (real component)
|
||||
@param tx_sig_im input signal (imaginary component)
|
||||
@param tx_sig_re input signal (real component)
|
||||
@param tx_sig_im input signal (imaginary component)
|
||||
@param rx_sig_re output signal (real component)
|
||||
@param rx_sig_im output signal (imaginary component)
|
||||
@param length Length of input signal
|
||||
@@ -234,19 +234,19 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag);
|
||||
*/
|
||||
|
||||
void multipath_channel(channel_desc_t *desc,
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel);
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel);
|
||||
/*
|
||||
\fn double compute_pbch_sinr(channel_desc_t *desc,
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb)
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb)
|
||||
|
||||
\brief This function computes the average SINR over all frequency resources of the PBCH. It is used for PHY abstraction of the PBCH BLER
|
||||
@param desc Pointer to channel descriptor of eNB
|
||||
@@ -258,18 +258,18 @@ void multipath_channel(channel_desc_t *desc,
|
||||
@param nb_rb Number of RBs in system
|
||||
*/
|
||||
double compute_pbch_sinr(channel_desc_t *desc,
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb);
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb);
|
||||
|
||||
double compute_sinr(channel_desc_t *desc,
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb);
|
||||
channel_desc_t *desc_i1,
|
||||
channel_desc_t *desc_i2,
|
||||
double snr_dB,double snr_i1_dB,
|
||||
double snr_i2_dB,
|
||||
uint16_t nb_rb);
|
||||
|
||||
double pbch_bler(double sinr);
|
||||
|
||||
@@ -279,16 +279,16 @@ void load_pbch_desc(FILE *pbch_file_fd);
|
||||
|
||||
/**
|
||||
* @defgroup _taus_ Tausworthe Uniform Random Variable Generator
|
||||
* @ingroup _numerical_
|
||||
* @ingroup _numerical_
|
||||
* @{
|
||||
\fn unsigned int taus()
|
||||
\brief Tausworthe Uniform Random Generator. This is based on the hardware implementation described in
|
||||
\brief Tausworthe Uniform Random Generator. This is based on the hardware implementation described in
|
||||
Lee et al, "A Hardware Gaussian Noise Generator Usign the Box-Muller Method and its Error Analysis," IEEE Trans. on Computers, 2006.
|
||||
*/
|
||||
unsigned int taus(void);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
\fn void set_taus_seed(unsigned int seed_init)
|
||||
\brief Sets the seed for the Tausworthe generator.
|
||||
@param seed_init 0 means generate based on CPU time, otherwise provide the seed
|
||||
@@ -296,27 +296,27 @@ unsigned int taus(void);
|
||||
void set_taus_seed(unsigned int seed_init);
|
||||
/**@} */
|
||||
|
||||
/** @defgroup _gauss_ Generation of Quantized Gaussian Random Variables
|
||||
/** @defgroup _gauss_ Generation of Quantized Gaussian Random Variables
|
||||
* @ingroup _numerical_
|
||||
* @{
|
||||
This set of routines are used to generate quantized (i.e. fixed-point) Gaussian random noise efficiently.
|
||||
The use of these routines allows for rapid computer simulation of digital communication systems. The method
|
||||
is based on a lookup-table of the quantized normal probability distribution. The routines assume that the
|
||||
This set of routines are used to generate quantized (i.e. fixed-point) Gaussian random noise efficiently.
|
||||
The use of these routines allows for rapid computer simulation of digital communication systems. The method
|
||||
is based on a lookup-table of the quantized normal probability distribution. The routines assume that the
|
||||
continuous-valued Gaussian random-variable,\f$x\f$ is quantized
|
||||
to \f$N\f$ bits over the interval \f$[-L\sigma,L\sigma)\f$ where \f$N\f$ and \f$L\f$ control the precision
|
||||
and range of the quantization. The
|
||||
random variable, \f$l\in\{-2^{N-1},-2^{N-1}+1,\cdots,0,1,\cdots,2^{N-1}-1\}\f$ corresponds to the event,
|
||||
\f$E_l =
|
||||
\begin{cases}
|
||||
x\in\left[-\infty,-L\sigma\right) & l=-2^{N-1}, \\
|
||||
x\in\left[\frac{lL\sigma}{2^{N-1}},\frac{(l+1)L\sigma}{2^{N-1}}\right) & <l>-2^{N-1}, \\
|
||||
to \f$N\f$ bits over the interval \f$[-L\sigma,L\sigma)\f$ where \f$N\f$ and \f$L\f$ control the precision
|
||||
and range of the quantization. The
|
||||
random variable, \f$l\in\{-2^{N-1},-2^{N-1}+1,\cdots,0,1,\cdots,2^{N-1}-1\}\f$ corresponds to the event,
|
||||
\f$E_l =
|
||||
\begin{cases}
|
||||
x\in\left[-\infty,-L\sigma\right) & l=-2^{N-1}, \\
|
||||
x\in\left[\frac{lL\sigma}{2^{N-1}},\frac{(l+1)L\sigma}{2^{N-1}}\right) & <l>-2^{N-1}, \\
|
||||
x\in\left[L\sigma,\infty\right) & l>-2^{N-1},
|
||||
\end{cases}\f$
|
||||
which occurs with probability
|
||||
\f$\Pr(E_l) =
|
||||
\begin{cases}
|
||||
\mathrm{erfc}(L) & l=-2^{N-1}, \\
|
||||
\mathrm{erfc}(L) & l>-2^{N-1}, \\
|
||||
\f$\Pr(E_l) =
|
||||
\begin{cases}
|
||||
\mathrm{erfc}(L) & l=-2^{N-1}, \\
|
||||
\mathrm{erfc}(L) & l>-2^{N-1}, \\
|
||||
\mathrm{erf}\left(\frac{lL}{2^{N-1}}\right) \mathrm{erfc}\left(\frac{(l-1)L}{2^{N-1}}\right)& l>-2^{N-1}.
|
||||
\end{cases}\f$
|
||||
*/
|
||||
@@ -324,7 +324,7 @@ which occurs with probability
|
||||
|
||||
/** \fn unsigned int *generate_gauss_LUT(unsigned char Nbits,unsigned char L)
|
||||
\brief This routine generates a Gaussian pdf lookup table (LUT). The table has \f$2^{\mathrm{Nbits}-1}\f$ entries which represent
|
||||
the right half of the pdf. The data stored in position \f$i\f$ is actually the scaled cumulative probability distribution,
|
||||
the right half of the pdf. The data stored in position \f$i\f$ is actually the scaled cumulative probability distribution,
|
||||
\f$2^{31}\mathrm{erf}\left(\frac{iL}{2^{N-1}}\right)\f$. This represents the average number of times that the random variable
|
||||
falls in the interval \f$\left[0,\frac{i}{2^{N-1}}\right)\f$. This format allows for rapid conversion of uniform 32-bit
|
||||
random variables to \f$N\f$-bit Gaussian random variables using binary search.
|
||||
@@ -333,18 +333,18 @@ random variables to \f$N\f$-bit Gaussian random variables using binary search.
|
||||
@param L Number of standard deviations in range
|
||||
*/
|
||||
unsigned int *generate_gauss_LUT(unsigned char Nbits,unsigned char L);
|
||||
|
||||
|
||||
/** \fn int gauss(unsigned int *gauss_LUT,unsigned char Nbits);
|
||||
\brief This routine returns a zero-mean unit-variance Gaussian random variable.
|
||||
Given a 32-bit uniform random variable,
|
||||
\f$\mathrm{u}\f$ (from \ref _taus_, we first extract the sign and then search in the monotonically increasing Gaussian LUT for
|
||||
the two entries \f$(i,i+1)\f$ for which
|
||||
\f$ 2^{31}\mathrm{erf}\left(\frac{i}{2^{Nbits-1}}\right) < |u| \leq 2^{31}\mathrm{erf}\left(\frac{i+1}{2^{Nbits-1}}\right) \f$ and assign
|
||||
\brief This routine returns a zero-mean unit-variance Gaussian random variable.
|
||||
Given a 32-bit uniform random variable,
|
||||
\f$\mathrm{u}\f$ (from \ref _taus_, we first extract the sign and then search in the monotonically increasing Gaussian LUT for
|
||||
the two entries \f$(i,i+1)\f$ for which
|
||||
\f$ 2^{31}\mathrm{erf}\left(\frac{i}{2^{Nbits-1}}\right) < |u| \leq 2^{31}\mathrm{erf}\left(\frac{i+1}{2^{Nbits-1}}\right) \f$ and assign
|
||||
the value \f$\mathrm{sgn}(u)i\f$. The search requires at most \f$Nbits-1\f$ comparisons.
|
||||
@see generate_gauss_LUT
|
||||
@see taus
|
||||
@param gauss_LUT pointer to lookup-table
|
||||
@param Nbits number of bits for output variable ( between 1 and 16)
|
||||
@param Nbits number of bits for output variable ( between 1 and 16)
|
||||
*/
|
||||
int gauss(unsigned int *gauss_LUT,unsigned char Nbits);
|
||||
|
||||
@@ -355,12 +355,12 @@ void freq_channel(channel_desc_t *desc,uint16_t nb_rb, int16_t n_samples);
|
||||
void init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples);
|
||||
uint8_t multipath_channel_nosigconv(channel_desc_t *desc);
|
||||
void multipath_tv_channel(channel_desc_t *desc,
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint16_t length,
|
||||
uint8_t keep_channel);
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint16_t length,
|
||||
uint8_t keep_channel);
|
||||
|
||||
/**@} */
|
||||
/**@} */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -32,9 +32,9 @@
|
||||
#include "defs.h"
|
||||
|
||||
|
||||
unsigned int *generate_gauss_LUT(unsigned char Nbits,
|
||||
unsigned char L
|
||||
)
|
||||
unsigned int *generate_gauss_LUT(unsigned char Nbits,
|
||||
unsigned char L
|
||||
)
|
||||
{
|
||||
|
||||
unsigned int *LUT_ptr,i;
|
||||
@@ -43,7 +43,7 @@ unsigned int *generate_gauss_LUT(unsigned char Nbits,
|
||||
assert(LUT_ptr);
|
||||
|
||||
|
||||
for (i=0;i<(1<<(Nbits-1));i++) {
|
||||
for (i=0; i<(1<<(Nbits-1)); i++) {
|
||||
LUT_ptr[i] = (unsigned int)((double)((unsigned int)(1<<31))*erf(i*L/(double)(1<<(Nbits-1))));
|
||||
|
||||
#ifdef LUTDEBUG
|
||||
@@ -52,21 +52,22 @@ unsigned int *generate_gauss_LUT(unsigned char Nbits,
|
||||
}
|
||||
|
||||
return(LUT_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int gauss(unsigned int *gauss_LUT,
|
||||
unsigned char Nbits
|
||||
) {
|
||||
|
||||
int gauss(unsigned int *gauss_LUT,
|
||||
unsigned char Nbits
|
||||
)
|
||||
{
|
||||
|
||||
unsigned int search_pos,step_size,u,tmp,tmpm1,tmpp1,s;
|
||||
|
||||
// Get a 32-bit uniform random-variable
|
||||
u = taus();
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("u = %u\n",u);
|
||||
printf("u = %u\n",u);
|
||||
#endif //DEBUG
|
||||
|
||||
// if it is larger than 2^31 (here negative), save the sign and rescale down to 31-bits.
|
||||
@@ -75,36 +76,35 @@ int gauss(unsigned int *gauss_LUT,
|
||||
u &= 0x7fffffff;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("u = %x,s=%d\n",u,s);
|
||||
#ifdef DEBUG
|
||||
printf("u = %x,s=%d\n",u,s);
|
||||
#endif //DEBUG
|
||||
|
||||
search_pos = (1<<(Nbits-2)); // starting position of the binary search
|
||||
step_size = search_pos;
|
||||
|
||||
|
||||
do {
|
||||
|
||||
step_size >>= 1;
|
||||
|
||||
|
||||
tmp = gauss_LUT[search_pos];
|
||||
tmpm1 = gauss_LUT[search_pos-1];
|
||||
tmpp1 = gauss_LUT[search_pos+1];
|
||||
#ifdef DEBUG
|
||||
printf("search_pos %d, step_size %d: t %x tm %x,tp %x\n",search_pos,step_size,tmp,tmpm1,tmpp1);
|
||||
#endif //DEBUG
|
||||
if (u <= tmp)
|
||||
if (u >tmpm1)
|
||||
return s==0 ? (search_pos-1) : 1-search_pos;
|
||||
|
||||
if (u <= tmp)
|
||||
if (u >tmpm1)
|
||||
return s==0 ? (search_pos-1) : 1-search_pos;
|
||||
else
|
||||
search_pos -= step_size;
|
||||
search_pos -= step_size;
|
||||
else if (u <= tmpp1)
|
||||
return s==0 ? search_pos : - search_pos;
|
||||
else
|
||||
if (u <= tmpp1)
|
||||
return s==0 ? search_pos : - search_pos;
|
||||
else
|
||||
search_pos += step_size;
|
||||
|
||||
}
|
||||
while (step_size > 0);
|
||||
search_pos += step_size;
|
||||
|
||||
} while (step_size > 0);
|
||||
|
||||
// If it gets here we're beyond the positive edge so return max
|
||||
return s==0 ? (1<<(Nbits-1))-1 : 1-((1<<(Nbits-1)));
|
||||
@@ -116,7 +116,8 @@ int gauss(unsigned int *gauss_LUT,
|
||||
|
||||
#define Nhistbits 8
|
||||
|
||||
void main(int argc,char **argv) {
|
||||
void main(int argc,char **argv)
|
||||
{
|
||||
|
||||
unsigned int *gauss_LUT_ptr,i;
|
||||
unsigned int hist[(1<<Nhistbits)];
|
||||
@@ -136,14 +137,16 @@ void main(int argc,char **argv) {
|
||||
// Generate Gaussian LUT 12-bit quantization over 5 standard deviations
|
||||
gauss_LUT_ptr = generate_gauss_LUT(Nbits,L);
|
||||
|
||||
for (i=0;i<(1<<Nhistbits);i++)
|
||||
for (i=0; i<(1<<Nhistbits); i++)
|
||||
hist[i] = 0;
|
||||
|
||||
for (i=0;i<Ntrials;i++) {
|
||||
for (i=0; i<Ntrials; i++) {
|
||||
|
||||
gvar = gauss(gauss_LUT_ptr,Nbits);
|
||||
|
||||
if (gvar == ((1<<(Nbits-1))-1))
|
||||
maxnum++;
|
||||
|
||||
maxg = gvar > maxg ? gvar : maxg;
|
||||
ming = gvar < ming ? gvar : ming;
|
||||
meang += (double)gvar/Ntrials;
|
||||
@@ -156,8 +159,8 @@ void main(int argc,char **argv) {
|
||||
printf("Tail probability = %e(%x)\n",2*erfc((double)L*gauss_LUT_ptr[(1<<(Nbits-1))-1]/(unsigned int)(1<<31)),gauss_LUT_ptr[(1<<(Nbits-1))-1]);
|
||||
printf("max %d, min %d, mean %f, stddev %f, Pr(maxnum)=%e(%d)\n",maxg,ming,meang,sqrt(varg),(double)maxnum/Ntrials,maxnum);
|
||||
|
||||
// for (i=0;i<(1<<Nhistbits);i++)
|
||||
// printf("%d : %u\n",i,hist[i]);
|
||||
// for (i=0;i<(1<<Nhistbits);i++)
|
||||
// printf("%d : %u\n",i,hist[i]);
|
||||
|
||||
free(gauss_LUT_ptr);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -36,81 +36,86 @@
|
||||
|
||||
short max_array(const short *p, unsigned int size)
|
||||
{
|
||||
short max = *p;
|
||||
unsigned int i;
|
||||
short max = *p;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < size; ++i)
|
||||
if (max < p[i])
|
||||
max = p[i];
|
||||
|
||||
return max;
|
||||
for (i = 1; i < size; ++i)
|
||||
if (max < p[i])
|
||||
max = p[i];
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
short min_array(const short *p, unsigned int size)
|
||||
{
|
||||
short min = *p;
|
||||
unsigned int i;
|
||||
short min = *p;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < size; ++i)
|
||||
if (min > p[i])
|
||||
min = p[i];
|
||||
|
||||
return min;
|
||||
for (i = 1; i < size; ++i)
|
||||
if (min > p[i])
|
||||
min = p[i];
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
|
||||
// Note that 'arraySize = 8*((3*8*6144)+12)';
|
||||
// Note that 'arraySize = 8*((3*8*6144)+12)';
|
||||
void dlsch_LLR_quant(const short *llr, const unsigned int arraySize, const short Mlevel, short *llr_quant)
|
||||
{
|
||||
|
||||
unsigned int i, j;
|
||||
short max_llr, min_llr;
|
||||
short llr_interval;
|
||||
float quant_step;
|
||||
float *transLevelArray;
|
||||
|
||||
min_llr = min_array(llr, arraySize);
|
||||
max_llr = max_array(llr, arraySize);
|
||||
llr_interval = (max_llr - min_llr);
|
||||
quant_step = (float)llr_interval / Mlevel;
|
||||
unsigned int i, j;
|
||||
short max_llr, min_llr;
|
||||
short llr_interval;
|
||||
float quant_step;
|
||||
float *transLevelArray;
|
||||
|
||||
min_llr = min_array(llr, arraySize);
|
||||
max_llr = max_array(llr, arraySize);
|
||||
llr_interval = (max_llr - min_llr);
|
||||
quant_step = (float)llr_interval / Mlevel;
|
||||
|
||||
|
||||
if ((Mlevel%2) != 0){
|
||||
printf("Mlevel should be mutiple of 2...\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
transLevelArray = (float *)malloc((Mlevel+1)*sizeof(float));
|
||||
if (!transLevelArray){
|
||||
printf("Cannot allocate memory for transLevelArray...!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for(j=0; j < Mlevel+1; j++){
|
||||
transLevelArray[j] = min_llr + j*quant_step;
|
||||
}
|
||||
if ((Mlevel%2) != 0) {
|
||||
printf("Mlevel should be mutiple of 2...\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
transLevelArray = (float *)malloc((Mlevel+1)*sizeof(float));
|
||||
|
||||
if (!transLevelArray) {
|
||||
printf("Cannot allocate memory for transLevelArray...!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for(j=0; j < Mlevel+1; j++) {
|
||||
transLevelArray[j] = min_llr + j*quant_step;
|
||||
}
|
||||
|
||||
for (i=0; i < arraySize; i++) {
|
||||
for(j=0; j < Mlevel; j++) {
|
||||
if ((transLevelArray[j] <= llr[i]) && (llr[i] <= transLevelArray[j+1])) {
|
||||
llr_quant[i] = (short)(transLevelArray[j] + quant_step/2); // mid-points are selected;
|
||||
break;
|
||||
}
|
||||
|
||||
if (transLevelArray[j+1] <= llr[i]) { // the last term;
|
||||
llr_quant[i] = (short)(transLevelArray[j] + quant_step/2); // mid-points are selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST_DEBUG
|
||||
printf("min_llr: %d : max_llr: %d \n", min_llr, max_llr);
|
||||
printf("llr_interval: %d : quant_step: %f \n", llr_interval, quant_step);
|
||||
printf("transLevelArray = [");
|
||||
|
||||
for(j=0; j < Mlevel+1; j++)
|
||||
printf("%f ", transLevelArray[j]);
|
||||
|
||||
printf("] \n\n");
|
||||
#endif // TEST_DEBUG
|
||||
|
||||
for (i=0; i < arraySize; i++){
|
||||
for(j=0; j < Mlevel; j++){
|
||||
if ((transLevelArray[j] <= llr[i]) && (llr[i] <= transLevelArray[j+1])){
|
||||
llr_quant[i] = (short)(transLevelArray[j] + quant_step/2); // mid-points are selected;
|
||||
break;
|
||||
}
|
||||
if (transLevelArray[j+1] <= llr[i]){ // the last term;
|
||||
llr_quant[i] = (short)(transLevelArray[j] + quant_step/2); // mid-points are selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef TEST_DEBUG
|
||||
printf("min_llr: %d : max_llr: %d \n", min_llr, max_llr);
|
||||
printf("llr_interval: %d : quant_step: %f \n", llr_interval, quant_step);
|
||||
printf("transLevelArray = [");
|
||||
for(j=0; j < Mlevel+1; j++)
|
||||
printf("%f ", transLevelArray[j]);
|
||||
printf("] \n\n");
|
||||
#endif // TEST_DEBUG
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -118,81 +123,82 @@ void dlsch_LLR_quant(const short *llr, const unsigned int arraySize, const short
|
||||
void dlsch_LLR_quant2(const short *llr, const unsigned int arraySize, const short bitsPerLLR, short *llr_quant)
|
||||
{
|
||||
|
||||
unsigned int i;
|
||||
short max_llr, min_llr;
|
||||
short peak_llr;
|
||||
unsigned char shift;
|
||||
|
||||
min_llr = min_array(llr, arraySize);
|
||||
max_llr = max_array(llr, arraySize);
|
||||
|
||||
peak_llr = max(abs(max_llr), abs(min_llr));
|
||||
shift = log2_approx(peak_llr);
|
||||
unsigned int i;
|
||||
short max_llr, min_llr;
|
||||
short peak_llr;
|
||||
unsigned char shift;
|
||||
|
||||
if (bitsPerLLR < 1){
|
||||
printf("Bits per LLR should be greater than 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i=0; i < 6072; i++){
|
||||
llr_quant[i] = llr[i] >> max(0, shift-bitsPerLLR); // quantize the LLRs;
|
||||
llr_quant[i] <<= max(0, shift-bitsPerLLR); // reconstruct the LLRs;
|
||||
printf("[%d] llr: %d : llr_quant %d \n",i, llr[i], llr_quant[i]);
|
||||
}
|
||||
exit(-1);
|
||||
min_llr = min_array(llr, arraySize);
|
||||
max_llr = max_array(llr, arraySize);
|
||||
|
||||
peak_llr = max(abs(max_llr), abs(min_llr));
|
||||
shift = log2_approx(peak_llr);
|
||||
|
||||
if (bitsPerLLR < 1){
|
||||
printf("Bits per LLR should be greater than 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i=0; i < 6072; i++){
|
||||
llr_quant[i] = llr[i] >> max(0, shift-bitsPerLLR); // quantize the LLRs;
|
||||
llr_quant[i] <<= max(0, shift-bitsPerLLR); // reconstruct the LLRs;
|
||||
printf("[%d] llr: %d : llr_quant %d \n",i, llr[i], llr_quant[i]);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
void clearbits(short *llr, const unsigned short startbit, const unsigned short nbits)
|
||||
{
|
||||
|
||||
unsigned short i;
|
||||
|
||||
for (i=0; i < nbits; i++){
|
||||
*llr &= ~(1 << (startbit + i));
|
||||
}
|
||||
unsigned short i;
|
||||
|
||||
for (i=0; i < nbits; i++){
|
||||
*llr &= ~(1 << (startbit + i));
|
||||
}
|
||||
}
|
||||
|
||||
void dlsch_LLR_quant3(const short *llr, const unsigned int arraySize, const short bitsPerLLR, short *llr_quant)
|
||||
{
|
||||
|
||||
unsigned int i;
|
||||
unsigned char shift;
|
||||
unsigned int abs_mean_llr = 0;
|
||||
|
||||
//mean of the LLRs;
|
||||
for(i=0; i < 6072; i++){
|
||||
abs_mean_llr += abs(llr[i]);
|
||||
}
|
||||
abs_mean_llr /= 6072;
|
||||
|
||||
shift = log2_approx(abs_mean_llr);
|
||||
|
||||
printf("abs_mean_llr=%d, shift = %d\n", abs_mean_llr, shift);
|
||||
exit(-1);
|
||||
|
||||
for (i=0; i < 6072; i++){
|
||||
llr_quant[i] = llr[i] >> max(0, shift-bitsPerLLR); // quantize the LLRs;
|
||||
printf("[%d] llr: %d : ", i, llr[i]);
|
||||
//mask the llr_quant values such that their values do not exceed 2^(bitsPerLLR);
|
||||
clearbits(&llr_quant[i], bitsPerLLR, sizeof(short)-bitsPerLLR-1);
|
||||
printf("llr_quant_mask: %d : ", llr_quant[i]);
|
||||
llr_quant[i] <<= max(0, shift-bitsPerLLR); // reconstruct the LLRs;
|
||||
printf("llr_quant: %d \n", llr_quant[i]);
|
||||
|
||||
}
|
||||
}
|
||||
unsigned int i;
|
||||
unsigned char shift;
|
||||
unsigned int abs_mean_llr = 0;
|
||||
|
||||
//mean of the LLRs;
|
||||
for(i=0; i < 6072; i++){
|
||||
abs_mean_llr += abs(llr[i]);
|
||||
}
|
||||
abs_mean_llr /= 6072;
|
||||
|
||||
shift = log2_approx(abs_mean_llr);
|
||||
|
||||
printf("abs_mean_llr=%d, shift = %d\n", abs_mean_llr, shift);
|
||||
exit(-1);
|
||||
|
||||
for (i=0; i < 6072; i++){
|
||||
llr_quant[i] = llr[i] >> max(0, shift-bitsPerLLR); // quantize the LLRs;
|
||||
printf("[%d] llr: %d : ", i, llr[i]);
|
||||
//mask the llr_quant values such that their values do not exceed 2^(bitsPerLLR);
|
||||
clearbits(&llr_quant[i], bitsPerLLR, sizeof(short)-bitsPerLLR-1);
|
||||
printf("llr_quant_mask: %d : ", llr_quant[i]);
|
||||
llr_quant[i] <<= max(0, shift-bitsPerLLR); // reconstruct the LLRs;
|
||||
printf("llr_quant: %d \n", llr_quant[i]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void dlsch_MRC_relay_LLR(const short *llr_quant, const unsigned int arraySize, short *llr_quant_sum){
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i < arraySize; i++){
|
||||
llr_quant_sum[i] += llr_quant[i];
|
||||
}
|
||||
void dlsch_MRC_relay_LLR(const short *llr_quant, const unsigned int arraySize, short *llr_quant_sum)
|
||||
{
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i < arraySize; i++) {
|
||||
llr_quant_sum[i] += llr_quant[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,23 +207,24 @@ void dlsch_MRC_relay_LLR(const short *llr_quant, const unsigned int arraySize,
|
||||
|
||||
void test_llr_quant()
|
||||
{
|
||||
short test[10] = {-1800, -5446, 345, 243, 130, -2111, 433, 4210, -10, -134};
|
||||
short channel_output[10];
|
||||
|
||||
unsigned int i;
|
||||
short test[10] = {-1800, -5446, 345, 243, 130, -2111, 433, 4210, -10, -134};
|
||||
short channel_output[10];
|
||||
|
||||
|
||||
dlsch_LLR_quant(test, 10, 2, channel_output);
|
||||
|
||||
for (i = 0; i < 10; i++){
|
||||
printf("llr: %d : llr_quant %d \n",test[i], channel_output[i]);
|
||||
}
|
||||
unsigned int i;
|
||||
|
||||
|
||||
dlsch_LLR_quant(test, 10, 2, channel_output);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
printf("llr: %d : llr_quant %d \n",test[i], channel_output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
void main()
|
||||
{
|
||||
|
||||
test_llr_quant();
|
||||
test_llr_quant();
|
||||
}
|
||||
|
||||
#endif // TEST_DEBUG
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -34,22 +34,24 @@
|
||||
#include "SIMULATION/RF/defs.h"
|
||||
|
||||
//#define DEBUG_CH
|
||||
uint8_t multipath_channel_nosigconv(channel_desc_t *desc){
|
||||
|
||||
uint8_t multipath_channel_nosigconv(channel_desc_t *desc)
|
||||
{
|
||||
|
||||
random_channel(desc,0);
|
||||
return(1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
#define CHANNEL_SSE
|
||||
#ifdef CHANNEL_SSE
|
||||
void multipath_channel(channel_desc_t *desc,
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel) {
|
||||
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel)
|
||||
{
|
||||
|
||||
int i,ii,j,l;
|
||||
int length1, length2, tail;
|
||||
__m128d rx_tmp128_re_f,rx_tmp128_im_f,rx_tmp128_re,rx_tmp128_im, rx_tmp128_1,rx_tmp128_2,rx_tmp128_3,rx_tmp128_4,tx128_re,tx128_im,ch128_x,ch128_y,pathloss128;
|
||||
@@ -63,61 +65,68 @@ void multipath_channel(channel_desc_t *desc,
|
||||
printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length);
|
||||
#endif
|
||||
|
||||
if (keep_channel) {
|
||||
// do nothing - keep channel
|
||||
} else {
|
||||
random_channel(desc,0);
|
||||
}
|
||||
if (keep_channel) {
|
||||
// do nothing - keep channel
|
||||
} else {
|
||||
random_channel(desc,0);
|
||||
}
|
||||
|
||||
start_meas(&desc->convolution);
|
||||
start_meas(&desc->convolution);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
for (l = 0;l<(int)desc->channel_length;l++) {
|
||||
|
||||
for (l = 0; l<(int)desc->channel_length; l++) {
|
||||
printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
tail = ((int)length-dd)%2;
|
||||
|
||||
if(tail)
|
||||
length1 = ((int)length-dd)-1;
|
||||
else
|
||||
length1 = ((int)length-dd);
|
||||
|
||||
length2 = length1/2;
|
||||
for (i=0;i<length2;i++) { //
|
||||
for (ii=0;ii<desc->nb_rx;ii++) {
|
||||
|
||||
for (i=0; i<length2; i++) { //
|
||||
for (ii=0; ii<desc->nb_rx; ii++) {
|
||||
// rx_tmp.x = 0;
|
||||
// rx_tmp.y = 0;
|
||||
rx_tmp128_re_f = _mm_setzero_pd();
|
||||
rx_tmp128_im_f = _mm_setzero_pd();
|
||||
for (j=0;j<desc->nb_tx;j++) {
|
||||
for (l = 0;l<(int)desc->channel_length;l++) {
|
||||
if ((i>=0) && (i-l)>=0) { //SIMD correct only if length1 > 2*channel_length...which is almost always satisfied
|
||||
// tx.x = tx_sig_re[j][i-l];
|
||||
// tx.y = tx_sig_im[j][i-l];
|
||||
tx128_re = _mm_loadu_pd(&tx_sig_re[j][2*i-l]); // tx_sig_re[j][i-l+1], tx_sig_re[j][i-l]
|
||||
tx128_im = _mm_loadu_pd(&tx_sig_im[j][2*i-l]);
|
||||
}
|
||||
else {
|
||||
//tx.x =0;
|
||||
//tx.y =0;
|
||||
tx128_re = _mm_setzero_pd();
|
||||
tx128_im = _mm_setzero_pd();
|
||||
}
|
||||
ch128_x = _mm_set1_pd(desc->ch[ii+(j*desc->nb_rx)][l].x);
|
||||
ch128_y = _mm_set1_pd(desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
// rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
// rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
rx_tmp128_1 = _mm_mul_pd(tx128_re,ch128_x);
|
||||
rx_tmp128_2 = _mm_mul_pd(tx128_re,ch128_y);
|
||||
rx_tmp128_3 = _mm_mul_pd(tx128_im,ch128_x);
|
||||
rx_tmp128_4 = _mm_mul_pd(tx128_im,ch128_y);
|
||||
rx_tmp128_re = _mm_sub_pd(rx_tmp128_1,rx_tmp128_4);
|
||||
rx_tmp128_im = _mm_add_pd(rx_tmp128_2,rx_tmp128_3);
|
||||
rx_tmp128_re_f = _mm_add_pd(rx_tmp128_re_f,rx_tmp128_re);
|
||||
rx_tmp128_im_f = _mm_add_pd(rx_tmp128_im_f,rx_tmp128_im);
|
||||
} //l
|
||||
|
||||
for (j=0; j<desc->nb_tx; j++) {
|
||||
for (l = 0; l<(int)desc->channel_length; l++) {
|
||||
if ((i>=0) && (i-l)>=0) { //SIMD correct only if length1 > 2*channel_length...which is almost always satisfied
|
||||
// tx.x = tx_sig_re[j][i-l];
|
||||
// tx.y = tx_sig_im[j][i-l];
|
||||
tx128_re = _mm_loadu_pd(&tx_sig_re[j][2*i-l]); // tx_sig_re[j][i-l+1], tx_sig_re[j][i-l]
|
||||
tx128_im = _mm_loadu_pd(&tx_sig_im[j][2*i-l]);
|
||||
} else {
|
||||
//tx.x =0;
|
||||
//tx.y =0;
|
||||
tx128_re = _mm_setzero_pd();
|
||||
tx128_im = _mm_setzero_pd();
|
||||
}
|
||||
|
||||
ch128_x = _mm_set1_pd(desc->ch[ii+(j*desc->nb_rx)][l].x);
|
||||
ch128_y = _mm_set1_pd(desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
// rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
// rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
rx_tmp128_1 = _mm_mul_pd(tx128_re,ch128_x);
|
||||
rx_tmp128_2 = _mm_mul_pd(tx128_re,ch128_y);
|
||||
rx_tmp128_3 = _mm_mul_pd(tx128_im,ch128_x);
|
||||
rx_tmp128_4 = _mm_mul_pd(tx128_im,ch128_y);
|
||||
rx_tmp128_re = _mm_sub_pd(rx_tmp128_1,rx_tmp128_4);
|
||||
rx_tmp128_im = _mm_add_pd(rx_tmp128_2,rx_tmp128_3);
|
||||
rx_tmp128_re_f = _mm_add_pd(rx_tmp128_re_f,rx_tmp128_re);
|
||||
rx_tmp128_im_f = _mm_add_pd(rx_tmp128_im_f,rx_tmp128_im);
|
||||
} //l
|
||||
} // j
|
||||
|
||||
//rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss;
|
||||
//rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss;
|
||||
rx_tmp128_re_f = _mm_mul_pd(rx_tmp128_re_f,pathloss128);
|
||||
@@ -126,12 +135,12 @@ void multipath_channel(channel_desc_t *desc,
|
||||
_mm_storeu_pd(&rx_sig_im[ii][2*i+dd],rx_tmp128_im_f);
|
||||
/*
|
||||
if ((ii==0)&&((i%32)==0)) {
|
||||
printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]);
|
||||
printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]);
|
||||
}
|
||||
*/
|
||||
//rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]);
|
||||
//rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]);
|
||||
|
||||
|
||||
} // ii
|
||||
} // i
|
||||
|
||||
@@ -141,13 +150,14 @@ void multipath_channel(channel_desc_t *desc,
|
||||
|
||||
#else
|
||||
void multipath_channel(channel_desc_t *desc,
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel) {
|
||||
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint32_t length,
|
||||
uint8_t keep_channel)
|
||||
{
|
||||
|
||||
int i,ii,j,l;
|
||||
struct complex rx_tmp,tx;
|
||||
|
||||
@@ -159,47 +169,51 @@ void multipath_channel(channel_desc_t *desc,
|
||||
printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length);
|
||||
#endif
|
||||
|
||||
if (keep_channel) {
|
||||
// do nothing - keep channel
|
||||
} else {
|
||||
random_channel(desc,0);
|
||||
}
|
||||
if (keep_channel) {
|
||||
// do nothing - keep channel
|
||||
} else {
|
||||
random_channel(desc,0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
for (l = 0;l<(int)desc->channel_length;l++) {
|
||||
|
||||
for (l = 0; l<(int)desc->channel_length; l++) {
|
||||
printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
for (i=0;i<((int)length-dd);i++) {
|
||||
for (ii=0;ii<desc->nb_rx;ii++) {
|
||||
for (i=0; i<((int)length-dd); i++) {
|
||||
for (ii=0; ii<desc->nb_rx; ii++) {
|
||||
rx_tmp.x = 0;
|
||||
rx_tmp.y = 0;
|
||||
for (j=0;j<desc->nb_tx;j++) {
|
||||
for (l = 0;l<(int)desc->channel_length;l++) {
|
||||
if ((i>=0) && (i-l)>=0) {
|
||||
tx.x = tx_sig_re[j][i-l];
|
||||
tx.y = tx_sig_im[j][i-l];
|
||||
}
|
||||
else {
|
||||
tx.x =0;
|
||||
tx.y =0;
|
||||
}
|
||||
rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
} //l
|
||||
|
||||
for (j=0; j<desc->nb_tx; j++) {
|
||||
for (l = 0; l<(int)desc->channel_length; l++) {
|
||||
if ((i>=0) && (i-l)>=0) {
|
||||
tx.x = tx_sig_re[j][i-l];
|
||||
tx.y = tx_sig_im[j][i-l];
|
||||
} else {
|
||||
tx.x =0;
|
||||
tx.y =0;
|
||||
}
|
||||
|
||||
rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y);
|
||||
} //l
|
||||
} // j
|
||||
|
||||
rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss;
|
||||
rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss;
|
||||
/*
|
||||
if ((ii==0)&&((i%32)==0)) {
|
||||
printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]);
|
||||
printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]);
|
||||
}
|
||||
*/
|
||||
//rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]);
|
||||
//rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]);
|
||||
|
||||
|
||||
} // ii
|
||||
} // i
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -39,156 +39,169 @@ double frand_a_b(double a, double b);
|
||||
void tv_conv(double complex **h, double complex *x, double complex *y, uint16_t nb_samples, uint8_t nb_taps, int delay);
|
||||
|
||||
void multipath_tv_channel(channel_desc_t *desc,
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint16_t length,
|
||||
uint8_t keep_channel) {
|
||||
|
||||
double complex **tx,**rx,***H_t,*rx_temp;//, *tv_H_t;
|
||||
double **tx_sig_re,
|
||||
double **tx_sig_im,
|
||||
double **rx_sig_re,
|
||||
double **rx_sig_im,
|
||||
uint16_t length,
|
||||
uint8_t keep_channel)
|
||||
{
|
||||
|
||||
double complex **tx,**rx,***H_t,*rx_temp;//, *tv_H_t;
|
||||
double path_loss = pow(10,desc->path_loss_dB/20);
|
||||
int i,j,k,dd;
|
||||
|
||||
dd = abs(desc->channel_offset);
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
printf("[TV CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d max_doppler %d\n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length,desc->max_Doppler);
|
||||
printf("[TV CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d max_doppler %d\n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length,
|
||||
desc->max_Doppler);
|
||||
#endif
|
||||
|
||||
tx = (double complex **)malloc(desc->nb_tx*sizeof(double complex));
|
||||
rx = (double complex **)malloc(desc->nb_rx*sizeof(double complex));
|
||||
|
||||
|
||||
H_t= (double complex ***) malloc(desc->nb_tx*desc->nb_rx*sizeof(double complex **));
|
||||
// tv_H_t = (double complex *) malloc(length*sizeof(double complex));
|
||||
rx_temp= (double complex *) calloc(length,sizeof(double complex));
|
||||
|
||||
for(i=0;i<desc->nb_tx;i++){
|
||||
tx[i] = (double complex *)calloc(length,sizeof(double complex));
|
||||
}
|
||||
|
||||
for(i=0;i<desc->nb_rx;i++){
|
||||
rx[i] = (double complex *)calloc(length,sizeof(double complex));
|
||||
}
|
||||
|
||||
for(i=0;i<desc->nb_tx*desc->nb_rx;i++){
|
||||
H_t[i] = (double complex **) malloc(length*sizeof(double complex *));
|
||||
for(j=0;j<length;j++) {
|
||||
H_t[i][j] = (double complex *) calloc (desc->nb_taps,sizeof(double complex));
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<desc->nb_tx;i++){
|
||||
for(j=0;j<length;j++) {
|
||||
tx[i][j] = tx_sig_re[i][j] +I*tx_sig_im[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
if (keep_channel) {
|
||||
// do nothing - keep channel
|
||||
} else {
|
||||
tv_channel(desc,H_t,length);
|
||||
}
|
||||
|
||||
for(i=0;i<desc->nb_rx;i++){
|
||||
for(j=0;j<desc->nb_tx;j++){
|
||||
tv_conv(H_t[i+(j*desc->nb_rx)],tx[j],rx_temp,length,desc->nb_taps,dd);
|
||||
for(k=0;k<length;k++){
|
||||
rx[i][k] += rx_temp[k];
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<desc->nb_tx; i++) {
|
||||
tx[i] = (double complex *)calloc(length,sizeof(double complex));
|
||||
}
|
||||
|
||||
for(i=0;i<desc->nb_rx;i++){
|
||||
for(j=0;j<length;j++){
|
||||
rx_sig_re[i][j] = creal(rx[i][j])*path_loss;
|
||||
rx_sig_im[i][j] = cimag(rx[i][j])*path_loss;
|
||||
for(i=0; i<desc->nb_rx; i++) {
|
||||
rx[i] = (double complex *)calloc(length,sizeof(double complex));
|
||||
}
|
||||
|
||||
for(i=0; i<desc->nb_tx*desc->nb_rx; i++) {
|
||||
H_t[i] = (double complex **) malloc(length*sizeof(double complex *));
|
||||
|
||||
for(j=0; j<length; j++) {
|
||||
H_t[i][j] = (double complex *) calloc (desc->nb_taps,sizeof(double complex));
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<desc->nb_tx; i++) {
|
||||
for(j=0; j<length; j++) {
|
||||
tx[i][j] = tx_sig_re[i][j] +I*tx_sig_im[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
if (keep_channel) {
|
||||
// do nothing - keep channel
|
||||
} else {
|
||||
tv_channel(desc,H_t,length);
|
||||
}
|
||||
|
||||
for(i=0; i<desc->nb_rx; i++) {
|
||||
for(j=0; j<desc->nb_tx; j++) {
|
||||
tv_conv(H_t[i+(j*desc->nb_rx)],tx[j],rx_temp,length,desc->nb_taps,dd);
|
||||
|
||||
for(k=0; k<length; k++) {
|
||||
rx[i][k] += rx_temp[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<desc->nb_rx; i++) {
|
||||
for(j=0; j<length; j++) {
|
||||
rx_sig_re[i][j] = creal(rx[i][j])*path_loss;
|
||||
rx_sig_im[i][j] = cimag(rx[i][j])*path_loss;
|
||||
}
|
||||
}
|
||||
|
||||
/* for(k=0;k<length;k++) {
|
||||
tv_H_t[k] = H_t[0][k][0];
|
||||
}*/
|
||||
|
||||
for(i=0;i<desc->nb_tx;i++){
|
||||
free(tx[i]);
|
||||
for(i=0; i<desc->nb_tx; i++) {
|
||||
free(tx[i]);
|
||||
}
|
||||
|
||||
free(tx);
|
||||
for(i=0;i<desc->nb_rx;i++) {
|
||||
free(rx[i]);
|
||||
|
||||
for(i=0; i<desc->nb_rx; i++) {
|
||||
free(rx[i]);
|
||||
}
|
||||
|
||||
free(rx);
|
||||
|
||||
for(i=0;i<desc->nb_rx*desc->nb_tx;i++){
|
||||
for(j=0;j<length;j++){
|
||||
free(H_t[i][j]);
|
||||
}
|
||||
free(H_t[i]);
|
||||
|
||||
for(i=0; i<desc->nb_rx*desc->nb_tx; i++) {
|
||||
for(j=0; j<length; j++) {
|
||||
free(H_t[i][j]);
|
||||
}
|
||||
|
||||
free(H_t[i]);
|
||||
}
|
||||
|
||||
free(H_t);
|
||||
|
||||
|
||||
free(rx_temp);
|
||||
}
|
||||
|
||||
//TODO: make phi_rad a parameter of this function
|
||||
void tv_channel(channel_desc_t *desc,double complex ***H,uint16_t length){
|
||||
|
||||
void tv_channel(channel_desc_t *desc,double complex ***H,uint16_t length)
|
||||
{
|
||||
|
||||
int i,j,p,l,k;
|
||||
double *alpha,*phi_rad,pi=acos(-1),*w_Hz;
|
||||
|
||||
|
||||
alpha = (double *)calloc(desc->nb_paths,sizeof(double));
|
||||
phi_rad = (double *)calloc(desc->nb_paths,sizeof(double));
|
||||
w_Hz = (double *)calloc(desc->nb_paths,sizeof(double));
|
||||
|
||||
for(i=0;i<desc->nb_paths;i++) {
|
||||
w_Hz[i]=desc->max_Doppler*cos(frand_a_b(0,2*pi));
|
||||
phi_rad[i]=frand_a_b(0,2*pi);
|
||||
|
||||
for(i=0; i<desc->nb_paths; i++) {
|
||||
w_Hz[i]=desc->max_Doppler*cos(frand_a_b(0,2*pi));
|
||||
phi_rad[i]=frand_a_b(0,2*pi);
|
||||
}
|
||||
|
||||
if(desc->ricean_factor == 1){
|
||||
for(i=0;i<desc->nb_paths;i++) {
|
||||
alpha[i]=1/sqrt(desc->nb_paths);
|
||||
}
|
||||
}
|
||||
else {
|
||||
alpha[0]=sqrt(desc->ricean_factor/(desc->ricean_factor+1));
|
||||
for(i=1;i<desc->nb_paths;i++) {
|
||||
alpha[i] = (1/sqrt(desc->nb_paths-1))*(sqrt(1/(desc->ricean_factor+1)));
|
||||
}
|
||||
|
||||
if(desc->ricean_factor == 1) {
|
||||
for(i=0; i<desc->nb_paths; i++) {
|
||||
alpha[i]=1/sqrt(desc->nb_paths);
|
||||
}
|
||||
} else {
|
||||
alpha[0]=sqrt(desc->ricean_factor/(desc->ricean_factor+1));
|
||||
|
||||
for(i=1; i<desc->nb_paths; i++) {
|
||||
alpha[i] = (1/sqrt(desc->nb_paths-1))*(sqrt(1/(desc->ricean_factor+1)));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// This is the code when we only consider a SISO case
|
||||
for(i=0;i<length;i++)
|
||||
{
|
||||
for(j=0;j<desc->nb_taps;j++)
|
||||
{
|
||||
for(p=0;p<desc->nb_paths;p++)
|
||||
{
|
||||
H[i][j] += sqrt(desc->amps[j]/2)*alpha[p]*cexp(-I*(2*pi*w_Hz[p]*i*(1/(desc->BW*1e6))+phi_rad[p]));
|
||||
}
|
||||
}
|
||||
for(j=0;j<desc->nb_taps;j++)
|
||||
{
|
||||
for(p=0;p<desc->nb_paths;p++)
|
||||
{
|
||||
H[i][j] += sqrt(desc->amps[j]/2)*alpha[p]*cexp(-I*(2*pi*w_Hz[p]*i*(1/(desc->BW*1e6))+phi_rad[p]));
|
||||
}
|
||||
}
|
||||
}
|
||||
for(j=0;j<desc->nb_paths;j++)
|
||||
for(j=0;j<desc->nb_paths;j++)
|
||||
{
|
||||
phi_rad[j] = fmod(2*pi*w_Hz[j]*(length-1)*(1/desc->BW)+phi_rad[j],2*pi);
|
||||
phi_rad[j] = fmod(2*pi*w_Hz[j]*(length-1)*(1/desc->BW)+phi_rad[j],2*pi);
|
||||
}
|
||||
*/
|
||||
|
||||
// if MIMO
|
||||
for (i=0;i<desc->nb_rx;i++){
|
||||
for(j=0;j<desc->nb_tx;j++){
|
||||
for(k=0;k<length;k++){
|
||||
for(l=0;l<desc->nb_taps;l++){
|
||||
H[i+(j*desc->nb_rx)][k][l] = 0;
|
||||
for(p=0;p<desc->nb_paths;p++){
|
||||
H[i+(j*desc->nb_rx)][k][l] += sqrt(desc->amps[l]/2)*alpha[p]*cexp(I*(2*pi*w_Hz[p]*k*(1/(desc->BW*1e6))+phi_rad[p]));
|
||||
}
|
||||
}
|
||||
}
|
||||
for(j=0;j<desc->nb_paths;j++){
|
||||
phi_rad[j] = fmod(2*pi*w_Hz[j]*(length-1)*(1/desc->BW)+phi_rad[j],2*pi);
|
||||
for (i=0; i<desc->nb_rx; i++) {
|
||||
for(j=0; j<desc->nb_tx; j++) {
|
||||
for(k=0; k<length; k++) {
|
||||
for(l=0; l<desc->nb_taps; l++) {
|
||||
H[i+(j*desc->nb_rx)][k][l] = 0;
|
||||
|
||||
for(p=0; p<desc->nb_paths; p++) {
|
||||
H[i+(j*desc->nb_rx)][k][l] += sqrt(desc->amps[l]/2)*alpha[p]*cexp(I*(2*pi*w_Hz[p]*k*(1/(desc->BW*1e6))+phi_rad[p]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(j=0; j<desc->nb_paths; j++) {
|
||||
phi_rad[j] = fmod(2*pi*w_Hz[j]*(length-1)*(1/desc->BW)+phi_rad[j],2*pi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(alpha);
|
||||
@@ -196,19 +209,22 @@ for(j=0;j<desc->nb_paths;j++)
|
||||
free(phi_rad);
|
||||
}
|
||||
|
||||
// time varying convolution
|
||||
void tv_conv(double complex **h, double complex *x, double complex *y, uint16_t nb_samples, uint8_t nb_taps, int dd) {
|
||||
|
||||
// time varying convolution
|
||||
void tv_conv(double complex **h, double complex *x, double complex *y, uint16_t nb_samples, uint8_t nb_taps, int dd)
|
||||
{
|
||||
|
||||
int i,j;
|
||||
for(i=0;i<((int)nb_samples-dd);i++) {
|
||||
for(j=0;j<nb_taps;j++) {
|
||||
if(i>j)
|
||||
y[i+dd] += creal(h[i][j])*creal(x[i-j])-cimag(h[i][j])*cimag(x[i-j]) + I*(creal(h[i][j])*cimag(x[i-j])+cimag(h[i][j])*creal(x[i-j]));
|
||||
|
||||
}
|
||||
|
||||
for(i=0; i<((int)nb_samples-dd); i++) {
|
||||
for(j=0; j<nb_taps; j++) {
|
||||
if(i>j)
|
||||
y[i+dd] += creal(h[i][j])*creal(x[i-j])-cimag(h[i][j])*cimag(x[i-j]) + I*(creal(h[i][j])*cimag(x[i-j])+cimag(h[i][j])*creal(x[i-j]));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double frand_a_b(double a, double b){
|
||||
return (rand()/(double)RAND_MAX)*(b-a)+a;
|
||||
double frand_a_b(double a, double b)
|
||||
{
|
||||
return (rand()/(double)RAND_MAX)*(b-a)+a;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -32,12 +32,12 @@
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
static unsigned int seed, iy, ir[98];
|
||||
/*
|
||||
@defgroup _uniformdouble
|
||||
@defgroup _uniformdouble
|
||||
@ingroup numerical Uniform linear congruential random number generator.
|
||||
*/
|
||||
|
||||
@@ -50,24 +50,24 @@ static unsigned int seed, iy, ir[98];
|
||||
void randominit(unsigned seed_init)
|
||||
{
|
||||
int i;
|
||||
// this need to be integrated with the existing rng, like taus: navid
|
||||
// this need to be integrated with the existing rng, like taus: navid
|
||||
msg("Initializing random number generator, seed %x\n",seed_init);
|
||||
|
||||
if (seed_init == 0) {
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
seed = (unsigned int) rand();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
seed = seed_init;
|
||||
}
|
||||
|
||||
|
||||
if (seed % 2 == 0) seed += 1; /* seed and mod are relative prime */
|
||||
for (i=1; i<=97; i++)
|
||||
{
|
||||
seed = a*seed; /* mod 2**32 */
|
||||
ir[i]= seed; /* initialize the shuffle table */
|
||||
|
||||
for (i=1; i<=97; i++) {
|
||||
seed = a*seed; /* mod 2**32 */
|
||||
ir[i]= seed; /* initialize the shuffle table */
|
||||
}
|
||||
|
||||
iy=1;
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ void randominit(unsigned seed_init)
|
||||
|
||||
double uniformrandom(void)
|
||||
{
|
||||
#define a 1664525lu
|
||||
#define mod 4294967296.0 /* is 2**32 */
|
||||
#define a 1664525lu
|
||||
#define mod 4294967296.0 /* is 2**32 */
|
||||
|
||||
int j;
|
||||
|
||||
@@ -88,8 +88,8 @@ double uniformrandom(void)
|
||||
}
|
||||
|
||||
/*
|
||||
@defgroup _gaussdouble Gaussian random number generator based on modified Box-Muller transformation.
|
||||
@ingroup numerical
|
||||
@defgroup _gaussdouble Gaussian random number generator based on modified Box-Muller transformation.
|
||||
@ingroup numerical
|
||||
*/
|
||||
|
||||
/*!\brief Gaussian random number generator based on modified Box-Muller transformation.Returns a double-precision floating-point number. */
|
||||
@@ -100,31 +100,34 @@ double gaussdouble(double mean, double variance)
|
||||
static double gset;
|
||||
double fac,r,v1,v2;
|
||||
|
||||
if (iset == 0){
|
||||
do{
|
||||
v1 = 2.0*uniformrandom()-1.0;
|
||||
v2 = 2.0*uniformrandom()-1.0;
|
||||
r = v1*v1+v2*v2;
|
||||
} while (r >= 1.0);
|
||||
fac = sqrt(-2.0*log(r)/r);
|
||||
gset= v1*fac;
|
||||
iset=1;
|
||||
return(sqrt(variance)*v2*fac + mean);
|
||||
if (iset == 0) {
|
||||
do {
|
||||
v1 = 2.0*uniformrandom()-1.0;
|
||||
v2 = 2.0*uniformrandom()-1.0;
|
||||
r = v1*v1+v2*v2;
|
||||
} while (r >= 1.0);
|
||||
|
||||
fac = sqrt(-2.0*log(r)/r);
|
||||
gset= v1*fac;
|
||||
iset=1;
|
||||
return(sqrt(variance)*v2*fac + mean);
|
||||
} else {
|
||||
iset=0;
|
||||
return(sqrt(variance)*gset + mean);
|
||||
iset=0;
|
||||
return(sqrt(variance)*gset + mean);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef MAIN
|
||||
main(int argc,char **argv) {
|
||||
main(int argc,char **argv)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
randominit();
|
||||
for (i=0;i<10;i++) {
|
||||
|
||||
for (i=0; i<10; i++) {
|
||||
printf("%f\n",gaussdouble(0.0,1.0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,39 +14,39 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
double R22_sqrt[6][32] = {
|
||||
{0.921700, -0.000000, 0.010380, -0.027448, -0.250153, 0.294754, 0.005961, 0.010769, 0.010380, 0.027448, 0.921700, 0.000000, -0.011595, -0.004130, -0.250153, 0.294754, -0.250153, -0.294754, -0.011595, 0.004130, 0.921700, 0.000000, 0.010380, -0.027448, 0.005961, -0.010769, -0.250153, -0.294754, 0.010380, 0.027448, 0.921700, 0.000000},
|
||||
{0.923810, 0.000000, 0.004069, 0.027832, 0.151730, 0.350180, -0.009882, 0.006114, 0.004069, -0.027832, 0.923810, 0.000000, 0.011218, -0.003029, 0.151730, 0.350180, 0.151730, -0.350180, 0.011218, 0.003029, 0.923810, -0.000000, 0.004069, 0.027832, -0.009882, -0.006114, 0.151730, -0.350180, 0.004069, -0.027832, 0.923810, 0.000000},
|
||||
{0.927613, 0.000000, 0.014253, 0.025767, -0.061171, -0.367133, 0.009258, -0.007340, 0.014253, -0.025767, 0.927613, -0.000000, -0.011138, -0.003942, -0.061171, -0.367133, -0.061171, 0.367133, -0.011138, 0.003942, 0.927613, 0.000000, 0.014253, 0.025767, 0.009258, 0.007340, -0.061171, 0.367133, 0.014253, -0.025767, 0.927613, 0.000000},
|
||||
{0.869794, -0.000000, -0.010613, -0.001218, 0.399115, 0.289852, -0.004464, -0.004096, -0.010613, 0.001218, 0.869794, -0.000000, -0.005276, -0.002978, 0.399115, 0.289852, 0.399115, -0.289852, -0.005276, 0.002978, 0.869794, -0.000000, -0.010613, -0.001218, -0.004464, 0.004096, 0.399115, -0.289852, -0.010613, 0.001218, 0.869794, 0.000000},
|
||||
{0.919726, -0.000000, 0.038700, -0.111146, 0.217804, 0.300925, 0.045531, -0.013659, 0.038700, 0.111146, 0.919726, 0.000000, -0.027201, 0.038983, 0.217804, 0.300925, 0.217804, -0.300925, -0.027201, -0.038983, 0.919726, 0.000000, 0.038700, -0.111146, 0.045531, 0.013659, 0.217804, -0.300925, 0.038700, 0.111146, 0.919726, 0.000000},
|
||||
{0.867608, -0.000000, 0.194097, -0.112414, -0.418811, 0.095938, -0.081264, 0.075727, 0.194097, 0.112414, 0.867608, -0.000000, -0.106125, -0.032801, -0.418811, 0.095938, -0.418811, -0.095938, -0.106125, 0.032801, 0.867608, 0.000000, 0.194097, -0.112414, -0.081264, -0.075727, -0.418811, -0.095938, 0.194097, 0.112414, 0.867608, 0.000000},
|
||||
{0.921700, -0.000000, 0.010380, -0.027448, -0.250153, 0.294754, 0.005961, 0.010769, 0.010380, 0.027448, 0.921700, 0.000000, -0.011595, -0.004130, -0.250153, 0.294754, -0.250153, -0.294754, -0.011595, 0.004130, 0.921700, 0.000000, 0.010380, -0.027448, 0.005961, -0.010769, -0.250153, -0.294754, 0.010380, 0.027448, 0.921700, 0.000000},
|
||||
{0.923810, 0.000000, 0.004069, 0.027832, 0.151730, 0.350180, -0.009882, 0.006114, 0.004069, -0.027832, 0.923810, 0.000000, 0.011218, -0.003029, 0.151730, 0.350180, 0.151730, -0.350180, 0.011218, 0.003029, 0.923810, -0.000000, 0.004069, 0.027832, -0.009882, -0.006114, 0.151730, -0.350180, 0.004069, -0.027832, 0.923810, 0.000000},
|
||||
{0.927613, 0.000000, 0.014253, 0.025767, -0.061171, -0.367133, 0.009258, -0.007340, 0.014253, -0.025767, 0.927613, -0.000000, -0.011138, -0.003942, -0.061171, -0.367133, -0.061171, 0.367133, -0.011138, 0.003942, 0.927613, 0.000000, 0.014253, 0.025767, 0.009258, 0.007340, -0.061171, 0.367133, 0.014253, -0.025767, 0.927613, 0.000000},
|
||||
{0.869794, -0.000000, -0.010613, -0.001218, 0.399115, 0.289852, -0.004464, -0.004096, -0.010613, 0.001218, 0.869794, -0.000000, -0.005276, -0.002978, 0.399115, 0.289852, 0.399115, -0.289852, -0.005276, 0.002978, 0.869794, -0.000000, -0.010613, -0.001218, -0.004464, 0.004096, 0.399115, -0.289852, -0.010613, 0.001218, 0.869794, 0.000000},
|
||||
{0.919726, -0.000000, 0.038700, -0.111146, 0.217804, 0.300925, 0.045531, -0.013659, 0.038700, 0.111146, 0.919726, 0.000000, -0.027201, 0.038983, 0.217804, 0.300925, 0.217804, -0.300925, -0.027201, -0.038983, 0.919726, 0.000000, 0.038700, -0.111146, 0.045531, 0.013659, 0.217804, -0.300925, 0.038700, 0.111146, 0.919726, 0.000000},
|
||||
{0.867608, -0.000000, 0.194097, -0.112414, -0.418811, 0.095938, -0.081264, 0.075727, 0.194097, 0.112414, 0.867608, -0.000000, -0.106125, -0.032801, -0.418811, 0.095938, -0.418811, -0.095938, -0.106125, 0.032801, 0.867608, 0.000000, 0.194097, -0.112414, -0.081264, -0.075727, -0.418811, -0.095938, 0.194097, 0.112414, 0.867608, 0.000000},
|
||||
};
|
||||
double R21_sqrt[6][8] = {
|
||||
{0.922167, 0.000000,-0.250280, 0.294903,-0.250280, -0.294903,0.922167, 0.000000},
|
||||
{0.924238, 0.000000,0.151801, 0.350342,0.151801, -0.350342,0.924238, 0.000000},
|
||||
{0.928080, 0.000000,-0.061202, -0.367318,-0.061202, 0.367318,0.928080, 0.000000},
|
||||
{0.869860, 0.000000,0.399145, 0.289874,0.399145, -0.289874,0.869860, 0.000000},
|
||||
{0.927225, 0.000000,0.219580, 0.303378,0.219580, -0.303378,0.927225, 0.000000},
|
||||
{0.896133, 0.000000,-0.432581, 0.099092,-0.432581, -0.099092,0.896133, 0.000000},
|
||||
{0.922167, 0.000000,-0.250280, 0.294903,-0.250280, -0.294903,0.922167, 0.000000},
|
||||
{0.924238, 0.000000,0.151801, 0.350342,0.151801, -0.350342,0.924238, 0.000000},
|
||||
{0.928080, 0.000000,-0.061202, -0.367318,-0.061202, 0.367318,0.928080, 0.000000},
|
||||
{0.869860, 0.000000,0.399145, 0.289874,0.399145, -0.289874,0.869860, 0.000000},
|
||||
{0.927225, 0.000000,0.219580, 0.303378,0.219580, -0.303378,0.927225, 0.000000},
|
||||
{0.896133, 0.000000,-0.432581, 0.099092,-0.432581, -0.099092,0.896133, 0.000000},
|
||||
};
|
||||
double R12_sqrt[6][8] = {
|
||||
{0.999494, 0.000000,0.011256, -0.029765,0.011256, 0.029765,0.999494, 0.000000},
|
||||
{0.999537, 0.000000,0.004402, 0.030114,0.004402, -0.030114,0.999537, 0.000000},
|
||||
{0.999497, 0.000000,0.015358, 0.027764,0.015358, -0.027764,0.999497, 0.000000},
|
||||
{0.999925, -0.000000,-0.012201, -0.001400,-0.012201, 0.001400,0.999925, 0.000000},
|
||||
{0.991912, 0.000000,0.041738, -0.119870,0.041738, 0.119870,0.991912, 0.000000},
|
||||
{0.968169, 0.000000,0.216594, -0.125443,0.216594, 0.125443,0.968169, 0.000000},
|
||||
{0.999494, 0.000000,0.011256, -0.029765,0.011256, 0.029765,0.999494, 0.000000},
|
||||
{0.999537, 0.000000,0.004402, 0.030114,0.004402, -0.030114,0.999537, 0.000000},
|
||||
{0.999497, 0.000000,0.015358, 0.027764,0.015358, -0.027764,0.999497, 0.000000},
|
||||
{0.999925, -0.000000,-0.012201, -0.001400,-0.012201, 0.001400,0.999925, 0.000000},
|
||||
{0.991912, 0.000000,0.041738, -0.119870,0.041738, 0.119870,0.991912, 0.000000},
|
||||
{0.968169, 0.000000,0.216594, -0.125443,0.216594, 0.125443,0.968169, 0.000000},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
@@ -14,15 +14,15 @@
|
||||
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,
|
||||
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@eurecom.fr
|
||||
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
@@ -47,7 +47,8 @@ unsigned int s0, s1, s2, b;
|
||||
*/
|
||||
//
|
||||
|
||||
unsigned int taus(void) {
|
||||
unsigned int taus(void)
|
||||
{
|
||||
|
||||
b = (((s0 << 13) ^ s0) >> 19);
|
||||
s0 = (((s0 & 0xFFFFFFFE) << 12)^ b);
|
||||
@@ -58,7 +59,8 @@ unsigned int taus(void) {
|
||||
return s0 ^ s1 ^ s2;
|
||||
}
|
||||
|
||||
void set_taus_seed(unsigned int seed_init) {
|
||||
void set_taus_seed(unsigned int seed_init)
|
||||
{
|
||||
|
||||
#ifdef USER_MODE
|
||||
struct drand48_data buffer;
|
||||
@@ -66,11 +68,10 @@ void set_taus_seed(unsigned int seed_init) {
|
||||
#endif
|
||||
|
||||
if (seed_init == 0) {
|
||||
s0 = (unsigned int)time(NULL);
|
||||
s1 = (unsigned int)time(NULL);
|
||||
s2 = (unsigned int)time(NULL);
|
||||
}
|
||||
else {
|
||||
s0 = (unsigned int)time(NULL);
|
||||
s1 = (unsigned int)time(NULL);
|
||||
s2 = (unsigned int)time(NULL);
|
||||
} else {
|
||||
#ifndef USER_MODE
|
||||
s0 = (unsigned int)0x1e23d852;
|
||||
s1 = (unsigned int)0x81f38a1c;
|
||||
@@ -90,13 +91,14 @@ void set_taus_seed(unsigned int seed_init) {
|
||||
|
||||
#ifdef MAIN
|
||||
|
||||
main() {
|
||||
main()
|
||||
{
|
||||
|
||||
unsigned int i,rand;
|
||||
|
||||
set_taus_seed();
|
||||
|
||||
for (i=0;i<10;i++){
|
||||
for (i=0; i<10; i++) {
|
||||
|
||||
rand = taus();
|
||||
printf("%u\n",rand);
|
||||
@@ -105,5 +107,5 @@ main() {
|
||||
}
|
||||
#endif //MAIN
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user