function [outputI,outputQ] = ofdm_TX(SampleRate,TimeWindow,BitRate);
% 该程序仿真基于自相关的定时同步和频偏估计(仅仅可估计小数倍频偏,但是该方法存在明显的残余频偏)
% the sample rate has to give a power of two number of samples per bit
if ~isequal(ceil(log2(SampleRate/BitRate)),floor(log2(SampleRate/BitRate)))
SR = num2str(SampleRate);
SPB = num2str(SampleRate/BitRate);
error(['SampleRate ' SR ' does not yield a number of samples per bit which is a power of two, but ' SPB ' samples per bit']);
end
% the sample rate multiplied by the time window (=total number of samples) must yield
% a vector which is a power of two
if ~isequal(floor(log2(SampleRate*TimeWindow)),ceil(log2(SampleRate*TimeWindow)))
VL = num2str(SampleRate*TimeWindow);
error(['SampleRate times Duration must be a power of two,but the current value is ' VL]);
end
Number_Of_Samples = TimeWindow*BitRate; % 传输的总的符号数 (由于是在matlab中产生传输的QAM符号数,故我在这里直接将VPI中定义的比特速率视作符号速率,真实的比特速率应该等于该速率乘以QAM的调制阶数)
samplesPerBit = SampleRate / BitRate; % 在VPI中的过采样率:表示对每一个数据点VPI对其的采样个数
%++++++++++++++++++++++++++系统参数++++++++++++++++++++++++++++++++++++++++
mod = 16; % 16QAM调制
K = log2(mod);
Sample_Rate = BitRate; % QAM符号速率(定义由VPI中传输的速率是波特速率,也就是QAM符号的速率)
% Bit_rate = BaudRate*K;
Fs = SampleRate; % 采样频率
C = 256; % 总的子载波数
Mc = 248; % 数据子载波数
guard = floor((C-Mc)/2); % 保护频带的宽度
TS_level = [1 4]; % 训练序列的强度
CP_length = 64; % 循环前缀长度
FrameLength = CP_length+C; % OFDM帧长度
num = floor(Number_Of_Samples/(CP_length+C))-2; % OFDM符号个数
ts_Length = 1; % 初始化训练序列的长度
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++传输符号产生++++++++++++++++++++++++++++++++++++
num_bits = Mc*num*log2(mod);
load('PBRS');
bits = PBRS(1:num_bits);
save('C:\Users\Administrator\Desktop\ofdm\Untitled-1.vtmu_pack\Inputs\bits.mat','bits');
data = bi2de(reshape(bits,log2(mod),Mc*num).','left-msb');
mc = reshape(data,Mc,num);
mc = qammod(mc, mod); % 原始的传输数据符号
save('C:\Users\Administrator\Desktop\ofdm\Untitled-1.vtmu_pack\Inputs\mc.mat','mc');
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%+++++++++++++++++++++++++++ 产生训练序列 ++++++++++++++++++++++++++++++
% trains_tongbu = gen_syn_CAZAC(1,Mc).'; % 用于同步
trains = add_trains(Mc,4).'; % 用于信道估计
Trains=[trains];
%-----添加训练序列------
mc=[Trains,mc];
%----------------------
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%+++++++++++++++++++++++++++ DSB传输 ++++++++++++++++++++++++++++++++++++
DSB_Data = zeros(C,num+ts_Length);
carriers = (1:Mc /2)+1+3; % guard:数据子载波距离中心DC的子载波个数
conjugate_carriers = C - carriers +2; % DSB ofdm
DSB_Data(carriers,:) = mc(1:Mc/2,:);
DSB_Data(conjugate_carriers,:) = mc(Mc/2+1:end,:);
%------添加用于同步的序列------
%---长前导序列-----
trains_tongbu = gen_syn_CAZAC(1,C/2).'; % 用于同步
trains_tongbu = upsample(trains_tongbu,2);
trains_tongbu = real(trains_tongbu);
%------------------
DSB_Data=[trains_tongbu,DSB_Data];
DSB_Data(1,:)=20;
%------------------------------
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++ IFFT转换 ++++++++++++++++++++++++++++++++++++
signal_modulation = ifft(DSB_Data);
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++ 添加cp ++++++++++++++++++++++++++++++++++++++
CP = signal_modulation( C - CP_length + 1 : C , : ); %提取循环前缀
TimeSignal_Guard = [CP ; signal_modulation]; %加载到原信号前
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++ 串并转换 +++++++++++++++++++++++++++++++++++++
TimeSignal = reshape(TimeSignal_Guard,1,size(TimeSignal_Guard,1)*size(TimeSignal_Guard,2));
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++后续重复使其为2的N次幂+++++++++++++++++++++++++++++
% 不补零的原因主要是因为补零使接收的0的序列的同步特别强
TimeO1 = 0:TimeWindow/(length(TimeSignal)-1):TimeWindow; % 由Matlab中生成的总的符号数
save('C:\Users\Administrator\Desktop\ofdm\Untitled-1.vtmu_pack\Inputs\TimeO1.mat','TimeO1');
TimeOS = 0:TimeWindow/(Number_Of_Samples-1):TimeWindow; % VPI中生成的总的传输符号数
% add_zeros=zeros(1,length(TimeOS)-length(TimeO1));
% TimeSignal=[TimeSignal,add_zeros]; % 后面添0使之能在VPI中传输
add_numbers=length(TimeOS)-length(TimeO1);
TimeSignal=[TimeSignal, TimeSignal(1:add_numbers)];
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%+++++++++++++++++++++++++++++IQ分离++++++++++++++++++++++++++++++++++++++
TimeSignalX = real(TimeSignal);
TimeSignalY = imag(TimeSignal);
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++++创造频域网格+++++++++++++++++++++++++++++++++
deltaf1 = Sample_Rate/Number_Of_Samples;
figure(1)
freqO = [ (-Number_Of_Samples /2) : (Number_Of_Samples /2 - 1)] * deltaf1;
plot(freqO, 10*log10((real(fftshift(fft(TimeSignal)))./length(TimeSignal)).^2), '-b')
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++ 输出信号类型定义 ++++++++++++++++++++++++++++++++
%------输出端口1定义----------
y1.type = 'esignal'; % 信号类型:'esignal'——电信号 'osignal'——光信号
y1.boundaries = 'Periodic'; % 信号的约束条件:周期信号
y1.dt = 1/SampleRate; % 采样间隔
y1.df = 1/TimeWindow; % 该式应该计算的是频域分辨率——1/(时域上的采样点数*时域上的采样间隔)
y1.t0 = 0; % set the time stamp
y1.T = 1/(y1.dt * y1.df); % 总的仿真的时间窗口/时间间隔=时域上的采样点数 % set the duration of the signal in grid points unit (=Duration/time grid spacing)
y1.fs = round(SampleRate/y1.df); % set the bandwidth of the structure in grid points unit
y1.band.type = 'eband';
y1.band.fs = round(SampleRate/y1.df);
%-------------------------------
%------输出端口2定义----------
y2.type = 'esignal'; % 信号类型:'esignal'——电信号 'osignal'——光信号
y2.boundaries = 'Periodic'; % 信号的约束条件:周期信号
y2.dt = 1/SampleRate; % 采样间隔
y2.df = 1/TimeWindow; % 该式应该计算的是频域分辨率——1/(时域上的采样点数*时域上的采样间隔)
y2.t0 = 0; % set the time stamp
y2.T = 1/(y2.dt * y2.df); % 总的仿真的时间窗口/时间间隔=时域上的采样点数 % set the duration of the signal in grid points unit (=Duration/time grid spacing)
y2.fs = round(SampleRate/y2.df); % set the bandwidth of the structure in grid points unit
y2.band.type = 'eband';
y2.band.fs = round(SampleRate/y2.df);
%-------------------------------
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ofdm_Signal_Real = zeros(1,Number_Of_Samples*samplesPerBit);
ofdm_Signal_Imag = zeros(1,Number_Of_Samples*samplesPerBit);
for i = 1 : Number_Of_Samples
ofdm_Signal_Real((i-1)*samplesPerBit+1) = (TimeSignalX(i)); % 采用置0的方式进行过采样
ofdm_Signal_Imag((i-1)*samplesPerBit+1) = (TimeSignalY(i));
end
y1.band