%
% ofdm97.m
%
% 仿真主要完成OFDM系统建模,实现OFDM系统传输流程,
% 并对OFDM信号的时域波形及功率普密度进行分析.
clear;clc;
%********************** 参数设定部分 ***************************
bitrate = 64; % 系统传输速率
Tu =1; % 一个OFDM信号中有用信号持续时间[S],1/Tu为OFDM信号中子载波的间隔
Tp = 0; % 一个OFDM信号中循环前缀持续时间[S]
Tg =0; % 总保护间隔长度[S]
nf =330; % 一帧设定的OFDM符号
ml =4; % 映射类别:BPSK=1,QPSK=2,16QAM=4,64QAM=6
over=16; % 过采样倍数
NFFT =16; % FFT点数
A = 1; % 形成OFDM信号的成形脉冲幅度[V]
fp = 25; % 载频
% fs =80; % 采样频率
% ts = 1/fs; % 采样间隔
%----------------------主要参数计算--------------------------------------
nb = bitrate*(Tu+Tp); % 一个符号所需传送的bit数:64比特
numcarrier = nb/ml; % 子载波数
numbits = nb*nf; % 一帧的bit数
%--------------------------------------------------------------------------
tc = Tu / NFFT; % 一个切普持续时间1.0000e-007
ncp = floor(Tp/tc); % Number of tones of the cyclic prefix:8
n = (-ncp+1:1:NFFT);
N = length(n); % Total number of tones per symbol:40
%--------------------------------------------------------------------------
if ncp>0
tc = (Tu+Tp)/N ; % Tone duration
end
%************************** 发射部分 **************************************
%**************************************************************************
% 数据产生
%**************************************************************************
ge_bits=randint(1,numbits); % 产生二进制数据流
%**************************************************************************
% 星座点映射
%**************************************************************************
S =mapping(ge_bits,ml);
%**************************************************************************
% 串并转换
%**************************************************************************
para_S = reshape(S,numcarrier,nf); % 串并转换
%*************************************************************************
% IFFT变换
%*************************************************************************
%----------------------插零满足IFFT变换长度---------------------------------
%---------------------------第一种插零方式----------------------------------
para_S0 = zeros(NFFT,nf);
up1 = floor(numcarrier/2);
down1 = numcarrier-up1;
para_S0(1:up1,:) = para_S(1:up1,:);
para_S0(NFFT-down1+1:NFFT,:) = para_S(numcarrier-down1+1:numcarrier,:);
%---------------------------第二种插零方式----------------------------------
% para_S1 = zeros(2*numcarrier,nf);
% para_S0=zeros(2*numcarrier,nf);
% for a=1:nf
% para_S0(1,a)=real(para_S(1,a));
% para_S0(17,a)=imag(para_S(1,a));
% para_S0(2:16,a)=para_S(2:end,a);
% para_S0(32:-1:18,a)=conj(para_S(2:end,a));
% end
%------------------------四倍过采样-----------------------------------------
up2 = floor(NFFT/2);
down2 = NFFT-up2;
FS = over*NFFT; %FS=32
FS_cp =over*(ncp+NFFT); %FS_cp=40
ifftlen = nf*FS_cp; %ifftlen=20000
paras_cp=zeros(FS_cp,nf);
for b = 1:nf %循环说明一个一个发送符号
ch = para_S0(:,b);
C_zp = zeros(FS,1); %4倍过采样中间补0(zero padding)
C_zp(1:up2)=ch(1:up2);
C_zp(FS-down2+1:FS)=ch(NFFT-down2+1:NFFT);
%------------------------IFFT-----------------------------------------
C = ifft(C_zp,FS); % IFFT of the zero-padded input
C = sqrt(FS)*C;
%**************************************************************************
% 插入CP
%**************************************************************************
if ncp>0
C_cp=zeros(length(C)+over*ncp,1);
C_cp(1:(over*ncp))=C(over*NFFT-(over*ncp)+1:over*NFFT);
C_cp(over*ncp+1:length(C_cp))=C;
else
C_cp=C;
end
paras_cp(:,b)=C_cp(:);
end
% %**************************************************************************
% % 信号加窗与并串转换
% %**************************************************************************
% beta=0.1; %滚降系数
% T_cp=Tu+Tp; %一个OFDM符号持续时间
% df=FS_cp/(T_cp); %160000000Hz:信号的采样速率
% postfix=floor(beta*(T_cp)*df); %循环后缀中的采样点数,ncp为循环前缀的采样点数
% nflen=FS_cp+postfix; % 加窗后一个OFDM符号的采样点数
% %ifftlen = nf*FS_cp; %ifftlen=160*nf
% temp=zeros(nflen,nf);
% seridata=zeros(1,(ifftlen+postfix));
% %temp1=zeros(1,(ifftlen+postfix));
% ws=zeros(nflen,nf);
% %tt1 = linspace (0,beta*T_cp,postfix);
% %w1 = 0.5+0.5*cos(pi+tt1*pi./(beta*T_cp));
% %tt2=linspace(beta*T_cp,T_cp,(nflen-postfix));
% %w2=1;
% %tt3=linspace(T_cp,(T_cp+beta*T_cp),postfix);
% %w3 = 0.5+0.5*cos((tt3-T_cp)*pi./(beta*T_cp));
% for c=1:nf
% temp(1:FS_cp,c)=paras_cp(:,c);
% temp((FS_cp+1):nflen,c)=paras_cp((over*ncp+1):(over*ncp+postfix),c);
% tt1 = linspace((c-1)*T_cp,(beta+c-1)*T_cp,postfix);
% w1 = 0.5+0.5*cos(pi+tt1*pi./(beta*T_cp));
% tt2=linspace((beta+c-1)*T_cp,c*T_cp,(nflen-postfix));
% w2=1;
% tt3=linspace(c*T_cp,(beta+c)*T_cp,postfix);
% w3 = 0.5+0.5*cos((tt3-T_cp)*pi./(beta*T_cp));
% ws(1:postfix,c)=temp(1:postfix,c).*w1.';
% ws(postfix+1:nflen-postfix,c)=temp(postfix+1:nflen-postfix,c).*w2.';
% ws(nflen-postfix+1:nflen,c)=temp(nflen-postfix+1:nflen,c).*w3.'; %ws=zeros(nflen,nf),加窗后OFDM符号的采样点数
% end
% for d=1:nf
% temp1=zeros(1,(ifftlen+postfix));
% temp1((d-1)*FS_cp+1:(d-1)*FS_cp+nflen)=ws(:,d);
% seridata=seridata+temp1; %得到加窗后nf个OFDM符号的串行数据采样点数
% temp1=zeros(1,(ifftlen+postfix));
% end
%
% %**************************************************************************
% % 并串转换
% %**************************************************************************
%
% Stx_data=seridata;
% %**************************************************************************
% % 并串转换
% %**************************************************************************
Stx_data2=reshape(paras_cp,ifftlen,1);
Stx_data=Stx_data2.';
%--------------------------------------------------------------------------
t3 = linspace (0,nf*(Tu+Tg),ifftlen); %时域波形
%figure
%plot(t3,real(Stx_data))
% X = xlabel('Time [S]');
% Y = ylabel('Amplitude [V]');
% title('一帧基带OFDM信号同相分量波形')
df=FS_cp/(Tu+Tp); %10000000Hz
[PSD2,frequency2] = cp_PSD(Stx_data,df); %频域波形(功率普密度)
%figure
%plot(frequency2,10*log10(PSD2))
% X = xlabel('Frequency [Hz]');
% Y = ylabel('PSD [dB]');
% title('一帧基带OFDM符号的功率普密度')
%Stx_data=zeros(1,length(Stx_data));
%**************************************************************************
% 上变频
%**************************************************************************
t=linspace(0,nf*(Tu+Tg),length(Stx_data));
%[Stx_ofdm] = modulation(Stx_data,t,fp);
Stx_ofdm=Stx_data.*exp(j*2*pi*fp*t);
%Stx_ofdm=Stx_data;
%**************************************************************************
% 加性高斯白噪声信道
%**************************************************************************
snrdb=0;
Ec=sum(abs(Stx_ofdm).^2)./length(Stx_ofdm);
ecn = 10.^(snrdb/10);
noise_var = sqrt(Ec/(2*ecn));
[Rx_data] = add_whitenoise2(Stx_ofdm,noise_var);
%*************************************************************************
% 接收信号检测部分
%**************************************************************************
redata=Stx_data;
redata1=redata-mean(redata);