%a_run_design.m 文件
setup
QAM
OFDM
Analysis
%系统设置
%QAM 调制方式
%OFDM 调制方式
%QAM 和 OFDM 两种方式对比
%初始化部分
1setup
% setup
disp(' '), disp('------------------------------------------------------------')
disp('Simulation Setup')
% OFDM Setup -----------------------------------------------------------
fft_size = 128
% should be a power of 2 for fast computation
% more points = more time domain samples (smoother & more cycles)
num_carriers = 32 % should be <= fft_size/4
% number of carriers used for each data chunk
% new var - denotes even spacing or variations of carriers among fft points
input_type = 2;
% 1 = test input
test_input_type = 1;
% 1 = bit specified (binary)
binary_data = [0 1 0 1 0 1 0 1];
% 2 = random data stream (samples in the range of 0-255)
num_symbols = 9;
% 3 = sinusoidal
frequency = 2;
num_samples = 50;
% 2 = external file input
file_name = 'shortest.wav';
file_input_type = 3;
% Name of input file
% 1 = binary (not implemented)
% 2 = text
% 3 = sound
% 4 = image (not implemented)
% Demo file:
'text.txt'
% Demo files: 'shortest.wav' & 'shorter.wav'
% QAM Setup ------------------------------------------------------------
do_QAM = 1;
QAM_periods = 10;
% (1=on, 0=off)
% defines the number of periods per QAM Symbos (1=2*pi)
% Channel Simulation Parameters --------------------------------------------
channel_on = 1;
clip_level = 1.0;
% 1=on, 0=off
% 0.0 - 1.0 (0-100%)
% Max magnitude of the signal is 'clip_level' times the full magnitude of the signal
noise_level = 0.0; % 0.0 - 1.0 (0-100%)
1
% Magnitude of noise is 'noise_level' times the magnitude of the signal
% Multipath Channel Simulation
% Good defaults when fft_size = 128 and num_carriers = 32:
% d1=6; a1=0.30; d2=10; a2=0.25
d1 = 6;
a1 = 0.30;
d2 = 10;
a2 = 0.25;
% delay in units
% attenuation factor - multipath signal is x% of size or original signal
% delay for second multipath signal
% attenuation factor for second multipath signal
% ****************** TEST INPUT SETUP - DO NOT MODIFY **************************
if input_type == 1
if test_input_type == 1
%specify BINARY input bit-by-bit
data_in = binary_data;
end
if test_input_type == 2
%random input defined by parameters
num_levels = 255;
%number of possible levels of a symbol
%must be integer between 1-255
data_samples = round(rand(1,num_symbols)*(num_levels-1));
data_in = zeros(1,8*length(data_samples));
for i = 1:length(data_samples)
data_in(1 + (i-1)*8:(i-1)*8 + 8) = eight2bin(data_samples(i));
end
end
if test_input_type == 3
%data stream represents sine wave samples
t = linspace(0,1,num_symbols); %evenly space number of samples
%take 8-bit samples of sine wave
data_samples = round(127.5*sin(frequency*2*pi*t) +127.5);
data_in = zeros(1,8*length(data_samples));
for i = 1:length(data_samples)
data_in(1 + (i-1)*8:(i-1)*8 + 8) = eight2bin(data_samples(i));
end
end
end
already_made_noise = 0;
% initialization (don't change)
2、QAM.m
% QAM.m compares OFDM (multicarrier) to multi-level QAM (single carrier)
% when they transmit the same # of bits in a given time period
read
% read data for QAM - does not affect OFDM
2
data_in_pol = bin2pol(data_in);
% Converts binary data to polar data
% check to see if num_carriers is a power of 2
is_pow_2 = num_carriers;
temp_do_QAM = 0;
if is_pow_2 ~= 2
while temp_do_QAM == 0
temp_do_QAM = rem(is_pow_2,2);
is_pow_2 = is_pow_2/2;
if is_pow_2 == 2
temp_do_QAM = -99;
% it is a power of 2 -> can do QAM
end
end
else
temp_do_QAM = -99; % 2 is a power of 2
end
if temp_do_QAM ~= -99
do_QAM = 0; % don't do it if it's not possible
disp(' '),disp('ERROR: Cannot run QAM because num_carriers is not valid.')
disp('
Please see "setup.m" for details.')
end
if do_QAM == 1
tic % Start stopwatch to calculate how long QAM simulation takes
disp(' '), disp('------------------------------------------------------------')
disp('QAM simulation'), disp('Transmitting')
% Pad with zeros so data can be divided evenly
data_length = length(data_in_pol);
r = rem(data_length,num_carriers);
if r ~= 0
for i = 1:num_carriers-r
data_in_pol(data_length+i) = 0; %pad input with zeros to complete last data set
end
%speed improve possible
end
data_length = length(data_in_pol);
%update after padding
num_OFDM_symbols = ceil(data_length / (2*num_carriers));
% num QAM symbols that represent equal amount of data to one OFDM symbol
num_QAM_symbols = num_carriers / 2;
% num samples per QAM symbol
num_symbol_samples = fft_size / num_QAM_symbols;
% convert polar data [-1, 1] to 4 level data [-3, -1, 1, 3]
3
data_in_4 = zeros(1,data_length/2);
for i = 1:2:data_length
data_in_4(i - (i-1)/2) = data_in_pol(i)*2 + data_in_pol(i+1);
end
% define sample points between 0 and 2*pi
ts = linspace(0, 2*pi*QAM_periods, num_symbol_samples+1);
% Generate 16-QAM data
% total length of 16-QAM transmission
tx_length = num_OFDM_symbols * num_QAM_symbols * num_symbol_samples;
QAM_tx_data = zeros(1,tx_length);
for i = 1:2:data_length/2
for k = 1:num_symbol_samples
QAM_tx_data(k+((i-1)/2)*num_symbol_samples)
=
data_in_4(i)*cos(ts(k))
+
data_in_4(i+1)*sin(ts(k));
end
end
% ch uses 'xmit' data and returns 'recv'
% Do channel simulation on QAM data
xmit = QAM_tx_data;
ch
QAM_rx_data = recv;
clear recv
clear xmit
% save QAM data after channel
% remove 'recv' so it won't interfere with OFDM
% remove 'xmit' so it won't interfere with OFDM
% Recover Binary data (Decode QAM)
disp('Receiving')
cos_temp = zeros(1,num_symbol_samples);
sin_temp = cos_temp;
xxx = zeros(1,data_length/4);
yyy = xxx;
QAM_data_out_4 = zeros(1,data_length/2);
%
%
% Initialize to zeros for speed
%
%
for i = 1:2:data_length/2 % "cheating"
for k = 1:num_symbol_samples
% multiply by carriers to produce high frequency term and original data
cos_temp(k) = QAM_rx_data(k+((i-1)/2)*num_symbol_samples) * cos(ts(k));
sin_temp(k) = QAM_rx_data(k+((i-1)/2)*num_symbol_samples) * sin(ts(k));
end
% LPF and decide - we will do very simple LPF by averaging
xxx(1+(i-1)/2) = mean(cos_temp);
yyy(1+(i-1)/2) = mean(sin_temp);
% Reconstruct data in serial form
QAM_data_out_4(i) = xxx(1+(i-1)/2);
QAM_data_out_4(i+1) = yyy(1+(i-1)/2);
end
4
% Make decision between [-3, -1, 1, 3]
for i = 1:data_length/2
if QAM_data_out_4(i) >= 1, QAM_data_out_4(i) = 3;
elseif QAM_data_out_4(i) >= 0, QAM_data_out_4(i) = 1;
elseif QAM_data_out_4(i) >= -1, QAM_data_out_4(i) = -1;
else QAM_data_out_4(i) = -3;
end
end
% Convert 4 level data [-3, -1, 1, 3] back to polar data [-1, 1]
QAM_data_out_pol = zeros(1,data_length); % "cheating"
for i = 1:2:data_length
switch QAM_data_out_4(1 + (i-1)/2)
case -3
QAM_data_out_pol(i) = -1;
QAM_data_out_pol(i+1) = -1;
case -1
QAM_data_out_pol(i) = -1;
QAM_data_out_pol(i+1) = 1;
case 1
QAM_data_out_pol(i) = 1;
QAM_data_out_pol(i+1) = -1;
case 3
QAM_data_out_pol(i) = 1;
QAM_data_out_pol(i+1) = 1;
otherwise
disp('Error detected in switch statment - This should not be happening.');
end
end
QAM_data_out = pol2bin(QAM_data_out_pol); % convert back to binary
% Stop stopwatch to calculate how long QAM simulation takes
QAM_simulation_time = toc;
if QAM_simulation_time > 60
disp(strcat('Time for QAM simulation=', num2str(QAM_simulation_time/60), ' minutes.'));
disp(strcat('Time for QAM simulation=', num2str(QAM_simulation_time), ' seconds.'));
else
end
end
3 % Run OFDM simulation
tic % Start stopwatch to calculate how long QAM simulation takes
disp(' '),disp('------------------------------------------------------------')
disp('OFDM Simulation')
5
tx
ch
rx
% Stop stopwatch to calculate how long QAM simulation takes
OFDM_simulation_time = toc;
if OFDM_simulation_time > 60
disp(strcat('Time for OFDM simulation=', num2str(OFDM_simulation_time/60), ' minutes.'));
disp(strcat('Time for OFDM simulation=', num2str(OFDM_simulation_time), ' seconds.'));
else
end
3.1 发送
% tx
disp('Transmitting')
read
data_in_pol = bin2pol(data_in);
tx_chunk
%read original data
% Converts binary data to polar data
%convert polar data into chunks.
% perform ifft to create time domain waveform representing data
td_sets = zeros(num_chunks,fft_size);
for i = 1:num_chunks
td_sets(i,1:fft_size) = real(ifft(spaced_chunks(i,1:fft_size)));
end
tx_dechunk
% Construct signal to transmit by placing time domain sets in series
3.1.1 % tx_chunk %双极性数组转化成 OFDM 字符串
data_length = length(data_in_pol)
num_carriers
num_chunks = ceil(data_length/(2*num_carriers))
r = rem(data_length,2*num_carriers)
if r ~= 0
%number of symbols in original input
%2 data on each carrier (real and imaginary)
for i = 1:num_carriers*2-r
data_in_pol(data_length+i) = 0; %pad input with zeros to complete last data set
%speed improve possible
end
end
% break data into chunks
chunks = zeros(num_chunks,num_carriers); % for speed
for i = 1:num_chunks
% *********************chunk done
for k = 1:num_carriers
chunks(i,k)
=
data_in_pol(2*num_carriers*(i-1)+k)
+
data_in_pol(2*num_carriers*(i-1)+k+num_carriers)*j;
end
end
6
chunks
% Padding chunks with zeros so num_carriers and fft_size are compatible
% Once compatible, further spacing is simplified
num_desired_carriers = num_carriers;
num_zeros = 0;
thinking = 1;
while thinking == 1 % Continue if num_carriers and fft_size are not compatible
if rem(fft_size/2,num_desired_carriers) == 0
thinking = 0;
num_desired_carriers = num_desired_carriers + 1;
num_zeros = num_zeros + 1;
else
end
end
padded_chunks = zeros(num_chunks,num_carriers + num_zeros); % for speed
padded_chunks(1:num_chunks,num_zeros + 1:num_carriers + num_zeros) = chunks;
%compute zeros_between
zeros_between = ((fft_size/2) - (num_carriers + num_zeros))/(num_carriers + num_zeros);
spaced_chunks = zeros(num_chunks,fft_size); % for speed - extra room for folding later
%add zeros_between
i = 1;
for k = zeros_between +1:zeros_between +1:fft_size/2
spaced_chunks(1:num_chunks,k) = padded_chunks(1:num_chunks,i);
i = i+1;
end
% folding data to produce an odd function for ifft input
for i = 1:num_chunks
% Note: index = 1 is actually DC freq for ifft -> it does not get copied over y-axis
spaced_chunks(i,fft_size:-1:fft_size/2+2) = conj(spaced_chunks(i,2:fft_size/2));
end
3.1.2 tx_dechunk
% tx_dechunk
% Construct signal to transmit by placing time domain sets in series
xmit = zeros(1,num_chunks*fft_size);
for i = 1:num_chunks
for k = 1:fft_size
xmit(k + (i-1)*fft_size) = td_sets(i,k);
end
7
end
3.2 %ch.m
% ch
recv = xmit; % channel is applied to recv, don't modify transmitted data
if channel_on == 1
disp('Simulating Channel')
norm_factor = max(abs(recv)); % Normalize all data before applying
recv = (1/norm_factor) * recv;
ch_clipping
ch_multipath
ch_noise
recv = norm_factor * recv;
%clipp data
%
%
% channel for a fair comparison
% Restore data magnitude for proper decoding
end
3.2.1 %ch_clipping.m
% ch_clipping
for i = 1:length(recv)
if recv(i) > clip_level
recv(i) = clip_level;
end
if recv(i) < -clip_level
recv(i) = -clip_level;
end
end
3.2.2 % ch_multipath
copy1=zeros(size(recv));
for i=1+d1:length(recv)
copy1(i)=a1*recv(i-d1);
end
copy2=zeros(size(recv));
for i=1+d2:length(recv)
copy2(i)=a2*recv(i-d2);
end
recv=recv+copy1+copy2;
% 产生多经的方法
3.2.3、%ch_noise
%施加信道噪声
% ch_noise (operate on recv)
% random noise defined by noise_level amplitude
if already_made_noise == 0 % only generate once and use for both QAM and OFDM
noise = (rand(1,length(recv))-0.5)*2*noise_level;
already_made_noise = 1;
end
recv = recv + noise;
8