⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ofdm.c

📁 OFDM系统的C语言程序
💻 C
字号:
// ---------------------------------------------
//                   参数定义                    
// ---------------------------------------------
#include   <stdio.h>   
#include   <stdlib.h>   
#include   <time.h>
#include   <complex>

// 变量初始化
int NumLoop = 500;
int NumSubc = 128;
int NumCP = 8;
int SyncDelay = 0;
//-----------------------------------------------
// 子载波数            128
// 位数/ 符号          2
// 符号数/ 载波        500
// 训练符号数          0
// 循环前缀长度        8   (1/16)*T
// 调制方式            4-QAM
// 多径信道数          3 
// IFFT Size           128 
// 信道最大时延        2
//-----------------------------------------------

// --------------------------------------------- 
//                      QAM 调制                 
// --------------------------------------------- 
// 产生随机二进制输入数据
        
void 
data_in()   
  {   
  long   int   p;   
  int   i;   
  char   datatmp=0;
  int   BitsTx[64000]={0};
  for   (i=0;i<NumLoop*NumSubc;i++)   
  {   
  p=rand();   
  if   (p/16383<1)   {datatmp=0;}   //p是随机数,如果小于阈值(式中为16383)
  else 
  {
	  datatmp=1;
  } 
  BitsTx[i]=datatmp;    
  }     
  }

//将二进制数据转化为极性数据
//void
//bin2pol()
//{
//	for (i=0;i<64000;i++)
//		if (datatmp[i]==0)
//			data[i]=-1;
//		else
//			data[i]=1;
//}

//调整数组
void
data_reshape()
{
	int BitsTx[64000];
	int QAM_tmp[2][32000]={0};
	int i;
	for(j=0;j<32000;j++)
	{
		for(k=0;k<2;k++)
		{
			QAM_tmp[k][j]=BitsTx[i];
			i++;
		}
	}


// 调制 (产生 QAM 符号->s/p)
// 输入: BitsTx[NumLoop*NumSubc]; 输出: SymQAM(NumLoop,NumSubc/2)
//void
//data_QAM()
//{
//	int    BitsTxtmp1[32000]={0};
//	int    BitsTxtmp2[32000]={0};
//	int    BitsTxtmp[128][500];
  //  int    j,k;
	//int    i=0;
//	int    BitsTx[64000];
//	for   (k=0;k<128;k++)
//   {
//     for   (j=0;j<500;j++)
//         BitsTxtmp[k][j]=BitsTx[i];
//	 i++;
//   }
//}
//SymQAMtmptmp = bi2de(SymQAMtmp,2,'left-msb');?

// QAM 调制
void
QAM_mod()
{
	int k;
	int j=0;
	int Bits_tmp[2][32000];
	typedef complex<float> SymQAM[32000];
	for (k=0;k<32000;k++)
	{
    if
	((BitsTxtmp[j][k]==0)&(BitsTxtmp[j+1][k]==0))
	SymQAM[k]=1+i;
	if
	((BitsTxtmp[j][k]==0)&(BitsTxtmp[j+1][k]==1))
	SymQAM[k]=-1+i;
    if
	((BitsTxtmp[j][k]==1)&(BitsTxtmp[j+1][k]==0))
	SymQAM[k]=-1-i;
	if
	((BitsTxtmp[j][k]==1)&(BitsTxtmp[j+1][k]==1))
	SymQAM[k]=1-i;
	}
}


// --------------------------------------------- 
//                   IFFT                        
// --------------------------------------------- 
// 输入: SymQAM[NumLoop][NumSubc/2]; 输出: SymIFFT[NumSubc][NumLoop]
int l=1;
int n=32000;
void
Sym_fft(double ifft_in_real[], double ifft__in_imag[], int n, int k, double ifft_out_real[], double ifft_out_image[], int l)
{
// 入口参数: 
// l: l = 0, 傅立叶变换; l = 1, 逆傅立叶变换
// il: il = 0,不计算傅立叶变换或逆变换模和幅角;il = 1,计算模和幅角
// n: 输入的点数,为偶数,一般为32,64,128,...,1024等
// k: 满足n=2^k(k>0),实质上k是n个采样数据可以分解为偶次幂和奇次幂的次数
// ifft_in_real[]: l=0时,存放N点采样数据的实部
// l=1时, 存放傅立叶变换的N个实部
// double ifft__in_imag[]: l=0时,存放N点采样数据的虚部 
// l=1时, 存放傅立叶变换的N个虚部
//
// 出口参数:
// ifft_out_real: l=0, 返回傅立叶变换的实部
// l=1, 返回逆傅立叶变换的实部
// ifft_out_image: l=0, 返回傅立叶变换的虚部
// l=1, 返回逆傅立叶变换的虚部
// pr[]: il = 1,i = 0 时,返回傅立叶变换的模
// il = 1,i = 1 时,返回逆傅立叶变换的模
// pi[]: il = 1,i = 0 时,返回傅立叶变换的辐角
// il = 1,i = 1 时,返回逆傅立叶变换的辐角
int it,m,is,i,j,nv,l0;
double p,q,s,vr,vi,poddr,poddi;
for (it=0;it<=n-1;it++)
{
	m=it;
	is=0;
	for(i=0;i<=k-1;i++)
	{
		j=m/2;
		is=2*is+(m-2*j);
		m=j;
	}
	fr[it]=pr[is];
	fi[it]=pi[is];
}
//----------------------------
ifft_in_real[0]=1.0;
ifft__in_imag[0]=0.0;
p=6.283185306/(1.0*n);
pr[1]=cos(p);
pi[1]=-sin(p);
if (l!=0)
pi[1]=-pi[1];
for (i=2;i<=n-1;i++)
{
	p=pr[i-1]*pr[1];
	q=pi[i-1]*pi[1];
	s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
	pr[i]=p-q;
	pi[i]=s-p-q;
}
for (it=0;it<=n-2;it=it+2)
{
	vr=fr[it];
	vi=fi[it];
	fr[it]=vr+fr[it+1];
	fi[it]=vi+fi[it+1];
	fr[it+1]=vr-fr[it+1];
	fi[it+1]=vi-fi[it+1];
}
m=n/2;
nv=2;
for (l0=k-2;l0>=0;l0--)
{
	m=m/2;
	nv=2*nv;
	for(it=0;it<=(m-1)*nv;it=it+nv)
		for (j=0;j<=(nv/2)-1;j++)
		{
			p=pr[m*j]*fr[it+j+nv/2];
			q=pi[m*j]*fi[it+j+nv/2];
			s=pr[m*j]+pi[m*j];
			s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
			poddr=p-q;
			poddi=s-p-q;
			fr[it+j+nv/2]=fr[it+j]-poddr;
			fi[it+j+nv/2]=fi[it+j]-poddi;
			fr[it+j]=fr[it+j]+poddr;
			fi[it+j]=fi[it+j]+poddi;
		}
}
if(l!=0)
for(i=0;i<=n-1;i++)
{
	fr[i]=fr[i]/(1.0*n);
	fi[i]=fi[i]/(1.0*n);
}
if(il!=0)
for(i=0;i<=n-1;i++)
{
	pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
	if(fabs(fr[i])<0.000001*fabs(fi[i]))
	{
		if ((fi[i]*fr[i])>0)
			pi[i] = 90.0;
		else
			pi[i] = -90.0;
	}
	else
		pi[i] = atan(fi[i]/fr[i])*360.0/6.283185306;
}
return;
}

//char SymIFFT[NumSubc][NumLoop] = 0;
//SymIFFTtmp = reshape(SymQAM,NumSubc/2,NumLoop);
//SymIFFTtmptmp = zeros(NumSubc,NumLoop);
//SymIFFTtmptmp(1,:) = real(SymIFFTtmp(1,:)); % 实数
//SymIFFTtmptmp(NumSubc/2+1,:) = imag(SymIFFTtmp(1,:)); % 实数
// 这么安排矩阵的目的是为了构造共轭对称矩阵
// 共轭对称矩阵的特点是 在ifft/fft的矢量上 N点的矢量
// 在0,N/2点必须是实数 一般选为0
// 1至N/2点 与 (N/2)+1至N-1点关于N/2共轭对称

//SymIFFTtmptmp(2:NumSubc/2,:) = SymIFFTtmp(2:NumSubc/2,:);
//SymIFFTtmptmp((NumSubc/2+2):NumSubc,:) = flipdim(conj(SymIFFTtmp(2:NumSubc/2,:)),1);
//%--------------------------------------------------------------------------
//% 函数说明:
//% B = flipdim(A,dim) returns A with dimension dim flipped.
//%/ When the value of dim is 1, the array is flipped row-wise down. When dim is 2,
//% the array is flipped columnwise left to right. flipdim(A,1) is the same as
//% flipud(A), and flipdim(A,2) is the same as fliplr(A).
//%--------------------------------------------------------------------------
//%  >> a = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
//%  a =
//%      1     2     3
//%      4     5     6
//%      7     8     9
//%     10    11    12
//%  >> b = flipdim(a,1)
//%  b =
//%     10    11    12
//%      7     8     9
//%      4     5     6
//%      1     2     3

//SymIFFT = ifft(SymIFFTtmptmp,NumSubc,1);
  
// --------------------------------------------- 
//                   循环前缀                 
// --------------------------------------------- 
// 输入: SymIFFT[NumSubc][NumLoop]; 输出: SymCP[NumAddPrefix][NumLoop]
void
Data_CP()
{
	int NumAddPrefix;
	int RowPrefix;
	NumAddPrefix=NumSubc+NumCP;
	int SymCP[NumAddPrefix][NumLoop]=0;
	for (RowPrefix=NumSubc-NumCP+1;RowPrefix<=NumSubc;RowPrefix++;)
		SymCP[NumAddPrefix][NumLoop]=SymIFFT[RowPrefix][NumLoop];
}

// --------------------------------------------- 
//                    通过信道            
// --------------------------------------------- 
// input: SymCP(NumSubc + NumCP,NumLoop); output: SymCh(1,(NumSubc + NumCP)*NumLoop)
// 输入:SymCP[NumAddPrefix][NumLoop];输出:SymCP[1][NumAddPrefix*NumLoop]
//SymCh = zeros(1,(NumSubc + NumCP)*NumLoop);
void
Data_ch()
{
	int SymCh[1][NumAddPrefix*NumLoop]=0;
	int SymChtmp[1][NumAddPrefix*NumLoop]=0;
	int SymChtmptmp[1][NumAddPrefix*NumLoop]=0;
	int i;
	int j=1;
	for (i=1;i<=NumAddPrefix*NumLoop;i++)
	{
		SymChtmp[j][1]=SymCP[1][NumAddPrefix*NumLoop];
		j++;
	}
//SymChtmp = SymCP(:).';   % 进行这个转置操作之后就成了一个矢量
//                         % 相当于把矩阵的列向量依次排列 改变为一个行向量
//Ch = [1 1/2 1/4];
	Ch=[1 1/2 1/4];
}
//SymChtmptmp = filter(Ch,1,SymChtmp);
//%--------------------------------------------------------------------------
//% 函数说明:
//% Firlter data with an infinite impulse response (IIR) or finite impulse response
//% (FIR) filter
//% y = filter(b,a,X) filters the data in vector X with the filter described by
//% numerator coefficient vector b and denominator coefficient vector a. If a(1) is
//% not equal to 1, filter normalizes the filter coefficients by a(1). If a(1) equals
//% 0, filter returns an error.
//%--------------------------------------------------------------------------
//% If X is a matrix, filter operates on the columns of X. If X is a multidimensional
//% array, filter operates on the first nonsingleton dimension.
//%-------------------------------------------------------------------------

// 添加AWGN?
//BerSnrTable = zeros(20,3);
//for snr=0:19;  % = SNR + 10*log10(log2(2));
//   BerSnrTable(snr+1,1) = snr;
//SymCh = awgn(SymChtmptmp,snr,'measured');
//%--------------------------------------------------------------------------
//% 函数说明:
//%  AWGN Add white Gaussian noise to a signal.
//%     Y = AWGN(X,SNR) adds white Gaussian noise to X.  The SNR is in dB.
//%     The power of X is assumed to be 0 dBW.  If X is complex, then 
//%     AWGN adds complex noise.
//%  ------------------------------------------------------------------------
//% 
//%     Y = AWGN(X,SNR,SIGPOWER) when SIGPOWER is numeric, it represents 
//%     the signal power in dBW. When SIGPOWER is 'measured', AWGN measures
//%     the signal power before adding noise.
//%U.p5h.{.f8M.b0% ------------------------------------------------------------------------- 
//%     Y = AWGN(X,SNR,SIGPOWER,STATE) resets the state of RANDN to STATE.
//%  
//%     Y = AWGN(..., POWERTYPE) specifies the units of SNR and SIGPOWER.
//%i.?#B0T0%     POWERTYPE can be 'db' or 'linear'.  If POWERTYPE is 'db', then SNR
//%     is measured in dB and SIGPOWER is measured in dBW.  If POWERTYPE is
//%     'linear', then SNR is measured as a ratio and SIGPOWER is measured
//%     in Watts.
//%  
//%     Example: To specify the power of X to be 0 dBW and add noise to produce
//%              an SNR of 10dB, use:
//%              X = sqrt(2)*sin(0:pi/8:6*pi);
//%              Y = AWGN(X,10,0);
//%  
//%     Example: To specify the power of X to be 0 dBW, set RANDN to the
//%     1234th
//%              state and add noise to produce an SNR of 10dB, use:
//%              X = sqrt(2)*sin(0:pi/8:6*pi);
//%              Y = AWGN(X,10,0,1234);
//%  
//%     Example: To specify the power of X to be 3 Watts and add noise to
//%              produce a linear SNR of 4, use:
//%              X = sqrt(2)*sin(0:pi/8:6*pi);
//%              Y = AWGN(X,4,3,'linear');
//%     Example: To cause AWGN to measure the power of X, set RANDN to the 
//%              1234th state and add noise to produce a linear SNR of 4, use:
//%              X = sqrt(2)*sin(0:pi/8:6*pi);
//%              Y = AWGN(X,4,'measured',1234,'linear');

// --------------------------------------------- 
//                  移除保护间隔             
// --------------------------------------------- 
// input: SymCh(1,(NumSubc + NumCP)*NumLoop); output: SymDeCP(NumSubc,NumLoop)
// 输入:SymCh[NumAddPrefix*NumLoop];输出:SymDeCP[NumSubc][NumLoop]
//SymDeCP = zeros(NumSubc,NumLoop);
void
Data_deCP()
{

int SymDeCP[NumSubc][NumLoop]=0;
int SymDeCPtmp[NumSubc][NumLoop]=0;
int i,j;
int k=0;
for (i=1;i<=NumLoop;i++)
{
	for(j=1;j<=NumAddPrefix;j++)
	{
       SymDeCPtmp[j][i]=SymCh[k];
	   k++;
	}
SymDeCp[NumSubc][NumLoop]=SymDeCPtmp[NumSubc][Loop];
}
//SymDeCPtmp = reshape(SymCh,NumAddPrefix,NumLoop);
//SymDeCP = SymDeCPtmp((NumCP+1+SyncDelay):NumAddPrefix+SyncDelay,:);

// --------------------------------------------- 
//                     FFT                       
// --------------------------------------------- 
/* 采样来的数据放在dataR[ ]数组中,运算前dataI[ ]数组初始化为0 */ 
void FFT(float dataR[],float dataI[])
{
	int x0,x1,x2,x3,x4,x5,x6; 
    int L,j,k,b,p; 
    float TR,TI,temp; 
/********** following code invert sequence ************/ 
    for(i=0;i<128;i++)
	{ 
		x0=x1=x2=x3=x4=x5=x6=0;
		x0=i&0x01;
		x1=(i/2)&0x01;
		x2=(i/4)&0x01;
		x3=(i/8)&0x01;
		x4=(i/16)&0x01;
		x5=(i/32)&0x01;
		x6=(i/64)&0x01;
		xx=x0*64+x1*32+x2*16+x3*8+x4*4+x5*2+x6;
		dataI[xx]=dataR[i];
	}
	for(i=0;i<128;i++)
	{
		dataR[i]=dataI[i];
		dataI[i]=0; 
	} 
/************** following code FFT *******************/ 
for(L=1;L<=7;L++)
{/* for(1) */
	b=1;
	i=L-1; 
while(i>0)
{
	b=b*2;
	i--;
}/*b=2^(L-1)*/ 
for(j=0;j<=b-1;j++)/*for(2)*/ 
{
	p=1;
	i=7-L; 
while(i>0)/*p=pow(2,7-L)*j;*/ 
{
	p=p*2;
	i--;
} 
p=p*j; 
for(k=j;k<128;k=k+2*b)/*for(3)*/ 
{
	TR=dataR[k];
	TI=dataI[k];
	temp=dataR[k+b];
	dataR[k]=dataR[k]+dataR[k+b]*cos_tab[p]+dataI[k+b]*sin_tab[p];
	dataI[k]=dataI[k]-dataR[k+b]*sin_tab[p]+dataI[k+b]*cos_tab[p];
	dataR[k+b]=TR-dataR[k+b]*cos_tab[p]-dataI[k+b]*sin_tab[p];
	dataI[k+b]=TI+temp*sin_tab[p]-dataI[k+b]*cos_tab[p];
} /* END for (3) */ 
} /* END for (2) */ 
} /* END for (1) */ 
for(i=0;i<32;i++){ /* 只需要32次以下的谐波进行分析 */ 
w[i]=sqrt(dataR[i]*dataR[i]+dataI[i]*dataI[i]); 
w[i]=w[i]/64
} 
w[0]=w[0]/2; 
} /* END FFT */  
//SymFFT = fft(SymDeCP,NumSubc,1);

// --------------------------------------------- 
//              判决(包括QAM解码)           
// --------------------------------------------- 
// SymFFT(NumSubc,NumLoop); output: SymDec(NumSubc,NumLoop)
// 输入:SymFFT[NumSubc][NumLoop];输出:SymDec[NumSubc][NumLoop]
//SymDec = zeros(NumSubc,NumLoop);
void
Data_Dec()
{

int SymDec[NumSubc][NumLoop]=0;
//SymEqtmp(1,:) = SymFFT(1,:)+i*SymFFT(NumSubc/2+1,:);?
//SymEqtmp(2:NumSubc/2,:) = SymFFT(2:NumSubc/2,:);?
for (m=1;m<=NumLoop;m++)
{
    for (n=1;n<=NumSubc/2;n++)
	{
        Real = real(SymEqtmp(n,m));
        Imag = imag(SymEqtmp(n,m));       
        if( abs((Real -1)) < abs((Real +1)))
           SymDec[2*n-1][m]=1;
        else
            SymDec[2*n-1][m]=0;
	

        if( abs((Imag -1)) < abs((Imag +1  )) )  
            SymDec[2*n][m]=1;
        else
            SymDec[2*n][m]=0;
	}
}



//            误码率
void
Data_err()
{

int BitsRx[NumSubc*NumLoop]=0;
int i;
int j=1;
int k=1;
int m=0;
int n;
for (i=1;i<=NumLoop;i++)
{
	for(k=1;k<=NumSubc;k++)
	{
		BitsRx[j] = SymDec[k][i];
		j++;
	}
for (j=1;j<=NumSubc*NumLoop;j++)
if (BitsTx[j]!=BitsRx)
m++;
n=m/(NumSubc*NumLoop)*100%;
printf('%d',m);
printf('%d',n);
}

// --------------------------------------------- 
//                   The END                     
// --------------------------------------------- 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -