├── OFDM.m └── OFDM_Distortions.m /OFDM.m: -------------------------------------------------------------------------------- 1 | clear all; 2 | close all; 3 | clc; 4 | 5 | %% Parameters 6 | 7 | PPM = 20; 8 | R = 1e5; % [bits/sec] 9 | duration = 0.128; % [sec] 10 | DataL = R*duration/2; % Data length in symbols 11 | NFFT = 128; 12 | 13 | M = 4; % 4 QAM 14 | snr = 20; % [dB] 15 | 16 | Nsym = 4; % Filter order in symbol durations 17 | beta = 0.5; % Roll-off factor 18 | sampsPerSym = 10; % Upsampling factor 19 | L = sampsPerSym*Nsym + 1; % Raised cosine filter order 20 | Fs = R * sampsPerSym; % Sampling frequency 21 | f1 = Fs/5; 22 | cyclic_prefix_signal = []; 23 | 24 | %% Raised cosine filter design 25 | 26 | shape = 'Raised Cosine'; 27 | % Specifications of the raised cosine filter with given order in symbols 28 | rcosSpec = fdesign.pulseshaping(sampsPerSym, shape, 'Nsym,beta', Nsym, beta); 29 | rcosFlt = design(rcosSpec); 30 | rcosFlt.Numerator = rcosFlt.Numerator / max(rcosFlt.Numerator); 31 | 32 | 33 | %% Tranceiver 34 | 35 | bernoulli_binary_generator = randint(R*duration,1); 36 | 37 | % Transmiter 38 | 39 | bernoulli_two_samples = reshape(bernoulli_binary_generator, length(bernoulli_binary_generator)/2, 2); 40 | dec = bi2de(bernoulli_two_samples,'left-msb'); % Bit to integer 41 | modulated_data = qammod(dec,M); % 4 QAM 42 | 43 | % Serial to Parallel 44 | for id = 1:length(modulated_data)/NFFT 45 | ifft_signal = ifft(modulated_data((id-1)*NFFT+1:id*NFFT)); % ifft 46 | % adding cyclic prefix 47 | cyclic_prefix = zeros(NFFT + L, 1); 48 | cyclic_prefix(1:L) = ifft_signal(end-L+1:end); 49 | cyclic_prefix(L+1:end) = ifft_signal; 50 | cyclic_prefix_signal = [cyclic_prefix_signal; cyclic_prefix]; 51 | end; 52 | % D/A 53 | signal_complex = filter(rcosFlt, upsample([cyclic_prefix_signal; zeros(Nsym/2,1)], sampsPerSym)); 54 | fltDelay = Nsym / (2*R); % Filter group delay, since raised cosine filter is linear phase and symmetric. 55 | signal_complex = signal_complex(fltDelay*Fs+1:end); % Correct for propagation delay by removing filter transients 56 | 57 | t = (0: length(signal_complex) - 1) / Fs; 58 | f = linspace(-Fs/2,Fs/2,length(signal_complex)); 59 | I = real(signal_complex); 60 | Q = imag(signal_complex); 61 | FI = fftshift(fft(I)); 62 | FQ = fftshift(fft(Q)); 63 | signal = I'.*cos(2*pi*f1*t) - Q'.*sin(2*pi*f1*t); 64 | 65 | % Channel 66 | noised_signal = awgn(signal,snr,'measured'); % Adding white gaussian noise 67 | % noised_signal = signal; 68 | 69 | % Reciever 70 | 71 | % A/D 72 | noised_recieved_signal = noised_signal.*cos(2*pi*f1*t) - 1i*noised_signal.*sin(2*pi*f1*t); 73 | 74 | filtered_reconstructed_digital_signal = filter(rcosFlt, [noised_recieved_signal.'; zeros(fltDelay*Fs,1)]); 75 | reconstructed_digital_signal = downsample(filtered_reconstructed_digital_signal, sampsPerSym); 76 | reconstructed_digital_signal = reconstructed_digital_signal(Nsym/2+1:end); % Correct for propagation delay by removing filter transients 77 | 78 | % Serial to Parallel 79 | N = L + NFFT; 80 | fft_signal = zeros(length(modulated_data),1); 81 | for id = 1:length(modulated_data)/NFFT 82 | tmp = reconstructed_digital_signal(N*(id-1) + 1 : N*id); 83 | removing_cyclic_prefix = tmp(end - NFFT + 1:end); % removing cyclic prefix 84 | fft_signal_SP = fft(removing_cyclic_prefix); % fft 85 | fft_signal(NFFT*(id-1) + 1 : id*NFFT) = fft_signal_SP; 86 | end; 87 | 88 | 89 | demodulated_data = qamdemod(fft_signal, M); % Demodulation 90 | demodulated_binary = de2bi(demodulated_data,'left-msb'); % Integer to bit 91 | recieved_signal = demodulated_binary(:); 92 | 93 | I = real(fft_signal); 94 | Q = imag(fft_signal); 95 | scatter(I,Q); 96 | hold on; 97 | scatter([1,-1,-1,1],[1,1,-1,-1]); 98 | title(sprintf('Reciever''s constelation, SNR = %d[dB]', snr)); 99 | 100 | BER = sum(xor(bernoulli_binary_generator,recieved_signal))/length(bernoulli_binary_generator); -------------------------------------------------------------------------------- /OFDM_Distortions.m: -------------------------------------------------------------------------------- 1 | clear all; 2 | close all; 3 | clc; 4 | 5 | %% Parameters 6 | 7 | PPM = 0; 8 | R = 1e5; % [bits/sec] 9 | Rtag = R * (1 + PPM/1e6); 10 | duration = 0.128; % [sec] 11 | DataL = R*duration/2; % Data length in symbols 12 | NFFT = 128; 13 | M = 4; % 4 QAM 14 | 15 | snr = 20; % [dB] 16 | 17 | Nsym = 4; % Filter order in symbol durations 18 | beta = 0.5; % Roll-off factor 19 | sampsPerSym = 10; % Upsampling factor 20 | L = sampsPerSym*Nsym + 1; % Raised cosine filter order 21 | Fs = R * sampsPerSym; % Sampling frequency 22 | 23 | df = 0; 24 | f1 = Fs/5; 25 | f2 = f1 * (1 + df); 26 | theta = 0; 27 | 28 | cyclic_prefix_signal = []; 29 | 30 | %% Raised cosine filter design 31 | 32 | shape = 'Raised Cosine'; 33 | % Specifications of the raised cosine filter with given order in symbols 34 | rcosSpec = fdesign.pulseshaping(sampsPerSym, shape, 'Nsym,beta', Nsym, beta); 35 | rcosFlt = design(rcosSpec); 36 | rcosFlt.Numerator = rcosFlt.Numerator / max(rcosFlt.Numerator); 37 | 38 | 39 | %% Tranceiver 40 | 41 | bernoulli_binary_generator = randint(R*duration,1); 42 | 43 | % Transmiter 44 | 45 | bernoulli_two_samples = reshape(bernoulli_binary_generator, length(bernoulli_binary_generator)/2, 2); 46 | dec = bi2de(bernoulli_two_samples,'left-msb'); % Bit to integer 47 | modulated_data = qammod(dec,M); % 4 QAM 48 | 49 | % Serial to Parallel 50 | for id = 1:length(modulated_data)/NFFT 51 | ifft_signal = ifft(modulated_data((id-1)*NFFT+1:id*NFFT)); % ifft 52 | % adding cyclic prefix 53 | cyclic_prefix = zeros(NFFT + L, 1); 54 | cyclic_prefix(1:L) = ifft_signal(end-L+1:end); 55 | cyclic_prefix(L+1:end) = ifft_signal; 56 | cyclic_prefix_signal = [cyclic_prefix_signal; cyclic_prefix]; 57 | end; 58 | % D/A 59 | signal_complex = filter(rcosFlt, upsample([cyclic_prefix_signal; zeros(Nsym/2,1)], sampsPerSym)); 60 | fltDelay = Nsym / (2*R); % Filter group delay, since raised cosine filter is linear phase and symmetric. 61 | signal_complex = signal_complex(fltDelay*Fs+1:end); % Correct for propagation delay by removing filter transients 62 | 63 | t = (0: length(signal_complex) - 1) / Fs; 64 | % f = linspace(-Fs/2,Fs/2,length(signal_complex)); 65 | I = real(signal_complex); 66 | Q = imag(signal_complex); 67 | % FI = fftshift(fft(I)); 68 | % FQ = fftshift(fft(Q)); 69 | signal = I'.*cos(2*pi*f1*t) - Q'.*sin(2*pi*f1*t); 70 | 71 | % Channel 72 | noised_signal = awgn(signal,snr,'measured'); % Adding white gaussian noise 73 | % noised_signal = signal; 74 | 75 | % Reciever 76 | 77 | % A/D 78 | noised_recieved_signal = noised_signal.*cos(2*pi*f2*t + theta) - 1i*noised_signal.*sin(2*pi*f2*t + theta); 79 | 80 | filtered_reconstructed_digital_signal = filter(rcosFlt, [noised_recieved_signal.'; zeros(fltDelay*Fs,1)]); 81 | reconstructed_digital_signal = downsample(filtered_reconstructed_digital_signal, sampsPerSym); 82 | % reconstructed_digital_signal = downsample_with_another_symbol_rate(filtered_reconstructed_digital_signal, sampsPerSym, R, Rtag); 83 | reconstructed_digital_signal = reconstructed_digital_signal(Nsym/2+1:end); % Correct for propagation delay by removing filter transients 84 | 85 | % Serial to Parallel 86 | N = L + NFFT; 87 | fft_signal = zeros(length(modulated_data),1); 88 | for id = 1:length(modulated_data)/NFFT 89 | tmp = reconstructed_digital_signal(N*(id-1) + 1 : N*id); 90 | removing_cyclic_prefix = tmp(end - NFFT + 1:end); % removing cyclic prefix 91 | fft_signal_SP = fft(removing_cyclic_prefix); % fft 92 | fft_signal(NFFT*(id-1) + 1 : id*NFFT) = fft_signal_SP; 93 | end; 94 | 95 | 96 | demodulated_data = qamdemod(fft_signal, M); % Demodulation 97 | demodulated_binary = de2bi(demodulated_data,'left-msb'); % Integer to bit 98 | recieved_signal = demodulated_binary(:); 99 | 100 | I = real(fft_signal); 101 | Q = imag(fft_signal); 102 | scatter(I,Q); 103 | hold on; 104 | scatter([1,-1,-1,1],[1,1,-1,-1]); 105 | title(sprintf('Reciever''s constelation, SNR = %d[dB]', snr)); 106 | 107 | BER = sum(xor(bernoulli_binary_generator,recieved_signal))/length(bernoulli_binary_generator); --------------------------------------------------------------------------------