main.m
上传用户:look542
上传日期:2009-06-04
资源大小:784k
文件大小:23k
源码类别:

传真(Fax)编程

开发平台:

Matlab

  1. clear all;
  2. close all;
  3. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4. % OFDMA链路层仿真程序框架
  5. % 变量命名原则:
  6. % 1) 开头大写,表示常量或可调全局变量,控制程序流程
  7. % 2) 小写加下划线,表示临时变量,传递数据
  8. % 变量使用原则:
  9. % 1) 不同用户的临时变量数据封装在cell结构体元素中,这是因为其数据长度可能不同
  10. % 2) 频域矩阵,不同列表示时间(OFDM符号),不同行表示子载波,矩阵第三维表示不同天线的数据
  11. % 3) 时域矩阵,不同列表示时间的样点, 如有不同行则表示时延(如时域信道响应矩阵), 第三维同样表示天线
  12. % 4) 部分常量或可调全局变量,用struct结构体归类
  13. % 函数命名和使用原则:
  14. % 1) 小写加下划线命名
  15. % 2) 部分函数可以根据输入变量个数实现函数功能重载
  16. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  18. % 一. 初始化部分
  19. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  20. % 1.程序复杂度控制单元, 用结构体TurnOn, 和一些全局参数控制,
  21. % 目的是针对特定需求, 降低运行复杂度, 使之在学术科研中发挥较大作用
  22. % 打开相应模块功能---1,关闭相应模块功能---0
  23. % 如关闭信道估计和补偿模块, 使用理想信道估计
  24. ChannelEst = 1;
  25. TurnOn = struct('ChannelEst',ChannelEst);
  26. % 使用收发天线数进行控制, 开关多天线模块(包括空时编码和多天线信道).
  27. % 单天线多径信道,其功率时延谱, 多普勒频移等参数由结构体ch确定. 
  28. % 多天线多径信道,同一用户的不同收发天线假设功率时延谱相同, 
  29. % 发送天线数, 可选1,2和4. 发送天线为1则没有空时编码
  30. N_Tx_ant = 4;      
  31. % 接收天线数, 可选1,2,4,8,..,2^N.  接收天线为1则没有合并
  32. N_Rx_ant = 8;
  33. % 信道编码模块
  34. TurnOn.ChannelCoding = 0;
  35. % 频域加信道模块。打开此模块,则关闭时域加信道模块,时域同步模块,OFDM调制解调模块。
  36. TurnOn.AddChFreq = 1;
  37. %  用户数目
  38. N_user = 1;           
  39. % 自适应调制
  40. TurnOn.AdptMod = 0;
  41. % 如关闭包检测和帧定时同步模块, 定时位置准确
  42. TurnOn.Timing = 0;
  43. % 如关闭频率同步模块, 载波频率偏差为 0 Hz, 不使用频偏纠正算法
  44. TurnOn.FreqSyn = 0;
  45. % 建议: 不同重点的研究,使用不同的程序结构,关闭认为次要的模块.
  46. % 如要评估系统总的性能,则可以打开所有模块
  47. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  48. % 2 参数定义单元,用户自定义
  49. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  50. % 2.1 OFDMA收发机系统参数定义单元
  51. % 命名规律: N_xxx: xxx的数目,为非负整数
  52. %           T_xxx: xxx的持续时间,为非负实数
  53. %           Idx_xxx: xxx的编号,为整数向量
  54. %           一些约定俗成的表示, 如fc载频, Bw信道带宽等
  55. % 1) 系统的帧结构(对863帧结构进行了简化,只考虑上行或下行时隙,不考虑切换时间,时隙的时隙结构可调)
  56. %----------------------------------------------------------------------------------------------------
  57. %|   同步时隙    |  数据时隙1     |   数据时隙2      |   数据时隙3      |   ...   |  数据时隙N      |
  58. %|               |                |                  |                  |   ...   |                 |
  59. %----------------------------------------------------------------------------------------------------
  60. %|<----------------------------------------- 1帧 -------------------------------------------------->| 
  61. N_frame = 10;               %  仿真的帧总数
  62. % a) 同步时隙, 包括三个OFDM符号。用于定时,初始载波同步
  63. N_syn_preamble = 3;          % 同步时隙训练符号为3个
  64. % b) 数据时隙, 由多个数据OFDM符号组成,分为数据符号和导频符号。             
  65. %  假设每个数据时隙有N_sym_ts个OFDM符号,而一共假设有N_ts个数据时隙。
  66. %  数据符号,主要传输用户数据,并在数据符号子载波上间隔插入导频,用于载波相位跟踪, 导频位置由Idx_pilot确定。
  67. %  导频符号,用于估计信道,并抵抗多普勒频移。可全插导频,也可以间隔插导频。
  68. N_ts = 2;                                   % 总共的数据时隙数目
  69. Pos_pilot_sym = [1 7];                      % 导频OFDM符号在时间上的位置
  70. Pos_data_sym = [2:6];                         %  数据OFDM符号在时间上的位置
  71. N_pilot_sym_ts = length(Pos_pilot_sym);     % 每个数据时隙的导频OFDM符号数目
  72. N_data_sym_ts = length(Pos_data_sym);       % 每个数据时隙的数据OFDM符号数目
  73. N_sym_ts = N_pilot_sym_ts + N_data_sym_ts;  % 每个数据时隙的OFDM符号数目
  74. N_sym = N_sym_ts*N_ts + N_syn_preamble;     % 总的OFDM符号数目
  75. N_data_sym = N_data_sym_ts*N_ts;            % 总的数据OFDM符号数目
  76. % 2) OFDM相关参数:
  77. % 调制方式:
  78. % a) 当TurnOn.AdptMod = 0 时表示所有子载波用调制方式:(不使用信道编码时)
  79. % 1--BPSK调制, 2--QPSK调制,3--8PSK调制, 4--16QAM调制,6--64QAM调制
  80. % b) 当TurnOn.AdptMod = 1 时表示自适应调制,平均每个子载波上调制的比特数
  81. % 此时最大只能设置为4, 否则调制器无法处理
  82. Modulation = 2;       
  83. % 仿真循环开始的Eb_No,定义为每比特的能量Eb
  84. % 和噪声的单边功率谱密度No的比值, dB值
  85. Eb_NoStart = 0;                                                          
  86. Eb_NoInterval = 2;              % 仿真Eb/No的间隔值(dB)
  87. Eb_NoEnd = 20;                   % 仿真Eb/No的终止值(dB)                        
  88. N_subc = 64;                              %  OFDM 子载波总数
  89. switch N_subc
  90. case 1024
  91.     %Idx_used = [-416:-1 1:416];             %  使用的子载波位置编号
  92.     Idx_used = [-512:1:511];
  93.     Idx_pilot = [-400:25:-25 25:25:400];    %  数据OFDM符号中的导频子载波在频率上的位置编号
  94.     PrefixRatio = 27/128;                   %  OFDM循环前缀占有效FFT时间的比例
  95. case 512
  96.     Idx_used = [-200:-1 1:200];             
  97.     Idx_pilot = [-200:25:-25 25:25:200];    
  98.     PrefixRatio = 1/4;                   
  99. case 64
  100.     %Idx_used = [-26:-1 1:26];    
  101.     Idx_used = [-32:1:31];  
  102.     Idx_pilot = [-21:14:-7 7:14:21];    
  103.     PrefixRatio = 1/4;
  104. end
  105. Es = 1;                 % 在16QAM, 64QAM调制方式下,符号能量都已经被归一化 
  106. Eb = Es/Modulation;     % 每比特能量    
  107. fc = 3.5e9;                             %  载波频率(Hz)
  108. Bw = 20e6;                              %  基带系统带宽(Hz)
  109. fs = 20e6;                              %  基带抽样频率
  110. T_sample = 1/fs;                        %  基带时域样点间隔(s)
  111. N_used = length(Idx_used);              % 使用子载波数
  112. N_pilot = length(Idx_pilot);            % 导频子载波数
  113. N_data = N_used - N_pilot;              % 数据子载波数
  114. Idx_data = zeros(1,N_data);
  115. % 得到数据子载波的编号
  116. m = 1; n = 1;
  117. for k  = 1:length(Idx_used)
  118.     if Idx_used(k) ~= Idx_pilot(m);
  119.         Idx_data(n) = Idx_used(k);
  120.         n = n + 1;
  121.     else
  122.         if m ~= N_pilot
  123.             m = m + 1;
  124.         end
  125.     end
  126. end
  127. %  为编程使用方便,调整子载波编号为从1开始,到子载波总数
  128. Idx_used = Idx_used + N_subc/2 +1;       
  129. Idx_pilot = Idx_pilot + N_subc/2 +1;
  130. Idx_data = Idx_data + N_subc/2 +1; 
  131. % 数据符号用于同步的导频的取值
  132. PilotValue = (( rand(N_pilot,1)>.5 )*2 - 1)/sqrt(N_Tx_ant);
  133. % OFDM符号持续时间
  134. T_sym = T_sample*( (1 + PrefixRatio)*N_subc );
  135. N_ant_pair = N_Tx_ant * N_Rx_ant;   % 收发天线对的数目
  136. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  137. % 2.2 信道参数定义单元, 每个用户移动台参数不同
  138. for u = 1:N_user
  139.     % 车辆运动速度, 单位:km/hr. 范围:5km/hr~ 250km/hr. 对应多普勒频移:16.2Hz ~ 810.2Hz
  140.     speed = 5;         
  141.     ch{u} = struct('Speed', speed);
  142.     % 多普勒频移, 单位: Hz
  143.     ch{u}.fd = ch{u}.Speed *(1e3/3.6e3)*fc/3e8;  
  144.     % 指数衰落的信道功率时延谱, 时延:ns    
  145.     ch{u}.Power = 10.^([ 0 -6 -12 -18 -24 -30 ]'./10);  % 6径信道每条径的功率
  146.     if N_subc == 1024
  147.         ch{u}.Delay = [ 0 2000 4000 6000 8000 10000 ]';      % 最大多径时延 10us 室外信道
  148.         %ch{u}.Delay = [ 0 1400 2800 4200 5600 7000 ]';      % 最大多径时延 7us 室外信道
  149.         %ch{u}.Delay = [ 0 300 600 900 1200 1500 ]';         % 最大多径时延 1.5us 室外信道
  150.     elseif N_subc == 512
  151.         ch{u}.Delay = [ 0 1000 2000 3000 4000 5000 ]';     % 最大多径时延 5us 室外信道参数
  152.     elseif N_subc == 64         %ch{u}.Delay = [ 0 50 100 150 200 250 ]';          % 最大多径时延 250ns 室内信道参数
  153.         ch{u}.Delay = [ 0 100 200 300 400 500 ]';          % 最大多径时延 500ns 室内信道参数
  154.     end
  155.     Idx_cir = round(ch{u}.Delay/(T_sample*10^9)) + 1;           % 时域信道响应的径对应的时域样点位置
  156.     % 室内信道的功率时延谱(HIPERLAN2)
  157.     %        ch{u}.Power = [ 0.3240 0.4015 0.0929 0.0961 0.0291 0.0340 0.0060 0.0165];
  158.     %        ch{u}.Delay = [ 50 100 150 200 250 300 350 400 ]';    
  159.     
  160.     ch{u}.Power = ch{u}.Power/ sum(ch{u}.Power); % 功率归一化
  161.     % 每个用户每条径对应的样点数
  162.     ch{u}.Delay_sample = round(ch{u}.Delay  * 1e-9 * fs);                 
  163.     ch{u}.N_path = size(ch{u}.Power,1);          % 径数 
  164.     % 每个用户,各条径对应的莱斯衰落K因子
  165.     % ch{u}.Ricean_K = zeros(N_path,1) ;         
  166. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  167. % 2.3 OFDMA收发机算法选择和参数定义单元
  168. % 1) 信道估计: 单天线信道估计算法,使用导频辅助进行信道估计
  169. % 1 - 基本LS算法; 2 - LS的DFT改进算法; 3 - 加判决反馈的LS-DFT
  170. % 4 - 基本MMSE算法; 5 - MMSE的DFT改进算法; 6 - 加判决反馈的MMSE-DFT
  171. % 7 - SVD分解算法,8 - Robust算法
  172. % 9 - 自适应滤波器结合单天线信道估计的方法, 10 - EM 方法
  173. SISO_CE_Method = 1;                    
  174. % 使用LS或MMSE的DFT改进算法时,所保留的子载波数                                    
  175. L_delay = max(ch{u}.Delay_sample) + 1;        % 最大多径时延对应的样点数  
  176. % 插值方法: 1 - 线性插值, 2 - 二次插值, 3 - 三次样条插值,  
  177. %           4 - 时域插值, 5 - 低通滤波器插值
  178. InterpMethod = 3;
  179. % 多天线信道估计方法,使用导频辅助进行信道估计
  180. % 1 - 基本LS算法; 2 - LS的改进算法1; 3 - LS的改进算法2; 4 - LS的改进算法3; 
  181. % 5 - 频域区分子载波的方法,使用 SISO_CE_Method 选择的算法,以及 InterpMethod 选择的插值方法
  182. % 6 - 使用发送多个OFDM符号,线性组合求得多天线信道响应
  183. MIMO_CE_Method = 1;
  184. % 在方法6中使用正交导频--1,使用非正交导频--0
  185. SwitchOrthogonalPilot = 0;
  186. % 2) 空时编码:  1--空时分组码,2发,码率为1;4发,码率为1/2
  187. %                 2--分层空时码,4发8收,码率为4。         
  188. ST_Code = 2;
  189. HardOrSoft = 0; % 0 - 分层空时码输出为未判决的星座点,1-- 分层空时码输出为判决后的星座点
  190. LST_method = 1; % 分层空时码解码算法,1-- SIC-ZF, 2 -- MMSE.
  191. % 空时处理的编码速率
  192. if (ST_Code == 1)&(N_Tx_ant == 4)   % 4发STBC,码率1/2
  193.     RateSTCoding = 1/2;
  194. elseif (ST_Code == 2)&(N_Tx_ant == 4)   % 4发BLAST,码率4
  195.     RateSTCoding = 4;
  196. else
  197.     RateSTCoding = 1;               
  198. end
  199. % 3) 信道编码,速率:1/3, 1/2, 2/3, 3/4
  200. ChCodingMethod = 1;         % 1 - Turbo码+交织 , 2 - 卷积+RS+交织
  201. Puncture = 0;                               % 是否凿孔
  202. if TurnOn.ChannelCoding == 1
  203.     if ChCodingMethod == 1
  204.         RateChCoding = 1/(2 + Puncture);        % 编码速率
  205.     elseif ChCodingMethod == 2
  206.         RateChCoding = 1/2;               
  207.     end
  208. else 
  209.     RateChCoding = 1;
  210. end
  211. % 如果使用Turbo码+交织:
  212. Dec_alg = 0;                                             % 解码算法
  213. N1 = 1;
  214. L_total = N_data*RateChCoding*N1;                           % 帧长,也是交织长度
  215. Generator = [ 1 1 1;
  216.     1 0 1 ];                                            % 码字生成多项式
  217. N_iter = 5;                                             % 解码器迭代次数
  218. [temp, Alpha] = sort(rand(1,L_total));                  % 得到交织的顺序序列alpha
  219. Turbo_frame = L_total - (size(Generator,2) - 1);
  220. N_Turbo_frame = (Modulation * RateSTCoding * N_ts * N_data_sym_ts)/N1;
  221. [temp, Alpha2] = sort(rand(1, L_total / RateChCoding * N_Turbo_frame));
  222. % 如果使用卷积+RS+交织: 
  223. % 假设每个用户的RS码参数相同,均为(204,188,8)                                   
  224. UserRS_Coding = repmat([255,239,8]',1,N_user);                              
  225. TraceBackLen = 3;       % 卷积码译码参数
  226. % 假设每个用户的卷积码trellis 结构体相同
  227. UserTrellis = repmat( poly2trellis(3,[6 7]),1,N_user );
  228. % 4) 自适应调制: ,当TurnOn.AdptMod == 1时, 
  229. % 1--自适应调制方法1, 给功率增加最小的子载波分配比特和功率, 子载波分配由AllocMethod确定
  230. % 2--自适应调制方法2, 按照信道响应降序排列,子载波间争夺比特和功率, 子载波分配由AllocMethod确定
  231. % 当TurnOn.AdptMod == 0 时,此不起作用, 无自适应调制
  232. AdptMethod = 1;
  233. % 子载波分配方法, 1--相邻分配, 2--交织分配, 3---跳频分配 ,4--自适应子载波分配
  234. AllocMethod = 1;
  235. % 自适应调制算法中需要的目标误比特率
  236. TargetBer = 1e-3;
  237. % 5)定时同步:
  238. PreNoiseLen = 500;      % 为定时算法加的前噪样点数
  239. PostNoiseLen = 500;     % 后噪样点数
  240. delta_fc = 10e3;        % 载波频偏 (Hz)
  241. % 帧(粗)定时
  242. % 帧定时算法, 1--单窗口能量检测方法, 2--双窗口能量检测方法 , 3--延时相关方法帧定时
  243. FrameTiming = 1;         
  244. Window1 = 128;          % 帧定时算法的窗口宽度
  245. Threshold1 = 0.4;       % 帧定时算法门限
  246. Delay1 = 128;           % 帧定时延时相关算法的延时样点数
  247. % 载波频偏粗估计
  248. WinStart = 128*2;       
  249. WinSize = 128;
  250. Delay2 = 128*9;
  251. % 符号定时算法
  252. Window2 = 256;         % 和已知序列求相关,序列的长度
  253. TimingAhead = 0;        % 定时提前的样点数
  254. % 载波频偏细估计
  255. WinStart2 = 256; 
  256. WinSize2 = 1024;
  257. Delay3 = 1280;
  258. % 6) 测试选项
  259. % 0 -- 无测试, 加AWGN和瑞利多径信道效应; 1 -- 测试,不加AWGN,仅考虑瑞利多径信道效应;
  260. % 2 -- 测试,不加瑞利多径信道效应, 仅考虑AWGN;
  261. ChannelEffectTest = 0;
  262. end
  263. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  264. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  265. % 二. 仿真主体程序部分
  266. % Eb/No信噪比循环
  267. snr_idx = 1;
  268. for Eb_No_dB = Eb_NoStart:Eb_NoInterval:Eb_NoEnd  
  269.     Eb_No_dB
  270.     Eb_No = 10^(Eb_No_dB/10); 
  271.     var_noise = Eb/(2*Eb_No*RateChCoding);              % 噪声样点的功率
  272.     tic;                                                % 计算时间开始
  273.     
  274.     % OFDM帧/数据包循环
  275.     for frame = 1:N_frame                       
  276.         
  277.         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  278.         % 1. 信道参数产生部分
  279.         % 产生不同用户(cell区分), 不同收发天线对(矩阵的第三维区分),不同OFDM符号
  280.         % 时间(矩阵列区分), 多径信道不同时延径(矩阵行区分)的时域信道响应
  281.         h_time = cell(1,N_user);
  282.         H_freq = cell(1,N_user);
  283.         
  284.         for u = 1:N_user
  285.             % 得到时域信道的参数
  286.             
  287.             h_time{u} = channel_gen( ch{u}.Power,ch{u}.fd, T_sym*fs, T_sample, N_sym, ...
  288.                 N_frame, frame, N_Tx_ant, N_Rx_ant );
  289.             % 由信道时域响应,得到信道的频域响应
  290.             H_freq{u} = to_freq_channel( h_time{u}, ch{u} ,N_subc ,N_sym, N_Tx_ant,...
  291.                 N_Rx_ant,ChannelEffectTest);
  292.         end
  293.         
  294.         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  295.         % 2. 发射机部分
  296.         
  297.         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  298.         
  299.         
  300.         % 多用户数据生成模块
  301.         [user_bit,user_bit_cnt] = user_bit_gen( N_user, N_data ,N_ts, N_data_sym_ts, RateSTCoding,...
  302.             Modulation,RateChCoding,Turbo_frame , N_Turbo_frame , TurnOn.ChannelCoding );
  303.         
  304.         % 信道编码模块, 包括RS编码, 卷积编码等
  305.         coded_user_bit = channel_coding( user_bit,ChCodingMethod,Dec_alg,L_total,Generator,Puncture,...
  306.             N_iter,RateChCoding,Alpha,Turbo_frame,N_Turbo_frame, UserRS_Coding ,UserTrellis,...
  307.             TraceBackLen,TurnOn.ChannelCoding );
  308.         
  309.         coded_user_bit{1} = coded_user_bit{1}(Alpha2);
  310.         
  311.         % 自适应调制和多用户复用模块
  312.         % 单用户情况,有自适应调制
  313.         if TurnOn.AdptMod           
  314.             [user_subc_alloc , mod_subc ,pwr_subc, pad_bit_cnt] = adpt_mod_para... 
  315.                 ( coded_user_bit,N_data_sym,Idx_data,AllocMethod,AdptMethod ,...
  316.                 H_freq,var_noise,TargetBer );
  317.             % 多用户情况,使用固定或动态子载波分配,不需要自适应调制            
  318.         else                        
  319.             [user_subc_alloc , mod_subc ,pwr_subc, pad_bit_cnt]  = adpt_mod_para...
  320.                 ( coded_user_bit,N_data_sym*RateSTCoding ,Idx_data ,AllocMethod ); 
  321.         end
  322.         
  323.         % 按照给定的每用户,每子载波的调制方式,进行自适应调制
  324.         mod_sym =  modulator(coded_user_bit,user_subc_alloc,mod_subc,...
  325.             pwr_subc, pad_bit_cnt ,N_subc,N_data_sym*RateSTCoding ,TurnOn.AdptMod );
  326.         
  327.         % 发送分集, 使用空时编码
  328.        st_coded = st_coding( mod_sym, N_Tx_ant, N_data_sym, ST_Code);
  329.         
  330.         % 在数据符号帧之间插入导频OFDM符号, 并在数据OFDM符号中加间隔的导频
  331.         [pilot_added ,known_pilot] = pilot_insert(st_coded,N_pilot_sym_ts,N_data_sym_ts,N_ts,Pos_pilot_sym,...
  332.             Pos_data_sym,Idx_pilot,PilotValue,N_subc,Idx_used,N_Tx_ant,L_delay,MIMO_CE_Method,SwitchOrthogonalPilot);
  333.            
  334.         % OFDM调制. 如果使用发送分集,则输出多条天线的信号
  335.         transmit_signal = ofdm_mod(pilot_added,PrefixRatio,N_subc,N_used,N_sym_ts,N_ts,...
  336.             Idx_used,N_Tx_ant,TurnOn.AddChFreq);
  337.         
  338.         % 成帧,加前导序列
  339.         [transmit_signal, syn_preamble] = framing(transmit_signal,N_syn_preamble,PrefixRatio,N_subc,N_used,...
  340.             Idx_used,N_Tx_ant,TurnOn.AddChFreq);
  341.         
  342.         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  343.         % 3. 多天线多径信道部分
  344.         for u = 1:N_user        % 多个用户接收机的循环
  345.             
  346.             % 信道和接收机区分开不同用户的原因:
  347.             % 1) 每个用户(移动台)的信道功率时延谱和衰落系数是不同的, 需要区别
  348.             % 2) 自适应调制和子载波分配算法中, 需要知道每个用户的信道响应
  349.             
  350.             recv_signal = channel( transmit_signal,h_time{u}, ch{u}, N_Tx_ant, N_Rx_ant,...
  351.                 PreNoiseLen, PostNoiseLen , var_noise,N_subc,PrefixRatio,N_sym,...
  352.                 delta_fc,T_sample,TurnOn.FreqSyn ,TurnOn.AddChFreq );
  353.             
  354.             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  355.             % 4. 接收机部分
  356.             
  357.             % 接收机帧定时(包检测,粗定时)
  358.             [recv_frame, err_frame_timing] = frame_timing( recv_signal ,Window1, Threshold1,...
  359.                 Delay1,PreNoiseLen, PostNoiseLen, N_subc, PrefixRatio, FrameTiming, N_Rx_ant ,...
  360.                 TurnOn.Timing ,TurnOn.AddChFreq);
  361.             
  362.             % 粗频偏估计 (整数倍的频偏估计). 也可以在频域做,使用freq_syn_freqdomain模块
  363.             [coarse_freq_out, offset1] = freq_syn_timedomain( recv_frame, WinStart, WinSize, Delay2, T_sample,...
  364.                 N_Rx_ant,TurnOn.FreqSyn ,TurnOn.AddChFreq);
  365.             
  366.             % 符号定时(精定时)
  367.             [timed_sym , err_sym_timing] = sym_timing( coarse_freq_out ,N_subc, PrefixRatio, N_sym ,...
  368.                 N_syn_preamble,syn_preamble,Window2,TimingAhead, N_Rx_ant, TurnOn.Timing ,TurnOn.AddChFreq);
  369.             
  370.             % 精频偏估计(分数倍的频偏估计),如果粗频偏估计已经满足估计器的MSE要求, 则可以不使用此模块
  371.             % 调用和粗频偏估计相同的函数,只是输入参数不同
  372.             [fine_freq_out,offset2] = freq_syn_timedomain( timed_sym,WinStart2, WinSize2, Delay3, T_sample,...
  373.                 N_Rx_ant,TurnOn.FreqSyn ,TurnOn.AddChFreq);
  374.             
  375.             % OFDM解调
  376.             ofdm_sym = ofdm_demod( fine_freq_out, PrefixRatio, N_subc, N_sym_ts, N_ts , N_Rx_ant ,TurnOn.AddChFreq );
  377.             
  378.             % 在频域加入信道响应
  379.             
  380.             ofdm_sym = add_freqdomain_reponse(pilot_added,H_freq{u},N_subc,N_syn_preamble,N_sym,N_Rx_ant,...
  381.                 N_Tx_ant,var_noise,ofdm_sym,ChannelEffectTest,TurnOn.AddChFreq);
  382.             
  383.             % 分离提取数据OFDM符号和导频OFDM符号
  384.             [ data_sym,pilot_sym] = pilot_extract(ofdm_sym,N_subc,N_pilot_sym_ts,N_data_sym_ts,N_ts,Pos_pilot_sym,...
  385.                 Pos_data_sym,N_Rx_ant);
  386.             
  387.             % 频域信道估计器, 如果使用了时域均衡, 则不使用此模块            
  388.             [channel_est , mse_ce] = channel_estimator( pilot_sym,known_pilot,SISO_CE_Method,MIMO_CE_Method,...
  389.                 L_delay,InterpMethod,H_freq{u},N_Tx_ant,N_Rx_ant,N_subc,N_used,Idx_used,Modulation,var_noise,...
  390.                 ch{u},N_ts,N_sym_ts,N_pilot_sym_ts,N_data_sym_ts,Pos_pilot_sym,Pos_data_sym,N_syn_preamble,...
  391.                 frame,Idx_cir,TurnOn.ChannelEst ,ChannelEffectTest ,SwitchOrthogonalPilot );
  392.             
  393.             % 接收机分集处理和空时解码    
  394.             st_decoded = st_decoding( data_sym,channel_est,N_subc,N_data_sym, N_Tx_ant, N_Rx_ant ,ST_Code ,...
  395.                 Idx_data,RateSTCoding,Modulation,HardOrSoft,LST_method,var_noise,ChannelEffectTest);
  396.             
  397.             % 根据每用户,每子载波的调制方式,进行解调
  398.             demod_user_bit = demodulator( st_decoded, user_subc_alloc{u} ,mod_subc{u} ,pad_bit_cnt(u),TurnOn.AdptMod);            
  399.             
  400.             % 信道解码, 包括RS解码, 卷积码Viterbi编码等
  401.             
  402.             demod_user_bit(Alpha2) = demod_user_bit;
  403.             
  404.             decoded_user_bit{u} = channel_decoding( demod_user_bit,ChCodingMethod,Dec_alg,L_total,Generator,Puncture,...
  405.                 N_iter,RateChCoding,Alpha,Turbo_frame,N_Turbo_frame, UserRS_Coding(:,u) ,UserTrellis(u) ,...
  406.                 TraceBackLen, user_bit_cnt(u) , TurnOn.ChannelCoding );
  407.             
  408.             % 本帧,本信噪比下,本用户的性能统计
  409.             bit_err = sum(abs(decoded_user_bit{u} - user_bit{u}));
  410.             ber = bit_err / length(decoded_user_bit{u});
  411.             frame_err(frame, snr_idx) = ( bit_err ~= 0 );
  412.             
  413.             if TurnOn.FreqSyn 
  414.                 freq_err = delta_fc - (offset1 + offset2);
  415.             else
  416.                 freq_err = NaN;
  417.             end   
  418.             
  419.             user_bit_err{u}(frame,snr_idx) = bit_err;
  420.             
  421.             mse_ce_acc{u}(frame,snr_idx) = mse_ce;
  422.             mean_nor_H = sum(H_freq{u}(Idx_used,2,1)'* H_freq{u}(Idx_used,2,1))/N_used;
  423.             mean_nor_H = sum(abs(mean_nor_H))/N_Rx_ant;
  424.             nmse_ce_acc{u}(frame,snr_idx) = mse_ce/mean_nor_H ;
  425.             frame_timing_acc{u}(frame,snr_idx) = err_frame_timing ;
  426.             freq_syn_acc{u}(frame,snr_idx) = freq_err ;
  427.             
  428.             
  429.         end                  % 多个用户接收机的循环结束 
  430.         
  431.         % 实时显示仿真性能
  432.         fprintf('Eb/No:%d dBtFrame No.:%d  Err Bits:%dtBER:%ftCh.Est. MSE:%f  Timing Err(Sample):%dtFreq.Syn. Err(Hz):%dn',...
  433.             Eb_No_dB, frame, bit_err,ber, mse_ce, err_frame_timing , freq_err);
  434.         
  435.     end                      % OFDM帧
  436.     
  437.     ber_snr = sum(user_bit_err{u}(:,snr_idx))/(length(decoded_user_bit{u})*N_frame);
  438.     fer_snr = sum(frame_err(:,snr_idx))/(N_frame);
  439.     mse_snr = sum(mse_ce_acc{u}(:,snr_idx))/(N_frame);
  440.     fprintf('nStatistics for the current Eb/No:t');
  441.     fprintf('BER:%ft FER:%ft Ch.Est. MSE:%fn',ber_snr,fer_snr,mse_snr);
  442.     
  443.     timer(snr_idx) = toc;     % 计算时间结束
  444.     time_passed = round(sum(timer)/60);
  445.     time_left = round( (length([Eb_NoStart:Eb_NoInterval:Eb_NoEnd]) - snr_idx)*time_passed/snr_idx );
  446.     fprintf('nTime Passed:t%d mint Time Left:t  %d minnnn',time_passed,time_left);
  447.     
  448.     snr_idx = snr_idx + 1;
  449.     save saved_data.mat;     % 保存数据
  450.     
  451. end                      % Eb/No信噪比循环结束     
  452. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  453. % 5. 性能评估部分,可以保存需要的数据,并对目标性能数据进行操作
  454. % 如画图, 比较,进一步计算得到结论等
  455. performance_eval;
  456. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  457. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  458. % 仿真程序结尾