📄 common.c
字号:
/***********************************
*Copyright (C) 2004 FUTURE@NCRL SEU
*All Rights Reserved.
*FileName: _COMMON_H_
*Abstract: Used for GMC System.
*Cue.Ver : V4.0
*Author : Bin Jiang
*Date : 2004-06-02
*Modify : New detector:
SIC with spatial domain filter.
*Pre.Ver : V3.0
*Author : Bin Jiang
*Date : 2004-04-08
*Modify : Add multi-carrier modulation.
*Pre.Ver : V2.0
*Author : Bin Jiang
*Date : 2004-03-25
*Modify : (1) Change the structure of detector.
(2) Improve the channel estimation.
*Pre.Ver : V1.2
*Author : Bin Jiang
*Date : 2003-12-24
*Ref. : Matlab Program.
*************************************/
#include "common.h"
//----------------------------------------------------------------------
//----------------------_COMPLEX_C_-------------------------------------
//----------------------------------------------------------------------
//Compute the energy of a.
double eng_cmx(COMPLEX a)
{
double result;
result = pow(a.real,2)+pow(a.image,2);
return result;
}
//Compute the norm of a .
double abs_cmx(COMPLEX a)
{
double result;
result = sqrt( pow(a.real,2)+pow(a.image,2) );
return result;
}
//Compute the conjugate of a .
COMPLEX conj_cmx(COMPLEX a)
{
COMPLEX b;
b.real = a.real;
b.image = -1*a.image;
return b;
}
//Add two complex a and b.
COMPLEX add_cmx(COMPLEX a, COMPLEX b)
{
COMPLEX result;
result.real = a.real + b.real;
result.image = a.image + b.image;
return result;
}
//Subtract complex b from a.
COMPLEX sub_cmx(COMPLEX a, COMPLEX b)
{
COMPLEX result;
result.real = a.real - b.real;
result.image = a.image - b.image;
return result;
}
//Multiple complexs a and b.
COMPLEX mul_cmx(COMPLEX a, COMPLEX b)
{
COMPLEX result;
result.real = a.real*b.real - a.image*b.image;
result.image = a.real*b.image + a.image*b.real;
return result;
}
//Multiple complex a with a real b.
COMPLEX mul_cmxreal(COMPLEX a, double b)
{
COMPLEX result;
result.real = a.real*b;
result.image = a.image*b;
return result;
}
//Divide complex a by real b.
COMPLEX div_cmxreal(COMPLEX a, double b)
{
COMPLEX result;
result.real = a.real/b;
result.image = a.image/b;
return result;
}
//Divide complex a by complex b.
COMPLEX div_cmx(COMPLEX a, COMPLEX b)
{
COMPLEX result;
double denominator = pow(b.real,2)+pow(b.image,2);
result.real = (a.real*b.real + a.image*b.image)/denominator;
result.image = (a.image*b.real - a.real*b.image)/denominator;
return result;
}
/* END _COMPLEX_C_ */
//----------------------------------------------------------------------
//----------------------_RANDOM_C_--------------------------------------
//----------------------------------------------------------------------
long s1,s2;
/*Generate a uniform random number between 0 and 1.*/
double random_source()
{
long z,k;
k = s1 / 53668L;
s1 = 40014L * (s1 - k * 53668L) - k * 12211L;
if(s1 < 0)
s1 = s1 + 2147483563L;
k = s2 / 52774;
s2 = 40692L * (s2 - k * 52774L) - k * 3791L;
if(s2 < 0)
s2 = s2 + 2147483399L;
z = s1 - s2;
if(z < 1)
z = z + 2147483562L;
return (double) z / (double) 2147483563.0;
}
/*Generate a uniform random number between -1 and 1. */
double generate_random_source()
{
double sign;
if(random_source() >= 0.5)
sign = -1.0;
else
sign = 1.0;
return sign * random_source();
}
/*Generate a random number 0 and 1 with p0=p1=0.5.*/
int generate_binary_source()
{
if(random_source() < 0.5)
return 0;
else
return 1;
}
/*Generate a gaussian random with 0 mean sigma2 variance. */
double generate_gaussian_source(double sigma2)
{
static int iset = 0; /* It save the last value. */
static double gset;
double fac,r,v1,v2;
if(iset == 0)
{
do
{
v1 = generate_random_source();
v2 = generate_random_source();
r = v1 * v1 + v2 * v2;
}while(r >= 1.0 || r == 0.0);
fac = sqrt(-2.0 * sigma2 * log(r) / r);
gset = v1 * fac;
iset = 1;
return (double)(v2 * fac);
}
else
{
iset = 0;
return (double)(gset);
}
}
/* END _RANDOM_C_ */
//----------------------------------------------------------------------
//----------------------_INTERLEAVER_C_---------------------------------
//----------------------------------------------------------------------
//Generate a uniform random number between 0 and 1
double s_random_source(long *s1, long *s2)
{
long z,k;
k = (*s1) / 53668L;
(*s1) = 40014L * ((*s1) - k * 53668L) - k * 12211L;
if((*s1) < 0)
{
(*s1) += 2147483563L;
}
k = (*s2) / 52774;
(*s2) = 40692L * ((*s2) - k * 52774L) - k * 3791L;
if((*s2) < 0)
{
(*s2) += 2147483399L;
}
z = (*s1) - (*s2);
if(z < 1)
{
z += 2147483562L;
}
return (double) z / (double) 2147483563.0;
}
//Generate interleaver table by S-interleaver.
void s_inter_generate(int N, int S, int *inter_index, long ss1, long ss2)
{
int i,temp;
int bit1,flag;
int *index;
long *s1,*s2;
s1 = &ss1;
s2 = &ss2;
index = (int *)malloc(N*2*sizeof(int));
if (index == NULL)
{
printf("not enough memery to alloc!\n");
exit(0);
}
/* initialise all the array at -1 */
for (i=0; i<N; i++)
{
index[i*2+0]=-1;
index[i*2+1]=-1;
}
for (i=0; i<N; i++)
{
do
{
flag = 0;
/* generate a random number between 0 and (N-1) */
bit1=(int)(s_random_source(s1,s2)*(double) N);
if (i>0)
{
/* check if two consecutive bits are at more than S */
temp=index[(i-1)*2+1]-bit1;
if (temp<0)
temp = -temp;
if (temp>=S)
flag = 1;
/* check the condition 2 of the interleaver */
if (i>3)
{
temp = index[(i-4)*2+1]-bit1;
if (temp<0)
temp = -temp;
if ((temp!=4) && (flag==1))
flag = 1;
else
flag = 0;
}
}
else
{
flag = 1;
}
}while ( (index[bit1*2+0]!=-1) || (flag==0) );
/* fill the results array if all the conditions are true */
index[bit1*2+0] = 0;
index[i*2+1] = bit1;
inter_index[i] = index[i*2+1];
}
free(index);
}
void s_interleave_int(int * p_block, int N, int * p_InlvTable)
{
int i;
int * p_interleaved_block;
p_interleaved_block = (int *)malloc(N*sizeof(int));
for(i=0; i<N; i++)
{
*(p_interleaved_block+i) = *(p_block+(*(p_InlvTable+i)));
}
for(i=0; i<N; i++)
{
*(p_block+i) = *(p_interleaved_block+i);
}
free(p_interleaved_block);
}
void s_interleave_double(double * p_block, int N, int * p_InlvTable)
{
int i;
double * p_interleaved_block;
p_interleaved_block = (double *)malloc(N*sizeof(double));
for(i=0; i<N; i++)
{
p_interleaved_block[i] = p_block[p_InlvTable[i]];
}
for(i=0; i<N; i++)
{
p_block[i] = p_interleaved_block[i];
}
free(p_interleaved_block);
}
void s_deinterleave_double(double * p_block, int N, int * p_InlvTable)
{
int i;
double * p_deinterleaved_block;
p_deinterleaved_block = (double *)malloc(N*sizeof(double));
for(i=0; i<N; i++)
{
p_deinterleaved_block[p_InlvTable[i]] = p_block[i];
}
for(i=0; i<N; i++)
{
p_block[i] = p_deinterleaved_block[i];
}
free(p_deinterleaved_block);
}
/* END _INTERLEAVER_C_ */
//----------------------------------------------------------------------
//----------------------_MAP_C_-----------------------------------------
//----------------------------------------------------------------------
int GrayMapQAM(int * inBit, int bitlength, COMPLEX * outSymbol, int ModType)
{
int i;
int inpos = 0;
int outpos = 0;
int con_site_r = 0;
int con_site_i = 0;
int M;
double GrayMapQAM[64];
if(bitlength%ModType)
{
puts("Wrong bit length for QAM modulation!");
return -1;
}
switch(ModType)
{
case 2:
GrayMapQAM[0] = -1/sqrt(2); GrayMapQAM[1] = 1/sqrt(2);
break;
case 4:
GrayMapQAM[0] = -1/sqrt(10); GrayMapQAM[1] = -3/sqrt(10);
GrayMapQAM[2] = 1/sqrt(10); GrayMapQAM[3] = 3/sqrt(10);
break;
case 6:
GrayMapQAM[0] = -3/sqrt(42); GrayMapQAM[1] = -1/sqrt(42);
GrayMapQAM[2] = -5/sqrt(42); GrayMapQAM[3] = -7/sqrt(42);
GrayMapQAM[4] = 3/sqrt(42); GrayMapQAM[5] = 1/sqrt(42);
GrayMapQAM[6] = 5/sqrt(42); GrayMapQAM[7] = 7/sqrt(42);
break;
case 8:
GrayMapQAM[0] = -5/sqrt(170); GrayMapQAM[1] = -7/sqrt(170);
GrayMapQAM[2] = -3/sqrt(170); GrayMapQAM[3] = -1/sqrt(170);
GrayMapQAM[4] = -11/sqrt(170); GrayMapQAM[5] = -9/sqrt(170);
GrayMapQAM[6] = -13/sqrt(170); GrayMapQAM[7] = -15/sqrt(170);
GrayMapQAM[8] = 5/sqrt(170); GrayMapQAM[9] = 7/sqrt(170);
GrayMapQAM[10] = 3/sqrt(170); GrayMapQAM[11] = 1/sqrt(170);
GrayMapQAM[12] = 11/sqrt(170); GrayMapQAM[13] = 9/sqrt(170);
GrayMapQAM[14] = 13/sqrt(170); GrayMapQAM[15] = 15/sqrt(170);
break;
default:
printf("Wrong modulation Type, only support 4QAM, 16QAM, 64QAM, 256QAM!");
return -1;
}
M = ModType/2;
while(inpos<bitlength)
{
con_site_r = 0;
con_site_i = 0;
for(i=0; i<M; i++)
{
if( *(inBit+inpos) ) con_site_r += (1<<(M-1-i));
inpos++;
}
for(i=0; i<M; i++)
{
if( *(inBit+inpos) ) con_site_i += (1<<(M-1-i));
inpos++;
}
(outSymbol+outpos)->real = GrayMapQAM[con_site_r];
(outSymbol+outpos)->image = GrayMapQAM[con_site_i];
outpos++;
}
return outpos;
}
int SoftDemod16QAM(COMPLEX * p_x_Intf, int n_IntfLen, double * p_x_Sigma, double * p_Rou, double * p_CodedBitLLR)
{
int i;
int n_TxAntenna;
int n_SupDomain;
int LenPerTx = n_IntfLen/TxANTENNA_NUM;
double mui;
double sigma2i;
double LLR1,LLR2,LLR3,LLR4;
double Xi,Yi;
double * p_oldLLR;
p_oldLLR = (double *)malloc(TxANTENNA_NUM*LenPerTx*4*sizeof(double));
for(i=0; i<TxANTENNA_NUM*LenPerTx*4; i++)
{
*(p_oldLLR+i) = *(p_CodedBitLLR+i);
}
for(n_TxAntenna=0; n_TxAntenna<TxANTENNA_NUM; n_TxAntenna++)
{
for(n_SupDomain=0; n_SupDomain<MAXSUPDOM; n_SupDomain++)
{
mui = p_Rou[n_SupDomain*TxANTENNA_NUM+n_TxAntenna];
for(i=SUP_DOM[n_SupDomain]; i<SUP_DOM[n_SupDomain+1]; i++)
{
Xi = p_x_Intf[n_TxAntenna*LenPerTx+i].real;
Yi = p_x_Intf[n_TxAntenna*LenPerTx+i].image;
sigma2i = p_x_Sigma[n_TxAntenna*LenPerTx+i];
/* First bit */
LLR1 = -pow( (Xi - 1/sqrt(10)*mui), 2 )/sigma2i - 0.5*(p_oldLLR[(n_TxAntenna*LenPerTx+i)*4+1]);
LLR2 = -pow( (Xi - 3/sqrt(10)*mui), 2 )/sigma2i + 0.5*(p_oldLLR[(n_TxAntenna*LenPerTx+i)*4+1]);
LLR3 = -pow( (Xi + 1/sqrt(10)*mui), 2 )/sigma2i - 0.5*(p_oldLLR[(n_TxAntenna*LenPerTx+i)*4+1]);
LLR4 = -pow( (Xi + 3/sqrt(10)*mui), 2 )/sigma2i + 0.5*(p_oldLLR[(n_TxAntenna*LenPerTx+i)*4+1]);
// SoftDetOut = [ SoftDetOut (log((exp(LLR1)+exp(LLR2))/(exp(LLR3)+exp(LLR4)))) ];
p_CodedBitLLR[(n_TxAntenna*LenPerTx+i)*4+0] //= max(LLR1, LLR2) - max(LLR3, LLR4);
//= log((exp(LLR1)+exp(LLR2))/(exp(LLR3)+exp(LLR4)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -