% Lyceum-friendly function for plotting the BER vs SNR curve of BPSK modulation in an AWGN channel.
% This function will attempt to simulate the SNRs (in dB) from the set SNR_start:SNR_delta:SNR_stop.
% It will stop if the BER target BER_stop is reached or if the job is killed.
% On Lyceum, this will happen if you run out of time or if you use the qdel command.
% On a PC, you can kill the job by pressing Ctrl-C.
% The function is written so that the results obtained so far are not lost when the job is killed.
% Copyright (C) 2009 Robert G. Maunder
% This program is free software: you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation, either version 3 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.
% The GNU General Public License can be seen at http://www.gnu.org/licenses/.
function main_qpsk(SNR_start, SNR_delta, SNR_stop, BER_stop)
% Choose a file to save the results into.
filename = ['results_',num2str(SNR_start),'.mat'];
% Doing the simulation frame-by-frame rather than bit-by-bit speeds it up. This is because we can use vector operations instead of longer loops.
frame_length = 10000;
% Setup the SNR for the first iteration of the loop.
SNR_count = 1;
SNR = SNR_start;
BER = 1;
% Loop until the job is killed or until the SNR or BER target is reached.
while SNR <= SNR_stop && BER >= BER_stop
% Convert from SNR (in dB) to noise power spectral density.
N0 = 1/(10^(SNR/10));
% Counters to store the number of errors and bits simulated so far.
error_count=0;
bit_count=0;
% Keep going until enough errors have been observed. This runs the simulation only as long as is required to keep the BER vs SNR curve smooth.
while error_count < 100
% Generate some random bits.
bits = round(rand(1,frame_length));
b_1 = bits(1:2:frame_length);
b_2 = bits(2:2:frame_length);
j=sqrt(-1);
a = 1/sqrt(2); % amplitude
symbols=a*(-2*(b_1-0.5)+j*-2*(b_2-0.5)); % QPSK symbols
% Add some complex Gaussian distributed noise.
received_symbols = symbols + sqrt(N0/2)*(randn(1,length(symbols))+j*randn(1,length(symbols)));
% Perform BPSK demodulation.
recovered_bits_r = real(received_symbols)<0;
recovered_bits_i = imag(received_symbols)<0;
% Accumulate the number of errors and bits that have been simulated so far.
error_count = error_count + sum(recovered_bits_r ~= b_1)+sum(recovered_bits_i ~= b_2);
bit_count = bit_count + frame_length;
end
% Calculate the BER.
BER = error_count/bit_count;
% Store the SNR and BER in a matrix and display it.
results(SNR_count,1) = SNR;
results(SNR_count,2) = BER
% Save the results into binary files. This avoids the loss of precision that is associated with ASCII files.
save(filename, 'results', '-MAT');
% Plot the results. This will be ignored on Lyceum.
semilogy(results(:,1),results(:,2));
title('BPSK modulation in an AWGN channel');
ylabel('BER');
xlabel('SNR (in dB)');
if BER_stop ~= 0
ylim([BER_stop,1]);
end
if SNR_stop ~= inf
xlim([SNR_start, SNR_stop]);
end
% Setup the SNR for the next iteration of the loop.
SNR = SNR + SNR_delta;
SNR_count = SNR_count + 1;
end
end
% input : main_qpsk(2,2,12,0.00001)