├── Michael - Part I - V12 (Final) ├── Part I - V12.zip ├── Simulation_yu_backup.zip ├── Simulation_yu_backup ├── Cold1.m ├── Cold1_v3.m ├── CommunicationChain.m ├── FoM.m ├── MaxLikelihood.m ├── RRCfilterDesign.m ├── demapping.m ├── demappinga.m ├── makeLdpc.m ├── makeParityChk.m ├── mapping.m ├── mappinga.m ├── maxLikelihooda.m ├── mlf2pdfExample.m └── rrc.m ├── Simulations-V11 ├── DVBS2CommunicationChain.m ├── FoM.m ├── RRCFDesign.m ├── demapping.m ├── makeLdpc.m ├── makeParityChk.m ├── mapping.m ├── maxLikelihood.m └── rx_constellations.fig ├── Simulations-V21 ├── CFO_est.m ├── DVBS2CommunicationChain.m ├── DVBS2CommunicationChain_GC.m ├── FoM.m ├── RRCFDesign.m ├── RRCfilterDesign.m ├── demapping.m ├── gardner_est.m ├── makeLdpc.m ├── makeParityChk.m ├── mapping.m ├── maxLikelihood.m └── pilot_est.m ├── Simulations-V22r.zip ├── Simulations-V31.zip ├── Simulations-V32-Gardner-Pilot.zip ├── Simulations-V32 ├── DVBS2CommunicationChain.m ├── DVBS2CommunicationChain.m~ ├── DVBS2CommunicationChain_GC.m ├── FoM.m ├── RRCFDesign.m ├── RRCfilterDesign.m ├── demapping.m ├── gardner_est.m ├── makeLdpc.m ├── makeParityChk.m ├── mapping.m ├── maxLikelihood.m └── pilot_est.m ├── document ├── Labo 1v2016_2.pptx ├── MC-Report-V3.docx ├── labProject-ModCod.pdf ├── report_s1.docx ├── report_s2.docx └── report_s3.docx └── figures ├── BERvsEbN0.jpg ├── Block Diagram.png ├── Sans titre.png ├── Transceiver Block Diagram - Baseband Equivalent Model.png ├── Transceiver Block Diagram.png ├── constellations.fig ├── filterfreq.jpg ├── filterfreq.svg └── filtert.jpg /Michael - Part I - V12 (Final): -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Part I - V12.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Part I - V12.zip -------------------------------------------------------------------------------- /Simulation_yu_backup.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulation_yu_backup.zip -------------------------------------------------------------------------------- /Simulation_yu_backup/Cold1.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Projcect 2 | % Part 1 3 | % 2015/Mar/19 4 | % TEAM:MOY Michael,Omar,Yu 5 | 6 | %% Readme 7 | % For part one, we implement following funcions: 8 | % 1. generate informaiton (binary) sequence 9 | % 2. mapping the binary seq 10 | % 3. apply filter for tx side 11 | % 4. add Gausion noise 12 | 13 | %% 1.[TX] Initialization and Generating Bit-stream 14 | clear; 15 | close all; 16 | 17 | % generate input binary sequence by equal possiblity 0 and 1 18 | tx_len = 40000; 19 | Modu.mod = 'qam'; %[!] using QAM 20 | Modu.Nbps = 4; %[!] 16QAM(4bits) 21 | Modu.bps = tx_len; % [bits/sec] assuming 1sec for such length of bits 22 | Modu.fsymb = tx_len/Modu.Nbps; % [sample/sec] 1e4 23 | Modu.tsymb = 1/Modu.fsymb; % [sec]T:symbol time 24 | Modu.M = 4; %[!]Up sampling factor 25 | Modu.fsample = Modu.M*Modu.fsymb; % define sampling time 4*fsymbol=4e4 26 | 27 | tx_bin = randi([0 1],tx_len,1); 28 | [tx_symb] = mapping(tx_bin,Modu.Nbps,Modu.mod); % mapping the binary seq get Re,Im 29 | tx_symb_R = real(tx_symb); 30 | tx_symb_I = imag(tx_symb); 31 | % plot constellations figure 32 | figure 33 | scatter(tx_symb_R,tx_symb_I); 34 | title('Constellation Mapping of 16QAM'); 35 | 36 | 37 | %% 2.1[TX] Filtering with RRC 38 | % using self-define function to design RRC filter 39 | RRCF.beta = 0.5; 40 | RRCF.Ntaps = 33; %[?] How to select 41 | RRCF.td = RRCfilterDesign(RRCF.beta,RRCF.Ntaps,Modu.tsymb,Modu.fsample); 42 | 43 | % using rcosdesign ToolBox to design the filter 44 | span = 8; 45 | sps = 4; 46 | h1 = rcosdesign(RRCF.beta,span,sps,'sqrt'); 47 | figure 48 | stem(h1,'r'); 49 | hold on 50 | stem(RRCF.td,'b'); 51 | legend('Toolbox','SelfDefine'); 52 | title('Square Raised Cosine Filter') 53 | 54 | %RRCF.td = RRCfilterDesign(RRCF.beta,RRCF.Ntaps,1e-6,4e6); %[?] How to do Upsampling 55 | 56 | %% 2.2[TX] Upsampling 57 | % Upsampling *M, is to upsample the fsymbol to fsample by factor [4] 58 | tx_usymb = upsample(tx_symb,Modu.M); 59 | 60 | tx_usymb_R = real(tx_usymb); 61 | tx_usymb_I = imag(tx_usymb); 62 | 63 | % apply the filter 64 | tx_af = conv(tx_usymb,h1); 65 | % trunc the result 66 | tx_af_trunc = tx_af((RRCF.Ntaps+1)/2:length(tx_af)-(RRCF.Ntaps+1)/2+1); 67 | tx_af_R_trunc = real(tx_af_trunc); 68 | 69 | 70 | %% 3.[Channel] Adding noise 71 | 72 | % Calculate the energy of the signal 73 | SignalEnergy = (trapz(abs(tx_af_R_trunc).^2))*(1/Modu.fsample); 74 | Eb = SignalEnergy/Modu.Nbps; 75 | Eb = Eb/2; %[?] why we need to divide by 2 here [?] 76 | EbN0 = 3; %[!]EbN0: signal noise ratio[dB] 77 | N0 = Eb/db2mag(EbN0); 78 | NoisePower = 0; 79 | noise = zeros(1,length(tx_af_trunc)); 80 | noise = sqrt(NoisePower/2)*(randn(1,length(noise))+1i*randn(1,length(noise))); 81 | 82 | % add noise to the signal 83 | rx_usymb = tx_af_trunc+noise'; 84 | % rx_usymb_ = tx_af; 85 | 86 | % Match filter with the RRC 87 | rx_af = conv(rx_usymb,h1); 88 | % rx_af_ = conv(rx_usymb_,h1); 89 | 90 | rx_af_trunc = rx_af((RRCF.Ntaps+1)/2:length(rx_af)-(RRCF.Ntaps+1)/2+1); 91 | rx_af_R_trunc = real(rx_af_trunc); 92 | 93 | % rx_af_trunc_ = rx_af_(RRCF.Ntaps:length(rx_af_)-RRCF.Ntaps+1); 94 | 95 | % Downsampling the signal with factor M 96 | rx_symb = downsample(rx_af_trunc,Modu.M); 97 | % rx_symb_ = downsample(rx_af_trunc_,Modu.M); 98 | 99 | % plot the tx and rx filtered signal 100 | figure 101 | plot(tx_usymb_R(1:100),'rx'); 102 | hold on 103 | plot(tx_af_R_trunc(1:100),'g-o'); 104 | hold on 105 | plot(rx_af_R_trunc(1:100),'b-x'); 106 | title('[TX] after filter') 107 | 108 | 109 | %% 4.[RX] Demapping from Binary Sequence after the channel tx 110 | 111 | [rx_bin] = demapping(rx_symb,Modu.Nbps,Modu.mod); 112 | % [rx_bin_] = demapping(rx_symb_,Modu.Nbps,Modu.mod); 113 | 114 | rx_symb_R = real(rx_symb); 115 | rx_symb_I = imag(rx_symb); 116 | 117 | % rx_symb_R_ = real(rx_symb_); 118 | % rx_symb_I_ = imag(rx_symb_); 119 | 120 | % plot constellations figure 121 | figure 122 | scatter(rx_symb_R,rx_symb_I); 123 | title('Constellation Mapping of 16QAM'); 124 | 125 | rtcmp = rx_bin==tx_bin; 126 | num_rtcmp = sum(rtcmp); 127 | rat_rtcmp = num_rtcmp/tx_len % output the error ration of the coding and modulation. 128 | -------------------------------------------------------------------------------- /Simulation_yu_backup/Cold1_v3.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Projcect 2 | % Part 1 3 | % 2015/Mar/19 4 | % TEAM:MOY Michael,Omar,Yu 5 | 6 | %% Readme 7 | % For part one, we implement following funcions: 8 | % 1. generate informaiton (binary) sequence 9 | % 2. mapping the binary seq 10 | % 3. apply filter for tx side 11 | % 4. add Gausion noise 12 | 13 | %% 1.[TX] Initialization and Generating Bit-stream 14 | clear; 15 | close all; 16 | 17 | % generate input binary sequence by equal possiblity 0 and 1 18 | tx_len = 4000; 19 | Modu.mod = 'qam'; %[!] using QAM 20 | Modu.Nbps = 4; %[!] 16QAM(4bits) 21 | Modu.bps = 1e7; % [bits/sec] assuming 1sec for such length of bits 22 | Modu.fsymb = Modu.bps/Modu.Nbps; % [sample/sec] 1e4 23 | Modu.tsymb = 1/Modu.fsymb; % [sec]T:symbol time 24 | Modu.M = 20; %[!]Up sampling factor 25 | Modu.fsample = Modu.M*Modu.fsymb; % define sampling time 4*fsymbol=4e4 26 | 27 | tx_bin = randi([0 1],tx_len,1); 28 | %[tx_symb] = mapping(tx_bin,Modu.Nbps,Modu.mod); % mapping the binary seq get Re,Im 29 | [tx_symb] = mappinga(tx_bin,Modu.Nbps,'QAM'); % mapping the binary seq get Re,Im 30 | tx_symb_R = real(tx_symb); 31 | tx_symb_I = imag(tx_symb); 32 | % plot constellations figure 33 | figure 34 | scatter(tx_symb_R,tx_symb_I); 35 | title('Constellation Mapping of 16QAM'); 36 | 37 | 38 | %% 2.1[TX] Filtering with RRC 39 | % using self-define function to design RRC filter 40 | RRCF.beta = 0.5; 41 | RRCF.Ntaps = 33; %[?] How to select 42 | RRCF.td = RRCfilterDesign(RRCF.beta,RRCF.Ntaps,Modu.tsymb,Modu.fsample); 43 | %[RRCF.td]=rrc(Modu.fsample,Modu.fsymb,RRCF.Ntaps); 44 | 45 | % using rcosdesign ToolBox to design the filter 46 | span = 8; 47 | sps = 4; 48 | % [!]Select to use system design filter or Self-Design Filter 49 | % h1 = rcosdesign(RRCF.beta,span,sps,'sqrt'); 50 | h1 = RRCF.td; 51 | figure 52 | stem(h1,'r'); 53 | hold on 54 | stem(RRCF.td,'b'); 55 | legend('Toolbox','SelfDefine'); 56 | title('Square Raised Cosine Filter') 57 | 58 | %RRCF.td = RRCfilterDesign(RRCF.beta,RRCF.Ntaps,1e-6,4e6); %[?] How to do Upsampling 59 | 60 | %% 2.2[TX] Upsampling 61 | % Upsampling *M, is to upsample the fsymbol to fsample by factor [4] 62 | tx_usymb = upsample(tx_symb,Modu.M); 63 | 64 | tx_usymb_R = real(tx_usymb); 65 | tx_usymb_I = imag(tx_usymb); 66 | 67 | % apply the filter 68 | tx_af = conv(tx_usymb,h1); 69 | tx_af_R = real(tx_af); 70 | 71 | %% 3.[Channel] Adding noise 72 | 73 | % Calculate the energy of the signa 74 | 75 | EbN0 = 3; 76 | EbN0mag = 10^(EbN0/10); 77 | SignalEnergy = (trapz(abs(tx_af).^2))*(1/(Modu.fsample)); 78 | Eb = SignalEnergy/tx_len; 79 | Eb = Eb/2; 80 | N0 = Eb/EbN0mag; 81 | NoisePower = 2*N0*Modu.fsample; 82 | noise = (sqrt(NoisePower/2)*(rand(1,length(tx_af))+1i*rand(1,length(tx_af))))'; 83 | % add noise to the signal 84 | rx_usymb = tx_af+noise; 85 | %rx_usymb = awgn(tx_af,SNR); 86 | 87 | % Match filter with the RRC 88 | rx_af = conv(rx_usymb,h1); 89 | 90 | rx_af_trunc = rx_af(RRCF.Ntaps:length(rx_af)-RRCF.Ntaps+1); 91 | rx_af_R_trunc = real(rx_af_trunc); 92 | 93 | % Downsampling the signal with factor M 94 | rx_symb = downsample(rx_af_trunc,Modu.M); 95 | 96 | % plot the tx and rx filtered signal 97 | figure 98 | plot(tx_usymb_R(100:200),'ro'); 99 | hold on 100 | plot(rx_af_R_trunc(100:200),'b-x'); 101 | title('[TX] after filter') 102 | 103 | 104 | %% 4.[RX] Demapping from Binary Sequence after the channel tx 105 | 106 | [rx_bin] = demapping(rx_symb,Modu.Nbps,Modu.mod); 107 | 108 | rx_symb_R = real(rx_symb); 109 | rx_symb_I = imag(rx_symb); 110 | 111 | % plot constellations figure 112 | figure 113 | scatter(rx_symb_R,rx_symb_I); 114 | title('Constellation Mapping of 16QAM'); 115 | 116 | rtcmp = rx_bin==tx_bin; 117 | num_rtcmp = sum(rtcmp); 118 | rat_rtcmp = 1-num_rtcmp/tx_len % output the error ration of the coding and modulation. -------------------------------------------------------------------------------- /Simulation_yu_backup/CommunicationChain.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Projcect 2 | % Part 1 3 | % 2015/Mar/19 4 | % TEAM:MOY Michael,Omar,Yu 5 | 6 | %% Readme 7 | % For part one, we implement following funcions: 8 | % 1. generate informaiton (binary) sequence 9 | % 2. mapping the binary seq 10 | % 3. apply filter for tx side 11 | % 4. add Gausion noise 12 | 13 | %% 1.[TX] Initialization and Generating Bit-stream 14 | clear; 15 | close all; 16 | 17 | % generate input binary sequence by equal possiblity 0 and 1 18 | tx_len = 4000; 19 | Modu.mod = 'qam'; %[!] using QAM 20 | Modu.Nbps = 4; %[!] 16QAM(4bits) 21 | Modu.bps = 1e7; % [bits/sec] assuming 1sec for such length of bits 22 | Modu.fsymb = Modu.bps/Modu.Nbps; % [sample/sec] 1e4 23 | Modu.tsymb = 1/Modu.fsymb; % [sec]T:symbol time 24 | Modu.M = 4; %[!]Up sampling factor 25 | Modu.fsample = Modu.M*Modu.fsymb; % define sampling time 4*fsymbol=4e4 26 | 27 | tx_bin = randi([0 1],tx_len,1); 28 | %[tx_symb] = mapping(tx_bin,Modu.Nbps,Modu.mod); % mapping the binary seq get Re,Im 29 | [tx_symb] = mappinga(tx_bin,Modu.Nbps,'PSK'); % mapping the binary seq get Re,Im 30 | tx_symb_R = real(tx_symb); 31 | tx_symb_I = imag(tx_symb); 32 | % plot constellations figure 33 | figure 34 | scatter(tx_symb_R,tx_symb_I); 35 | title('Constellation Mapping of 16QAM'); 36 | 37 | 38 | %% 2.1[TX] Filtering with RRC 39 | % using self-define function to design RRC filter 40 | RRCF.beta = 0.5; 41 | RRCF.Ntaps = 33; %[?] How to select 42 | RRCF.td = RRCfilterDesign(RRCF.beta,RRCF.Ntaps,Modu.tsymb,Modu.fsample); 43 | %[RRCF.td]=rrc(Modu.fsample,Modu.fsymb,RRCF.Ntaps); 44 | 45 | % using rcosdesign ToolBox to design the filter 46 | span = 8; 47 | sps = 4; 48 | % [!]Select to use system design filter or Self-Design Filter 49 | % h1 = rcosdesign(RRCF.beta,span,sps,'sqrt'); 50 | h1 = RRCF.td; 51 | figure 52 | stem(h1,'r'); 53 | hold on 54 | stem(RRCF.td,'b'); 55 | legend('Toolbox','SelfDefine'); 56 | title('Square Raised Cosine Filter') 57 | 58 | %RRCF.td = RRCfilterDesign(RRCF.beta,RRCF.Ntaps,1e-6,4e6); %[?] How to do Upsampling 59 | 60 | %% 2.2[TX] Upsampling 61 | % Upsampling *M, is to upsample the fsymbol to fsample by factor [4] 62 | tx_usymb = upsample(tx_symb,Modu.M); 63 | 64 | tx_usymb_R = real(tx_usymb); 65 | tx_usymb_I = imag(tx_usymb); 66 | 67 | % apply the filter 68 | tx_af = conv(tx_usymb,h1); 69 | tx_af_R = real(tx_af); 70 | 71 | %% 3.[Channel] Adding noise 72 | 73 | % Calculate the energy of the signa 74 | 75 | EbN0 = 10; 76 | EbN0mag = 10^(EbN0/10); 77 | SignalEnergy = (trapz(abs(tx_af).^2))*(1/(Modu.fsample)); 78 | Eb = SignalEnergy/tx_len; 79 | Eb = Eb/2; 80 | N0 = Eb/EbN0mag; 81 | NoisePower = 2*N0*Modu.fsample; 82 | noise = (sqrt(NoisePower/2)*(rand(1,length(tx_af))+1i*rand(1,length(tx_af))))'; 83 | % add noise to the signal 84 | rx_usymb = tx_af+noise; 85 | %rx_usymb = awgn(tx_af,SNR); 86 | 87 | % Match filter with the RRC 88 | rx_af = conv(rx_usymb,h1); 89 | 90 | rx_af_trunc = rx_af(RRCF.Ntaps:length(rx_af)-RRCF.Ntaps+1); 91 | rx_af_R_trunc = real(rx_af_trunc); 92 | 93 | % Downsampling the signal with factor M 94 | rx_symb = downsample(rx_af_trunc,Modu.M); 95 | 96 | % plot the tx and rx filtered signal 97 | figure 98 | plot(tx_usymb_R(100:200),'ro'); 99 | hold on 100 | plot(rx_af_R_trunc(100:200),'b-x'); 101 | title('[TX] after filter') 102 | 103 | 104 | %% 4.[RX] Demapping from Binary Sequence after the channel tx 105 | 106 | [rx_bin] = demapping(rx_symb,Modu.Nbps,Modu.mod); 107 | 108 | rx_symb_R = real(rx_symb); 109 | rx_symb_I = imag(rx_symb); 110 | 111 | % plot constellations figure 112 | figure 113 | scatter(rx_symb_R,rx_symb_I); 114 | title('Constellation Mapping of 16QAM'); 115 | 116 | rtcmp = rx_bin==tx_bin; 117 | num_rtcmp = sum(rtcmp); 118 | rat_rtcmp = 1-num_rtcmp/tx_len % output the error ration of the coding and modulation. -------------------------------------------------------------------------------- /Simulation_yu_backup/FoM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulation_yu_backup/FoM.m -------------------------------------------------------------------------------- /Simulation_yu_backup/MaxLikelihood.m: -------------------------------------------------------------------------------- 1 | function [rx_symb_ML] = MaxLikelihood(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% MAXIMUM LIKELIHOOD CRITERION 9 | % By comparing the Received Symbols 'rx_symb' with the Symbols of Reference 'symb_ref' we can apply the ML Criterion and deduce 'rx_symb_ML' 10 | % INPUTS 11 | % 'rx_symb' - Symbols 12 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, CQAM] 13 | % 'Nbps' - Number of bits per symbol [1, 2, 3, 4, 5, 6] 14 | % OUTPUT 15 | % 'rx_symb_ML' - Symbols after the application of the Maximum Likelihood Criterion 16 | 17 | %% INITIALIZATION 18 | Nsymb = 2^Nbps; % Number of Symbols of Reference 19 | switch modulation 20 | %% ***** PULSE AMPLITUDE MODULATION ***** 21 | case 'PAM' 22 | % Generating Symbols of Reference 23 | distance = 2/(2^Nbps-1); 24 | symb_ref = distance * ((0:2^Nbps-1) - (2^Nbps-1)/2); 25 | 26 | % Application of the Maximum Likelihood Criterion 27 | rx_symb_ML = zeros(1,length(rx_symb)); % Initialize the length of the vector 28 | for index = 1:length(rx_symb) % At each loop, application of the ML Criterion on a Symbol of the Received Signal 29 | trans = norm(rx_symb(index) - symb_ref(1)); % Measure the Euclidean Norm with the first Symbol of Reference 30 | rx_symb_ML(index) = symb_ref(1); % This step is needed in order to apply a comparison from the first inner loop 31 | 32 | for index2 = 2:Nsymb % Loop to determine the minimal Euclidean Norm of each Received Symbol 33 | if norm(rx_symb(index) - symb_ref(index2)) < trans 34 | trans = norm(rx_symb(index) - symb_ref(index2)); 35 | rx_symb_ML(index) = symb_ref(index2); 36 | end 37 | end 38 | end 39 | rx_symb_ML = rx_symb_ML'; 40 | 41 | 42 | 43 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 44 | case 'QAM' 45 | % Generating Symbols of Reference 46 | Nbps_I = Nbps/2; 47 | distance_I = 2/(2^Nbps_I-1); 48 | symb_ref_I = distance_I * ((0:2^Nbps_I-1) - (2^Nbps_I-1)/2); 49 | Nbps_Q = Nbps/2; 50 | distance_Q = 2/(2^Nbps_Q-1); 51 | symb_ref_Q = distance_Q * ((0:2^Nbps_Q-1) - (2^Nbps_Q-1)/2); 52 | 53 | t = 1; 54 | symb_ref = zeros(1,length(symb_ref_I)*length(symb_ref_Q)); 55 | for index = 1:length(symb_ref_I) 56 | for index2 = 1:length(symb_ref_Q) 57 | symb_ref(t) = symb_ref_I(index) + 1i*symb_ref_Q(index2); 58 | t = t + 1; 59 | end 60 | end 61 | 62 | % Application of the Maximum Likelihood Criterion 63 | rx_symb_ML = zeros(1,length(rx_symb)); 64 | for index = 1:length(rx_symb) 65 | trans = norm(rx_symb(index) - symb_ref(1)); 66 | rx_symb_ML(index) = symb_ref(1); 67 | 68 | for index2 = 2:Nsymb % Loop to determine the minimal Euclidean Norm of each Received Symbol 69 | if norm(rx_symb(index) - symb_ref(index2)) < trans 70 | trans = norm(rx_symb(index) - symb_ref(index2)); 71 | rx_symb_ML(index) = symb_ref(index2); 72 | end 73 | end 74 | end 75 | rx_symb_ML = rx_symb_ML.'; 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /Simulation_yu_backup/RRCfilterDesign.m: -------------------------------------------------------------------------------- 1 | function [RRCf_time] = RRCfilterDesign(beta, NRRCtaps, tsymb, fsample) 2 | %INPUTS: 3 | % -beta: roll-off coefficient 4 | % -NRRCtaps: Number of RRC taps 5 | % -Tsym: sampling rate 6 | %OUTPUTS: 7 | % -RRCf_time: filter in time domain 8 | 9 | fmax = (1/NRRCtaps)*fsample*(NRRCtaps-1)/2; 10 | f = linspace(-fmax, fmax, NRRCtaps); % build the f x-axis 11 | Hrcf=zeros(1,NRRCtaps); 12 | 13 | for i=1:NRRCtaps 14 | if abs(f(i))<=((1-beta)/(2*tsymb)) 15 | Hrcf(i) = tsymb; 16 | elseif abs(f(i))>((1-beta)/(2*tsymb)) && abs(f(i))<=((1+beta)/(2*tsymb)) 17 | Hrcf(i) = tsymb/2*(1+cos(pi*tsymb/beta*(abs(f(i))-(1-beta)/(2*tsymb)))); 18 | else 19 | Hrcf(i) = 0; 20 | end 21 | end 22 | 23 | %Hrcf = fftshift(Hrcf); 24 | Hrrcf = sqrt(Hrcf); 25 | Hrrct = fftshift(ifft(ifftshift(Hrrcf), 'symmetric')); 26 | normCoeff = sqrt(max(abs(conv(Hrrct,Hrrct)))); 27 | Hrrct=Hrrct/normCoeff; 28 | %Hrrct = Hrrctv; 29 | % figure 30 | % stem(Hrrct); 31 | % title('Hrrct') 32 | 33 | %Hrctv = ifftshift(ifft(Hrcf,'symmetric')) 34 | %Hrct = circshift(Hrctv',-1); 35 | %fa = 1/Hrct((NRRCtaps+1)/2); 36 | %Hrct = Hrct.*fa; 37 | %Hrrct = Hrct.^(-2); 38 | 39 | % 40 | % Hrrcf = sqrt(Hrcf); 41 | % Hrrcf = fftshift(Hrrcf); 42 | % % figure 43 | % % plot(Hrcf); 44 | % % title('H(f) Square Root Cosine Filter') 45 | % 46 | % %Hrrct = ifft(Hrrcf); 47 | % Hrrctv = ifftshift(ifft(Hrrcf,'symmetric')); 48 | % Hrrct = circshift(Hrrctv',-1); 49 | % 50 | 51 | % figure 52 | % stem(Hrrct); 53 | % title('H(t)'); 54 | RRCf_time=Hrrct; 55 | 56 | end -------------------------------------------------------------------------------- /Simulation_yu_backup/demapping.m: -------------------------------------------------------------------------------- 1 | function [bit_rx] = demapping(symb_rx,Nbps,modulation) 2 | 3 | % INPUTS: 4 | % - symb_rx : vector of input symbols (variance 1) 5 | % - Nbps : number of bits per symbol 6 | % - modulation : 'pam' or 'qam' 7 | % 8 | % OUTPUTS: 9 | % - bit_rx : vector of ouput bits 10 | 11 | Nsymb = size(symb_rx,1); % Number of symbols 12 | 13 | switch modulation, 14 | 15 | case 'pam' 16 | 17 | % Symbol to integer 18 | sigma = sqrt(sum(([0:2^Nbps-1]-(2^Nbps-1)/2).^2)/2^Nbps); 19 | int_rx = sigma * symb_rx + (2^Nbps-1)/2; 20 | 21 | % Integer detection 22 | int_det = round(int_rx); 23 | int_det(find(int_det<0)) = 0; 24 | int_det(find(int_det>2^Nbps-1)) = 2^Nbps-1; 25 | 26 | % Integer to binary 27 | mapp_rx = fliplr(de2bi(int_det)); 28 | 29 | % Binary to gray 30 | bit_rx2(:,1) = mapp_rx(:,1); 31 | for ii = 2:Nbps, 32 | bit_rx2(:,ii) = xor( mapp_rx(:,ii-1) , mapp_rx(:,ii) ); 33 | end 34 | 35 | bit_rx = reshape(bit_rx2',Nsymb*Nbps,1); 36 | 37 | case 'qam' 38 | 39 | % REAL PART 40 | NbpsI = Nbps/2; 41 | symb_rxI = real(symb_rx); 42 | 43 | % Symbol to integer 44 | sigmaI = sqrt(sum(([0:2^NbpsI-1]-(2^NbpsI-1)/2).^2)/2^NbpsI); 45 | int_rxI = sigmaI * sqrt(2) * symb_rxI + (2^NbpsI-1)/2; 46 | 47 | % Integer detection 48 | int_detI = round(int_rxI); 49 | int_detI(find(int_detI<0)) = 0; 50 | int_detI(find(int_detI>2^NbpsI-1)) = 2^NbpsI-1; 51 | 52 | % Integer to binary 53 | mapp_rxI = fliplr(de2bi(int_detI)); 54 | 55 | % Binary to gray 56 | bit_rx2I(:,1) = mapp_rxI(:,1); 57 | for ii = 2:NbpsI, 58 | bit_rx2I(:,ii) = xor( mapp_rxI(:,ii-1) , mapp_rxI(:,ii) ); 59 | end 60 | 61 | 62 | % IMAGINARY PART 63 | NbpsQ = Nbps/2; 64 | symb_rxQ = imag(symb_rx); 65 | 66 | % Symbol to integer 67 | sigmaQ = sqrt(sum(([0:2^NbpsQ-1]-(2^NbpsQ-1)/2).^2)/2^NbpsQ); 68 | int_rxQ = sigmaQ * sqrt(2) * symb_rxQ + (2^NbpsQ-1)/2; 69 | 70 | % Integer detection 71 | int_detQ = round(int_rxQ); 72 | int_detQ(find(int_detQ<0)) = 0; 73 | int_detQ(find(int_detQ>2^NbpsI-1)) = 2^NbpsQ-1; 74 | 75 | % Integer to binary 76 | mapp_rxQ = fliplr(de2bi(int_detQ)); 77 | 78 | % Binary to gray 79 | bit_rx2Q(:,1) = mapp_rxQ(:,1); 80 | for ii = 2:NbpsQ, 81 | bit_rx2Q(:,ii) = xor( mapp_rxQ(:,ii-1) , mapp_rxQ(:,ii) ); 82 | end 83 | 84 | 85 | % BIT CONCATENATION 86 | bit_rx = reshape([bit_rx2I,bit_rx2Q]',Nsymb*Nbps,1); 87 | 88 | end -------------------------------------------------------------------------------- /Simulation_yu_backup/demappinga.m: -------------------------------------------------------------------------------- 1 | function [rx_bin] = demapping(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% DEMAPPING 9 | % INPUTS 10 | % 'rx_symb' - Symbols 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'rx_bit' - Bitstream 15 | 16 | 17 | %% INITIALIZATION 18 | Nsymb = size(rx_symb,1); % Number of symbols 19 | 20 | switch modulation 21 | %% ***** PULSE AMPLITUDE MODULATION ***** 22 | case 'PAM' 23 | % Symbol to Gray-Integer 24 | rx_int = maxLikelihood(rx_symb,Nbps,'PAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 25 | % Gray-Integer to Integer 26 | rx_int = gray2bin(rx_int,'PAM',2^Nbps); 27 | % Integer to Binary 28 | rx_bin = fliplr(de2bi(rx_int)); 29 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 30 | 31 | 32 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 33 | case 'QAM' 34 | % Symbol to Gray-Integer 35 | rx_int = maxLikelihood(rx_symb,Nbps,'QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 36 | % Gray-Integer to Integer 37 | switch Nbps 38 | case 3 39 | gray2bin_matrix = [0 1 3 2 4 5 7 6]; 40 | for index = 1:length(rx_int) 41 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 42 | end 43 | case 5 44 | gray2bin_matrix = [0 1 3 2 7 6 4 5 8 9 11 10 15 14 12 13 24 25 27 26 31 30 28 29 16 17 19 18 23 22 20 21]; 45 | for index = 1:length(rx_int) 46 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 47 | end 48 | otherwise 49 | rx_int = gray2bin(rx_int,'QAM',2^Nbps); 50 | end 51 | % Integer to Binary 52 | rx_bin = fliplr(de2bi(rx_int)); 53 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 54 | 55 | 56 | %% ***** PHASE SHIFT KEYING ***** 57 | case 'PSK' 58 | % Symbol to Gray-Integer 59 | rx_int = maxLikelihood(rx_symb,Nbps,'PSK'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 60 | % Gray-Integer to Integer 61 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 62 | % Integer to Binary 63 | rx_bin = fliplr(de2bi(rx_int)); 64 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 65 | 66 | 67 | %% ***** CROSS-QAM ***** 68 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM'(one of the most famous flavor of the Cross-QAM) 69 | case 'Cross-QAM' 70 | % Symbol to Gray-Integer 71 | rx_int = maxLikelihood(rx_symb,Nbps,'Cross-QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 72 | % Gray-Integer to Integer 73 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 74 | % Integer to Binary 75 | rx_bin = fliplr(de2bi(rx_int)); 76 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 77 | 78 | 79 | %% ***** OPTIMAL-8QAM ***** 80 | case 'Optimal-8QAM' 81 | % Symbol to Gray-Integer 82 | rx_int = maxLikelihood(rx_symb,Nbps,'Optimal-8QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 83 | % Gray-Integer to Integer 84 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 85 | % Integer to Binary 86 | rx_bin = fliplr(de2bi(rx_int)); 87 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 88 | end 89 | end -------------------------------------------------------------------------------- /Simulation_yu_backup/makeLdpc.m: -------------------------------------------------------------------------------- 1 | function H = makeLdpc(M, N, method, noCycle, onePerCol) 2 | % Create R = 1/2 low density parity check matrix 3 | % 4 | % M : Number of row 5 | % N : Number of column 6 | % method : Method for distributing non-zero element 7 | % {0} Evencol : For each column, place 1s uniformly at random 8 | % {1} Evenboth: For each column and row, place 1s uniformly at random 9 | % noCyle : Length-4 cycle 10 | % {0} Ignore (do nothing) 11 | % {1} Eliminate 12 | % onePerCol: Number of ones per column 13 | % 14 | % H : Low density parity check matrix 15 | % 16 | % 17 | % Copyright Bagawan S. Nugroho, 2007 18 | % http://bsnugroho.googlepages.com 19 | 20 | 21 | % Number of ones per row (N/M ratio must be 2) 22 | if N/M ~= 2 23 | fprintf('Code rate must be 1/2\n'); 24 | end 25 | onePerRow = (N/M)*onePerCol; 26 | 27 | fprintf('Creating LDPC matrix...\n'); 28 | 29 | switch method 30 | % Evencol 31 | case {0} 32 | % Distribute 1s uniformly at random within column 33 | for i = 1:N 34 | onesInCol(:, i) = randperm(M)'; 35 | end 36 | 37 | % Create non zero elements (1s) index 38 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 39 | tmp = repmat([1:N], onePerCol, 1); 40 | c = reshape(tmp, N*onePerCol, 1); 41 | 42 | % Create sparse matrix H 43 | H = full(sparse(r, c, 1, M, N)); 44 | 45 | % Evenboth 46 | case {1} 47 | % Distribute 1s uniformly at random within column 48 | for i = 1:N 49 | onesInCol(:, i) = randperm(M)'; 50 | end 51 | 52 | % Create non zero elements (1s) index 53 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 54 | tmp = repmat([1:N], onePerCol, 1); 55 | c = reshape(tmp, N*onePerCol, 1); 56 | 57 | % Make the number of 1s between rows as uniform as possible 58 | 59 | % Order row index 60 | [r, ix] = sort(r); 61 | 62 | % Order column index based on row index 63 | for i = 1:N*onePerCol 64 | cSort(i, :) = c(ix(i)); 65 | end 66 | 67 | % Create new row index with uniform weight 68 | tmp = repmat([1:M], onePerRow, 1); 69 | r = reshape(tmp, N*onePerCol, 1); 70 | 71 | % Create sparse matrix H 72 | % Remove any duplicate non zero elements index using logical AND 73 | S = and(sparse(r, cSort, 1, M, N), ones(M, N)); 74 | H = full(S); 75 | 76 | end % switch 77 | 78 | % Check rows that have no 1 or only have one 1 79 | for i = 1:M 80 | 81 | n = randperm(N); 82 | % Add two 1s if row has no 1 83 | if length(find(r == i)) == 0 84 | H(i, n(1)) = 1; 85 | H(i, n(2)) = 1; 86 | % Add one 1 if row has only one 1 87 | elseif length(find(r == i)) == 1 88 | H(i, n(1)) = 1; 89 | end 90 | 91 | end % for i 92 | 93 | % If desired, eliminate any length-4 cycle 94 | if noCycle == 1 95 | 96 | for i = 1:M 97 | % Look for pair of row - column 98 | for j = (i + 1):M 99 | w = and(H(i, :), H(j, :)); 100 | c1 = find(w); 101 | lc = length(c1); 102 | if lc > 1 103 | 104 | % If found, flip one 1 to 0 in the row with less number of 1s 105 | if length(find(H(i, :))) < length(find(H(j, :))) 106 | % Repeat the process until only one column left 107 | for cc = 1:lc - 1 108 | H(j, c1(cc)) = 0; 109 | end 110 | else 111 | for cc = 1:lc - 1 112 | H(i, c1(cc)) = 0; 113 | end 114 | end % if 115 | 116 | end % if 117 | end % for j 118 | end % for i 119 | 120 | end % if 121 | 122 | fprintf('LDPC matrix is created.\n'); 123 | -------------------------------------------------------------------------------- /Simulation_yu_backup/makeParityChk.m: -------------------------------------------------------------------------------- 1 | function [c, newH] = makeParityChk(dSource, H, strategy) 2 | % Generate parity check vector bases on LDPC matrix H using sparse LU decomposition 3 | % 4 | % dSource : Binary source (0/1) 5 | % H : LDPC matrix 6 | % strategy: Strategy for finding the next non-zero diagonal elements 7 | % {0} First : First non-zero found by column search 8 | % {1} Mincol : Minimum number of non-zeros in later columns 9 | % {2} Minprod: Minimum product of: 10 | % - Number of non-zeros its column minus 1 11 | % - Number of non-zeros its row minus 1 12 | % 13 | % c : Check bits 14 | % 15 | % 16 | % Copyright Bagawan S. Nugroho, 2007 17 | % http://bsnugroho.googlepages.com 18 | 19 | % Get the matric dimension 20 | [M, N] = size(H); 21 | % Set a new matrix F for LU decomposition 22 | F = H; 23 | % LU matrices 24 | L = zeros(M, N - M); 25 | U = zeros(M, N - M); 26 | 27 | % Re-order the M x (N - M) submatrix 28 | for i = 1:M 29 | 30 | % strategy {0 = First; 1 = Mincol; 2 = Minprod} 31 | switch strategy 32 | 33 | % Create diagonally structured matrix using 'First' strategy 34 | case {0} 35 | 36 | % Find non-zero elements (1s) for the diagonal 37 | [r, c] = find(F(:, i:end)); 38 | 39 | % Find non-zero diagonal element candidates 40 | rowIndex = find(r == i); 41 | 42 | % Find the first non-zero column 43 | chosenCol = c(rowIndex(1)) + (i - 1); 44 | 45 | % Create diagonally structured matrix using 'Mincol' strategy 46 | case {1} 47 | 48 | % Find non-zero elements (1s) for the diagonal 49 | [r, c] = find(F(:, i:end)); 50 | colWeight = sum(F(:, i:end), 1); 51 | 52 | % Find non-zero diagonal element candidates 53 | rowIndex = find(r == i); 54 | 55 | % Find the minimum column weight 56 | [x, ix] = min(colWeight(c(rowIndex))); 57 | % Add offset to the chosen row index to match the dimension of the... 58 | % original matrix F 59 | chosenCol = c(rowIndex(ix)) + (i - 1); 60 | 61 | % Create diagonally structured matrix using 'Minprod' strategy 62 | case {2} 63 | 64 | % Find non-zero elements (1s) for the diagonal 65 | [r, c] = find(F(:, i:end)); 66 | colWeight = sum(F(:, i:end), 1) - 1; 67 | rowWeight = sum(F(i, :), 2) - 1; 68 | 69 | % Find non-zero diagonal element candidates 70 | rowIndex = find(r == i); 71 | 72 | % Find the minimum product 73 | [x, ix] = min(colWeight(c(rowIndex))*rowWeight); 74 | % Add offset to the chosen row index to match the dimension of the... 75 | % original matrix F 76 | chosenCol = c(rowIndex(ix)) + (i - 1); 77 | 78 | otherwise 79 | fprintf('Please select columns re-ordering strategy!\n'); 80 | 81 | end % switch 82 | 83 | % Re-ordering columns of both H and F 84 | tmp1 = F(:, i); 85 | tmp2 = H(:, i); 86 | F(:, i) = F(:, chosenCol); 87 | H(:, i) = H(:, chosenCol); 88 | F(:, chosenCol) = tmp1; 89 | H(:, chosenCol) = tmp2; 90 | 91 | % Fill the LU matrices column by column 92 | L(i:end, i) = F(i:end, i); 93 | U(1:i, i) = F(1:i, i); 94 | 95 | % There will be no rows operation at the last row 96 | if i < M 97 | 98 | % Find the later rows with non-zero elements in column i 99 | [r2, c2] = find(F((i + 1):end, i)); 100 | % Add current row to the later rows which have a 1 in column i 101 | F((i + r2), :) = mod(F((i + r2), :) + repmat(F(i, :), length(r2), 1), 2); 102 | 103 | end % if 104 | 105 | end % for i 106 | 107 | % Find B.dsource 108 | z = mod(H(:, (N - M) + 1:end)*dSource, 2); 109 | 110 | % Parity check vector found by solving sparse LU 111 | c = mod(U\(L\z), 2); 112 | 113 | % Return the rearrange H 114 | newH = H; 115 | 116 | fprintf('Message encoded.\n'); 117 | -------------------------------------------------------------------------------- /Simulation_yu_backup/mapping.m: -------------------------------------------------------------------------------- 1 | function [symb_tx] = mapping(bit_tx,Nbps,modulation) 2 | 3 | % INPUTS: 4 | % - bit_tx : vector of input bits 5 | % - Nbps : number of bits per symbol 6 | % - modulation : 'pam' or 'qam' 7 | % 8 | % OUTPUTS: 9 | % - symb_tx : vector of ouput symbols (variance 1) 10 | 11 | Nsymb = size(bit_tx,1)/Nbps; % Number of symbols 12 | 13 | bit_tx2 = reshape(bit_tx,Nbps,Nsymb)'; 14 | 15 | switch modulation, 16 | 17 | case 'pam' 18 | 19 | % Gray to binary 20 | mapp_tx(:,1) = bit_tx2(:,1); 21 | for ii = 2:Nbps, 22 | mapp_tx(:,ii) = xor( mapp_tx(:,ii-1) , bit_tx2(:,ii) ); 23 | end 24 | 25 | % Binary to integer 26 | int_tx = bi2de(fliplr(mapp_tx)); 27 | 28 | % Integer to symbol 29 | sigma = sqrt(sum(([0:2^Nbps-1]-(2^Nbps-1)/2).^2)/2^Nbps); 30 | symb_tx = 1/sigma * (int_tx - (2^Nbps-1)/2); 31 | 32 | case 'qam' 33 | 34 | % REAL PART 35 | NbpsI = Nbps/2; 36 | bit_tx2I = bit_tx2(:,1:NbpsI); 37 | 38 | % Gray to binary 39 | mapp_txI(:,1) = bit_tx2I(:,1); 40 | for ii = 2:NbpsI, 41 | mapp_txI(:,ii) = xor( mapp_txI(:,ii-1) , bit_tx2I(:,ii) ); 42 | end 43 | 44 | % Binary to integer 45 | int_txI = bi2de(fliplr(mapp_txI)); 46 | 47 | % Integer to symbol 48 | sigmaI = sqrt(sum(([0:2^NbpsI-1]-(2^NbpsI-1)/2).^2)/2^NbpsI); 49 | symb_txI = 1/sigmaI/sqrt(2) * (int_txI - (2^NbpsI-1)/2); 50 | 51 | 52 | % IMAGINARY PART 53 | NbpsQ = Nbps/2; 54 | bit_tx2Q = bit_tx2(:,NbpsQ+1:end); 55 | 56 | % Gray to binary 57 | mapp_txQ(:,1) = bit_tx2Q(:,1); 58 | for ii = 2:NbpsQ, 59 | mapp_txQ(:,ii) = xor( mapp_txQ(:,ii-1) , bit_tx2Q(:,ii) ); 60 | end 61 | 62 | % Binary to integer 63 | int_txQ = bi2de(fliplr(mapp_txQ)); 64 | 65 | % Integer to symbol 66 | sigmaQ = sqrt(sum(([0:2^NbpsQ-1]-(2^NbpsQ-1)/2).^2)/2^NbpsQ); 67 | symb_txQ = 1/sigmaQ/sqrt(2) * (int_txQ - (2^NbpsQ-1)/2); 68 | 69 | 70 | % COMPLEX SYMBOL 71 | symb_tx = symb_txI + j*symb_txQ; 72 | 73 | end -------------------------------------------------------------------------------- /Simulation_yu_backup/mappinga.m: -------------------------------------------------------------------------------- 1 | function [tx_symb] = mapping(tx_bin,Nbps,modulation) % Maps bitstream to Symbols depending on the selected mapping 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% MAPPING 9 | % INPUTS 10 | % 'tx_bin' - Bitstream 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'tx_symb' - Symbols 15 | 16 | 17 | %% INITIALIZATION AND VALIDITY CHECK 18 | if mod(Nbps, 1) ~=0 || Nbps <= 0 19 | error('You have entered an unsupported Number of Bits Per Symbol. Nbps must be a positive real integer.'); 20 | end 21 | Nsymb = size(tx_bin,1)/Nbps; % Number of symbols 22 | tx_bin = reshape(tx_bin,Nbps,Nsymb)'; % Reshapes the vector into a matrix: each row corresponds to a symbol (Nbps bits) 23 | 24 | switch modulation 25 | %% ***** PULSE AMPLITUDE MODULATION ***** 26 | case 'PAM' 27 | % Binary to Integer - Convert 'Binary Word' to corresponding 'Integer' [10 -> 2] 28 | tx_int = bi2de(fliplr(tx_bin)); %[!]fliplr to adjust MSB and LSB in the right position for f_bi2de 29 | % Integer to Gray-Integer - Convert 'Integer' to corresponding 'Gray-Integer' according to the desired Modulation Scheme and Npbs [2 <-> 3] 30 | tx_int = bin2gray(tx_int,'PAM',2^Nbps); 31 | % Gray-Integer to Symbol - Convert 'Gray Integer' to corresponding 'Symbol' according to the desired Modulation Scheme and Npbs 32 | distance = 2/(2^Nbps-1); 33 | tx_symb = distance * (tx_int - (2^Nbps-1)/2); 34 | 35 | 36 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 37 | case 'QAM' 38 | % Binary to Integer 39 | tx_int = bi2de(fliplr(tx_bin)); 40 | % Integer to Gray-Integer 41 | switch Nbps 42 | case 3 43 | bin2gray_matrix = [0 1 3 2 4 5 7 6]; 44 | for index = 1:length(tx_int) 45 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 46 | end 47 | case 5 48 | bin2gray_matrix = [0 1 3 2 6 7 5 4 8 9 11 10 14 15 13 12 24 25 27 26 30 31 29 28 16 17 19 18 22 23 21 20]; 49 | for index = 1:length(tx_int) 50 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 51 | end 52 | otherwise 53 | tx_int = bin2gray(tx_int,'QAM',2^Nbps); 54 | end 55 | 56 | % Gray-Integer to Symbol 57 | Nbps_I = ceil(Nbps/2); % Number of symbols carried in the 'Inphase Carrier' 58 | Nbps_Q = Nbps - Nbps_I; % Number of symbols carried in the 'Quadrature Carrier' 59 | distance = 2/(2^Nbps_I-1); 60 | tx_symb = distance*( (mod(tx_int,2^(Nbps_I)) - (2^Nbps_I-1)/2) - 1i*(floor(tx_int/(2^Nbps_I)) - (2^Nbps_Q-1)/2) ); 61 | 62 | 63 | %% ***** PHASE SHIFT KEYING ***** 64 | case 'PSK' 65 | % Binary to Integer 66 | tx_int = bi2de(fliplr(tx_bin)); 67 | % Integer to Gray-Integer 68 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 69 | % Gray-Integer to Symbol 70 | tx_symb = exp(1i*pi*(0+ 2/(2^Nbps)*tx_int)); %[?] 3/4 <- 0 71 | 72 | 73 | %% ***** CROSS-QAM ***** 74 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM' (one of the most famous flavour of the Cross-QAM) 75 | case 'Cross-QAM' 76 | switch Nbps 77 | case 1 % Simple PSK 78 | tx_int = bi2de(fliplr(tx_bin)); 79 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 80 | otherwise 81 | % Binary to Integer 82 | tx_int = bi2de(fliplr(tx_bin)); 83 | % Integer to Gray-Integer 84 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 85 | % Gray-Integer to Symbol 86 | tx_symb = zeros(length(tx_int),1); 87 | for index = 1:length(tx_int) 88 | radius = (2 + floor(tx_int(index)/4)) / (2^Nbps/4 + 1); 89 | phase = (mod(floor(tx_int(index)/4), 2) == 0)*3/4; 90 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 91 | end 92 | end 93 | 94 | 95 | %% ***** OPTIMAL-8QAM ***** 96 | case 'Optimal-8QAM' 97 | if Nbps ~= 3 98 | error('This particular Modulation Scheme only works with 3 Bits per Symbol. For Nbps other than 3, please choose among [PSK, PAM, QAM, Cross-QAM].'); 99 | end 100 | % Binary to Integer 101 | tx_int = bi2de(fliplr(tx_bin)); 102 | % Integer to Gray-Integer 103 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 104 | % Gray-Integer to Symbol 105 | tx_symb = zeros(length(tx_int),1); 106 | for index = 1:length(tx_int) 107 | if tx_int(index) > 3 108 | radius = 1; 109 | else 110 | radius = sqrt(2) / (1 + sqrt(3)); 111 | end 112 | phase = (floor(tx_int(index)/4) == 0)*3/4; 113 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 114 | end 115 | 116 | otherwise 117 | error('You have entered an unsupported Digital Modulation scheme. Please choose among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM].'); 118 | end -------------------------------------------------------------------------------- /Simulation_yu_backup/maxLikelihooda.m: -------------------------------------------------------------------------------- 1 | function [rx_symb_ML] = maxLikelihood(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% MAXIMUM LIKELIHOOD CRITERION 9 | % By comparing the Received Symbols 'rx_symb' with the Symbols of Reference 'symb_ref' we can apply the ML Criterion and deduce 'rx_symb_ML' 10 | % INPUTS 11 | % 'rx_symb' - Symbols 12 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 13 | % 'Nbps' - Number of bits per symbol 14 | % OUTPUT 15 | % 'rx_symb_ML' - Symbols after the application of the Maximum Likelihood Criterion 16 | 17 | 18 | %% ALGORITHM 19 | % 'symb_ref' is a [2^Nbps x 2] matrix used as a Containers.map 20 | % The 1st column includes all the Symbols of Reference in their Complex form (-0.7071 + i*0.7071, +0.7071 - i*0.7071,...) 21 | % The 2nd column includes the associated Decimal Value (0, 1, 2, 3, ...) 22 | % Step 1: Generating Symbols of Reference in function of (Nbps, modulation) 23 | % Step 2: Application of the Maximum Likelihood Criterion -> Compare each element of 'rx_symb' with the Symbols of Reference 'symb_ref' 24 | % Step 3: Return the Symbols after the application of the Maximum Likelihood Criterion 'rx_symb_ML' 25 | 26 | switch modulation 27 | %% ***** PULSE AMPLITUDE MODULATION ***** 28 | case 'PAM' 29 | % Generating Symbols of Reference 30 | symb_ref = zeros(2^Nbps,2); 31 | distance = 2/(2^Nbps-1); 32 | for index = 1:2^Nbps 33 | symb_ref(index,:) = [distance*(index-1 - (2^Nbps-1)/2), index-1]; 34 | end 35 | % Application of the Maximum Likelihood Criterion 36 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 37 | 38 | 39 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 40 | case 'QAM' 41 | % Generating Symbols of Reference 42 | Nbps_I = ceil(Nbps/2); Nbps_Q = Nbps - Nbps_I; 43 | symb_ref = zeros(2^Nbps,2); 44 | distance = 2/(2^Nbps_I-1); 45 | for index_I = 1:2^Nbps_I 46 | for index_Q = 1:2^Nbps_Q 47 | symb_ref(index_I + (2^Nbps_I)*(index_Q-1), :) = [distance*((index_I-1 - (2^Nbps_I-1)/2) - 1i* (index_Q-1 - (2^Nbps_Q-1)/2)), index_I-1 + (2^Nbps_I)*(index_Q-1)]; 48 | end 49 | end 50 | % Application of the Maximum Likelihood Criterion 51 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 52 | 53 | %% ***** PHASE SHIFT KEYING ***** 54 | case 'PSK' 55 | symb_ref = zeros(2^Nbps,2); 56 | % Generating Symbols of Reference 57 | for index = 1:2^Nbps 58 | symb_ref(index,:) = [exp(1i*pi*(3/4 + 2/(2^Nbps)*(index-1))), index-1]; 59 | end 60 | % Application of the Maximum Likelihood Criterion 61 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 62 | 63 | %% ***** CROSS-QUADRATURE AMPLITUDE MODULATION ***** 64 | case 'Cross-QAM' 65 | % Generating Symbols of Reference 66 | symb_ref = zeros(2^Nbps,2); 67 | switch Nbps 68 | case 1 % Only 2 Symbols on the 1st Orbit => Elementary PSK Case 69 | symb_ref = [exp(1i*pi*(3/4 + 2/(2^Nbps)*0)), 0; exp(1i*pi*(3/4 + 2/(2^Nbps)*1)), 1]; 70 | otherwise 71 | for index = 1:2^Nbps 72 | radius = (2 + floor((index - 1)/4)) / (2^Nbps/4 + 1); 73 | phase = (mod(floor((index-1)/4), 2) == 0)*3/4; 74 | symb_ref(index,:) = [radius*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 75 | end 76 | end 77 | % Application of the Maximum Likelihood Criterion 78 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 79 | 80 | 81 | %% ***** OPTIMAL-8QAM ***** 82 | case 'Optimal-8QAM' 83 | % Generating Symbols of Reference 84 | symb_ref = zeros(2^Nbps,2); 85 | radius = [sqrt(2)/(1 + sqrt(3)), 1]; 86 | for index = 1:2^Nbps 87 | phase = (floor((index-1)/4) == 0)*3/4; 88 | symb_ref(index,:) = [radius(floor((index-1)/4) + 1)*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 89 | end 90 | % Application of the Maximum Likelihood Criterion 91 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 92 | end 93 | 94 | 95 | %% ***** APPLICATION OF THE MAXIMUM LIKELIHOOD CRITERION ***** 96 | function [rx_symb_ML] = appML(rx_symb, Nbps, symb_ref) 97 | rx_symb_ML = zeros(length(rx_symb), 1); % Initialize the size of 'rx_symb_ML' in order to save some time 98 | CSM = sqrt(abs((rx_symb(:) - symb_ref(1, 1)) .^ 2)); % CSM - Current Smallest Norm: Transient save allowing to 'compare before assign' 99 | 100 | for index = 1:2^Nbps % Loop to determine the minimal Euclidean Norm of each Received Symbol 101 | BOOL = CSM > sqrt(abs((rx_symb(:) - symb_ref(index, 1)) .^ 2)); % Boolean Vector taking a true value ('1') when the corresponding CSM row appears to not be the smallest possible Euclidean Norm 102 | CSM(BOOL) = sqrt(abs((rx_symb(BOOL) - symb_ref(index, 1)) .^ 2)); % Update CSM accordingly 103 | rx_symb_ML(BOOL) = symb_ref(index, 2); 104 | end -------------------------------------------------------------------------------- /Simulation_yu_backup/mlf2pdfExample.m: -------------------------------------------------------------------------------- 1 | %% Script example for mlf2pdf 2 | 3 | clear % Clear all variables but not breakpoints 4 | close all % Close all the figures 5 | 6 | %% startup.m template 7 | set(0,'defaultFigurePosition', [10 10 600 450]); 8 | set(0,'defaultAxesFontSize', 12); 9 | set(0, 'defaultTextFontSize', 12); 10 | set(0, 'defaultAxesFontName', 'Palatino Linotype'); 11 | set(0, 'defaultTextFontName', 'Palatino Linotype'); 12 | 13 | %% Compute the two functions to plot 14 | x = linspace(-8,8, 31); 15 | yLin = 5*x; 16 | yQuad = x.^2; 17 | 18 | figure % Creates a new figure -> avoids erasing the previous one 19 | set(gca, 'FontSize', 13); % Font size for the axes == 13 20 | plot(x, yLin, '-', 'Marker', 's', 'Color', 'black',... 21 | 'MarkerSize', 6, 'LineWidth', 1,... 22 | 'DisplayName', '$y(x) = 5x$'); 23 | hold on; % Allows to plot several curves on the same figure 24 | plot(x, yQuad, '-', 'Marker', 'o', 'Color', 'blue',... 25 | 'MarkerSize', 6, 'LineWidth', 2,... 26 | 'DisplayName', '$y(x) = x^2$'); 27 | hold off; % Disables hold on 28 | grid on; % Shows the grid 29 | xlabel('Value of $x$'); 30 | ylabel('Value of $y(x)$'); 31 | title('A plot of two functions'); 32 | 33 | %% Other possibly interesting commands: 34 | % axis tight % Make the axis span thighly the extension of the curves 35 | % xlim([xMin, xMax]); % Show only the part of the x axis going from xMin to 36 | % xMax 37 | % ylim([yMin, yMax]); % Show only the part of the y axis going from yMin to 38 | % yMax 39 | % set(gca,'YDir','reverse'); % Reverses the orientation of the y axis 40 | % set(gca,'YDir','normal'); % Makes the orientation of the y axis standard 41 | 42 | %% Show the legend 43 | % Show the legend using the property 'DisplayName' of each curve that has 44 | % been plotted 45 | hLeg = legend('show'); 46 | 47 | % Modify the font size for the legend. Set LaTeX as interpreter for the 48 | % display and the computation of the legend box boundaries. Position works 49 | % like this: [(bottom left corner horizontal position), (bottom left corner 50 | % vertical position), (width), (height)]. If the width and/or height are 51 | % too small for proper display, then Matlab adjusts the parameters => 52 | % interesting to set 0.01 to have the tighest possible legend box. 53 | set(hLeg, 'fontsize', 12, 'interpreter', 'latex',... 54 | 'Position', [0.76,0.2,0.01,0.01]); 55 | 56 | %% Save to PDF 57 | % Now, we can use mlf2pdf to create the figure. The figure is Figure 1 as 58 | % only one figure has been plotted and the possibly preexisting figures 59 | % have been closed by executing 'close all'. 60 | % mlf2pdf(1, 'A_Figure'); 61 | -------------------------------------------------------------------------------- /Simulation_yu_backup/rrc.m: -------------------------------------------------------------------------------- 1 | %function[Trrc]=rrc(Fsampling,Fsymbol) 2 | Fsymbol=1e6; 3 | T=1/Fsymbol; 4 | Fsampling=8e6; 5 | beta=0.5; 6 | RRCTaps=101; 7 | fmax=Fsampling/2; 8 | f=linspace(-fmax,fmax,RRCTaps); 9 | 10 | pass=linspace(T,T,RRCTaps); 11 | trans=T/2*(1+cos(pi*T/beta*(abs(f)-(1-beta)/(2*T)))); 12 | zero=linspace(0,0,RRCTaps); 13 | 14 | part1=abs(f)<((1-beta)/(2*T)); 15 | part2=(abs(f)>=(1-beta)/(2*T))&(abs(f)<(1+beta)/(2*T)); 16 | part3=abs(f)>=(1+beta)/(2*T); 17 | 18 | Hrc=pass.*part1+trans.*part2+zero.*part3; 19 | 20 | Hrrc=sqrt(Hrc); 21 | Trrc=ifft(ifftshift(Hrrc)); 22 | 23 | figure 24 | plot(Hrc); 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Simulations-V11/DVBS2CommunicationChain.m: -------------------------------------------------------------------------------- 1 | function [BER, SER, tx_symb, rx_symb] = DVBS2CommunicationChain(mod_input, Nbps_input, EbN0_ratio_input) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% DVBS2CommunicationChain 9 | % INPUTS 10 | % 'mod_input' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 11 | % 'Nbps_input' - Number of bits per symbol 12 | % 'EbN0_ratio_input' - SNR per bit 13 | % OUTPUTS 14 | % 'BER' - Bit Error Ratio 15 | % 'SER' - Symbol Error Ratio 16 | % 'tx_symb' - Transmitted Symbols 17 | % 'rx_symb' - Received Symbols 18 | 19 | 20 | %% Implemented Features 21 | % 1. [TX] - GENERATING INFORMATION - RANDOM BITSTREAM 22 | % 2. [TX] - MAPPING BITSTREAM TO SYMBOLS - SUPPORTED MODULATION SCHEMES: [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] - Works for any Nbps 23 | % 3. [TX] - UPSAMPLING 24 | % 4. [TX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 25 | % 5. [CHAN] - ADDING AWGN IN THE IDEAL CHANNEL 26 | % 6. [RX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 27 | % 7. [RX] - DOWNSAMPLING 28 | % 8. [RX] - DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 29 | % X. [PLOT] - RELEVANT GRAPHS AND VALUES 30 | 31 | 32 | %% IF YOU WANT TO AUTO-RUN THIS FUNCTION - DECOMMENTS THE 4 NEXT LINES. 33 | %% IF YOU WANT TO RUN THIS FUNCTION FROM 'FoM' - COMMENTS THE 4 NEXT LINES. 34 | % clear; clc; close all; 35 | % mod_input = 'QAM'; 36 | % Nbps_input = 6; 37 | % EbN0_ratio_input = 5; 38 | 39 | 40 | %% ***** MODULATION SCHEME PARAMETERS ***** 41 | Modu.mod = mod_input; % Select the Digital Modulation among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] (NB: The 'Optimal-8QAM' is designed for 8 Symbols only (=> Nbps = 3)) 42 | Modu.Nbps = Nbps_input; % Select the Number of Bits Per Symbol 43 | Modu.fsymb = 5e6; % Select the Symbolrate [Symb/s] - Common to all Modulation Schemes and independent of Nbps 44 | Modu.bps = Modu.fsymb*Modu.Nbps; % Deduct the Bitrate [bits/s] - Depends on the Number of Bits carried per each Symbol (Nbps) 45 | Modu.Tsymb = 1/Modu.fsymb; % Deduct the Period of a symbol [s] (or more rigorously [s/Symb]) 46 | 47 | 48 | %% ***** RCF PARAMETERS ***** 49 | RRCF.fcutoff = 1e6; % Cutoff frequency of the RCF [1MHz] 50 | RRCF.beta = 0.3; % Roll-off factor of the RCF [0.3] 51 | RRCF.Ntaps = 33; % Number of taps of the RCF 52 | RRCF.M = 2; % Deduct the Upsampling Factor -> Needed in order to satisfy the ISI Nyquist Criterion 53 | RRCF.fs = RRCF.M*Modu.fsymb; % Deduct the Sampling Frequency [Hz] 54 | 55 | 56 | %% 1. [TX] GENERATING INFORMATION - RANDOM BITSTREAM 57 | tx_len = 5000; % Length of the bitstream 58 | tx_bin = randi([0 1], tx_len,1); % Bitstream - Generate binary sequence (0 and 1 are equiprobable) 59 | 60 | 61 | %% 2. [TX] MAPPING BITSTREAM TO SYMBOLS 62 | if mod(tx_len,Modu.Nbps) ~= 0 % ZERO PADDING -> Allows to avoid to get an error if the Bitstream length is not a multiple of Nbps 63 | tx_bin = [tx_bin; zeros(Modu.Nbps - mod(tx_len,Modu.Nbps),1)]; 64 | tx_len = tx_len + Modu.Nbps - mod(tx_len,Modu.Nbps); 65 | end 66 | tx_symb = mapping(tx_bin, Modu.Nbps, Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps 67 | 68 | 69 | %% 3. [TX] UPSAMPLING 70 | tx_symb_UP = upsample(tx_symb,RRCF.M); % Upsample 71 | 72 | 73 | %% 4. [TX] FILTERING WITH ROOT-RAISED-COSINE FILTER 74 | RRCF.IR = RRCFDesign(RRCF.beta, RRCF.Ntaps, RRCF.fs, Modu.Tsymb); % Impulse Response of the RRCF 75 | tx_symb_UP_F = conv(tx_symb_UP,RRCF.IR); % Apply the RRCF 76 | 77 | 78 | %% 5. [CHAN] ADDING AWGN IN THE IDEAL CHANNEL 79 | % In practice, we send in the channel the Narrowband Bandpass Signal (the Baseband Signal modulated at a high frequency) 80 | % In this simulation, we directly send the Baseband Signal (Complex Envelope) in the channel. This is done in order to save computing power 81 | % However, we have to take into account the fact that the energy of a Bandpass Signal is equal to the energy of its Complex Envelope divided by 2 82 | Es_CE = (trapz(abs(tx_symb_UP_F).^2))*(1/(RRCF.fs)); % Basedband Signal Energy (Complex Envelope of the Bandpass Signal) 83 | Es_BP = Es_CE/2; % Bandpass Signal Energy 84 | Eb = Es_BP/tx_len; % Average energy of a bit 85 | EbN0_dB = EbN0_ratio_input; % Energy per Bit to Noise PSD ratio [dB] 86 | EbN0_ratio = 10^(EbN0_dB/10); % Energy per Bit to Noise PSD ratio 87 | N0 = Eb/EbN0_ratio; % Noise PSD - We consider AWGN, so N0 is constant on the whole frequency domain 88 | NoisePower = 2*N0*RRCF.fs; % Noise Power 89 | noise_AWGN = sqrt(NoisePower/2)*(randn(length(tx_symb_UP_F), 1) + 1i*randn(length(tx_symb_UP_F), 1)); % Generate Zero-Mean AWGN 90 | rx_usymb_UP_F = tx_symb_UP_F + noise_AWGN; % Add the noise to the transmitted signal 91 | rx_usymb_UP_F = tx_symb_UP_F; 92 | 93 | 94 | %% 6. [RX] FILTERING WITH ROOT-RAISED-COSINE FILTER 95 | rx_usymb_UP = conv(rx_usymb_UP_F,RRCF.IR); % Apply the matched RRCF 96 | rx_usymb_UP = rx_usymb_UP(RRCF.Ntaps:length(rx_usymb_UP) - RRCF.Ntaps+1); % Removes the irrelevant values 97 | 98 | 99 | %% 7. [RX] DOWNSAMPLING 100 | rx_symb = downsample(rx_usymb_UP,RRCF.M); 101 | 102 | 103 | %% 8. [RX] DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 104 | rx_bin = demapping(rx_symb,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 105 | 106 | 107 | %% X. [PLOT] RELEVANT GRAPHS AND VALUES 108 | % See the function 'FoM' for all the preset Graphs 109 | BER = 1 - sum(rx_bin == tx_bin)/tx_len; % Bit Error Ratio 110 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,tx_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin,Modu.Nbps,tx_len/Modu.Nbps)'))) / (tx_len/Modu.Nbps); % Symbol Error Ratio 111 | end 112 | -------------------------------------------------------------------------------- /Simulations-V11/FoM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V11/FoM.m -------------------------------------------------------------------------------- /Simulations-V11/RRCFDesign.m: -------------------------------------------------------------------------------- 1 | function [IR_RRC, H_RRCF, t_axis, f_axis] = RRCFDesign(Beta, Ntaps, fs, Tsymb) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% RRCFDesign 9 | % INPUTsymb 10 | % 'Beta' - Roll-off Factor 11 | % 'Ntaps' - Number of RRC Taps [Needs to be odd] - Set the Time Extension and the Frequency Resolution 12 | % 'fs' - Sampling Frequency [Hz] 13 | % 'Tsymb' - Symbol Period [s] 14 | % OUTPUTsymb 15 | % 'IR_RRC' - Impulse Response of the designed RRCF 16 | % 'H_RRCF' - Spectrum of the designed RRCF 17 | 18 | 19 | %% The RCF is designed in the frequency domain 20 | %% The Impulse Response is then obtained by IFFT 21 | fmax = (1/Ntaps)*fs*(Ntaps-1)/2; % Maximal frequency on the axis - Tends to fs/2 for Ntaps tending to infinity 22 | f_axis = linspace(-fmax, fmax, Ntaps); 23 | t_axis = (-(Ntaps-1)/2:(Ntaps-1)/2)./(2*fmax); 24 | H_RCF = zeros(1,Ntaps); % Fourier Transform of the RCF 25 | 26 | for i=1:Ntaps % Ntaps seTsymb the Time Extension and the Frequency Resolution 27 | if abs(f_axis(i))<=((1-Beta)/(2*Tsymb)) 28 | H_RCF(i) = Tsymb; 29 | elseif abs(f_axis(i))>((1-Beta)/(2*Tsymb)) && abs(f_axis(i))<=((1+Beta)/(2*Tsymb)) 30 | H_RCF(i) = Tsymb/2*(1+cos(pi*Tsymb/Beta*(abs(f_axis(i))-(1-Beta)/(2*Tsymb)))); 31 | else 32 | H_RCF(i) = 0; 33 | end 34 | end 35 | 36 | H_RRCF = sqrt(H_RCF); 37 | IR_RRC = fftshift(ifft(ifftshift(H_RRCF), 'symmetric')); 38 | normCoeff = sqrt(max(abs(conv(IR_RRC,IR_RRC)))); 39 | IR_RRC=IR_RRC/normCoeff; % Normalize -> the RCF will then be equal to 1 @ t=0 (and not the RRCF !) 40 | end -------------------------------------------------------------------------------- /Simulations-V11/demapping.m: -------------------------------------------------------------------------------- 1 | function [rx_bin] = demapping(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% DEMAPPING 9 | % INPUTS 10 | % 'rx_symb' - Symbols 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'rx_bit' - Bitstream 15 | 16 | 17 | %% INITIALIZATION 18 | Nsymb = size(rx_symb,1); % Number of symbols 19 | 20 | switch modulation 21 | %% ***** PULSE AMPLITUDE MODULATION ***** 22 | case 'PAM' 23 | % Symbol to Gray-Integer 24 | rx_int = maxLikelihood(rx_symb,Nbps,'PAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 25 | % Gray-Integer to Integer 26 | rx_int = gray2bin(rx_int,'PAM',2^Nbps); 27 | % Integer to Binary 28 | rx_bin = fliplr(de2bi(rx_int)); 29 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 30 | 31 | 32 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 33 | case 'QAM' 34 | % Symbol to Gray-Integer 35 | rx_int = maxLikelihood(rx_symb,Nbps,'QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 36 | % Gray-Integer to Integer 37 | switch Nbps 38 | case 3 39 | gray2bin_matrix = [0 1 3 2 4 5 7 6]; 40 | for index = 1:length(rx_int) 41 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 42 | end 43 | case 5 44 | gray2bin_matrix = [0 1 3 2 7 6 4 5 8 9 11 10 15 14 12 13 24 25 27 26 31 30 28 29 16 17 19 18 23 22 20 21]; 45 | for index = 1:length(rx_int) 46 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 47 | end 48 | otherwise 49 | rx_int = gray2bin(rx_int,'QAM',2^Nbps); 50 | end 51 | % Integer to Binary 52 | rx_bin = fliplr(de2bi(rx_int)); 53 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 54 | 55 | 56 | %% ***** PHASE SHIFT KEYING ***** 57 | case 'PSK' 58 | % Symbol to Gray-Integer 59 | rx_int = maxLikelihood(rx_symb,Nbps,'PSK'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 60 | % Gray-Integer to Integer 61 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 62 | % Integer to Binary 63 | rx_bin = fliplr(de2bi(rx_int)); 64 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 65 | 66 | 67 | %% ***** CROSS-QAM ***** 68 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM'(one of the most famous flavor of the Cross-QAM) 69 | case 'Cross-QAM' 70 | % Symbol to Gray-Integer 71 | rx_int = maxLikelihood(rx_symb,Nbps,'Cross-QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 72 | % Gray-Integer to Integer 73 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 74 | % Integer to Binary 75 | rx_bin = fliplr(de2bi(rx_int)); 76 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 77 | 78 | 79 | %% ***** OPTIMAL-8QAM ***** 80 | case 'Optimal-8QAM' 81 | % Symbol to Gray-Integer 82 | rx_int = maxLikelihood(rx_symb,Nbps,'Optimal-8QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 83 | % Gray-Integer to Integer 84 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 85 | % Integer to Binary 86 | rx_bin = fliplr(de2bi(rx_int)); 87 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 88 | end 89 | end -------------------------------------------------------------------------------- /Simulations-V11/makeLdpc.m: -------------------------------------------------------------------------------- 1 | function H = makeLdpc(M, N, method, noCycle, onePerCol) 2 | % Create R = 1/2 low density parity check matrix 3 | % 4 | % M : Number of row 5 | % N : Number of column 6 | % method : Method for distributing non-zero element 7 | % {0} Evencol : For each column, place 1s uniformly at random 8 | % {1} Evenboth: For each column and row, place 1s uniformly at random 9 | % noCyle : Length-4 cycle 10 | % {0} Ignore (do nothing) 11 | % {1} Eliminate 12 | % onePerCol: Number of ones per column 13 | % 14 | % H : Low density parity check matrix 15 | % 16 | % 17 | % Copyright Bagawan S. Nugroho, 2007 18 | % http://bsnugroho.googlepages.com 19 | 20 | 21 | % Number of ones per row (N/M ratio must be 2) 22 | if N/M ~= 2 23 | fprintf('Code rate must be 1/2\n'); 24 | end 25 | onePerRow = (N/M)*onePerCol; 26 | 27 | fprintf('Creating LDPC matrix...\n'); 28 | 29 | switch method 30 | % Evencol 31 | case {0} 32 | % Distribute 1s uniformly at random within column 33 | for i = 1:N 34 | onesInCol(:, i) = randperm(M)'; 35 | end 36 | 37 | % Create non zero elements (1s) index 38 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 39 | tmp = repmat([1:N], onePerCol, 1); 40 | c = reshape(tmp, N*onePerCol, 1); 41 | 42 | % Create sparse matrix H 43 | H = full(sparse(r, c, 1, M, N)); 44 | 45 | % Evenboth 46 | case {1} 47 | % Distribute 1s uniformly at random within column 48 | for i = 1:N 49 | onesInCol(:, i) = randperm(M)'; 50 | end 51 | 52 | % Create non zero elements (1s) index 53 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 54 | tmp = repmat([1:N], onePerCol, 1); 55 | c = reshape(tmp, N*onePerCol, 1); 56 | 57 | % Make the number of 1s between rows as uniform as possible 58 | 59 | % Order row index 60 | [r, ix] = sort(r); 61 | 62 | % Order column index based on row index 63 | for i = 1:N*onePerCol 64 | cSort(i, :) = c(ix(i)); 65 | end 66 | 67 | % Create new row index with uniform weight 68 | tmp = repmat([1:M], onePerRow, 1); 69 | r = reshape(tmp, N*onePerCol, 1); 70 | 71 | % Create sparse matrix H 72 | % Remove any duplicate non zero elements index using logical AND 73 | S = and(sparse(r, cSort, 1, M, N), ones(M, N)); 74 | H = full(S); 75 | 76 | end % switch 77 | 78 | % Check rows that have no 1 or only have one 1 79 | for i = 1:M 80 | 81 | n = randperm(N); 82 | % Add two 1s if row has no 1 83 | if length(find(r == i)) == 0 84 | H(i, n(1)) = 1; 85 | H(i, n(2)) = 1; 86 | % Add one 1 if row has only one 1 87 | elseif length(find(r == i)) == 1 88 | H(i, n(1)) = 1; 89 | end 90 | 91 | end % for i 92 | 93 | % If desired, eliminate any length-4 cycle 94 | if noCycle == 1 95 | 96 | for i = 1:M 97 | % Look for pair of row - column 98 | for j = (i + 1):M 99 | w = and(H(i, :), H(j, :)); 100 | c1 = find(w); 101 | lc = length(c1); 102 | if lc > 1 103 | 104 | % If found, flip one 1 to 0 in the row with less number of 1s 105 | if length(find(H(i, :))) < length(find(H(j, :))) 106 | % Repeat the process until only one column left 107 | for cc = 1:lc - 1 108 | H(j, c1(cc)) = 0; 109 | end 110 | else 111 | for cc = 1:lc - 1 112 | H(i, c1(cc)) = 0; 113 | end 114 | end % if 115 | 116 | end % if 117 | end % for j 118 | end % for i 119 | 120 | end % if 121 | 122 | fprintf('LDPC matrix is created.\n'); 123 | -------------------------------------------------------------------------------- /Simulations-V11/makeParityChk.m: -------------------------------------------------------------------------------- 1 | function [c, newH] = makeParityChk(dSource, H, strategy) 2 | % Generate parity check vector bases on LDPC matrix H using sparse LU decomposition 3 | % 4 | % dSource : Binary source (0/1) 5 | % H : LDPC matrix 6 | % strategy: Strategy for finding the next non-zero diagonal elements 7 | % {0} First : First non-zero found by column search 8 | % {1} Mincol : Minimum number of non-zeros in later columns 9 | % {2} Minprod: Minimum product of: 10 | % - Number of non-zeros its column minus 1 11 | % - Number of non-zeros its row minus 1 12 | % 13 | % c : Check bits 14 | % 15 | % 16 | % Copyright Bagawan S. Nugroho, 2007 17 | % http://bsnugroho.googlepages.com 18 | 19 | % Get the matric dimension 20 | [M, N] = size(H); 21 | % Set a new matrix F for LU decomposition 22 | F = H; 23 | % LU matrices 24 | L = zeros(M, N - M); 25 | U = zeros(M, N - M); 26 | 27 | % Re-order the M x (N - M) submatrix 28 | for i = 1:M 29 | 30 | % strategy {0 = First; 1 = Mincol; 2 = Minprod} 31 | switch strategy 32 | 33 | % Create diagonally structured matrix using 'First' strategy 34 | case {0} 35 | 36 | % Find non-zero elements (1s) for the diagonal 37 | [r, c] = find(F(:, i:end)); 38 | 39 | % Find non-zero diagonal element candidates 40 | rowIndex = find(r == i); 41 | 42 | % Find the first non-zero column 43 | chosenCol = c(rowIndex(1)) + (i - 1); 44 | 45 | % Create diagonally structured matrix using 'Mincol' strategy 46 | case {1} 47 | 48 | % Find non-zero elements (1s) for the diagonal 49 | [r, c] = find(F(:, i:end)); 50 | colWeight = sum(F(:, i:end), 1); 51 | 52 | % Find non-zero diagonal element candidates 53 | rowIndex = find(r == i); 54 | 55 | % Find the minimum column weight 56 | [x, ix] = min(colWeight(c(rowIndex))); 57 | % Add offset to the chosen row index to match the dimension of the... 58 | % original matrix F 59 | chosenCol = c(rowIndex(ix)) + (i - 1); 60 | 61 | % Create diagonally structured matrix using 'Minprod' strategy 62 | case {2} 63 | 64 | % Find non-zero elements (1s) for the diagonal 65 | [r, c] = find(F(:, i:end)); 66 | colWeight = sum(F(:, i:end), 1) - 1; 67 | rowWeight = sum(F(i, :), 2) - 1; 68 | 69 | % Find non-zero diagonal element candidates 70 | rowIndex = find(r == i); 71 | 72 | % Find the minimum product 73 | [x, ix] = min(colWeight(c(rowIndex))*rowWeight); 74 | % Add offset to the chosen row index to match the dimension of the... 75 | % original matrix F 76 | chosenCol = c(rowIndex(ix)) + (i - 1); 77 | 78 | otherwise 79 | fprintf('Please select columns re-ordering strategy!\n'); 80 | 81 | end % switch 82 | 83 | % Re-ordering columns of both H and F 84 | tmp1 = F(:, i); 85 | tmp2 = H(:, i); 86 | F(:, i) = F(:, chosenCol); 87 | H(:, i) = H(:, chosenCol); 88 | F(:, chosenCol) = tmp1; 89 | H(:, chosenCol) = tmp2; 90 | 91 | % Fill the LU matrices column by column 92 | L(i:end, i) = F(i:end, i); 93 | U(1:i, i) = F(1:i, i); 94 | 95 | % There will be no rows operation at the last row 96 | if i < M 97 | 98 | % Find the later rows with non-zero elements in column i 99 | [r2, c2] = find(F((i + 1):end, i)); 100 | % Add current row to the later rows which have a 1 in column i 101 | F((i + r2), :) = mod(F((i + r2), :) + repmat(F(i, :), length(r2), 1), 2); 102 | 103 | end % if 104 | 105 | end % for i 106 | 107 | % Find B.dsource 108 | z = mod(H(:, (N - M) + 1:end)*dSource, 2); 109 | 110 | % Parity check vector found by solving sparse LU 111 | c = mod(U\(L\z), 2); 112 | 113 | % Return the rearrange H 114 | newH = H; 115 | 116 | fprintf('Message encoded.\n'); 117 | -------------------------------------------------------------------------------- /Simulations-V11/mapping.m: -------------------------------------------------------------------------------- 1 | function [tx_symb] = mapping(tx_bin,Nbps,modulation) % Maps bitstream to Symbols depending on the selected mapping 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% MAPPING 9 | % INPUTS 10 | % 'tx_bin' - Bitstream 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'tx_symb' - Symbols 15 | 16 | 17 | %% INITIALIZATION AND VALIDITY CHECK 18 | if mod(Nbps, 1) ~=0 || Nbps <= 0 19 | error('You have entered an unsupported Number of Bits Per Symbol. Nbps must be a positive real integer.'); 20 | end 21 | Nsymb = size(tx_bin,1)/Nbps; % Number of symbols 22 | tx_bin = reshape(tx_bin,Nbps,Nsymb)'; % Reshapes the vector into a matrix: each row corresponds to a symbol (Nbps bits) 23 | 24 | switch modulation 25 | %% ***** PULSE AMPLITUDE MODULATION ***** 26 | case 'PAM' 27 | % Binary to Integer - Convert 'Binary Word' to corresponding 'Integer' [10 -> 2] 28 | tx_int = bi2de(fliplr(tx_bin)); 29 | % Integer to Gray-Integer - Convert 'Integer' to corresponding 'Gray-Integer' according to the desired Modulation Scheme and Npbs [2 <-> 3] 30 | tx_int = bin2gray(tx_int,'PAM',2^Nbps); 31 | % Gray-Integer to Symbol - Convert 'Gray Integer' to corresponding 'Symbol' according to the desired Modulation Scheme and Npbs 32 | distance = 2/(2^Nbps-1); 33 | tx_symb = distance * (tx_int - (2^Nbps-1)/2); 34 | 35 | 36 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 37 | case 'QAM' 38 | % Binary to Integer 39 | tx_int = bi2de(fliplr(tx_bin)); 40 | % Integer to Gray-Integer 41 | switch Nbps 42 | case 3 43 | bin2gray_matrix = [0 1 3 2 4 5 7 6]; 44 | for index = 1:length(tx_int) 45 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 46 | end 47 | case 5 48 | bin2gray_matrix = [0 1 3 2 6 7 5 4 8 9 11 10 14 15 13 12 24 25 27 26 30 31 29 28 16 17 19 18 22 23 21 20]; 49 | for index = 1:length(tx_int) 50 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 51 | end 52 | otherwise 53 | tx_int = bin2gray(tx_int,'QAM',2^Nbps); 54 | end 55 | 56 | % Gray-Integer to Symbol 57 | Nbps_I = ceil(Nbps/2); % Number of symbols carried in the 'Inphase Carrier' 58 | Nbps_Q = Nbps - Nbps_I; % Number of symbols carried in the 'Quadrature Carrier' 59 | distance = 2/(2^Nbps_I-1); 60 | tx_symb = distance*( (mod(tx_int,2^(Nbps_I)) - (2^Nbps_I-1)/2) - 1i*(floor(tx_int/(2^Nbps_I)) - (2^Nbps_Q-1)/2) ); 61 | 62 | 63 | %% ***** PHASE SHIFT KEYING ***** 64 | case 'PSK' 65 | % Binary to Integer 66 | tx_int = bi2de(fliplr(tx_bin)); 67 | % Integer to Gray-Integer 68 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 69 | % Gray-Integer to Symbol 70 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 71 | 72 | 73 | %% ***** CROSS-QAM ***** 74 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM' (one of the most famous flavour of the Cross-QAM) 75 | case 'Cross-QAM' 76 | switch Nbps 77 | case 1 % Simple PSK 78 | tx_int = bi2de(fliplr(tx_bin)); 79 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 80 | otherwise 81 | % Binary to Integer 82 | tx_int = bi2de(fliplr(tx_bin)); 83 | % Integer to Gray-Integer 84 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 85 | % Gray-Integer to Symbol 86 | tx_symb = zeros(length(tx_int),1); 87 | for index = 1:length(tx_int) 88 | radius = (2 + floor(tx_int(index)/4)) / (2^Nbps/4 + 1); 89 | phase = (mod(floor(tx_int(index)/4), 2) == 0)*3/4; 90 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 91 | end 92 | end 93 | 94 | 95 | %% ***** OPTIMAL-8QAM ***** 96 | case 'Optimal-8QAM' 97 | if Nbps ~= 3 98 | error('This particular Modulation Scheme only works with 3 Bits per Symbol. For Nbps other than 3, please choose among [PSK, PAM, QAM, Cross-QAM].'); 99 | end 100 | % Binary to Integer 101 | tx_int = bi2de(fliplr(tx_bin)); 102 | % Integer to Gray-Integer 103 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 104 | % Gray-Integer to Symbol 105 | tx_symb = zeros(length(tx_int),1); 106 | for index = 1:length(tx_int) 107 | if tx_int(index) > 3 108 | radius = 1; 109 | else 110 | radius = sqrt(2) / (1 + sqrt(3)); 111 | end 112 | phase = (floor(tx_int(index)/4) == 0)*3/4; 113 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 114 | end 115 | 116 | otherwise 117 | error('You have entered an unsupported Digital Modulation scheme. Please choose among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM].'); 118 | end -------------------------------------------------------------------------------- /Simulations-V11/maxLikelihood.m: -------------------------------------------------------------------------------- 1 | function [rx_symb_ML] = maxLikelihood(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 1 - Optimal communication chain over the ideal channel 6 | 7 | 8 | %% MAXIMUM LIKELIHOOD CRITERION 9 | % By comparing the Received Symbols 'rx_symb' with the Symbols of Reference 'symb_ref' we can apply the ML Criterion and deduce 'rx_symb_ML' 10 | % INPUTS 11 | % 'rx_symb' - Symbols 12 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 13 | % 'Nbps' - Number of bits per symbol 14 | % OUTPUT 15 | % 'rx_symb_ML' - Symbols after the application of the Maximum Likelihood Criterion 16 | 17 | 18 | %% ALGORITHM 19 | % 'symb_ref' is a [2^Nbps x 2] matrix used as a Containers.map 20 | % The 1st column includes all the Symbols of Reference in their Complex form (-0.7071 + i*0.7071, +0.7071 - i*0.7071,...) 21 | % The 2nd column includes the associated Decimal Value (0, 1, 2, 3, ...) 22 | % Step 1: Generating Symbols of Reference in function of (Nbps, modulation) 23 | % Step 2: Application of the Maximum Likelihood Criterion -> Compare each element of 'rx_symb' with the Symbols of Reference 'symb_ref' 24 | % Step 3: Return the Symbols after the application of the Maximum Likelihood Criterion 'rx_symb_ML' 25 | 26 | switch modulation 27 | %% ***** PULSE AMPLITUDE MODULATION ***** 28 | case 'PAM' 29 | % Generating Symbols of Reference 30 | symb_ref = zeros(2^Nbps,2); 31 | distance = 2/(2^Nbps-1); 32 | for index = 1:2^Nbps 33 | symb_ref(index,:) = [distance*(index-1 - (2^Nbps-1)/2), index-1]; 34 | end 35 | % Application of the Maximum Likelihood Criterion 36 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 37 | 38 | 39 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 40 | case 'QAM' 41 | % Generating Symbols of Reference 42 | Nbps_I = ceil(Nbps/2); Nbps_Q = Nbps - Nbps_I; 43 | symb_ref = zeros(2^Nbps,2); 44 | distance = 2/(2^Nbps_I-1); 45 | for index_I = 1:2^Nbps_I 46 | for index_Q = 1:2^Nbps_Q 47 | symb_ref(index_I + (2^Nbps_I)*(index_Q-1), :) = [distance*((index_I-1 - (2^Nbps_I-1)/2) - 1i* (index_Q-1 - (2^Nbps_Q-1)/2)), index_I-1 + (2^Nbps_I)*(index_Q-1)]; 48 | end 49 | end 50 | % Application of the Maximum Likelihood Criterion 51 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 52 | 53 | %% ***** PHASE SHIFT KEYING ***** 54 | case 'PSK' 55 | symb_ref = zeros(2^Nbps,2); 56 | % Generating Symbols of Reference 57 | for index = 1:2^Nbps 58 | symb_ref(index,:) = [exp(1i*pi*(3/4 + 2/(2^Nbps)*(index-1))), index-1]; 59 | end 60 | % Application of the Maximum Likelihood Criterion 61 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 62 | 63 | %% ***** CROSS-QUADRATURE AMPLITUDE MODULATION ***** 64 | case 'Cross-QAM' 65 | % Generating Symbols of Reference 66 | symb_ref = zeros(2^Nbps,2); 67 | switch Nbps 68 | case 1 % Only 2 Symbols on the 1st Orbit => Elementary PSK Case 69 | symb_ref = [exp(1i*pi*(3/4 + 2/(2^Nbps)*0)), 0; exp(1i*pi*(3/4 + 2/(2^Nbps)*1)), 1]; 70 | otherwise 71 | for index = 1:2^Nbps 72 | radius = (2 + floor((index - 1)/4)) / (2^Nbps/4 + 1); 73 | phase = (mod(floor((index-1)/4), 2) == 0)*3/4; 74 | symb_ref(index,:) = [radius*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 75 | end 76 | end 77 | % Application of the Maximum Likelihood Criterion 78 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 79 | 80 | 81 | %% ***** OPTIMAL-8QAM ***** 82 | case 'Optimal-8QAM' 83 | % Generating Symbols of Reference 84 | symb_ref = zeros(2^Nbps,2); 85 | radius = [sqrt(2)/(1 + sqrt(3)), 1]; 86 | for index = 1:2^Nbps 87 | phase = (floor((index-1)/4) == 0)*3/4; 88 | symb_ref(index,:) = [radius(floor((index-1)/4) + 1)*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 89 | end 90 | % Application of the Maximum Likelihood Criterion 91 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 92 | end 93 | 94 | 95 | %% ***** APPLICATION OF THE MAXIMUM LIKELIHOOD CRITERION ***** 96 | function [rx_symb_ML] = appML(rx_symb, Nbps, symb_ref) 97 | rx_symb_ML = zeros(length(rx_symb), 1); % Initialize the size of 'rx_symb_ML' in order to save some time 98 | CSM = sqrt(abs((rx_symb(:) - symb_ref(1, 1)) .^ 2)); % CSM - Current Smallest Norm: Transient save allowing to 'compare before assign' 99 | 100 | for index = 1:2^Nbps % Loop to determine the minimal Euclidean Norm of each Received Symbol 101 | BOOL = CSM > sqrt(abs((rx_symb(:) - symb_ref(index, 1)) .^ 2)); % Boolean Vector taking a true value ('1') when the corresponding CSM row appears to not be the smallest possible Euclidean Norm 102 | CSM(BOOL) = sqrt(abs((rx_symb(BOOL) - symb_ref(index, 1)) .^ 2)); % Update CSM accordingly 103 | rx_symb_ML(BOOL) = symb_ref(index, 2); 104 | end -------------------------------------------------------------------------------- /Simulations-V11/rx_constellations.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V11/rx_constellations.fig -------------------------------------------------------------------------------- /Simulations-V21/CFO_est.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Project 2 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 3 | % April 2016 4 | % Part 2 - Time and Frequency Syncrhonisation 5 | % Gardner Function 6 | % carry out Gardner to Maximum Likelyhood estimation of t_0 7 | % input: 8 | % -rx_input: receiver rx_input upsampled by factor M 9 | % -M: upsampling factor 10 | % -K: constant in the Gardner algorithm 11 | % output: 12 | % -est_error: estimated est_error 13 | % -y_corr: corrected sequence 14 | 15 | function [CFO_esti] = pilot_est( signal, a , fsym ) 16 | 17 | N=numel(a); 18 | K=16; 19 | T=1/fsym; 20 | L=length(signal); 21 | 22 | D=zeros(K,L-N+1); 23 | for kk=1:K 24 | for ll=kk:N-1 25 | D(kk,:)= D(kk,:)+ transpose(conj(signal(ll:L-N+ll))*a(ll) .* (conj(conj(signal(1+ll-kk:L-N+ll-kk+1))*a(ll-kk+1)))); 26 | end 27 | D(kk,:)=D(kk,:)/(N-kk); 28 | end 29 | 30 | Dtot=sum(abs(D)); 31 | [maximum,n_est]= max(Dtot); 32 | 33 | CFO_esti=0; 34 | for kk=1:K 35 | CFO_esti= CFO_esti + phase(D(kk,n_est))/(2*pi*kk*T); 36 | end 37 | CFO_esti=-CFO_esti/K; 38 | end -------------------------------------------------------------------------------- /Simulations-V21/DVBS2CommunicationChain.m: -------------------------------------------------------------------------------- 1 | function [BER, SER, tx_symb, rx_symb] = DVBS2CommunicationChain(mod_input, Nbps_input, EbN0_ratio_input, CFO_input, t0_input, phi0_input) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DVBS2CommunicationChain 9 | % INPUTS 10 | % 'mod_input' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 11 | % 'Nbps_input' - Number of bits per symbol 12 | % 'EbN0_ratio_input' - SNR per bit 13 | % OUTPUTS 14 | % 'BER' - Bit Error Ratio 15 | % 'SER' - Symbol Error Ratio 16 | % 'tx_symb' - Transmitted Symbols 17 | % 'rx_symb' - Received Symbols 18 | 19 | 20 | %% Implemented Features 21 | % 1. [TX] - GENERATING INFORMATION - RANDOM BITSTREAM 22 | % 2. [TX] - MAPPING BITSTREAM TO SYMBOLS - SUPPORTED MODULATION SCHEMES: [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] - Works for any Nbps 23 | % 3. [TX] - UPSAMPLING 24 | % 4. [TX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 25 | % 5. [CHAN] - ADDING AWGN IN THE IDEAL CHANNEL 26 | % 6. [RX] - SYNCHRONISATION ERRORS 27 | % 7. [RX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 28 | % 8. [RX] - TIME SHIFT ON SAMPLING 29 | % 9. [RX] - DOWNSAMPLING 30 | % 10.[RX] - DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 31 | % X. [PLOT] - RELEVANT GRAPHS AND VALUES 32 | 33 | 34 | %% IF YOU WANT TO AUTO-RUN THIS FUNCTION - DECOMMENTS THE 4 NEXT LINES. 35 | %% IF YOU WANT TO RUN THIS FUNCTION FROM 'FoM' - COMMENTS THE 4 NEXT LINES. 36 | % clear; clc; close all; 37 | % mod_input = 'QAM'; 38 | % Nbps_input = 4; 39 | % EbN0_ratio_input = 5; 40 | %% RX settings 41 | % 1. On/Off Gardner => 0/1 42 | Gardner_S = 1; 43 | 44 | %% ***** RCF PARAMETERS ***** 45 | RRCF.fcutoff = 1e6; % 3dB Cutoff Frequency of the RCF [1MHz] 46 | RRCF.beta = 0.3; % Roll-off factor of the RCF [0.3] 47 | RRCF.M = 40; % [!] Deduct the Upsampling Factor -> Needed in order to satisfy the ISI Nyquist Criterion. Big M allows to simulate a Time Shift on sampling 48 | RRCF.fs = RRCF.M*2*RRCF.fcutoff; % = M*fsymb - Deduct the Sampling Frequency [Hz] 49 | RRCF.Ntaps = 16*RRCF.M + 1; % Number of taps of the RCF 50 | 51 | %% ***** MODULATION SCHEME PARAMETERS ***** 52 | Modu.mod = mod_input; % Select the Digital Modulation among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] (NB: The 'Optimal-8QAM' is designed for 8 Symbols only (=> Nbps = 3)) 53 | Modu.Nbps = Nbps_input; % Select the Number of Bits Per Symbol 54 | Modu.fsymb = 2*RRCF.fcutoff; % Select the Symbolrate [2MHz] - Common to all Modulation Schemes and independent of Nbps 55 | Modu.bps = Modu.fsymb*Modu.Nbps; % Deduct the Bitrate [bits/s] - Depends on the Number of Bits carried per each Symbol (Nbps) 56 | Modu.Tsymb = 1/Modu.fsymb; % Deduct the Period of a symbol [s] (or more rigorously [s/Symb]) 57 | 58 | %% ***** SYNC PARAMETERS ***** 59 | SYNC.CFO = CFO_input*Modu.fsymb; % Carrier Frequency Offset 60 | SYNC.t0 = t0_input; % Sample Time Shift - Always in [0:Tsymb] (Physically) - [0:M-1] (Digital Simulation) [Physically = Tsymb*t0/M-1 = t0*Tsample] 61 | SYNC.phi0 = phi0_input; % Carrier Phase Error - Always in [0:2pi] 62 | 63 | 64 | %% 1. [TX] GENERATING INFORMATION - RANDOM BITSTREAM 65 | tx_len = 10000; % Length of the bitstream 66 | tx_bin = randi([0 1], tx_len,1); % Bitstream - Generate binary sequence (0 and 1 are equiprobable) 67 | 68 | 69 | %% 2. [TX] MAPPING BITSTREAM TO SYMBOLS 70 | if mod(tx_len,Modu.Nbps) ~= 0 % ZERO PADDING -> Allows to avoid to get an error if the Bitstream length is not a multiple of Nbps 71 | tx_bin = [tx_bin; zeros(Modu.Nbps - mod(tx_len,Modu.Nbps),1)]; 72 | tx_len = tx_len + Modu.Nbps - mod(tx_len,Modu.Nbps); 73 | end 74 | tx_symb = mapping(tx_bin, Modu.Nbps, Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps 75 | 76 | 77 | %% 3. [TX] UPSAMPLING 78 | tx_symb_UP = upsample(tx_symb,RRCF.M); % Upsample 79 | tx_symb_UP_R = real(tx_symb_UP); 80 | 81 | %% 4. [TX] FILTERING WITH ROOT-RAISED-COSINE FILTER 82 | RRCF.IR = RRCFDesign(RRCF.beta, RRCF.Ntaps, RRCF.fs, Modu.Tsymb); % Impulse Response of the RRCF 83 | tx_symb_UP_F = conv(tx_symb_UP,RRCF.IR); % Apply the RRCF 84 | tx_symb_UP_F_R = real(tx_symb_UP_F); 85 | 86 | %% 5. [CHAN] ADDING AWGN IN THE IDEAL CHANNEL 87 | % In practice, we send in the channel the Narrowband Bandpass Signal (the Baseband Signal modulated at a high frequency) 88 | % In this simulation, we directly send the Baseband Signal (Complex Envelope) in the channel. This is done in order to save computing power 89 | % However, we have to take into account the fact that the energy of a Bandpass Signal is equal to the energy of its Complex Envelope divided by 2 90 | Es_CE = (trapz(abs(tx_symb_UP_F).^2))*(1/(RRCF.fs)); % Basedband Signal Energy (Complex Envelope of the Bandpass Signal) 91 | Es_BP = Es_CE/2; % Bandpass Signal Energy 92 | Eb = Es_BP/tx_len; % Average energy of a bit 93 | EbN0_dB = EbN0_ratio_input; % Energy per Bit to Noise PSD ratio [dB] 94 | EbN0_ratio = 10^(EbN0_dB/10); % Energy per Bit to Noise PSD ratio 95 | N0 = Eb/EbN0_ratio; % Noise PSD - We consider AWGN, so N0 is constant on the whole frequency domain 96 | NoisePower = 2*N0*RRCF.fs; % Noise Power 97 | noise_AWGN = sqrt(NoisePower/2)*(randn(length(tx_symb_UP_F), 1) + 1i*randn(length(tx_symb_UP_F), 1)); % Generate Zero-Mean AWGN 98 | rx_symb_UP_F = tx_symb_UP_F + noise_AWGN; % Add the noise to the transmitted signal 99 | 100 | 101 | %% 6. [RX] SYNCHRONISATION ERRORS 102 | t_axis = 0:1/RRCF.fs:(1/RRCF.fs*(length(rx_symb_UP_F)-1)); 103 | exp_async = exp(1j* (2*pi*SYNC.CFO*t_axis' + SYNC.phi0) ); 104 | rx_symb_UP_F_async = exp_async.*rx_symb_UP_F; 105 | 106 | 107 | %% 7. [RX] FILTERING WITH ROOT-RAISED-COSINE FILTER 108 | rx_symb_UP_async = conv(rx_symb_UP_F_async,RRCF.IR); % Apply the matched RRCF 109 | rx_symb_UP_async = rx_symb_UP_async(RRCF.Ntaps:length(rx_symb_UP_async) - RRCF.Ntaps+1); % Removes the irrelevant values 110 | 111 | 112 | %% 8. [RX] TIME SHIFT ON SAMPLING 113 | % Time shift with constant offset t_0 [after the matched filter, before the down sampler] 114 | 115 | rx_symb_UP_async_t0 = rx_symb_UP_async(SYNC.t0+1:end,1); % Thanks to the big oversampling M, we can simulated a Time Shift On Sampling 116 | rx_symb_UP_async_t0 = [rx_symb_UP_async_t0; zeros(SYNC.t0 - 1,1)]; % Zero-Padding to match the length 117 | 118 | rx_symb_UP_async_t0_R = real(rx_symb_UP_async_t0); 119 | 120 | 121 | %% 9. [RX] DOWNSAMPLING 122 | rx_symb = downsample(rx_symb_UP_async_t0,RRCF.M); 123 | 124 | %% 10. [RX] DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 125 | rx_bin = demapping(rx_symb,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 126 | 127 | 128 | %% X. [PLOT] RELEVANT GRAPHS AND VALUES 129 | % See the function 'FoM' for all the preset Graphs 130 | rx_bin_len = size(rx_bin,1); 131 | BER = 1 - sum(rx_bin(1:rx_bin_len) == tx_bin(1:rx_bin_len))/(rx_bin_len); % Bit Error Ratio 132 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,rx_bin_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin(1:rx_bin_len),Modu.Nbps,rx_bin_len/Modu.Nbps)'))) / (rx_bin_len/Modu.Nbps); % Symbol Error Ratio 133 | 134 | 135 | %% Gardner algorithm -> ML estimation for t_0 and correct the rx_symb 136 | if Gardner_S == 1 137 | 138 | %[T] 139 | figure 140 | plot(tx_symb_UP_R(200:300),'x-'); hold on 141 | %plot(tx_symb_UP_F_R(200:300),'o-r'); hold on; 142 | plot(rx_symb_UP_async_t0_R(200:300),'o-.k'); 143 | 144 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, 0.1); 145 | figure 146 | plot(est_error); 147 | title(['Applying Gardner to ',num2str(t0_input),' time shift unit for', num2str(2^Nbps_input), mod_input]); 148 | xlabel('Time (pts)'); ylabel('Estimated Error'); hold on; 149 | 150 | rx_symb_c = downsample(y_corr,RRCF.M); 151 | rx_bin_c = demapping(rx_symb_c,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 152 | rx_bin_c_len = size(rx_bin_c,1); 153 | BER_c = 1 - sum(rx_bin_c(1:rx_bin_c_len) == tx_bin(1:rx_bin_c_len))/(rx_bin_c_len); % Bit Error Ratio 154 | 155 | BER 156 | BER_c 157 | 158 | end 159 | 160 | end 161 | -------------------------------------------------------------------------------- /Simulations-V21/DVBS2CommunicationChain_GC.m: -------------------------------------------------------------------------------- 1 | function [BER, SER, tx_symb, rx_symb] = DVBS2CommunicationChain_GC(mod_input, Nbps_input, EbN0_ratio_input, CFO_input, t0_input, phi0_input) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DVBS2CommunicationChain 9 | % INPUTS 10 | % 'mod_input' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 11 | % 'Nbps_input' - Number of bits per symbol 12 | % 'EbN0_ratio_input' - SNR per bit 13 | % OUTPUTS 14 | % 'BER' - Bit Error Ratio 15 | % 'SER' - Symbol Error Ratio 16 | % 'tx_symb' - Transmitted Symbols 17 | % 'rx_symb' - Received Symbols 18 | 19 | 20 | %% Implemented Features 21 | % 1. [TX] - GENERATING INFORMATION - RANDOM BITSTREAM 22 | % 2. [TX] - MAPPING BITSTREAM TO SYMBOLS - SUPPORTED MODULATION SCHEMES: [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] - Works for any Nbps 23 | % 3. [TX] - UPSAMPLING 24 | % 4. [TX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 25 | % 5. [CHAN] - ADDING AWGN IN THE IDEAL CHANNEL 26 | % 6. [RX] - SYNCHRONISATION ERRORS 27 | % 7. [RX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 28 | % 8. [RX] - TIME SHIFT ON SAMPLING 29 | % 9. [RX] - DOWNSAMPLING 30 | % 10.[RX] - DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 31 | % X. [PLOT] - RELEVANT GRAPHS AND VALUES 32 | 33 | 34 | %% IF YOU WANT TO AUTO-RUN THIS FUNCTION - DECOMMENTS THE 4 NEXT LINES. 35 | %% IF YOU WANT TO RUN THIS FUNCTION FROM 'FoM' - COMMENTS THE 4 NEXT LINES. 36 | % clear; clc; close all; 37 | % mod_input = 'QAM'; 38 | % Nbps_input = 4; 39 | % EbN0_ratio_input = 5; 40 | %% RX settings 41 | % 1. On/Off Gardner => 0/1 42 | Gardner_S = 1; 43 | % 2. On/Off CFO correction 44 | 45 | %% ***** RCF PARAMETERS ***** 46 | RRCF.fcutoff = 1e6; % 3dB Cutoff Frequency of the RCF [1MHz] 47 | RRCF.beta = 0.3; % Roll-off factor of the RCF [0.3] 48 | RRCF.M = 40; % [!] Deduct the Upsampling Factor -> Needed in order to satisfy the ISI Nyquist Criterion. Big M allows to simulate a Time Shift on sampling 49 | RRCF.fs = RRCF.M*2*RRCF.fcutoff; % = M*fsymb - Deduct the Sampling Frequency [Hz] 50 | RRCF.Ntaps = 16*RRCF.M + 1; % Number of taps of the RCF 51 | 52 | %% ***** MODULATION SCHEME PARAMETERS ***** 53 | Modu.mod = mod_input; % Select the Digital Modulation among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] (NB: The 'Optimal-8QAM' is designed for 8 Symbols only (=> Nbps = 3)) 54 | Modu.Nbps = Nbps_input; % Select the Number of Bits Per Symbol 55 | Modu.fsymb = 2*RRCF.fcutoff; % Select the Symbolrate [2MHz] - Common to all Modulation Schemes and independent of Nbps 56 | Modu.bps = Modu.fsymb*Modu.Nbps; % Deduct the Bitrate [bits/s] - Depends on the Number of Bits carried per each Symbol (Nbps) 57 | Modu.Tsymb = 1/Modu.fsymb; % Deduct the Period of a symbol [s] (or more rigorously [s/Symb]) 58 | 59 | %% ***** SYNC PARAMETERS ***** 60 | SYNC.CFO = CFO_input*Modu.fsymb; % Carrier Frequency Offset 61 | SYNC.t0 = t0_input; % Sample Time Shift - Always in [0:Tsymb] (Physically) - [0:M-1] (Digital Simulation) [Physically = Tsymb*t0/M-1 = t0*Tsample] 62 | SYNC.phi0 = phi0_input; % Carrier Phase Error - Always in [0:2pi] 63 | 64 | 65 | %% 1. [TX] GENERATING INFORMATION - RANDOM BITSTREAM 66 | tx_len = 10000; % Length of the bitstream 67 | tx_bin = randi([0 1], tx_len,1); % Bitstream - Generate binary sequence (0 and 1 are equiprobable) 68 | 69 | 70 | %% 2. [TX] MAPPING BITSTREAM TO SYMBOLS 71 | if mod(tx_len,Modu.Nbps) ~= 0 % ZERO PADDING -> Allows to avoid to get an error if the Bitstream length is not a multiple of Nbps 72 | tx_bin = [tx_bin; zeros(Modu.Nbps - mod(tx_len,Modu.Nbps),1)]; 73 | tx_len = tx_len + Modu.Nbps - mod(tx_len,Modu.Nbps); 74 | end 75 | tx_symb = mapping(tx_bin, Modu.Nbps, Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps 76 | 77 | 78 | %% 3. [TX] UPSAMPLING 79 | tx_symb_UP = upsample(tx_symb,RRCF.M); % Upsample 80 | tx_symb_UP_R = real(tx_symb_UP); 81 | 82 | %% 4. [TX] FILTERING WITH ROOT-RAISED-COSINE FILTER 83 | RRCF.IR = RRCFDesign(RRCF.beta, RRCF.Ntaps, RRCF.fs, Modu.Tsymb); % Impulse Response of the RRCF 84 | tx_symb_UP_F = conv(tx_symb_UP,RRCF.IR); % Apply the RRCF 85 | tx_symb_UP_F_R = real(tx_symb_UP_F); 86 | 87 | %% 5. [CHAN] ADDING AWGN IN THE IDEAL CHANNEL 88 | % In practice, we send in the channel the Narrowband Bandpass Signal (the Baseband Signal modulated at a high frequency) 89 | % In this simulation, we directly send the Baseband Signal (Complex Envelope) in the channel. This is done in order to save computing power 90 | % However, we have to take into account the fact that the energy of a Bandpass Signal is equal to the energy of its Complex Envelope divided by 2 91 | Es_CE = (trapz(abs(tx_symb_UP_F).^2))*(1/(RRCF.fs)); % Basedband Signal Energy (Complex Envelope of the Bandpass Signal) 92 | Es_BP = Es_CE/2; % Bandpass Signal Energy 93 | Eb = Es_BP/tx_len; % Average energy of a bit 94 | EbN0_dB = EbN0_ratio_input; % Energy per Bit to Noise PSD ratio [dB] 95 | EbN0_ratio = 10^(EbN0_dB/10); % Energy per Bit to Noise PSD ratio 96 | N0 = Eb/EbN0_ratio; % Noise PSD - We consider AWGN, so N0 is constant on the whole frequency domain 97 | NoisePower = 2*N0*RRCF.fs; % Noise Power 98 | noise_AWGN = sqrt(NoisePower/2)*(randn(length(tx_symb_UP_F), 1) + 1i*randn(length(tx_symb_UP_F), 1)); % Generate Zero-Mean AWGN 99 | rx_symb_UP_F = tx_symb_UP_F + noise_AWGN; % Add the noise to the transmitted signal 100 | 101 | 102 | %% 6. [RX] SYNCHRONISATION ERRORS 103 | t_axis = 0:1/RRCF.fs:(1/RRCF.fs*(length(rx_symb_UP_F)-1)); 104 | exp_async = exp(1j* (2*pi*SYNC.CFO*t_axis' + SYNC.phi0) ); 105 | rx_symb_UP_F_async = exp_async.*rx_symb_UP_F; 106 | 107 | 108 | %% 7. [RX] FILTERING WITH ROOT-RAISED-COSINE FILTER 109 | rx_symb_UP_async = conv(rx_symb_UP_F_async,RRCF.IR); % Apply the matched RRCF 110 | rx_symb_UP_async = rx_symb_UP_async(RRCF.Ntaps:length(rx_symb_UP_async) - RRCF.Ntaps+1); % Removes the irrelevant values 111 | 112 | 113 | %% 8. [RX] TIME SHIFT ON SAMPLING 114 | % Time shift with constant offset t_0 [after the matched filter, before the down sampler] 115 | 116 | rx_symb_UP_async_t0 = rx_symb_UP_async(SYNC.t0+1:end,1); % Thanks to the big oversampling M, we can simulated a Time Shift On Sampling 117 | rx_symb_UP_async_t0 = [rx_symb_UP_async_t0; zeros(SYNC.t0 - 1,1)]; % Zero-Padding to match the length 118 | 119 | rx_symb_UP_async_t0_R = real(rx_symb_UP_async_t0); 120 | 121 | 122 | %% 9. [RX] DOWNSAMPLING 123 | rx_symb = downsample(rx_symb_UP_async_t0,RRCF.M); 124 | 125 | %% 10. [RX] DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 126 | rx_bin = demapping(rx_symb,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 127 | 128 | 129 | %% X. [PLOT] RELEVANT GRAPHS AND VALUES 130 | % See the function 'FoM' for all the preset Graphs 131 | rx_bin_len = size(rx_bin,1); 132 | BER = 1 - sum(rx_bin(1:rx_bin_len) == tx_bin(1:rx_bin_len))/(rx_bin_len); % Bit Error Ratio 133 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,rx_bin_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin(1:rx_bin_len),Modu.Nbps,rx_bin_len/Modu.Nbps)'))) / (rx_bin_len/Modu.Nbps); % Symbol Error Ratio 134 | 135 | 136 | %% Gardner algorithm -> ML estimation for t_0 and correct the rx_symb 137 | if Gardner_S == 1 138 | 139 | %[T] 140 | figure 141 | plot(tx_symb_UP_R(200:300),'x-'); hold on 142 | %plot(tx_symb_UP_F_R(200:300),'o-r'); hold on; 143 | plot(rx_symb_UP_async_t0_R(200:300),'o-.k'); 144 | 145 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, 0.1); 146 | figure 147 | plot(est_error,'b'); hold on 148 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, 0.5); 149 | plot(est_error,'r'); 150 | 151 | title(['Applying Gardner to ',num2str(t0_input),' time shift unit for', num2str(2^Nbps_input), mod_input]); 152 | xlabel('Time (pts)'); ylabel('Estimated Error'); hold on; 153 | legend('K=0.1','K=0.5'); 154 | 155 | rx_symb_c = downsample(y_corr,RRCF.M); 156 | rx_bin_c = demapping(rx_symb_c,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 157 | rx_bin_c_len = size(rx_bin_c,1); 158 | BER_c = 1 - sum(rx_bin_c(1:rx_bin_c_len) == tx_bin(1:rx_bin_c_len))/(rx_bin_c_len); % Bit Error Ratio 159 | 160 | end 161 | 162 | end 163 | -------------------------------------------------------------------------------- /Simulations-V21/FoM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V21/FoM.m -------------------------------------------------------------------------------- /Simulations-V21/RRCFDesign.m: -------------------------------------------------------------------------------- 1 | function [IR_RRC, H_RRCF, t_axis, f_axis] = RRCFDesign(Beta, Ntaps, fs, Tsymb) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% RRCFDesign 9 | % INPUTsymb 10 | % 'Beta' - Roll-off Factor 11 | % 'Ntaps' - Number of RRC Taps [Needs to be odd] - Set the Time Extension and the Frequency Resolution 12 | % 'fs' - Sampling Frequency [Hz] 13 | % 'Tsymb' - Symbol Period [s] 14 | % OUTPUTsymb 15 | % 'IR_RRC' - Impulse Response of the designed RRCF 16 | % 'H_RRCF' - Spectrum of the designed RRCF 17 | 18 | 19 | %% The RCF is designed in the frequency domain 20 | %% The Impulse Response is then obtained by IFFT 21 | fmax = (1/Ntaps)*fs*(Ntaps-1)/2; % Maximal frequency on the axis - Tends to fs/2 for Ntaps tending to infinity 22 | f_axis = linspace(-fmax, fmax, Ntaps); 23 | t_axis = (-(Ntaps-1)/2:(Ntaps-1)/2)./(2*fmax); 24 | H_RCF = zeros(1,Ntaps); % Fourier Transform of the RCF 25 | 26 | for i=1:Ntaps % Ntaps seTsymb the Time Extension and the Frequency Resolution 27 | if abs(f_axis(i))<=((1-Beta)/(2*Tsymb)) 28 | H_RCF(i) = Tsymb; 29 | elseif abs(f_axis(i))>((1-Beta)/(2*Tsymb)) && abs(f_axis(i))<=((1+Beta)/(2*Tsymb)) 30 | H_RCF(i) = Tsymb/2*(1+cos(pi*Tsymb/Beta*(abs(f_axis(i))-(1-Beta)/(2*Tsymb)))); 31 | else 32 | H_RCF(i) = 0; 33 | end 34 | end 35 | 36 | H_RRCF = sqrt(H_RCF); 37 | IR_RRC = fftshift(ifft(ifftshift(H_RRCF), 'symmetric')); 38 | normCoeff = sqrt(max(abs(conv(IR_RRC,IR_RRC)))); 39 | IR_RRC=IR_RRC/normCoeff; % Normalize -> the RCF will then be equal to 1 @ t=0 (and not the RRCF !) 40 | end -------------------------------------------------------------------------------- /Simulations-V21/RRCfilterDesign.m: -------------------------------------------------------------------------------- 1 | function [RRCf_time] = RRCfilterDesign(beta, NRRCtaps, tsymb, fsample) 2 | %INPUTS: 3 | % -beta: roll-off coefficient 4 | % -NRRCtaps: Number of RRC taps 5 | % -Tsym: sampling rate 6 | %OUTPUTS: 7 | % -RRCf_time: filter in time domain 8 | 9 | fmax = (1/NRRCtaps)*fsample*(NRRCtaps-1)/2; 10 | f = linspace(-fmax, fmax, NRRCtaps); % build the f x-axis 11 | Hrcf=zeros(1,NRRCtaps); 12 | 13 | for i=1:NRRCtaps 14 | if abs(f(i))<=((1-beta)/(2*tsymb)) 15 | Hrcf(i) = tsymb; 16 | elseif abs(f(i))>((1-beta)/(2*tsymb)) && abs(f(i))<=((1+beta)/(2*tsymb)) 17 | Hrcf(i) = tsymb/2*(1+cos(pi*tsymb/beta*(abs(f(i))-(1-beta)/(2*tsymb)))); 18 | else 19 | Hrcf(i) = 0; 20 | end 21 | end 22 | 23 | %Hrcf = fftshift(Hrcf); 24 | Hrrcf = sqrt(Hrcf); 25 | Hrrct = fftshift(ifft(ifftshift(Hrrcf), 'symmetric')); 26 | normCoeff = sqrt(max(abs(conv(Hrrct,Hrrct)))); 27 | Hrrct=Hrrct/normCoeff; 28 | %Hrrct = Hrrctv; 29 | % figure 30 | % stem(Hrrct); 31 | % title('Hrrct') 32 | 33 | %Hrctv = ifftshift(ifft(Hrcf,'symmetric')) 34 | %Hrct = circshift(Hrctv',-1); 35 | %fa = 1/Hrct((NRRCtaps+1)/2); 36 | %Hrct = Hrct.*fa; 37 | %Hrrct = Hrct.^(-2); 38 | 39 | % 40 | % Hrrcf = sqrt(Hrcf); 41 | % Hrrcf = fftshift(Hrrcf); 42 | % % figure 43 | % % plot(Hrcf); 44 | % % title('H(f) Square Root Cosine Filter') 45 | % 46 | % %Hrrct = ifft(Hrrcf); 47 | % Hrrctv = ifftshift(ifft(Hrrcf,'symmetric')); 48 | % Hrrct = circshift(Hrrctv',-1); 49 | % 50 | 51 | % figure 52 | % stem(Hrrct); 53 | % title('H(t)'); 54 | RRCf_time=Hrrct; 55 | 56 | end -------------------------------------------------------------------------------- /Simulations-V21/demapping.m: -------------------------------------------------------------------------------- 1 | function [rx_bin] = demapping(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DEMAPPING 9 | % INPUTS 10 | % 'rx_symb' - Symbols 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'rx_bit' - Bitstream 15 | 16 | 17 | %% INITIALIZATION 18 | Nsymb = size(rx_symb,1); % Number of symbols 19 | 20 | switch modulation 21 | %% ***** PULSE AMPLITUDE MODULATION ***** 22 | case 'PAM' 23 | % Symbol to Gray-Integer 24 | rx_int = maxLikelihood(rx_symb,Nbps,'PAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 25 | % Gray-Integer to Integer 26 | rx_int = gray2bin(rx_int,'PAM',2^Nbps); 27 | % Integer to Binary 28 | rx_bin = fliplr(de2bi(rx_int)); 29 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 30 | 31 | 32 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 33 | case 'QAM' 34 | % Symbol to Gray-Integer 35 | rx_int = maxLikelihood(rx_symb,Nbps,'QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 36 | % Gray-Integer to Integer 37 | switch Nbps 38 | case 3 39 | gray2bin_matrix = [0 1 3 2 4 5 7 6]; 40 | for index = 1:length(rx_int) 41 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 42 | end 43 | case 5 44 | gray2bin_matrix = [0 1 3 2 7 6 4 5 8 9 11 10 15 14 12 13 24 25 27 26 31 30 28 29 16 17 19 18 23 22 20 21]; 45 | for index = 1:length(rx_int) 46 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 47 | end 48 | otherwise 49 | rx_int = gray2bin(rx_int,'QAM',2^Nbps); 50 | end 51 | % Integer to Binary 52 | rx_bin = fliplr(de2bi(rx_int)); 53 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 54 | 55 | 56 | %% ***** PHASE SHIFT KEYING ***** 57 | case 'PSK' 58 | % Symbol to Gray-Integer 59 | rx_int = maxLikelihood(rx_symb,Nbps,'PSK'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 60 | % Gray-Integer to Integer 61 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 62 | % Integer to Binary 63 | rx_bin = fliplr(de2bi(rx_int)); 64 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 65 | 66 | 67 | %% ***** CROSS-QAM ***** 68 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM'(one of the most famous flavor of the Cross-QAM) 69 | case 'Cross-QAM' 70 | % Symbol to Gray-Integer 71 | rx_int = maxLikelihood(rx_symb,Nbps,'Cross-QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 72 | % Gray-Integer to Integer 73 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 74 | % Integer to Binary 75 | rx_bin = fliplr(de2bi(rx_int)); 76 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 77 | 78 | 79 | %% ***** OPTIMAL-8QAM ***** 80 | case 'Optimal-8QAM' 81 | % Symbol to Gray-Integer 82 | rx_int = maxLikelihood(rx_symb,Nbps,'Optimal-8QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 83 | % Gray-Integer to Integer 84 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 85 | % Integer to Binary 86 | rx_bin = fliplr(de2bi(rx_int)); 87 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 88 | end 89 | end -------------------------------------------------------------------------------- /Simulations-V21/gardner_est.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Project 2 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 3 | % April 2016 4 | % Part 2 - Time and Frequency Syncrhonisation 5 | % Gardner Function 6 | % carry out Gardner to Maximum Likelyhood estimation of t_0 7 | % input: 8 | % -rx_input: receiver rx_input upsampled by factor M 9 | % -M: upsampling factor 10 | % -K: constant in the Gardner algorithm 11 | % output: 12 | % -est_error: estimated est_error 13 | % -y_corr: corrected sequence 14 | 15 | function [est_error, y_corr]=gardner_est(rx_input, M, K) 16 | 17 | % Init the parameters 18 | rx_len = length(rx_input); 19 | n_sym = round(rx_len/M); 20 | est_error = zeros(1,(n_sym)); % initialize the error mat 21 | y_corr = rx_input; %init the corrected rx sequence 22 | 23 | % iterate through the length of the rx 24 | for ii = 1:n_sym-2 25 | % update the error 26 | est_error(ii+1) = est_error(ii) + K*real(y_corr((2*ii-1)*M/2+1)... 27 | *(conj(y_corr(ii*M+1))-conj(y_corr((ii-1)*M+1)))); 28 | 29 | y_corr((2*ii+1)*M/2+1) = interp1([ii*M+1,ii*M+2,(2*ii+1)*M/2+1,(ii+1)*M+1],... 30 | [rx_input(ii*M+1),rx_input(ii*M+2), rx_input((2*ii+1)*M/2+1), rx_input((ii+1)*M+1)],... 31 | (2*ii+1)*M/2+1-round(est_error(ii+1))); 32 | y_corr((ii+1)*M+1) = interp1([(2*ii+1)*M/2+1, (2*ii+2)*M/2+1, (2*ii+3)*M/2+1],... 33 | [rx_input((2*ii+1)*M/2+1), rx_input((2*ii+2)*M/2+1), rx_input((2*ii+3)*M/2+1)],... 34 | (ii+1)*M+1-round(est_error(ii+1))); 35 | end 36 | 37 | 38 | end -------------------------------------------------------------------------------- /Simulations-V21/makeLdpc.m: -------------------------------------------------------------------------------- 1 | function H = makeLdpc(M, N, method, noCycle, onePerCol) 2 | % Create R = 1/2 low density parity check matrix 3 | % 4 | % M : Number of row 5 | % N : Number of column 6 | % method : Method for distributing non-zero element 7 | % {0} Evencol : For each column, place 1s uniformly at random 8 | % {1} Evenboth: For each column and row, place 1s uniformly at random 9 | % noCyle : Length-4 cycle 10 | % {0} Ignore (do nothing) 11 | % {1} Eliminate 12 | % onePerCol: Number of ones per column 13 | % 14 | % H : Low density parity check matrix 15 | % 16 | % 17 | % Copyright Bagawan S. Nugroho, 2007 18 | % http://bsnugroho.googlepages.com 19 | 20 | 21 | % Number of ones per row (N/M ratio must be 2) 22 | if N/M ~= 2 23 | fprintf('Code rate must be 1/2\n'); 24 | end 25 | onePerRow = (N/M)*onePerCol; 26 | 27 | fprintf('Creating LDPC matrix...\n'); 28 | 29 | switch method 30 | % Evencol 31 | case {0} 32 | % Distribute 1s uniformly at random within column 33 | for i = 1:N 34 | onesInCol(:, i) = randperm(M)'; 35 | end 36 | 37 | % Create non zero elements (1s) index 38 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 39 | tmp = repmat([1:N], onePerCol, 1); 40 | c = reshape(tmp, N*onePerCol, 1); 41 | 42 | % Create sparse matrix H 43 | H = full(sparse(r, c, 1, M, N)); 44 | 45 | % Evenboth 46 | case {1} 47 | % Distribute 1s uniformly at random within column 48 | for i = 1:N 49 | onesInCol(:, i) = randperm(M)'; 50 | end 51 | 52 | % Create non zero elements (1s) index 53 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 54 | tmp = repmat([1:N], onePerCol, 1); 55 | c = reshape(tmp, N*onePerCol, 1); 56 | 57 | % Make the number of 1s between rows as uniform as possible 58 | 59 | % Order row index 60 | [r, ix] = sort(r); 61 | 62 | % Order column index based on row index 63 | for i = 1:N*onePerCol 64 | cSort(i, :) = c(ix(i)); 65 | end 66 | 67 | % Create new row index with uniform weight 68 | tmp = repmat([1:M], onePerRow, 1); 69 | r = reshape(tmp, N*onePerCol, 1); 70 | 71 | % Create sparse matrix H 72 | % Remove any duplicate non zero elements index using logical AND 73 | S = and(sparse(r, cSort, 1, M, N), ones(M, N)); 74 | H = full(S); 75 | 76 | end % switch 77 | 78 | % Check rows that have no 1 or only have one 1 79 | for i = 1:M 80 | 81 | n = randperm(N); 82 | % Add two 1s if row has no 1 83 | if length(find(r == i)) == 0 84 | H(i, n(1)) = 1; 85 | H(i, n(2)) = 1; 86 | % Add one 1 if row has only one 1 87 | elseif length(find(r == i)) == 1 88 | H(i, n(1)) = 1; 89 | end 90 | 91 | end % for i 92 | 93 | % If desired, eliminate any length-4 cycle 94 | if noCycle == 1 95 | 96 | for i = 1:M 97 | % Look for pair of row - column 98 | for j = (i + 1):M 99 | w = and(H(i, :), H(j, :)); 100 | c1 = find(w); 101 | lc = length(c1); 102 | if lc > 1 103 | 104 | % If found, flip one 1 to 0 in the row with less number of 1s 105 | if length(find(H(i, :))) < length(find(H(j, :))) 106 | % Repeat the process until only one column left 107 | for cc = 1:lc - 1 108 | H(j, c1(cc)) = 0; 109 | end 110 | else 111 | for cc = 1:lc - 1 112 | H(i, c1(cc)) = 0; 113 | end 114 | end % if 115 | 116 | end % if 117 | end % for j 118 | end % for i 119 | 120 | end % if 121 | 122 | fprintf('LDPC matrix is created.\n'); 123 | -------------------------------------------------------------------------------- /Simulations-V21/makeParityChk.m: -------------------------------------------------------------------------------- 1 | function [c, newH] = makeParityChk(dSource, H, strategy) 2 | % Generate parity check vector bases on LDPC matrix H using sparse LU decomposition 3 | % 4 | % dSource : Binary source (0/1) 5 | % H : LDPC matrix 6 | % strategy: Strategy for finding the next non-zero diagonal elements 7 | % {0} First : First non-zero found by column search 8 | % {1} Mincol : Minimum number of non-zeros in later columns 9 | % {2} Minprod: Minimum product of: 10 | % - Number of non-zeros its column minus 1 11 | % - Number of non-zeros its row minus 1 12 | % 13 | % c : Check bits 14 | % 15 | % 16 | % Copyright Bagawan S. Nugroho, 2007 17 | % http://bsnugroho.googlepages.com 18 | 19 | % Get the matric dimension 20 | [M, N] = size(H); 21 | % Set a new matrix F for LU decomposition 22 | F = H; 23 | % LU matrices 24 | L = zeros(M, N - M); 25 | U = zeros(M, N - M); 26 | 27 | % Re-order the M x (N - M) submatrix 28 | for i = 1:M 29 | 30 | % strategy {0 = First; 1 = Mincol; 2 = Minprod} 31 | switch strategy 32 | 33 | % Create diagonally structured matrix using 'First' strategy 34 | case {0} 35 | 36 | % Find non-zero elements (1s) for the diagonal 37 | [r, c] = find(F(:, i:end)); 38 | 39 | % Find non-zero diagonal element candidates 40 | rowIndex = find(r == i); 41 | 42 | % Find the first non-zero column 43 | chosenCol = c(rowIndex(1)) + (i - 1); 44 | 45 | % Create diagonally structured matrix using 'Mincol' strategy 46 | case {1} 47 | 48 | % Find non-zero elements (1s) for the diagonal 49 | [r, c] = find(F(:, i:end)); 50 | colWeight = sum(F(:, i:end), 1); 51 | 52 | % Find non-zero diagonal element candidates 53 | rowIndex = find(r == i); 54 | 55 | % Find the minimum column weight 56 | [x, ix] = min(colWeight(c(rowIndex))); 57 | % Add offset to the chosen row index to match the dimension of the... 58 | % original matrix F 59 | chosenCol = c(rowIndex(ix)) + (i - 1); 60 | 61 | % Create diagonally structured matrix using 'Minprod' strategy 62 | case {2} 63 | 64 | % Find non-zero elements (1s) for the diagonal 65 | [r, c] = find(F(:, i:end)); 66 | colWeight = sum(F(:, i:end), 1) - 1; 67 | rowWeight = sum(F(i, :), 2) - 1; 68 | 69 | % Find non-zero diagonal element candidates 70 | rowIndex = find(r == i); 71 | 72 | % Find the minimum product 73 | [x, ix] = min(colWeight(c(rowIndex))*rowWeight); 74 | % Add offset to the chosen row index to match the dimension of the... 75 | % original matrix F 76 | chosenCol = c(rowIndex(ix)) + (i - 1); 77 | 78 | otherwise 79 | fprintf('Please select columns re-ordering strategy!\n'); 80 | 81 | end % switch 82 | 83 | % Re-ordering columns of both H and F 84 | tmp1 = F(:, i); 85 | tmp2 = H(:, i); 86 | F(:, i) = F(:, chosenCol); 87 | H(:, i) = H(:, chosenCol); 88 | F(:, chosenCol) = tmp1; 89 | H(:, chosenCol) = tmp2; 90 | 91 | % Fill the LU matrices column by column 92 | L(i:end, i) = F(i:end, i); 93 | U(1:i, i) = F(1:i, i); 94 | 95 | % There will be no rows operation at the last row 96 | if i < M 97 | 98 | % Find the later rows with non-zero elements in column i 99 | [r2, c2] = find(F((i + 1):end, i)); 100 | % Add current row to the later rows which have a 1 in column i 101 | F((i + r2), :) = mod(F((i + r2), :) + repmat(F(i, :), length(r2), 1), 2); 102 | 103 | end % if 104 | 105 | end % for i 106 | 107 | % Find B.dsource 108 | z = mod(H(:, (N - M) + 1:end)*dSource, 2); 109 | 110 | % Parity check vector found by solving sparse LU 111 | c = mod(U\(L\z), 2); 112 | 113 | % Return the rearrange H 114 | newH = H; 115 | 116 | fprintf('Message encoded.\n'); 117 | -------------------------------------------------------------------------------- /Simulations-V21/mapping.m: -------------------------------------------------------------------------------- 1 | function [tx_symb] = mapping(tx_bin,Nbps,modulation) % Maps bitstream to Symbols depending on the selected mapping 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% MAPPING 9 | % INPUTS 10 | % 'tx_bin' - Bitstream 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'tx_symb' - Symbols 15 | 16 | 17 | %% INITIALIZATION AND VALIDITY CHECK 18 | if mod(Nbps, 1) ~=0 || Nbps <= 0 19 | error('You have entered an unsupported Number of Bits Per Symbol. Nbps must be a positive real integer.'); 20 | end 21 | Nsymb = size(tx_bin,1)/Nbps; % Number of symbols 22 | tx_bin = reshape(tx_bin,Nbps,Nsymb)'; % Reshapes the vector into a matrix: each row corresponds to a symbol (Nbps bits) 23 | 24 | switch modulation 25 | %% ***** PULSE AMPLITUDE MODULATION ***** 26 | case 'PAM' 27 | % Binary to Integer - Convert 'Binary Word' to corresponding 'Integer' [10 -> 2] 28 | tx_int = bi2de(fliplr(tx_bin)); 29 | % Integer to Gray-Integer - Convert 'Integer' to corresponding 'Gray-Integer' according to the desired Modulation Scheme and Npbs [2 <-> 3] 30 | tx_int = bin2gray(tx_int,'PAM',2^Nbps); 31 | % Gray-Integer to Symbol - Convert 'Gray Integer' to corresponding 'Symbol' according to the desired Modulation Scheme and Npbs 32 | distance = 2/(2^Nbps-1); 33 | tx_symb = distance * (tx_int - (2^Nbps-1)/2); 34 | 35 | 36 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 37 | case 'QAM' 38 | % Binary to Integer 39 | tx_int = bi2de(fliplr(tx_bin)); 40 | % Integer to Gray-Integer 41 | switch Nbps 42 | case 3 43 | bin2gray_matrix = [0 1 3 2 4 5 7 6]; 44 | for index = 1:length(tx_int) 45 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 46 | end 47 | case 5 48 | bin2gray_matrix = [0 1 3 2 6 7 5 4 8 9 11 10 14 15 13 12 24 25 27 26 30 31 29 28 16 17 19 18 22 23 21 20]; 49 | for index = 1:length(tx_int) 50 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 51 | end 52 | otherwise 53 | tx_int = bin2gray(tx_int,'QAM',2^Nbps); 54 | end 55 | 56 | % Gray-Integer to Symbol 57 | Nbps_I = ceil(Nbps/2); % Number of symbols carried in the 'Inphase Carrier' 58 | Nbps_Q = Nbps - Nbps_I; % Number of symbols carried in the 'Quadrature Carrier' 59 | distance = 2/(2^Nbps_I-1); 60 | tx_symb = distance*( (mod(tx_int,2^(Nbps_I)) - (2^Nbps_I-1)/2) - 1i*(floor(tx_int/(2^Nbps_I)) - (2^Nbps_Q-1)/2) ); 61 | 62 | 63 | %% ***** PHASE SHIFT KEYING ***** 64 | case 'PSK' 65 | % Binary to Integer 66 | tx_int = bi2de(fliplr(tx_bin)); 67 | % Integer to Gray-Integer 68 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 69 | % Gray-Integer to Symbol 70 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 71 | 72 | 73 | %% ***** CROSS-QAM ***** 74 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM' (one of the most famous flavour of the Cross-QAM) 75 | case 'Cross-QAM' 76 | switch Nbps 77 | case 1 % Simple PSK 78 | tx_int = bi2de(fliplr(tx_bin)); 79 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 80 | otherwise 81 | % Binary to Integer 82 | tx_int = bi2de(fliplr(tx_bin)); 83 | % Integer to Gray-Integer 84 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 85 | % Gray-Integer to Symbol 86 | tx_symb = zeros(length(tx_int),1); 87 | for index = 1:length(tx_int) 88 | radius = (2 + floor(tx_int(index)/4)) / (2^Nbps/4 + 1); 89 | phase = (mod(floor(tx_int(index)/4), 2) == 0)*3/4; 90 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 91 | end 92 | end 93 | 94 | 95 | %% ***** OPTIMAL-8QAM ***** 96 | case 'Optimal-8QAM' 97 | if Nbps ~= 3 98 | error('This particular Modulation Scheme only works with 3 Bits per Symbol. For Nbps other than 3, please choose among [PSK, PAM, QAM, Cross-QAM].'); 99 | end 100 | % Binary to Integer 101 | tx_int = bi2de(fliplr(tx_bin)); 102 | % Integer to Gray-Integer 103 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 104 | % Gray-Integer to Symbol 105 | tx_symb = zeros(length(tx_int),1); 106 | for index = 1:length(tx_int) 107 | if tx_int(index) > 3 108 | radius = 1; 109 | else 110 | radius = sqrt(2) / (1 + sqrt(3)); 111 | end 112 | phase = (floor(tx_int(index)/4) == 0)*3/4; 113 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 114 | end 115 | 116 | otherwise 117 | error('You have entered an unsupported Digital Modulation scheme. Please choose among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM].'); 118 | end -------------------------------------------------------------------------------- /Simulations-V21/maxLikelihood.m: -------------------------------------------------------------------------------- 1 | function [rx_symb_ML] = maxLikelihood(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% MAXIMUM LIKELIHOOD CRITERION 9 | % By comparing the Received Symbols 'rx_symb' with the Symbols of Reference 'symb_ref' we can apply the ML Criterion and deduce 'rx_symb_ML' 10 | % INPUTS 11 | % 'rx_symb' - Symbols 12 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 13 | % 'Nbps' - Number of bits per symbol 14 | % OUTPUT 15 | % 'rx_symb_ML' - Symbols after the application of the Maximum Likelihood Criterion 16 | 17 | 18 | %% ALGORITHM 19 | % 'symb_ref' is a [2^Nbps x 2] matrix used as a Containers.map 20 | % The 1st column includes all the Symbols of Reference in their Complex form (-0.7071 + i*0.7071, +0.7071 - i*0.7071,...) 21 | % The 2nd column includes the associated Decimal Value (0, 1, 2, 3, ...) 22 | % Step 1: Generating Symbols of Reference in function of (Nbps, modulation) 23 | % Step 2: Application of the Maximum Likelihood Criterion -> Compare each element of 'rx_symb' with the Symbols of Reference 'symb_ref' 24 | % Step 3: Return the Symbols after the application of the Maximum Likelihood Criterion 'rx_symb_ML' 25 | 26 | switch modulation 27 | %% ***** PULSE AMPLITUDE MODULATION ***** 28 | case 'PAM' 29 | % Generating Symbols of Reference 30 | symb_ref = zeros(2^Nbps,2); 31 | distance = 2/(2^Nbps-1); 32 | for index = 1:2^Nbps 33 | symb_ref(index,:) = [distance*(index-1 - (2^Nbps-1)/2), index-1]; 34 | end 35 | % Application of the Maximum Likelihood Criterion 36 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 37 | 38 | 39 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 40 | case 'QAM' 41 | % Generating Symbols of Reference 42 | Nbps_I = ceil(Nbps/2); Nbps_Q = Nbps - Nbps_I; 43 | symb_ref = zeros(2^Nbps,2); 44 | distance = 2/(2^Nbps_I-1); 45 | for index_I = 1:2^Nbps_I 46 | for index_Q = 1:2^Nbps_Q 47 | symb_ref(index_I + (2^Nbps_I)*(index_Q-1), :) = [distance*((index_I-1 - (2^Nbps_I-1)/2) - 1i* (index_Q-1 - (2^Nbps_Q-1)/2)), index_I-1 + (2^Nbps_I)*(index_Q-1)]; 48 | end 49 | end 50 | % Application of the Maximum Likelihood Criterion 51 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 52 | 53 | %% ***** PHASE SHIFT KEYING ***** 54 | case 'PSK' 55 | symb_ref = zeros(2^Nbps,2); 56 | % Generating Symbols of Reference 57 | for index = 1:2^Nbps 58 | symb_ref(index,:) = [exp(1i*pi*(3/4 + 2/(2^Nbps)*(index-1))), index-1]; 59 | end 60 | % Application of the Maximum Likelihood Criterion 61 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 62 | 63 | %% ***** CROSS-QUADRATURE AMPLITUDE MODULATION ***** 64 | case 'Cross-QAM' 65 | % Generating Symbols of Reference 66 | symb_ref = zeros(2^Nbps,2); 67 | switch Nbps 68 | case 1 % Only 2 Symbols on the 1st Orbit => Elementary PSK Case 69 | symb_ref = [exp(1i*pi*(3/4 + 2/(2^Nbps)*0)), 0; exp(1i*pi*(3/4 + 2/(2^Nbps)*1)), 1]; 70 | otherwise 71 | for index = 1:2^Nbps 72 | radius = (2 + floor((index - 1)/4)) / (2^Nbps/4 + 1); 73 | phase = (mod(floor((index-1)/4), 2) == 0)*3/4; 74 | symb_ref(index,:) = [radius*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 75 | end 76 | end 77 | % Application of the Maximum Likelihood Criterion 78 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 79 | 80 | 81 | %% ***** OPTIMAL-8QAM ***** 82 | case 'Optimal-8QAM' 83 | % Generating Symbols of Reference 84 | symb_ref = zeros(2^Nbps,2); 85 | radius = [sqrt(2)/(1 + sqrt(3)), 1]; 86 | for index = 1:2^Nbps 87 | phase = (floor((index-1)/4) == 0)*3/4; 88 | symb_ref(index,:) = [radius(floor((index-1)/4) + 1)*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 89 | end 90 | % Application of the Maximum Likelihood Criterion 91 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 92 | end 93 | 94 | 95 | %% ***** APPLICATION OF THE MAXIMUM LIKELIHOOD CRITERION ***** 96 | function [rx_symb_ML] = appML(rx_symb, Nbps, symb_ref) 97 | rx_symb_ML = zeros(length(rx_symb), 1); % Initialize the size of 'rx_symb_ML' in order to save some time 98 | CSM = sqrt(abs((rx_symb(:) - symb_ref(1, 1)) .^ 2)); % CSM - Current Smallest Norm: Transient save allowing to 'compare before assign' 99 | 100 | for index = 1:2^Nbps % Loop to determine the minimal Euclidean Norm of each Received Symbol 101 | BOOL = CSM > sqrt(abs((rx_symb(:) - symb_ref(index, 1)) .^ 2)); % Boolean Vector taking a true value ('1') when the corresponding CSM row appears to not be the smallest possible Euclidean Norm 102 | CSM(BOOL) = sqrt(abs((rx_symb(BOOL) - symb_ref(index, 1)) .^ 2)); % Update CSM accordingly 103 | rx_symb_ML(BOOL) = symb_ref(index, 2); 104 | end -------------------------------------------------------------------------------- /Simulations-V21/pilot_est.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Project 2 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 3 | % April 2016 4 | % Part 2 - Time and Frequency Syncrhonisation 5 | % Gardner Function 6 | % carry out Gardner to Maximum Likelyhood estimation of t_0 7 | % input: 8 | % -rx_input: receiver rx_input upsampled by factor M 9 | % -M: upsampling factor 10 | % -K: constant in the Gardner algorithm 11 | % output: 12 | % -est_error: estimated est_error 13 | % -y_corr: corrected sequence 14 | 15 | function [CFO_esti] = pilot_est(signal,pilot,fsym) 16 | 17 | N=numel(pilot); 18 | K=16; 19 | Tsym=1/fsym; 20 | L=length(signal); 21 | 22 | D=zeros(K,L-N+1); 23 | for kk=1:K 24 | for ll=kk:N-1 25 | D(kk,:)= D(kk,:)+ transpose(conj(signal(ll:L-N+ll))*pilot(ll) .* (conj(conj(signal(1+ll-kk:L-N+ll-kk+1))*pilot(ll-kk+1)))); 26 | end 27 | D(kk,:)=D(kk,:)/(N-kk); 28 | end 29 | 30 | Dtot=sum(abs(D)); 31 | [maximum,n_est]= max(Dtot); 32 | 33 | CFO_esti=0; 34 | for kk=1:K 35 | CFO_esti= CFO_esti + phase(D(kk,n_est))/(2*pi*kk*Tsym); 36 | end 37 | CFO_esti=-CFO_esti/K; 38 | end -------------------------------------------------------------------------------- /Simulations-V22r.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V22r.zip -------------------------------------------------------------------------------- /Simulations-V31.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V31.zip -------------------------------------------------------------------------------- /Simulations-V32-Gardner-Pilot.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V32-Gardner-Pilot.zip -------------------------------------------------------------------------------- /Simulations-V32/DVBS2CommunicationChain.m: -------------------------------------------------------------------------------- 1 | function [BER, SER, tx_symb, rx_symb] = DVBS2CommunicationChain(mod_input, Nbps_input, EbN0_ratio_input, CFO_input, t0_input, phi0_input) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DVBS2CommunicationChain 9 | % INPUTS 10 | % 'mod_input' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 11 | % 'Nbps_input' - Number of bits per symbol 12 | % 'EbN0_ratio_input' - SNR per bit 13 | % OUTPUTS 14 | % 'BER' - Bit Error Ratio 15 | % 'SER' - Symbol Error Ratio 16 | % 'tx_symb' - Transmitted Symbols 17 | % 'rx_symb' - Received Symbols 18 | 19 | 20 | %% Implemented Features 21 | % 1. [TX] - GENERATING INFORMATION - RANDOM BITSTREAM 22 | % 2. [TX] - MAPPING BITSTREAM TO SYMBOLS - SUPPORTED MODULATION SCHEMES: [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] - Works for any Nbps 23 | % 3. [TX] - UPSAMPLING 24 | % 4. [TX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 25 | % 5. [CHAN] - ADDING AWGN IN THE IDEAL CHANNEL 26 | % 6. [RX] - SYNCHRONISATION ERRORS 27 | % 7. [RX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 28 | % 8. [RX] - TIME SHIFT ON SAMPLING 29 | % 9. [RX] - DOWNSAMPLING 30 | % 10.[RX] - DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 31 | % X. [PLOT] - RELEVANT GRAPHS AND VALUES 32 | 33 | 34 | %% IF YOU WANT TO AUTO-RUN THIS FUNCTION - DECOMMENTS THE 4 NEXT LINES. 35 | %% IF YOU WANT TO RUN THIS FUNCTION FROM 'FoM' - COMMENTS THE 4 NEXT LINES. 36 | % clear; clc; close all; 37 | % mod_input = 'QAM'; 38 | % Nbps_input = 4; 39 | % EbN0_ratio_input = 5; 40 | %% RX settings 41 | % 1. On/Off Gardner => 0/1 42 | Gardner_S = 1; 43 | 44 | %% ***** RCF PARAMETERS ***** 45 | RRCF.fcutoff = 1e6; % 3dB Cutoff Frequency of the RCF [1MHz] 46 | RRCF.beta = 0.3; % Roll-off factor of the RCF [0.3] 47 | RRCF.M = 40; % [!] Deduct the Upsampling Factor -> Needed in order to satisfy the ISI Nyquist Criterion. Big M allows to simulate a Time Shift on sampling 48 | RRCF.fs = RRCF.M*2*RRCF.fcutoff; % = M*fsymb - Deduct the Sampling Frequency [Hz] 49 | RRCF.Ntaps = 16*RRCF.M + 1; % Number of taps of the RCF 50 | 51 | %% ***** MODULATION SCHEME PARAMETERS ***** 52 | Modu.mod = mod_input; % Select the Digital Modulation among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] (NB: The 'Optimal-8QAM' is designed for 8 Symbols only (=> Nbps = 3)) 53 | Modu.Nbps = Nbps_input; % Select the Number of Bits Per Symbol 54 | Modu.fsymb = 2*RRCF.fcutoff; % Select the Symbolrate [2MHz] - Common to all Modulation Schemes and independent of Nbps 55 | Modu.bps = Modu.fsymb*Modu.Nbps; % Deduct the Bitrate [bits/s] - Depends on the Number of Bits carried per each Symbol (Nbps) 56 | Modu.Tsymb = 1/Modu.fsymb; % Deduct the Period of a symbol [s] (or more rigorously [s/Symb]) 57 | 58 | %% ***** SYNC PARAMETERS ***** 59 | SYNC.CFO = CFO_input*Modu.fsymb; % Carrier Frequency Offset 60 | SYNC.t0 = t0_input; % Sample Time Shift - Always in [0:Tsymb] (Physically) - [0:M-1] (Digital Simulation) [Physically = Tsymb*t0/M-1 = t0*Tsample] 61 | SYNC.phi0 = phi0_input; % Carrier Phase Error - Always in [0:2pi] 62 | 63 | 64 | %% 1. [TX] GENERATING INFORMATION - RANDOM BITSTREAM 65 | tx_len = 10000; % Length of the bitstream 66 | tx_bin = randi([0 1], tx_len,1); % Bitstream - Generate binary sequence (0 and 1 are equiprobable) 67 | 68 | 69 | %% 2. [TX] MAPPING BITSTREAM TO SYMBOLS 70 | if mod(tx_len,Modu.Nbps) ~= 0 % ZERO PADDING -> Allows to avoid to get an error if the Bitstream length is not a multiple of Nbps 71 | tx_bin = [tx_bin; zeros(Modu.Nbps - mod(tx_len,Modu.Nbps),1)]; 72 | tx_len = tx_len + Modu.Nbps - mod(tx_len,Modu.Nbps); 73 | end 74 | tx_symb = mapping(tx_bin, Modu.Nbps, Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps 75 | 76 | 77 | %% 3. [TX] UPSAMPLING 78 | tx_symb_UP = upsample(tx_symb,RRCF.M); % Upsample 79 | tx_symb_UP_R = real(tx_symb_UP); 80 | 81 | %% 4. [TX] FILTERING WITH ROOT-RAISED-COSINE FILTER 82 | RRCF.IR = RRCFDesign(RRCF.beta, RRCF.Ntaps, RRCF.fs, Modu.Tsymb); % Impulse Response of the RRCF 83 | tx_symb_UP_F = conv(tx_symb_UP,RRCF.IR); % Apply the RRCF 84 | tx_symb_UP_F_R = real(tx_symb_UP_F); 85 | 86 | %% 5. [CHAN] ADDING AWGN IN THE IDEAL CHANNEL 87 | % In practice, we send in the channel the Narrowband Bandpass Signal (the Baseband Signal modulated at a high frequency) 88 | % In this simulation, we directly send the Baseband Signal (Complex Envelope) in the channel. This is done in order to save computing power 89 | % However, we have to take into account the fact that the energy of a Bandpass Signal is equal to the energy of its Complex Envelope divided by 2 90 | Es_CE = (trapz(abs(tx_symb_UP_F).^2))*(1/(RRCF.fs)); % Basedband Signal Energy (Complex Envelope of the Bandpass Signal) 91 | Es_BP = Es_CE/2; % Bandpass Signal Energy 92 | Eb = Es_BP/tx_len; % Average energy of a bit 93 | EbN0_dB = EbN0_ratio_input; % Energy per Bit to Noise PSD ratio [dB] 94 | EbN0_ratio = 10^(EbN0_dB/10); % Energy per Bit to Noise PSD ratio 95 | N0 = Eb/EbN0_ratio; % Noise PSD - We consider AWGN, so N0 is constant on the whole frequency domain 96 | NoisePower = 2*N0*RRCF.fs; % Noise Power 97 | noise_AWGN = sqrt(NoisePower/2)*(randn(length(tx_symb_UP_F), 1) + 1i*randn(length(tx_symb_UP_F), 1)); % Generate Zero-Mean AWGN 98 | rx_symb_UP_F = tx_symb_UP_F + noise_AWGN; % Add the noise to the transmitted signal 99 | 100 | 101 | %% 6. [RX] SYNCHRONISATION ERRORS 102 | t_axis = 0:1/RRCF.fs:(1/RRCF.fs*(length(rx_symb_UP_F)-1)); 103 | exp_async = exp(1j* (2*pi*SYNC.CFO*t_axis' + SYNC.phi0) ); 104 | rx_symb_UP_F_async = exp_async.*rx_symb_UP_F; 105 | 106 | 107 | %% 7. [RX] FILTERING WITH ROOT-RAISED-COSINE FILTER 108 | rx_symb_UP_async = conv(rx_symb_UP_F_async,RRCF.IR); % Apply the matched RRCF 109 | rx_symb_UP_async = rx_symb_UP_async(RRCF.Ntaps:length(rx_symb_UP_async) - RRCF.Ntaps+1); % Removes the irrelevant values 110 | 111 | 112 | %% 8. [RX] TIME SHIFT ON SAMPLING 113 | % Time shift with constant offset t_0 [after the matched filter, before the down sampler] 114 | 115 | rx_symb_UP_async_t0 = rx_symb_UP_async(SYNC.t0+1:end,1); % Thanks to the big oversampling M, we can simulated a Time Shift On Sampling 116 | rx_symb_UP_async_t0 = [rx_symb_UP_async_t0; zeros(SYNC.t0 - 1,1)]; % Zero-Padding to match the length 117 | 118 | rx_symb_UP_async_t0_R = real(rx_symb_UP_async_t0); 119 | 120 | 121 | %% 9. [RX] DOWNSAMPLING 122 | rx_symb = downsample(rx_symb_UP_async_t0,RRCF.M); 123 | 124 | %% 10. [RX] DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 125 | rx_bin = demapping(rx_symb,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 126 | 127 | 128 | %% X. [PLOT] RELEVANT GRAPHS AND VALUES 129 | % See the function 'FoM' for all the preset Graphs 130 | rx_bin_len = size(rx_bin,1); 131 | BER = 1 - sum(rx_bin(1:rx_bin_len) == tx_bin(1:rx_bin_len))/(rx_bin_len); % Bit Error Ratio 132 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,rx_bin_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin(1:rx_bin_len),Modu.Nbps,rx_bin_len/Modu.Nbps)'))) / (rx_bin_len/Modu.Nbps); % Symbol Error Ratio 133 | 134 | 135 | %% Gardner algorithm -> ML estimation for t_0 and correct the rx_symb 136 | if Gardner_S == 1 137 | 138 | %[T] 139 | figure 140 | plot(tx_symb_UP_R(200:300),'x-'); hold on 141 | %plot(tx_symb_UP_F_R(200:300),'o-r'); hold on; 142 | plot(rx_symb_UP_async_t0_R(200:300),'o-.k'); 143 | 144 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, 0.1); 145 | figure 146 | plot(est_error); 147 | title(['Applying Gardner to ',num2str(t0_input),' time shift unit for', num2str(2^Nbps_input), mod_input]); 148 | xlabel('Time (pts)'); ylabel('Estimated Error'); hold on; 149 | 150 | rx_symb_c = downsample(y_corr,RRCF.M); 151 | rx_bin_c = demapping(rx_symb_c,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 152 | rx_bin_c_len = size(rx_bin_c,1); 153 | BER_c = 1 - sum(rx_bin_c(1:rx_bin_c_len) == tx_bin(1:rx_bin_c_len))/(rx_bin_c_len); % Bit Error Ratio 154 | 155 | BER 156 | BER_c 157 | 158 | end 159 | 160 | end 161 | -------------------------------------------------------------------------------- /Simulations-V32/DVBS2CommunicationChain.m~: -------------------------------------------------------------------------------- 1 | function [BER, SER, tx_symb, rx_symb] = DVBS2CommunicationChain(mod_input, Nbps_input, EbN0_ratio_input, CFO_input, t0_input, phi0_input) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DVBS2CommunicationChain 9 | % INPUTS 10 | % 'mod_input' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 11 | % 'Nbps_input' - Number of bits per symbol 12 | % 'EbN0_ratio_input' - SNR per bit 13 | % OUTPUTS 14 | % 'BER' - Bit Error Ratio 15 | % 'SER' - Symbol Error Ratio 16 | % 'tx_symb' - Transmitted Symbols 17 | % 'rx_symb' - Received Symbols 18 | 19 | 20 | %% Implemented Features 21 | % 1. [TX] - GENERATING INFORMATION - RANDOM BITSTREAM 22 | % 2. [TX] - MAPPING BITSTREAM TO SYMBOLS - SUPPORTED MODULATION SCHEMES: [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] - Works for any Nbps 23 | % 3. [TX] - UPSAMPLING 24 | % 4. [TX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 25 | % 5. [CHAN] - ADDING AWGN IN THE IDEAL CHANNEL 26 | % 6. [RX] - SYNCHRONISATION ERRORS 27 | % 7. [RX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 28 | % 8. [RX] - TIME SHIFT ON SAMPLING 29 | % 9. [RX] - DOWNSAMPLING 30 | % 10.[RX] - DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 31 | % X. [PLOT] - RELEVANT GRAPHS AND VALUES 32 | 33 | 34 | %% IF YOU WANT TO AUTO-RUN THIS FUNCTION - DECOMMENTS THE 4 NEXT LINES. 35 | %% IF YOU WANT TO RUN THIS FUNCTION FROM 'FoM' - COMMENTS THE 4 NEXT LINES. 36 | % clear; clc; close all; 37 | % mod_input = 'QAM'; 38 | % Nbps_input = 4; 39 | % EbN0_ratio_input = 5; 40 | %% RX settings 41 | % 1. On/Off Gardner => 0/1 42 | Gardner_S = 1; 43 | 44 | %% ***** RCF PARAMETERS ***** 45 | RRCF.fcutoff = 1e6; % 3dB Cutoff Frequency of the RCF [1MHz] 46 | RRCF.beta = 0.3; % Roll-off factor of the RCF [0.3] 47 | RRCF.M = 40; % [!] Deduct the Upsampling Factor -> Needed in order to satisfy the ISI Nyquist Criterion. Big M allows to simulate a Time Shift on sampling 48 | RRCF.fs = RRCF.M*2*RRCF.fcutoff; % = M*fsymb - Deduct the Sampling Frequency [Hz] 49 | RRCF.Ntaps = 16*RRCF.M + 1; % Number of taps of the RCF 50 | 51 | %% ***** MODULATION SCHEME PARAMETERS ***** 52 | Modu.mod = mod_input; % Select the Digital Modulation among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] (NB: The 'Optimal-8QAM' is designed for 8 Symbols only (=> Nbps = 3)) 53 | Modu.Nbps = Nbps_input; % Select the Number of Bits Per Symbol 54 | Modu.fsymb = 2*RRCF.fcutoff; % Select the Symbolrate [2MHz] - Common to all Modulation Schemes and independent of Nbps 55 | Modu.bps = Modu.fsymb*Modu.Nbps; % Deduct the Bitrate [bits/s] - Depends on the Number of Bits carried per each Symbol (Nbps) 56 | Modu.Tsymb = 1/Modu.fsymb; % Deduct the Period of a symbol [s] (or more rigorously [s/Symb]) 57 | 58 | %% ***** SYNC PARAMETERS ***** 59 | SYNC.CFO = CFO_input*Modu.fsymb; % Carrier Frequency Offset 60 | SYNC.t0 = t0_input; % Sample Time Shift - Always in [0:Tsymb] (Physically) - [0:M-1] (Digital Simulation) [Physically = Tsymb*t0/M-1 = t0*Tsample] 61 | SYNC.phi0 = phi0_input; % Carrier Phase Error - Always in [0:2pi] 62 | 63 | 64 | %% 1. [TX] GENERATING INFORMATION - RANDOM BITSTREAM 65 | tx_len = 10000; % Length of the bitstream 66 | tx_bin = randi([0 1], tx_len,1); % Bitstream - Generate binary sequence (0 and 1 are equiprobable) 67 | 68 | 69 | %% 2. [TX] MAPPING BITSTREAM TO SYMBOLS 70 | if mod(tx_len,Modu.Nbps) ~= 0 % ZERO PADDING -> Allows to avoid to get an error if the Bitstream length is not a multiple of Nbps 71 | tx_bin = [tx_bin; zeros(Modu.Nbps - mod(tx_len,Modu.Nbps),1)]; 72 | tx_len = tx_len + Modu.Nbps - mod(tx_len,Modu.Nbps); 73 | end 74 | tx_symb = mapping(tx_bin, Modu.Nbps, Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps 75 | 76 | 77 | %% 3. [TX] UPSAMPLING 78 | tx_symb_UP = upsample(tx_symb,RRCF.M); % Upsample 79 | tx_symb_UP_R = real(tx_symb_UP); 80 | 81 | %% 4. [TX] FILTERING WITH ROOT-RAISED-COSINE FILTER 82 | RRCF.IR = RRCFDesign(RRCF.beta, RRCF.Ntaps, RRCF.fs, Modu.Tsymb); % Impulse Response of the RRCF 83 | tx_symb_UP_F = conv(tx_symb_UP,RRCF.IR); % Apply the RRCF 84 | tx_symb_UP_F_R = real(tx_symb_UP_F); 85 | 86 | %% 5. [CHAN] ADDING AWGN IN THE IDEAL CHANNEL 87 | % In practice, we send in the channel the Narrowband Bandpass Signal (the Baseband Signal modulated at a high frequency) 88 | % In this simulation, we directly send the Baseband Signal (Complex Envelope) in the channel. This is done in order to save computing power 89 | % However, we have to take into account the fact that the energy of a Bandpass Signal is equal to the energy of its Complex Envelope divided by 2 90 | Es_CE = (trapz(abs(tx_symb_UP_F).^2))*(1/(RRCF.fs)); % Basedband Signal Energy (Complex Envelope of the Bandpass Signal) 91 | Es_BP = Es_CE/2; % Bandpass Signal Energy 92 | Eb = Es_BP/tx_len; % Average energy of a bit 93 | EbN0_dB = EbN0_ratio_input; % Energy per Bit to Noise PSD ratio [dB] 94 | EbN0_ratio = 10^(EbN0_dB/10); % Energy per Bit to Noise PSD ratio 95 | N0 = Eb/EbN0_ratio; % Noise PSD - We consider AWGN, so N0 is constant on the whole frequency domain 96 | NoisePower = 2*N0*RRCF.fs; % Noise Power 97 | noise_AWGN = sqrt(NoisePower/2)*(randn(length(tx_symb_UP_F), 1) + 1i*randn(length(tx_symb_UP_F), 1)); % Generate Zero-Mean AWGN 98 | rx_symb_UP_F = tx_symb_UP_F + noise_AWGN; % Add the noise to the transmitted signal 99 | 100 | 101 | %% 6. [RX] SYNCHRONISATION ERRORS 102 | t_axis = 0:1/RRCF.fs:(1/RRCF.fs*(length(rx_symb_UP_F)-1)); 103 | exp_async = exp(1j* (2*pi*SYNC.CFO*t_axis' + SYNC.phi0) ); 104 | rx_symb_UP_F_async = exp_async.*rx_symb_UP_F; 105 | 106 | 107 | %% 7. [RX] FILTERING WITH ROOT-RAISED-COSINE FILTER 108 | rx_symb_UP_async = conv(rx_symb_UP_F_async,RRCF.IR); % Apply the matched RRCF 109 | rx_symb_UP_async = rx_symb_UP_async(RRCF.Ntaps:length(rx_symb_UP_async) - RRCF.Ntaps+1); % Removes the irrelevant values 110 | 111 | 112 | %% 8. [RX] TIME SHIFT ON SAMPLING 113 | % Time shift with constant offset t_0 [after the matched filter, before the down sampler] 114 | 115 | rx_symb_UP_async_t0 = rx_symb_UP_async(SYNC.t0+1:end,1); % Thanks to the big oversampling M, we can simulated a Time Shift On Sampling 116 | rx_symb_UP_async_t0 = [rx_symb_UP_async_t0; zeros(SYNC.t0 - 1,1)]; % Zero-Padding to match the length 117 | 118 | rx_symb_UP_async_t0_R = real(rx_symb_UP_async_t0); 119 | 120 | 121 | %% 9. [RX] DOWNSAMPLING 122 | rx_symb = downsample(rx_symb_UP_async_t0,RRCF.M); 123 | 124 | %% 10. [RX] DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 125 | rx_bin = demapping(rx_symb,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 126 | 127 | 128 | %% X. [PLOT] RELEVANT GRAPHS AND VALUES 129 | % See the function 'FoM' for all the preset Graphs 130 | rx_bin_len = size(rx_bin,1); 131 | BER = 1 - sum(rx_bin(1:rx_bin_len) == tx_bin(1:rx_bin_len))/(rx_bin_len); % Bit Error Ratio 132 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,rx_bin_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin(1:rx_bin_len),Modu.Nbps,rx_bin_len/Modu.Nbps)'))) / (rx_bin_len/Modu.Nbps); % Symbol Error Ratio 133 | 134 | 135 | %% Gardner algorithm -> ML estimation for t_0 and correct the rx_symb 136 | if Gardner_S == 1 137 | 138 | %[T] 139 | figure 140 | plot(tx_symb_UP_R(200:300),'x-'); hold on 141 | %plot(tx_symb_UP_F_R(200:300),'o-r'); hold on; 142 | plot(rx_symb_UP_async_t0_R(200:300),'o-.k'); 143 | 144 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, 0.1); 145 | figure 146 | plot(est_error); 147 | title(['Applying Gardner to ',num2str(t0_input),' time shift unit for', num2str(2^Nbps_input), mod_input]); 148 | xlabel('Time (pts)'); ylabel('Estimated Error'); hold on; 149 | 150 | rx_symb_c = downsample(y_corr,RRCF.M); 151 | rx_bin_c = demapping(rx_symb_c,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 152 | rx_bin_c_len = size(rx_bin_c,1); 153 | BER = 1 - sum(rx_bin(1:rx_bin_c_len) == tx_bin(1:rx_bin_c_len))/(rx_bin_c_len); % Bit Error Ratio 154 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,rx_bin_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin(1:rx_bin_len),Modu.Nbps,rx_bin_len/Modu.Nbps)'))) / (rx_bin_len/Modu.Nbps); % Symbol Error Ratio 155 | 156 | end 157 | 158 | end 159 | -------------------------------------------------------------------------------- /Simulations-V32/DVBS2CommunicationChain_GC.m: -------------------------------------------------------------------------------- 1 | function [BER, SER, tx_symb, rx_symb] = DVBS2CommunicationChain_GC(mod_input, Nbps_input, EbN0_ratio_input, CFO_input, t0_input, phi0_input) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DVBS2CommunicationChain 9 | % INPUTS 10 | % 'mod_input' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 11 | % 'Nbps_input' - Number of bits per symbol 12 | % 'EbN0_ratio_input' - SNR per bit 13 | % OUTPUTS 14 | % 'BER' - Bit Error Ratio 15 | % 'SER' - Symbol Error Ratio 16 | % 'tx_symb' - Transmitted Symbols 17 | % 'rx_symb' - Received Symbols 18 | 19 | 20 | %% Implemented Features 21 | % 1. [TX] - GENERATING INFORMATION - RANDOM BITSTREAM 22 | % 2. [TX] - MAPPING BITSTREAM TO SYMBOLS - SUPPORTED MODULATION SCHEMES: [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] - Works for any Nbps 23 | % 3. [TX] - UPSAMPLING 24 | % 4. [TX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 25 | % 5. [CHAN] - ADDING AWGN IN THE IDEAL CHANNEL 26 | % 6. [RX] - SYNCHRONISATION ERRORS 27 | % 7. [RX] - FILTERING WITH ROOT-RAISED-COSINE FILTER 28 | % 8. [RX] - TIME SHIFT ON SAMPLING 29 | % 9. [RX] - DOWNSAMPLING 30 | % 10.[RX] - DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 31 | % X. [PLOT] - RELEVANT GRAPHS AND VALUES 32 | 33 | 34 | %% IF YOU WANT TO AUTO-RUN THIS FUNCTION - DECOMMENTS THE 4 NEXT LINES. 35 | %% IF YOU WANT TO RUN THIS FUNCTION FROM 'FoM' - COMMENTS THE 4 NEXT LINES. 36 | % clear; clc; close all; 37 | % mod_input = 'QAM'; 38 | % Nbps_input = 4; 39 | % EbN0_ratio_input = 5; 40 | %% RX settings 41 | % 1. On/Off Gardner => 0/1 42 | Gardner_S = 0; 43 | % 2. Piloting Correlating 44 | Pilot_S =1; 45 | 46 | %% ***** RCF PARAMETERS ***** 47 | RRCF.fcutoff = 1e6; % 3dB Cutoff Frequency of the RCF [1MHz] 48 | RRCF.beta = 0.3; % Roll-off factor of the RCF [0.3] 49 | RRCF.M = 40; % [!] Deduct the Upsampling Factor -> Needed in order to satisfy the ISI Nyquist Criterion. Big M allows to simulate a Time Shift on sampling 50 | RRCF.fs = RRCF.M*2*RRCF.fcutoff; % = M*fsymb - Deduct the Sampling Frequency [Hz] 51 | RRCF.Ntaps = 16*RRCF.M + 1; % Number of taps of the RCF 52 | 53 | %% ***** MODULATION SCHEME PARAMETERS ***** 54 | Modu.mod = mod_input; % Select the Digital Modulation among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] (NB: The 'Optimal-8QAM' is designed for 8 Symbols only (=> Nbps = 3)) 55 | Modu.Nbps = Nbps_input; % Select the Number of Bits Per Symbol 56 | Modu.fsymb = 2*RRCF.fcutoff; % Select the Symbolrate [2MHz] - Common to all Modulation Schemes and independent of Nbps 57 | Modu.bps = Modu.fsymb*Modu.Nbps; % Deduct the Bitrate [bits/s] - Depends on the Number of Bits carried per each Symbol (Nbps) 58 | Modu.Tsymb = 1/Modu.fsymb; % Deduct the Period of a symbol [s] (or more rigorously [s/Symb]) 59 | 60 | %% ***** SYNC PARAMETERS ***** 61 | SYNC.CFO = CFO_input; % Carrier Frequency Offset [ppm] 62 | SYNC.t0 = t0_input; % Sample Time Shift - Always in [0:Tsymb] (Physically) - [0:M-1] (Digital Simulation) [Physically = Tsymb*t0/M-1 = t0*Tsample] 63 | SYNC.phi0 = phi0_input; % Carrier Phase Error - Always in [0:2pi] 64 | 65 | %% ***** Gardner PARAMETERS ***** 66 | Gard.K = [0.1 0.5]; 67 | 68 | %% ***** Pilot PARAMETERS ***** 69 | Pil_nSymb = 256; 70 | Pil_len = Nbps_input*Pil_nSymb; % pilot length is 128 bits 71 | 72 | 73 | %% 1. [TX] GENERATING INFORMATION - RANDOM BITSTREAM 74 | tx_len = 10000; % Length of the bitstream 75 | tx_bin = randi([0 1], tx_len,1); % Bitstream - Generate binary sequence (0 and 1 are equiprobable) 76 | Pil_bin = tx_bin(1:Pil_len); % Assuming the first Pil_len bits are pilots 77 | 78 | %% 2. [TX] MAPPING BITSTREAM TO SYMBOLS 79 | if mod(tx_len,Modu.Nbps) ~= 0 % ZERO PADDING -> Allows to avoid to get an error if the Bitstream length is not a multiple of Nbps 80 | tx_bin = [tx_bin; zeros(Modu.Nbps - mod(tx_len,Modu.Nbps),1)]; 81 | tx_len = tx_len + Modu.Nbps - mod(tx_len,Modu.Nbps); 82 | end 83 | tx_symb = mapping(tx_bin, Modu.Nbps, Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps 84 | Pil_symb = tx_symb(1:Pil_nSymb); % The first nSymb is the Pilot symbol 85 | 86 | 87 | %% 3. [TX] UPSAMPLING 88 | tx_symb_UP = upsample(tx_symb,RRCF.M); % Upsample 89 | tx_symb_UP_R = real(tx_symb_UP); 90 | 91 | %% 4. [TX] FILTERING WITH ROOT-RAISED-COSINE FILTER 92 | RRCF.IR = RRCFDesign(RRCF.beta, RRCF.Ntaps, RRCF.fs, Modu.Tsymb); % Impulse Response of the RRCF 93 | tx_symb_UP_F = conv(tx_symb_UP,RRCF.IR); % Apply the RRCF 94 | tx_symb_UP_F_R = real(tx_symb_UP_F); 95 | 96 | %% 5. [CHAN] ADDING AWGN IN THE IDEAL CHANNEL 97 | % In practice, we send in the channel the Narrowband Bandpass Signal (the Baseband Signal modulated at a high frequency) 98 | % In this simulation, we directly send the Baseband Signal (Complex Envelope) in the channel. This is done in order to save computing power 99 | % However, we have to take into account the fact that the energy of a Bandpass Signal is equal to the energy of its Complex Envelope divided by 2 100 | Es_CE = (trapz(abs(tx_symb_UP_F).^2))*(1/(RRCF.fs)); % Basedband Signal Energy (Complex Envelope of the Bandpass Signal) 101 | Es_BP = Es_CE/2; % Bandpass Signal Energy 102 | Eb = Es_BP/tx_len; % Average energy of a bit 103 | EbN0_dB = EbN0_ratio_input; % Energy per Bit to Noise PSD ratio [dB] 104 | EbN0_ratio = 10^(EbN0_dB/10); % Energy per Bit to Noise PSD ratio 105 | N0 = Eb/EbN0_ratio; % Noise PSD - We consider AWGN, so N0 is constant on the whole frequency domain 106 | NoisePower = 2*N0*RRCF.fs; % Noise Power 107 | noise_AWGN = sqrt(NoisePower/2)*(randn(length(tx_symb_UP_F), 1) + 1i*randn(length(tx_symb_UP_F), 1)); % Generate Zero-Mean AWGN 108 | rx_symb_UP_F = tx_symb_UP_F + noise_AWGN; % Add the noise to the transmitted signal 109 | 110 | 111 | %% 6. [RX] SYNCHRONISATION ERRORS 112 | t_axis = 0:1/RRCF.fs:(1/RRCF.fs*(length(rx_symb_UP_F)-1)); 113 | exp_async = exp(1j* (2*pi*SYNC.CFO*t_axis' + SYNC.phi0) ); 114 | rx_symb_UP_F_async = exp_async.*rx_symb_UP_F; 115 | 116 | 117 | %% 7. [RX] FILTERING WITH ROOT-RAISED-COSINE FILTER 118 | rx_symb_UP_async = conv(rx_symb_UP_F_async,RRCF.IR); % Apply the matched RRCF 119 | rx_symb_UP_async = rx_symb_UP_async(RRCF.Ntaps:length(rx_symb_UP_async) - RRCF.Ntaps+1); % Removes the irrelevant values 120 | 121 | 122 | %% 8. [RX] TIME SHIFT ON SAMPLING 123 | % Time shift with constant offset t_0 [after the matched filter, before the down sampler] 124 | 125 | rx_symb_UP_async_t0 = rx_symb_UP_async(SYNC.t0+1:end,1); % Thanks to the big oversampling M, we can simulated a Time Shift On Sampling 126 | rx_symb_UP_async_t0 = [rx_symb_UP_async_t0; zeros(SYNC.t0 - 1,1)]; % Zero-Padding to match the length 127 | 128 | rx_symb_UP_async_t0_R = real(rx_symb_UP_async_t0); 129 | 130 | 131 | %% 9. [RX] DOWNSAMPLING 132 | rx_symb = downsample(rx_symb_UP_async_t0,RRCF.M); 133 | 134 | %% 10. [RX] DEMAPPING SYMBOLS TO BITSTREAM - MAXIMUM LIKELIHOOD CRITERION 135 | rx_bin = demapping(rx_symb,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 136 | 137 | 138 | %% X. [PLOT] RELEVANT GRAPHS AND VALUES 139 | % See the function 'FoM' for all the preset Graphs 140 | rx_bin_len = size(rx_bin,1); 141 | BER = 1 - sum(rx_bin(1:rx_bin_len) == tx_bin(1:rx_bin_len))/(rx_bin_len); % Bit Error Ratio 142 | SER = 1 - sum( bi2de(fliplr(reshape(rx_bin,Modu.Nbps,rx_bin_len/Modu.Nbps)')) == bi2de(fliplr(reshape(tx_bin(1:rx_bin_len),Modu.Nbps,rx_bin_len/Modu.Nbps)'))) / (rx_bin_len/Modu.Nbps); % Symbol Error Ratio 143 | 144 | 145 | %% Gardner algorithm -> ML estimation for t_0 and correct the rx_symb 146 | if Gardner_S == 1 147 | display('Now we are having Gardner not Gardener !') 148 | %[T] 149 | figure 150 | plot(tx_symb_UP_R(200:300),'x-'); hold on 151 | %plot(tx_symb_UP_F_R(200:300),'o-r'); hold on; 152 | plot(rx_symb_UP_async_t0_R(200:300),'o-.k'); 153 | 154 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, Gard.K(1)); 155 | figure 156 | plot(est_error,'b'); hold on 157 | [est_error, y_corr] = gardner_est(rx_symb_UP_async_t0, RRCF.M, Gard.K(2)); 158 | plot(est_error,'r'); 159 | 160 | title(['Applying Gardner to ',num2str(t0_input),' time shift unit for', num2str(2^Nbps_input), mod_input]); 161 | xlabel('Time (pts)'); ylabel('Estimated Error'); hold on; 162 | legend('K=0.1','K=0.5'); 163 | 164 | rx_symb_c = downsample(y_corr,RRCF.M); 165 | rx_bin_c = demapping(rx_symb_c,Modu.Nbps,Modu.mod); % Realize the mapping according to the desired Digital Modulation Scheme and Nbps by applying the ML Criterion 166 | rx_bin_c_len = size(rx_bin_c,1); 167 | BER_c = 1 - sum(rx_bin_c(1:rx_bin_c_len) == tx_bin(1:rx_bin_c_len))/(rx_bin_c_len); % Bit Error Ratio 168 | 169 | BER 170 | display('After the Gardner Algorithm correcting the receiving time shift') 171 | BER_c 172 | end 173 | 174 | 175 | %% Gardner algorithm -> ML estimation for t_0 and correct the rx_symb 176 | if Pilot_S == 1 177 | display('Now we are having Pilot !') 178 | [n_est,CFO_est] = pilot_est(rx_symb,Pil_symb,Modu.fsymb) 179 | 180 | end 181 | 182 | end 183 | -------------------------------------------------------------------------------- /Simulations-V32/FoM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/Simulations-V32/FoM.m -------------------------------------------------------------------------------- /Simulations-V32/RRCFDesign.m: -------------------------------------------------------------------------------- 1 | function [IR_RRC, H_RRCF, t_axis, f_axis] = RRCFDesign(Beta, Ntaps, fs, Tsymb) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% RRCFDesign 9 | % INPUTsymb 10 | % 'Beta' - Roll-off Factor 11 | % 'Ntaps' - Number of RRC Taps [Needs to be odd] - Set the Time Extension and the Frequency Resolution 12 | % 'fs' - Sampling Frequency [Hz] 13 | % 'Tsymb' - Symbol Period [s] 14 | % OUTPUTsymb 15 | % 'IR_RRC' - Impulse Response of the designed RRCF 16 | % 'H_RRCF' - Spectrum of the designed RRCF 17 | 18 | 19 | %% The RCF is designed in the frequency domain 20 | %% The Impulse Response is then obtained by IFFT 21 | fmax = (1/Ntaps)*fs*(Ntaps-1)/2; % Maximal frequency on the axis - Tends to fs/2 for Ntaps tending to infinity 22 | f_axis = linspace(-fmax, fmax, Ntaps); 23 | t_axis = (-(Ntaps-1)/2:(Ntaps-1)/2)./(2*fmax); 24 | H_RCF = zeros(1,Ntaps); % Fourier Transform of the RCF 25 | 26 | for i=1:Ntaps % Ntaps seTsymb the Time Extension and the Frequency Resolution 27 | if abs(f_axis(i))<=((1-Beta)/(2*Tsymb)) 28 | H_RCF(i) = Tsymb; 29 | elseif abs(f_axis(i))>((1-Beta)/(2*Tsymb)) && abs(f_axis(i))<=((1+Beta)/(2*Tsymb)) 30 | H_RCF(i) = Tsymb/2*(1+cos(pi*Tsymb/Beta*(abs(f_axis(i))-(1-Beta)/(2*Tsymb)))); 31 | else 32 | H_RCF(i) = 0; 33 | end 34 | end 35 | 36 | H_RRCF = sqrt(H_RCF); 37 | IR_RRC = fftshift(ifft(ifftshift(H_RRCF), 'symmetric')); 38 | normCoeff = sqrt(max(abs(conv(IR_RRC,IR_RRC)))); 39 | IR_RRC=IR_RRC/normCoeff; % Normalize -> the RCF will then be equal to 1 @ t=0 (and not the RRCF !) 40 | end -------------------------------------------------------------------------------- /Simulations-V32/RRCfilterDesign.m: -------------------------------------------------------------------------------- 1 | function [RRCf_time] = RRCfilterDesign(beta, NRRCtaps, tsymb, fsample) 2 | %INPUTS: 3 | % -beta: roll-off coefficient 4 | % -NRRCtaps: Number of RRC taps 5 | % -Tsym: sampling rate 6 | %OUTPUTS: 7 | % -RRCf_time: filter in time domain 8 | 9 | fmax = (1/NRRCtaps)*fsample*(NRRCtaps-1)/2; 10 | f = linspace(-fmax, fmax, NRRCtaps); % build the f x-axis 11 | Hrcf=zeros(1,NRRCtaps); 12 | 13 | for i=1:NRRCtaps 14 | if abs(f(i))<=((1-beta)/(2*tsymb)) 15 | Hrcf(i) = tsymb; 16 | elseif abs(f(i))>((1-beta)/(2*tsymb)) && abs(f(i))<=((1+beta)/(2*tsymb)) 17 | Hrcf(i) = tsymb/2*(1+cos(pi*tsymb/beta*(abs(f(i))-(1-beta)/(2*tsymb)))); 18 | else 19 | Hrcf(i) = 0; 20 | end 21 | end 22 | 23 | %Hrcf = fftshift(Hrcf); 24 | Hrrcf = sqrt(Hrcf); 25 | Hrrct = fftshift(ifft(ifftshift(Hrrcf), 'symmetric')); 26 | normCoeff = sqrt(max(abs(conv(Hrrct,Hrrct)))); 27 | Hrrct=Hrrct/normCoeff; 28 | %Hrrct = Hrrctv; 29 | % figure 30 | % stem(Hrrct); 31 | % title('Hrrct') 32 | 33 | %Hrctv = ifftshift(ifft(Hrcf,'symmetric')) 34 | %Hrct = circshift(Hrctv',-1); 35 | %fa = 1/Hrct((NRRCtaps+1)/2); 36 | %Hrct = Hrct.*fa; 37 | %Hrrct = Hrct.^(-2); 38 | 39 | % 40 | % Hrrcf = sqrt(Hrcf); 41 | % Hrrcf = fftshift(Hrrcf); 42 | % % figure 43 | % % plot(Hrcf); 44 | % % title('H(f) Square Root Cosine Filter') 45 | % 46 | % %Hrrct = ifft(Hrrcf); 47 | % Hrrctv = ifftshift(ifft(Hrrcf,'symmetric')); 48 | % Hrrct = circshift(Hrrctv',-1); 49 | % 50 | 51 | % figure 52 | % stem(Hrrct); 53 | % title('H(t)'); 54 | RRCf_time=Hrrct; 55 | 56 | end -------------------------------------------------------------------------------- /Simulations-V32/demapping.m: -------------------------------------------------------------------------------- 1 | function [rx_bin] = demapping(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% DEMAPPING 9 | % INPUTS 10 | % 'rx_symb' - Symbols 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'rx_bit' - Bitstream 15 | 16 | 17 | %% INITIALIZATION 18 | Nsymb = size(rx_symb,1); % Number of symbols 19 | 20 | switch modulation 21 | %% ***** PULSE AMPLITUDE MODULATION ***** 22 | case 'PAM' 23 | % Symbol to Gray-Integer 24 | rx_int = maxLikelihood(rx_symb,Nbps,'PAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 25 | % Gray-Integer to Integer 26 | rx_int = gray2bin(rx_int,'PAM',2^Nbps); 27 | % Integer to Binary 28 | rx_bin = fliplr(de2bi(rx_int)); 29 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 30 | 31 | 32 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 33 | case 'QAM' 34 | % Symbol to Gray-Integer 35 | rx_int = maxLikelihood(rx_symb,Nbps,'QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 36 | % Gray-Integer to Integer 37 | switch Nbps 38 | case 3 39 | gray2bin_matrix = [0 1 3 2 4 5 7 6]; 40 | for index = 1:length(rx_int) 41 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 42 | end 43 | case 5 44 | gray2bin_matrix = [0 1 3 2 7 6 4 5 8 9 11 10 15 14 12 13 24 25 27 26 31 30 28 29 16 17 19 18 23 22 20 21]; 45 | for index = 1:length(rx_int) 46 | rx_int(index) = gray2bin_matrix(rx_int(index)+1); 47 | end 48 | otherwise 49 | rx_int = gray2bin(rx_int,'QAM',2^Nbps); 50 | end 51 | % Integer to Binary 52 | rx_bin = fliplr(de2bi(rx_int)); 53 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 54 | 55 | 56 | %% ***** PHASE SHIFT KEYING ***** 57 | case 'PSK' 58 | % Symbol to Gray-Integer 59 | rx_int = maxLikelihood(rx_symb,Nbps,'PSK'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 60 | % Gray-Integer to Integer 61 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 62 | % Integer to Binary 63 | rx_bin = fliplr(de2bi(rx_int)); 64 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 65 | 66 | 67 | %% ***** CROSS-QAM ***** 68 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM'(one of the most famous flavor of the Cross-QAM) 69 | case 'Cross-QAM' 70 | % Symbol to Gray-Integer 71 | rx_int = maxLikelihood(rx_symb,Nbps,'Cross-QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 72 | % Gray-Integer to Integer 73 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 74 | % Integer to Binary 75 | rx_bin = fliplr(de2bi(rx_int)); 76 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 77 | 78 | 79 | %% ***** OPTIMAL-8QAM ***** 80 | case 'Optimal-8QAM' 81 | % Symbol to Gray-Integer 82 | rx_int = maxLikelihood(rx_symb,Nbps,'Optimal-8QAM'); % Apply the Maximum Likelihood Criterion in order to find the exact Symbols 83 | % Gray-Integer to Integer 84 | rx_int = gray2bin(rx_int,'PSK',2^Nbps); 85 | % Integer to Binary 86 | rx_bin = fliplr(de2bi(rx_int)); 87 | rx_bin = reshape(rx_bin',Nsymb*Nbps,1); 88 | end 89 | end -------------------------------------------------------------------------------- /Simulations-V32/gardner_est.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Project 2 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 3 | % April 2016 4 | % Part 2 - Time and Frequency Syncrhonisation 5 | % Gardner Function 6 | % carry out Gardner to Maximum Likelyhood estimation of t_0 7 | % input: 8 | % -rx_input: receiver rx_input upsampled by factor M 9 | % -M: upsampling factor 10 | % -K: constant in the Gardner algorithm 11 | % output: 12 | % -est_error: estimated est_error 13 | % -y_corr: corrected sequence 14 | 15 | function [est_error, y_corr]=gardner_est(rx_input, M, K) 16 | 17 | % Init the parameters 18 | rx_len = length(rx_input); 19 | n_sym = round(rx_len/M); 20 | est_error = zeros(1,(n_sym)); % initialize the error mat 21 | y_corr = rx_input; %init the corrected rx sequence 22 | 23 | % iterate through the length of the rx 24 | for ii = 1:n_sym-2 25 | % update the error 26 | est_error(ii+1) = est_error(ii) + K*real(y_corr((2*ii-1)*M/2+1)... 27 | *(conj(y_corr(ii*M+1))-conj(y_corr((ii-1)*M+1)))); 28 | 29 | % update the corrected sequence 30 | % y_corr((2*ii+1)*M/2+1) = interp1([ii*M+1 (2*ii+1)*M/2+1 (ii+1)*M+1],... 31 | % [rx_input(ii*M+1) rx_input((2*ii+1)*M/2+1) rx_input((ii+1)*M+1)],... 32 | % (2*ii+1)*M/2+1-round(est_error(ii+1))); 33 | % y_corr((ii+1)*M+1) = interp1([(2*ii+1)*M/2+1 (2*ii+2)*M/2+1 (2*ii+3)*M/2+1],... 34 | % [rx_input((2*ii+1)*M/2+1) rx_input((2*ii+2)*M/2+1) rx_input((2*ii+3)*M/2+1)],... 35 | % (ii+1)*M+1-round(est_error(ii+1))); 36 | y_corr((2*ii+1)*M/2+1) = interp1([ii*M+1,ii*M+2,(2*ii+1)*M/2+1,(ii+1)*M+1],... 37 | [rx_input(ii*M+1),rx_input(ii*M+2), rx_input((2*ii+1)*M/2+1), rx_input((ii+1)*M+1)],... 38 | (2*ii+1)*M/2+1-round(est_error(ii+1))); 39 | y_corr((ii+1)*M+1) = interp1([(2*ii+1)*M/2+1, (2*ii+2)*M/2+1, (2*ii+3)*M/2+1],... 40 | [rx_input((2*ii+1)*M/2+1), rx_input((2*ii+2)*M/2+1), rx_input((2*ii+3)*M/2+1)],... 41 | (ii+1)*M+1-round(est_error(ii+1))); 42 | end 43 | 44 | 45 | end -------------------------------------------------------------------------------- /Simulations-V32/makeLdpc.m: -------------------------------------------------------------------------------- 1 | function H = makeLdpc(M, N, method, noCycle, onePerCol) 2 | % Create R = 1/2 low density parity check matrix 3 | % 4 | % M : Number of row 5 | % N : Number of column 6 | % method : Method for distributing non-zero element 7 | % {0} Evencol : For each column, place 1s uniformly at random 8 | % {1} Evenboth: For each column and row, place 1s uniformly at random 9 | % noCyle : Length-4 cycle 10 | % {0} Ignore (do nothing) 11 | % {1} Eliminate 12 | % onePerCol: Number of ones per column 13 | % 14 | % H : Low density parity check matrix 15 | % 16 | % 17 | % Copyright Bagawan S. Nugroho, 2007 18 | % http://bsnugroho.googlepages.com 19 | 20 | 21 | % Number of ones per row (N/M ratio must be 2) 22 | if N/M ~= 2 23 | fprintf('Code rate must be 1/2\n'); 24 | end 25 | onePerRow = (N/M)*onePerCol; 26 | 27 | fprintf('Creating LDPC matrix...\n'); 28 | 29 | switch method 30 | % Evencol 31 | case {0} 32 | % Distribute 1s uniformly at random within column 33 | for i = 1:N 34 | onesInCol(:, i) = randperm(M)'; 35 | end 36 | 37 | % Create non zero elements (1s) index 38 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 39 | tmp = repmat([1:N], onePerCol, 1); 40 | c = reshape(tmp, N*onePerCol, 1); 41 | 42 | % Create sparse matrix H 43 | H = full(sparse(r, c, 1, M, N)); 44 | 45 | % Evenboth 46 | case {1} 47 | % Distribute 1s uniformly at random within column 48 | for i = 1:N 49 | onesInCol(:, i) = randperm(M)'; 50 | end 51 | 52 | % Create non zero elements (1s) index 53 | r = reshape(onesInCol(1:onePerCol, :), N*onePerCol, 1); 54 | tmp = repmat([1:N], onePerCol, 1); 55 | c = reshape(tmp, N*onePerCol, 1); 56 | 57 | % Make the number of 1s between rows as uniform as possible 58 | 59 | % Order row index 60 | [r, ix] = sort(r); 61 | 62 | % Order column index based on row index 63 | for i = 1:N*onePerCol 64 | cSort(i, :) = c(ix(i)); 65 | end 66 | 67 | % Create new row index with uniform weight 68 | tmp = repmat([1:M], onePerRow, 1); 69 | r = reshape(tmp, N*onePerCol, 1); 70 | 71 | % Create sparse matrix H 72 | % Remove any duplicate non zero elements index using logical AND 73 | S = and(sparse(r, cSort, 1, M, N), ones(M, N)); 74 | H = full(S); 75 | 76 | end % switch 77 | 78 | % Check rows that have no 1 or only have one 1 79 | for i = 1:M 80 | 81 | n = randperm(N); 82 | % Add two 1s if row has no 1 83 | if length(find(r == i)) == 0 84 | H(i, n(1)) = 1; 85 | H(i, n(2)) = 1; 86 | % Add one 1 if row has only one 1 87 | elseif length(find(r == i)) == 1 88 | H(i, n(1)) = 1; 89 | end 90 | 91 | end % for i 92 | 93 | % If desired, eliminate any length-4 cycle 94 | if noCycle == 1 95 | 96 | for i = 1:M 97 | % Look for pair of row - column 98 | for j = (i + 1):M 99 | w = and(H(i, :), H(j, :)); 100 | c1 = find(w); 101 | lc = length(c1); 102 | if lc > 1 103 | 104 | % If found, flip one 1 to 0 in the row with less number of 1s 105 | if length(find(H(i, :))) < length(find(H(j, :))) 106 | % Repeat the process until only one column left 107 | for cc = 1:lc - 1 108 | H(j, c1(cc)) = 0; 109 | end 110 | else 111 | for cc = 1:lc - 1 112 | H(i, c1(cc)) = 0; 113 | end 114 | end % if 115 | 116 | end % if 117 | end % for j 118 | end % for i 119 | 120 | end % if 121 | 122 | fprintf('LDPC matrix is created.\n'); 123 | -------------------------------------------------------------------------------- /Simulations-V32/makeParityChk.m: -------------------------------------------------------------------------------- 1 | function [c, newH] = makeParityChk(dSource, H, strategy) 2 | % Generate parity check vector bases on LDPC matrix H using sparse LU decomposition 3 | % 4 | % dSource : Binary source (0/1) 5 | % H : LDPC matrix 6 | % strategy: Strategy for finding the next non-zero diagonal elements 7 | % {0} First : First non-zero found by column search 8 | % {1} Mincol : Minimum number of non-zeros in later columns 9 | % {2} Minprod: Minimum product of: 10 | % - Number of non-zeros its column minus 1 11 | % - Number of non-zeros its row minus 1 12 | % 13 | % c : Check bits 14 | % 15 | % 16 | % Copyright Bagawan S. Nugroho, 2007 17 | % http://bsnugroho.googlepages.com 18 | 19 | % Get the matric dimension 20 | [M, N] = size(H); 21 | % Set a new matrix F for LU decomposition 22 | F = H; 23 | % LU matrices 24 | L = zeros(M, N - M); 25 | U = zeros(M, N - M); 26 | 27 | % Re-order the M x (N - M) submatrix 28 | for i = 1:M 29 | 30 | % strategy {0 = First; 1 = Mincol; 2 = Minprod} 31 | switch strategy 32 | 33 | % Create diagonally structured matrix using 'First' strategy 34 | case {0} 35 | 36 | % Find non-zero elements (1s) for the diagonal 37 | [r, c] = find(F(:, i:end)); 38 | 39 | % Find non-zero diagonal element candidates 40 | rowIndex = find(r == i); 41 | 42 | % Find the first non-zero column 43 | chosenCol = c(rowIndex(1)) + (i - 1); 44 | 45 | % Create diagonally structured matrix using 'Mincol' strategy 46 | case {1} 47 | 48 | % Find non-zero elements (1s) for the diagonal 49 | [r, c] = find(F(:, i:end)); 50 | colWeight = sum(F(:, i:end), 1); 51 | 52 | % Find non-zero diagonal element candidates 53 | rowIndex = find(r == i); 54 | 55 | % Find the minimum column weight 56 | [x, ix] = min(colWeight(c(rowIndex))); 57 | % Add offset to the chosen row index to match the dimension of the... 58 | % original matrix F 59 | chosenCol = c(rowIndex(ix)) + (i - 1); 60 | 61 | % Create diagonally structured matrix using 'Minprod' strategy 62 | case {2} 63 | 64 | % Find non-zero elements (1s) for the diagonal 65 | [r, c] = find(F(:, i:end)); 66 | colWeight = sum(F(:, i:end), 1) - 1; 67 | rowWeight = sum(F(i, :), 2) - 1; 68 | 69 | % Find non-zero diagonal element candidates 70 | rowIndex = find(r == i); 71 | 72 | % Find the minimum product 73 | [x, ix] = min(colWeight(c(rowIndex))*rowWeight); 74 | % Add offset to the chosen row index to match the dimension of the... 75 | % original matrix F 76 | chosenCol = c(rowIndex(ix)) + (i - 1); 77 | 78 | otherwise 79 | fprintf('Please select columns re-ordering strategy!\n'); 80 | 81 | end % switch 82 | 83 | % Re-ordering columns of both H and F 84 | tmp1 = F(:, i); 85 | tmp2 = H(:, i); 86 | F(:, i) = F(:, chosenCol); 87 | H(:, i) = H(:, chosenCol); 88 | F(:, chosenCol) = tmp1; 89 | H(:, chosenCol) = tmp2; 90 | 91 | % Fill the LU matrices column by column 92 | L(i:end, i) = F(i:end, i); 93 | U(1:i, i) = F(1:i, i); 94 | 95 | % There will be no rows operation at the last row 96 | if i < M 97 | 98 | % Find the later rows with non-zero elements in column i 99 | [r2, c2] = find(F((i + 1):end, i)); 100 | % Add current row to the later rows which have a 1 in column i 101 | F((i + r2), :) = mod(F((i + r2), :) + repmat(F(i, :), length(r2), 1), 2); 102 | 103 | end % if 104 | 105 | end % for i 106 | 107 | % Find B.dsource 108 | z = mod(H(:, (N - M) + 1:end)*dSource, 2); 109 | 110 | % Parity check vector found by solving sparse LU 111 | c = mod(U\(L\z), 2); 112 | 113 | % Return the rearrange H 114 | newH = H; 115 | 116 | fprintf('Message encoded.\n'); 117 | -------------------------------------------------------------------------------- /Simulations-V32/mapping.m: -------------------------------------------------------------------------------- 1 | function [tx_symb] = mapping(tx_bin,Nbps,modulation) % Maps bitstream to Symbols depending on the selected mapping 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% MAPPING 9 | % INPUTS 10 | % 'tx_bin' - Bitstream 11 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 12 | % 'Nbps' - Number of bits per symbol 13 | % OUTPUT 14 | % 'tx_symb' - Symbols 15 | 16 | 17 | %% INITIALIZATION AND VALIDITY CHECK 18 | if mod(Nbps, 1) ~=0 || Nbps <= 0 19 | error('You have entered an unsupported Number of Bits Per Symbol. Nbps must be a positive real integer.'); 20 | end 21 | Nsymb = size(tx_bin,1)/Nbps; % Number of symbols 22 | tx_bin = reshape(tx_bin,Nbps,Nsymb)'; % Reshapes the vector into a matrix: each row corresponds to a symbol (Nbps bits) 23 | 24 | switch modulation 25 | %% ***** PULSE AMPLITUDE MODULATION ***** 26 | case 'PAM' 27 | % Binary to Integer - Convert 'Binary Word' to corresponding 'Integer' [10 -> 2] 28 | tx_int = bi2de(fliplr(tx_bin)); 29 | % Integer to Gray-Integer - Convert 'Integer' to corresponding 'Gray-Integer' according to the desired Modulation Scheme and Npbs [2 <-> 3] 30 | tx_int = bin2gray(tx_int,'PAM',2^Nbps); 31 | % Gray-Integer to Symbol - Convert 'Gray Integer' to corresponding 'Symbol' according to the desired Modulation Scheme and Npbs 32 | distance = 2/(2^Nbps-1); 33 | tx_symb = distance * (tx_int - (2^Nbps-1)/2); 34 | 35 | 36 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 37 | case 'QAM' 38 | % Binary to Integer 39 | tx_int = bi2de(fliplr(tx_bin)); 40 | % Integer to Gray-Integer 41 | switch Nbps 42 | case 3 43 | bin2gray_matrix = [0 1 3 2 4 5 7 6]; 44 | for index = 1:length(tx_int) 45 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 46 | end 47 | case 5 48 | bin2gray_matrix = [0 1 3 2 6 7 5 4 8 9 11 10 14 15 13 12 24 25 27 26 30 31 29 28 16 17 19 18 22 23 21 20]; 49 | for index = 1:length(tx_int) 50 | tx_int(index) = bin2gray_matrix(tx_int(index)+1); 51 | end 52 | otherwise 53 | tx_int = bin2gray(tx_int,'QAM',2^Nbps); 54 | end 55 | 56 | % Gray-Integer to Symbol 57 | Nbps_I = ceil(Nbps/2); % Number of symbols carried in the 'Inphase Carrier' 58 | Nbps_Q = Nbps - Nbps_I; % Number of symbols carried in the 'Quadrature Carrier' 59 | distance = 2/(2^Nbps_I-1); 60 | tx_symb = distance*( (mod(tx_int,2^(Nbps_I)) - (2^Nbps_I-1)/2) - 1i*(floor(tx_int/(2^Nbps_I)) - (2^Nbps_Q-1)/2) ); 61 | 62 | 63 | %% ***** PHASE SHIFT KEYING ***** 64 | case 'PSK' 65 | % Binary to Integer 66 | tx_int = bi2de(fliplr(tx_bin)); 67 | % Integer to Gray-Integer 68 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 69 | % Gray-Integer to Symbol 70 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 71 | 72 | 73 | %% ***** CROSS-QAM ***** 74 | % In particular, considering the 'Cross-QAM', we choose to implement the '4 symbols per orbit' also called 'Star-QAM' (one of the most famous flavour of the Cross-QAM) 75 | case 'Cross-QAM' 76 | switch Nbps 77 | case 1 % Simple PSK 78 | tx_int = bi2de(fliplr(tx_bin)); 79 | tx_symb = exp(1i*pi*(3/4 + 2/(2^Nbps)*tx_int)); 80 | otherwise 81 | % Binary to Integer 82 | tx_int = bi2de(fliplr(tx_bin)); 83 | % Integer to Gray-Integer 84 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 85 | % Gray-Integer to Symbol 86 | tx_symb = zeros(length(tx_int),1); 87 | for index = 1:length(tx_int) 88 | radius = (2 + floor(tx_int(index)/4)) / (2^Nbps/4 + 1); 89 | phase = (mod(floor(tx_int(index)/4), 2) == 0)*3/4; 90 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 91 | end 92 | end 93 | 94 | 95 | %% ***** OPTIMAL-8QAM ***** 96 | case 'Optimal-8QAM' 97 | if Nbps ~= 3 98 | error('This particular Modulation Scheme only works with 3 Bits per Symbol. For Nbps other than 3, please choose among [PSK, PAM, QAM, Cross-QAM].'); 99 | end 100 | % Binary to Integer 101 | tx_int = bi2de(fliplr(tx_bin)); 102 | % Integer to Gray-Integer 103 | tx_int = bin2gray(tx_int,'PSK',2^Nbps); 104 | % Gray-Integer to Symbol 105 | tx_symb = zeros(length(tx_int),1); 106 | for index = 1:length(tx_int) 107 | if tx_int(index) > 3 108 | radius = 1; 109 | else 110 | radius = sqrt(2) / (1 + sqrt(3)); 111 | end 112 | phase = (floor(tx_int(index)/4) == 0)*3/4; 113 | tx_symb(index) = radius*exp(1i*pi*(phase + 1/2*mod(tx_int(index),4))); 114 | end 115 | 116 | otherwise 117 | error('You have entered an unsupported Digital Modulation scheme. Please choose among [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM].'); 118 | end -------------------------------------------------------------------------------- /Simulations-V32/maxLikelihood.m: -------------------------------------------------------------------------------- 1 | function [rx_symb_ML] = maxLikelihood(rx_symb,Nbps,modulation) 2 | % Modulation and Coding Project 3 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 4 | % April 2016 5 | % Part 2 - Time and Frequency Syncrhonisation 6 | 7 | 8 | %% MAXIMUM LIKELIHOOD CRITERION 9 | % By comparing the Received Symbols 'rx_symb' with the Symbols of Reference 'symb_ref' we can apply the ML Criterion and deduce 'rx_symb_ML' 10 | % INPUTS 11 | % 'rx_symb' - Symbols 12 | % 'modulation' - Digital Modulation [PSK, PAM, QAM, Cross-QAM, Optimal-8QAM] 13 | % 'Nbps' - Number of bits per symbol 14 | % OUTPUT 15 | % 'rx_symb_ML' - Symbols after the application of the Maximum Likelihood Criterion 16 | 17 | 18 | %% ALGORITHM 19 | % 'symb_ref' is a [2^Nbps x 2] matrix used as a Containers.map 20 | % The 1st column includes all the Symbols of Reference in their Complex form (-0.7071 + i*0.7071, +0.7071 - i*0.7071,...) 21 | % The 2nd column includes the associated Decimal Value (0, 1, 2, 3, ...) 22 | % Step 1: Generating Symbols of Reference in function of (Nbps, modulation) 23 | % Step 2: Application of the Maximum Likelihood Criterion -> Compare each element of 'rx_symb' with the Symbols of Reference 'symb_ref' 24 | % Step 3: Return the Symbols after the application of the Maximum Likelihood Criterion 'rx_symb_ML' 25 | 26 | switch modulation 27 | %% ***** PULSE AMPLITUDE MODULATION ***** 28 | case 'PAM' 29 | % Generating Symbols of Reference 30 | symb_ref = zeros(2^Nbps,2); 31 | distance = 2/(2^Nbps-1); 32 | for index = 1:2^Nbps 33 | symb_ref(index,:) = [distance*(index-1 - (2^Nbps-1)/2), index-1]; 34 | end 35 | % Application of the Maximum Likelihood Criterion 36 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 37 | 38 | 39 | %% ***** QUADRATURE AMPLITUDE MODULATION ***** 40 | case 'QAM' 41 | % Generating Symbols of Reference 42 | Nbps_I = ceil(Nbps/2); Nbps_Q = Nbps - Nbps_I; 43 | symb_ref = zeros(2^Nbps,2); 44 | distance = 2/(2^Nbps_I-1); 45 | for index_I = 1:2^Nbps_I 46 | for index_Q = 1:2^Nbps_Q 47 | symb_ref(index_I + (2^Nbps_I)*(index_Q-1), :) = [distance*((index_I-1 - (2^Nbps_I-1)/2) - 1i* (index_Q-1 - (2^Nbps_Q-1)/2)), index_I-1 + (2^Nbps_I)*(index_Q-1)]; 48 | end 49 | end 50 | % Application of the Maximum Likelihood Criterion 51 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 52 | 53 | %% ***** PHASE SHIFT KEYING ***** 54 | case 'PSK' 55 | symb_ref = zeros(2^Nbps,2); 56 | % Generating Symbols of Reference 57 | for index = 1:2^Nbps 58 | symb_ref(index,:) = [exp(1i*pi*(3/4 + 2/(2^Nbps)*(index-1))), index-1]; 59 | end 60 | % Application of the Maximum Likelihood Criterion 61 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 62 | 63 | %% ***** CROSS-QUADRATURE AMPLITUDE MODULATION ***** 64 | case 'Cross-QAM' 65 | % Generating Symbols of Reference 66 | symb_ref = zeros(2^Nbps,2); 67 | switch Nbps 68 | case 1 % Only 2 Symbols on the 1st Orbit => Elementary PSK Case 69 | symb_ref = [exp(1i*pi*(3/4 + 2/(2^Nbps)*0)), 0; exp(1i*pi*(3/4 + 2/(2^Nbps)*1)), 1]; 70 | otherwise 71 | for index = 1:2^Nbps 72 | radius = (2 + floor((index - 1)/4)) / (2^Nbps/4 + 1); 73 | phase = (mod(floor((index-1)/4), 2) == 0)*3/4; 74 | symb_ref(index,:) = [radius*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 75 | end 76 | end 77 | % Application of the Maximum Likelihood Criterion 78 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 79 | 80 | 81 | %% ***** OPTIMAL-8QAM ***** 82 | case 'Optimal-8QAM' 83 | % Generating Symbols of Reference 84 | symb_ref = zeros(2^Nbps,2); 85 | radius = [sqrt(2)/(1 + sqrt(3)), 1]; 86 | for index = 1:2^Nbps 87 | phase = (floor((index-1)/4) == 0)*3/4; 88 | symb_ref(index,:) = [radius(floor((index-1)/4) + 1)*exp(1i*pi*(phase + 1/2*mod((index - 1),4))), index - 1]; 89 | end 90 | % Application of the Maximum Likelihood Criterion 91 | rx_symb_ML = appML(rx_symb, Nbps, symb_ref); 92 | end 93 | 94 | 95 | %% ***** APPLICATION OF THE MAXIMUM LIKELIHOOD CRITERION ***** 96 | function [rx_symb_ML] = appML(rx_symb, Nbps, symb_ref) 97 | rx_symb_ML = zeros(length(rx_symb), 1); % Initialize the size of 'rx_symb_ML' in order to save some time 98 | CSM = sqrt(abs((rx_symb(:) - symb_ref(1, 1)) .^ 2)); % CSM - Current Smallest Norm: Transient save allowing to 'compare before assign' 99 | 100 | for index = 1:2^Nbps % Loop to determine the minimal Euclidean Norm of each Received Symbol 101 | BOOL = CSM > sqrt(abs((rx_symb(:) - symb_ref(index, 1)) .^ 2)); % Boolean Vector taking a true value ('1') when the corresponding CSM row appears to not be the smallest possible Euclidean Norm 102 | CSM(BOOL) = sqrt(abs((rx_symb(BOOL) - symb_ref(index, 1)) .^ 2)); % Update CSM accordingly 103 | rx_symb_ML(BOOL) = symb_ref(index, 2); 104 | end -------------------------------------------------------------------------------- /Simulations-V32/pilot_est.m: -------------------------------------------------------------------------------- 1 | % Modulation and Coding Project 2 | % TEAM: MOY - Mroueh Michael, Asfour A. Omar, Liu Yu 3 | % April 2016 4 | % Part 2 - Time and Frequency Syncrhonisation 5 | % Gardner Function 6 | % carry out Gardner to Maximum Likelyhood estimation of t_0 7 | % input: 8 | % -sig_in: receiver rx_input downsampled 9 | % -pilot: pilot symbols 10 | % -K: constant in the Gardner algorithm 11 | % output: 12 | % -n_est: estimated best synchornized time 13 | % -CFO_est: estimated CFO 14 | 15 | function [n_est,CFO_est] = pilot_est(sig_in,pilot,f_sym) 16 | 17 | N = size(pilot,1); % N is the size of the Pilot symbols 18 | K = 16; % Cross-Correlation Window [!] Select to improve performance 19 | Tsymb = 1/f_sym; % Symbol interval 20 | len = length(sig_in); % length of the whole input signal 21 | 22 | matD = zeros(K,len-N+1); % initialize the diff corr matrix 23 | 24 | for kk=1:K % iterating the corr diff 25 | for l=kk:N-1 % going through the points 26 | m = (conj(sig_in(l:len-N+l))*pilot(l)... 27 | .* (conj(conj(sig_in(1+l-kk:len-N+l-kk+1))*pilot(l-kk+1)))); 28 | matD(kk,:)= matD(kk,:) + m.'; 29 | end 30 | matD(kk,:)=matD(kk,:)/(N-kk); 31 | end 32 | 33 | tot_matD=sum(abs(matD)); 34 | [~,n_est]= max(tot_matD); 35 | 36 | CFO_est=0; 37 | 38 | for kk=1:K 39 | CFO_est= CFO_est + phase(matD(kk,n_est))/(2*pi*kk*Tsymb); 40 | end 41 | 42 | CFO_est=-CFO_est/K; % the estimation 43 | 44 | end -------------------------------------------------------------------------------- /document/Labo 1v2016_2.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/document/Labo 1v2016_2.pptx -------------------------------------------------------------------------------- /document/MC-Report-V3.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/document/MC-Report-V3.docx -------------------------------------------------------------------------------- /document/labProject-ModCod.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/document/labProject-ModCod.pdf -------------------------------------------------------------------------------- /document/report_s1.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/document/report_s1.docx -------------------------------------------------------------------------------- /document/report_s2.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/document/report_s2.docx -------------------------------------------------------------------------------- /document/report_s3.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/document/report_s3.docx -------------------------------------------------------------------------------- /figures/BERvsEbN0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/BERvsEbN0.jpg -------------------------------------------------------------------------------- /figures/Block Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/Block Diagram.png -------------------------------------------------------------------------------- /figures/Sans titre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/Sans titre.png -------------------------------------------------------------------------------- /figures/Transceiver Block Diagram - Baseband Equivalent Model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/Transceiver Block Diagram - Baseband Equivalent Model.png -------------------------------------------------------------------------------- /figures/Transceiver Block Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/Transceiver Block Diagram.png -------------------------------------------------------------------------------- /figures/constellations.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/constellations.fig -------------------------------------------------------------------------------- /figures/filterfreq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/filterfreq.jpg -------------------------------------------------------------------------------- /figures/filtert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Walkerlikesfish/Simulation_Modulation/26139b60e08a1a71daf787166518dcf3d779a4c5/figures/filtert.jpg --------------------------------------------------------------------------------