📄 v06_03_dem_2up_arrange.m
字号:
wtp(1:Max_symbols)=0;
wtpp(1:Max_symbols)=0;
wnAp=0.05; % 信道幅度响应跟踪的环路带宽
SsAp=0.7;
fAp=1;
G1Ap=2*wnAp*SsAp;
G2Ap=wnAp.^2/fAp;
KsAp=1;
wtAp(1:Max_symbols)=0;
wtAp2(1:Max_symbols)=0;
% 读取发送的数据,与解调出来的数据进行比较
% 这是发送端调制在各个子载波上的原始符号,将解调出来的符号跟其比较可进行误符号率测试
fid=fopen('OFDM_mod_original_data_I_ser_2up_sam_50.dat','r');
Imapped_temp=fscanf(fid,'%f');
Imapped=Imapped_temp';
st=fclose(fid);
fid=fopen('OFDM_mod_original_data_Q_ser_2up_sam_50.dat','r');
Qmapped_temp=fscanf(fid,'%f');
Qmapped=Qmapped_temp';
st=fclose(fid);
% 误符号率测试参数设置
counts_I_error=0;
counts_Q_error=0;
counts_I_total=0;
counts_Q_total=0;
% ------------------------------------------------------------------------------------
% 测试参数设置
error_f_test = -1*0.2/(2*(Nfft)*2); % 模拟加入的频偏量
phase_channel_test(1:256) = 0; % 模拟加入的信道相位响应
Ap_channel_test(1:256) = 1; % 模拟加入的信道幅度响应
phase0 = 0; % 模拟加入的初始相位
% ------------------------------------------------------------------------------------
% 读取接收到的i,q两路参数
% 是用malab程序生成的2倍上采样的OFDM时域信号,共50个符号
fidi=fopen('OFDM_mod_I_ser_2up_sam_50.dat','r');
fidq=fopen('OFDM_mod_Q_ser_2up_sam_50.dat','r');
% ------------------------------------------------------------------------------------
% 解调部分
%for s_no = 1:Max_symbols
for s_no = 1:48
% 加入一定的高斯白噪声
% 这里matlab函数加入噪声的信噪比与实际的信噪比有一个换算关系
% SNR(实际)=SNR(这里)+3
SNR = 12;
% 信号轮流写入两个缓冲区,每个缓冲区的大小为一个OFDM符号的长度
if(rem(s_no,2) == 1)
MI_IN_1=fscanf(fidi,'%f',Ntotal*2*2);
MQ_IN_1=fscanf(fidq,'%f',Ntotal*2*2);
% I_INnoised_1=MI_IN_1;
% Q_INnoised_1=MQ_IN_1; % 不加高斯白噪声
I_INnoised_1=awgn(MI_IN_1,SNR,'measured');
Q_INnoised_1=awgn(MQ_IN_1,SNR,'measured'); % 加入高斯白噪声
else
MI_IN_2=fscanf(fidi,'%f',Ntotal*2*2);
MQ_IN_2=fscanf(fidq,'%f',Ntotal*2*2);
% I_INnoised_2=MI_IN_2;
% Q_INnoised_2=MQ_IN_2; % 不加高斯白噪声
I_INnoised_2=awgn(MI_IN_2,SNR,'measured');
Q_INnoised_2=awgn(MQ_IN_2,SNR,'measured'); % 加入高斯白噪声
end
% 一个大循环内处理一个OFDM符号长度的数据
for i=1:Ntotal*2*2
% 加入一定的频偏
i_total = (s_no-1)*Ntotal*2*2 + i; % 变量 i_total 用来加入模拟频偏,是与解调无关的测试量
% 这里对2取模,是为了区分两个两个缓冲区,即确认当前是在处理哪个缓冲区内的数据
if(rem(s_no,2) == 1)
% 加入一定的频偏
I_INnoised_error_f_1(i)=cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_1(i) - sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_1(i);
Q_INnoised_error_f_1(i)=sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_1(i) + cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_1(i);
IDEMOD_1(i)=I_INnoised_error_f_1(i);
QDEMOD_1(i)=Q_INnoised_error_f_1(i);
else
% 加入一定的频偏
I_INnoised_error_f_2(i)=cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_2(i) - sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_2(i);
Q_INnoised_error_f_2(i)=sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_2(i) + cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_2(i);
IDEMOD_2(i)=I_INnoised_error_f_2(i);
QDEMOD_2(i)=Q_INnoised_error_f_2(i);
end
% 进行内插滤波
% 具体算法参考Floyd M. Gardner关于内插器的两篇文章
% "Interpolation in Digital Modems - Part I: Fundamentals"
% "Interpolation in Digital Modems - Part II: Implementation and Performance"
Ix(1:3) = Ix(2:4);
Qx(1:3) = Qx(2:4);
% 这里对2取模,是为了区分两个两个缓冲区,即确认当前是在处理哪个缓冲区内的数据
if(rem(s_no,2) == 1)
Ix(4) = IDEMOD_1(i);
Qx(4) = QDEMOD_1(i);
else
Ix(4) = IDEMOD_2(i);
Qx(4) = QDEMOD_2(i);
end
reg0 = reg;
reg = reg - wint;
if (reg<=0)
% k3是对内插后缓冲区的位置的指示,k3_total则记录了总共处理的内插后的点数
% 为了便于仿真和测试,这里使用了变量k3_total
% 在matlab仿真程序中,关于k3_total的计算,在ccs程序中将会使用k3来计算,程序会增加一定的复杂性
k3_total = k3_total + 1;
u(k3)=reg0/wint;
IV=B*Ix';
QV=B*Qx';
Upower=[1 u(k3) u(k3).^2];
reg=reg+1;
IInter_2(k3)=Upower*IV;
QInter_2(k3)=Upower*QV;
c_2(k3) = IInter_2(k3) + j*QInter_2(k3); % c_2() 只在仿真程序中出现,便于复数计算
% 调试和测试时观察的中间变量
IInter_test(k3_total)=IInter_2(k3);
QInter_test(k3_total)=QInter_2(k3);
% 检测短训练字到达
% 当短训练字相关值大于门限的次数小于预先设置的次数时候,
% 认为信号到达检测还没有到达,继续进行到达检测
if(short_tr_timed < Times_short_should_find)
%if( k3_total > (2*Ng)*2)
if( k3_total > 0 )
short_tr_correlator(k3_total) = 0;
short_tr_power(k3_total) = 0;
% 进行相关运算以及功率计算
% 相关长度为Ng*2
for ii=1:1:Ng*2
% 由于缓冲区c_2是循环使用,当数据填到最后一个位置后,重新从第一个位置填起
% 所以当k3所指示的位置超出了c_2缓存区的范围时,需要进行取模运算,计算出去k3所对应的缓存区内的实际位置
if(k3-2*Ng+ii<=0)
temp_ii = k3-2*Ng+ii+Ntotal*2*2;
else
temp_ii = k3-2*Ng+ii;
end
if(k3-2*Ng-2*Ng+ii<=0)
temp_jj = k3-2*Ng-2*Ng+ii+Ntotal*2*2;
else
temp_jj = k3-2*Ng-2*Ng+ii;
end
short_tr_correlator(k3_total) = short_tr_correlator(k3_total) + c_2(temp_ii)*(c_2(temp_jj))'; % 求相关值
short_tr_power(k3_total) = short_tr_power(k3_total) + real(c_2(temp_ii)*(c_2(temp_ii))'); % 求相关长度内信号的能量
end
short_tr_mm(k3_total) = abs( short_tr_correlator( k3_total) );
%short_tr_threshold = short_tr_power(k3_total)*(19/20);
short_tr_threshold = short_tr_power(k3_total)*(9/10); % 设置一个比较相关值的门限
% 寻找最后一个极大值点
if(k3_total>2)
if(short_tr_threshold < short_tr_mm(k3_total-1))
if(short_tr_mm(k3_total-1) >= short_tr_mm(k3_total-2) & short_tr_mm(k3_total-1) >= short_tr_mm(k3_total))
Timing_short_index(t_short) = k3_total - 1;
short_tr_detected = 1;
end
end
end
end % end of if(short_tr_timed < Times_short_should_find)
% 每经过一个短训练字的长度的数据点进行一次判断
if(rem(k3_total,2*Ng) == 0)
if(short_tr_detected == 1)
short_tr_timed = short_tr_timed + 1;
% 如果两次检测到大于门限的极大值之间的距离大于一定的距离,认为前面检测到的信号到达错误的,重新开始信号到达检测
if(t_short > 1)
if( Timing_short_index(t_short) - Timing_short_index(t_short-1) > 2*Ng+2*Ng)
short_tr_timed = 1;
end
end
% 如果短训练字相关值大于门限的次数小于预先设置的次数,相关参数清0,继续进行到达检测
if(short_tr_timed < Times_short_should_find)
short_tr_detected = 0;
end
t_short = t_short + 1;
end
end
end % end of if if(short_tr_timed < Times_short_should_find)
% 当连续检测到大于门限的极大值的次数达到一定值后,认为信号到达,开始检测长训练字,检测FFT窗口的起始位置
if (short_tr_timed == Times_short_should_find)
% 如果符号同步标志表示没有完成符号同步,则继续进行符号同步估计
if(symbol_timed < 1)
PP(k3_total)=0;
RR(k3_total)=0;
for ii=1:1:Nfft
% 由于缓冲区c_2是循环使用,当数据填到最后一个位置后,重新从第一个位置填起
% 所以当k3所指示的位置超出了c_2缓存区的范围时,需要进行取模运算,计算出去k3所对应的缓存区内的实际位置
if(k3-Nfft+ii<=0)
temp_ii = k3-Nfft+ii+Ntotal*2*2;
else
temp_ii = k3-Nfft+ii;
end
if(k3-Nfft-Nfft+ii<=0)
temp_jj = k3-Nfft-Nfft+ii+Ntotal*2*2;
else
temp_jj = k3-Nfft-Nfft+ii;
end
PP(k3_total) = PP(k3_total) + c_2(temp_ii)*(c_2(temp_jj))'; % 求相关值
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -