From 4dd65313fe9d62a850be15de41afe4b3549723f2 Mon Sep 17 00:00:00 2001 From: Adrian Iain Lam Date: Mon, 22 Oct 2018 00:09:34 +0100 Subject: [PATCH] Use more library functions; generalized to 2^k-PSK The previous "initial" version was reinventing the wheel with PSK modulation/demod, AWGN etc. This version used the library functions, renamed some variables for consistency; generalized code to work for M-PSK (M=2^k), and included theoretical upper bounds and approximations for M > 4. --- BER_SNR_16PSK_100000.svg | 252 ++++++++++++++++++++++++++++++++++ BER_SNR_2PSK_100000.svg | 340 ++++++++++++++++++++++++++++++++++++++++++++++ BER_SNR_32PSK_100000.svg | 226 +++++++++++++++++++++++++++++++ BER_SNR_4PSK_100000.svg | 341 +++++++++++++++++++++++++++++++++++++++++++++++ BER_SNR_8PSK_100000.svg | 286 +++++++++++++++++++++++++++++++++++++++ BPSK_BER_SNR_1000.svg | 203 ---------------------------- BPSK_BER_SNR_1000000.svg | 321 -------------------------------------------- SNRvsBER_BPSKdiscrete.m | 53 -------- decodeNoisyBPSK.m | 3 - discreteAWGN.m | 3 - discretePSK_BER_SNR.m | 77 +++++++++++ randomPSK.m | 15 --- 12 files changed, 1522 insertions(+), 598 deletions(-) create mode 100644 BER_SNR_16PSK_100000.svg create mode 100644 BER_SNR_2PSK_100000.svg create mode 100644 BER_SNR_32PSK_100000.svg create mode 100644 BER_SNR_4PSK_100000.svg create mode 100644 BER_SNR_8PSK_100000.svg delete mode 100644 BPSK_BER_SNR_1000.svg delete mode 100644 BPSK_BER_SNR_1000000.svg delete mode 100644 SNRvsBER_BPSKdiscrete.m delete mode 100644 decodeNoisyBPSK.m delete mode 100644 discreteAWGN.m create mode 100644 discretePSK_BER_SNR.m delete mode 100644 randomPSK.m diff --git a/BER_SNR_16PSK_100000.svg b/BER_SNR_16PSK_100000.svg new file mode 100644 index 0000000..3ac1851 --- /dev/null +++ b/BER_SNR_16PSK_100000.svg @@ -0,0 +1,252 @@ + + + diff --git a/BER_SNR_2PSK_100000.svg b/BER_SNR_2PSK_100000.svg new file mode 100644 index 0000000..1966abf --- /dev/null +++ b/BER_SNR_2PSK_100000.svg @@ -0,0 +1,340 @@ + + + diff --git a/BER_SNR_32PSK_100000.svg b/BER_SNR_32PSK_100000.svg new file mode 100644 index 0000000..a45407f --- /dev/null +++ b/BER_SNR_32PSK_100000.svg @@ -0,0 +1,226 @@ + + + diff --git a/BER_SNR_4PSK_100000.svg b/BER_SNR_4PSK_100000.svg new file mode 100644 index 0000000..04a62ba --- /dev/null +++ b/BER_SNR_4PSK_100000.svg @@ -0,0 +1,341 @@ + + + diff --git a/BER_SNR_8PSK_100000.svg b/BER_SNR_8PSK_100000.svg new file mode 100644 index 0000000..d19634e --- /dev/null +++ b/BER_SNR_8PSK_100000.svg @@ -0,0 +1,286 @@ + + + diff --git a/BPSK_BER_SNR_1000.svg b/BPSK_BER_SNR_1000.svg deleted file mode 100644 index 1f4ce97..0000000 --- a/BPSK_BER_SNR_1000.svg +++ /dev/null @@ -1,203 +0,0 @@ - - -glps_renderer figure - -Creator: GL2PS 1.3.8, (C) 1999-2012 C. Geuzaine -For: Octave -CreationDate: Sun Oct 21 16:58:38 2018 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 -2 -4 -6 -8 -10 - - - - - - - - - - - - - - - - - - -1e-6 -1e-5 -1e-4 -1e-3 -1e-2 -1e-1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -$E_b/N_0$ (dB) -BER - - - - - - -Simulated -$Q\left(\sqrt{2 E_b / N_0}\right)$ - - - - diff --git a/BPSK_BER_SNR_1000000.svg b/BPSK_BER_SNR_1000000.svg deleted file mode 100644 index 9ff96eb..0000000 --- a/BPSK_BER_SNR_1000000.svg +++ /dev/null @@ -1,321 +0,0 @@ - - - diff --git a/SNRvsBER_BPSKdiscrete.m b/SNRvsBER_BPSKdiscrete.m deleted file mode 100644 index 4a6c30d..0000000 --- a/SNRvsBER_BPSKdiscrete.m +++ /dev/null @@ -1,53 +0,0 @@ -function SNRvsBER_BPSKdiscrete(numBits) - if nargin < 1 - numBits = 1000; - end - - if isOctave() - pkg load communications - end - - %% SNR: Eb/N0 - snr_db = 0:0.2:10; - snr = 10 .^ (snr_db ./ 10); - - %% Eb is assumed to be 1 - %% noise N ~ Gaussian(mean=0, variance=N0/2) - N0 = 1 ./ snr; - - ber = zeros(1, length(snr)); - - data = randomPSK(2, numBits); - - for i = 1:length(snr) - noisyData = discreteAWGN(data, N0(i)); - decodedData = decodeNoisyBPSK(noisyData); - - bitErrors = sum(data ~= decodedData); - ber(i) = bitErrors / numBits; - end - - fig1 = figure(1); - clf; - - %% Plot simulated results - semilogy(snr_db, ber, 'r', 'LineWidth', 2); - hold on; - - %% Plot theoretical curve - %% BPSK: bit error when noise N > sqrt(Eb) - %% Pr(N > sqrt(Eb)) - %% = Pr(Z > sqrt(Eb) / sqrt(N0/2)) - %% = Q(sqrt(2 * SNR)) - ber_th = qfunc(sqrt(2 * snr)); - semilogy(snr_db, ber_th, 'b', 'LineWidth', 1); - - grid on; - xlabel('$E_b/N_0$ (dB)'); - ylabel('BER'); - legend('Simulated', '$Q\left(\sqrt{2 E_b / N_0}\right)$'); - - formatFigure; - saveas(gcf, strcat('BPSK_BER_SNR_', num2str(numBits), '.svg')); - -end diff --git a/decodeNoisyBPSK.m b/decodeNoisyBPSK.m deleted file mode 100644 index 70ef8f8..0000000 --- a/decodeNoisyBPSK.m +++ /dev/null @@ -1,3 +0,0 @@ -function x = decodeNoisyBPSK(noisyData) - x = (noisyData > 0) - (noisyData <= 0); -end diff --git a/discreteAWGN.m b/discreteAWGN.m deleted file mode 100644 index 1aab2b9..0000000 --- a/discreteAWGN.m +++ /dev/null @@ -1,3 +0,0 @@ -function x = discreteAWGN(data, N0) - x = data + normrnd(0, sqrt(N0 / 2), 1, length(data)); -end diff --git a/discretePSK_BER_SNR.m b/discretePSK_BER_SNR.m new file mode 100644 index 0000000..fd8849c --- /dev/null +++ b/discretePSK_BER_SNR.m @@ -0,0 +1,77 @@ +function discretePSK_BER_SNR(M, numBits) + %% Set defaults for inputs + if nargin < 2 + numBits = 1000; + end + if nargin < 1 + M = 2; + end + + if isOctave() + pkg load communications + end + + EbN0_db = 0:0.2:10; + EbN0 = 10 .^ (EbN0_db ./ 10); + + Es = 1; + Eb = Es / log2(M); + N0 = Eb ./ EbN0; + + EsN0 = EbN0 .* log2(M); + EsN0_db = 10 .* log10(EsN0); + + plotlen = length(EbN0); + + ber = zeros(1, plotlen); + + data = randi([0, M - 1], 1, numBits); + txsig = pskmod(data, M, 0, 'gray'); + + for i = 1:plotlen + rxsig = awgn(txsig, EsN0_db(i)); + demodData = pskdemod(rxsig, M, 0, 'gray'); + + [bitErrors, ber(i)] = biterr(data, demodData); + end + + fig1 = figure(1); + clf; + + %% Plot simulated results + semilogy(EbN0_db, ber, 'r', 'LineWidth', 2); + hold on; + + %% Plot theoretical curve + %% BPSK: bit error when noise Nr > sqrt(Eb) + %% Pr(Nr > sqrt(Eb)) + %% = Pr(Z > sqrt(Eb) / sqrt(N0/2)) + %% + %% QPSK = 2 BPSKs, one real and one imaginary, each with one bit + %% so BER is the same as BPSK (assuming Gray code) + if M == 2 || M == 4 + ber_th = qfunc(sqrt(2 * EbN0)); + semilogy(EbN0_db, ber_th, 'b', 'LineWidth', 1); + legend('Simulated', 'Theoretical'); + else + %% Upper bound: R. Venkataramanan, Lent 2018, 3F4 Examples Paper 2 + %% (Question 5), CUED. + %% Approximation: J.G. Proakis and M. Salehi, 2000, Contemporary + %% Communication Systems using MATLAB (Equations + %% 7.3.18 and 7.3.19), Brooks/Cole. + ber_ub = 2 * qfunc(sqrt(EbN0 * log2(M)) * sin(pi / M)); + ber_ap = 2 * qfunc(sqrt(EbN0 * log2(M) * 2) * sin(pi / M)) / log2(M); + semilogy(EbN0_db, ber_ub, 'b', 'LineWidth', 1); + semilogy(EbN0_db, ber_ap, 'g', 'LineWidth', 1); + legend('Simulated', 'Upper bound', 'Approximation'); + end + + title(strcat(num2str(M), '-PSK with Gray code')); + grid on; + xlabel('$E_b/N_0$ (dB)'); + ylabel('BER'); + + formatFigure; + saveas(gcf, strcat('BER_SNR_', num2str(M), 'PSK_', num2str(numBits), ... + '.svg')); +end diff --git a/randomPSK.m b/randomPSK.m deleted file mode 100644 index 7521bef..0000000 --- a/randomPSK.m +++ /dev/null @@ -1,15 +0,0 @@ -function x = randomPSK(n, len) - % symbols: nth roots of unity - % i.e. solutions to polynomial x^n - 1 = 0 - symbols = roots([1 zeros(1, n-1) -1]); - - x = zeros(1, len); - for i = 1:len - x(i) = randomChoice(symbols); - end -end - -function x = randomChoice(arr) - i = randi(length(arr)); - x = arr(i); -end -- 2.7.4