├── MMSE_Equalize.m ├── Pilot_Generator.m ├── System_Parameter.m ├── LICENSE ├── README.md ├── Ideal_Channel_Estimation.m ├── Experimental_Simulation.m ├── System_Initialize.m └── LDPC_and_MIMOinDSRC.m /MMSE_Equalize.m: -------------------------------------------------------------------------------- 1 | function equalized_data = MMSE_Equalize(processed_ofdm_demodulated_data, channel_estimation_matrix, noise_variance) 2 | 3 | noise_factor = diag(noise_variance); 4 | data_length = size(processed_ofdm_demodulated_data, 1); 5 | equalized_data = complex(zeros(size(processed_ofdm_demodulated_data))); 6 | for n = 1:data_length 7 | h = squeeze(channel_estimation_matrix(n, :, :)); 8 | h = h.'; 9 | x = ((h'*h + noise_factor) \ h') * (processed_ofdm_demodulated_data(n, :).'); 10 | equalized_data(n, :) = x.'; 11 | end 12 | 13 | end -------------------------------------------------------------------------------- /Pilot_Generator.m: -------------------------------------------------------------------------------- 1 | function pilot_symbols = Pilot_Generator(number_of_symbol_per_subcarrier,number_of_transmit_antenna) 2 | 3 | pnseq = comm.PNSequence('Polynomial',[1 0 0 0 1 0 0 1], 'SamplesPerFrame', number_of_symbol_per_subcarrier,... 4 | 'InitialConditions',[1 1 1 1 1 1 1]); %% Generating PN sequence 5 | pilot = pnseq(); %% Creating pilot symbols 6 | pilots = repmat(pilot, 1, 4 ); %% Expanding to all pilot tones 7 | pilots = 2*double(pilots.'<1)-1; %% Converting bipolar to unipolar 8 | pilots(4,:) = -1*pilots(4,:); %% Inverting last pilot symbol 9 | pilot_symbols = repmat(pilots,[1, 1, number_of_transmit_antenna]); %% Generating pilot symbols for multiple antennas 10 | 11 | end -------------------------------------------------------------------------------- /System_Parameter.m: -------------------------------------------------------------------------------- 1 | number_of_data_subcarrier = 48; %% Declaring the number of data subcarriers 2 | number_of_pilot_subcarrier = 4; %% Declaring the number of pilot subcarriers 3 | pilot_subcarrier_indices_per_symbol = [6; 20; 33; 47]; %% Defining indices for pilot subcarriers in the resource block 4 | data_subcarrier_indices_per_symbol = [1:5,7:19,21:32,34:46,48:52]; %% Defining indices for data subcarriers in the resource block 5 | number_of_total_subcarrier = 52; %% Declaring total number of subcarriers 6 | channel_bandwidth = 10e6; %% Declaring channel bandwidth in Hz 7 | modulation_type = 1; %% Declaring modulation type [1 for QPSK] 8 | number_of_transmit_antenna = 2; %% Declaring the number of tranmit antennas 9 | number_of_receive_antenna = 2; %% Declaring the number of receive antennas 10 | EbNo = 0:1:15; %% Declaring SNR range for the simulation 11 | noise_factor = 2; %% Declaring AWGN noise factor 12 | maximum_number_of_bits = 1e5; %% Declaring maximum number of bits to be transmitted per SNR value 13 | doppler_effect = 100; %% Declaring doppler value in Hz 14 | coding_rate = 1/2; %% Declaring coding rate [1/3 or 1/2] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Utpal Kumar Dey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LDPC and MIMO in Vehicular Communication 2 | This project demonstrates how Low Density Parity Check (LDPC) Code and Multiple Input Multiple Output (MIMO) can be employed in Vehicular Communication. The simulation flow of this project is expressed with the block diagram below. 3 | 4 | ![MIMO and LDPC Coding in DSRC](https://user-images.githubusercontent.com/3108754/150695696-ddeebfc1-2100-4c1a-8df5-d48aa4d753a4.JPG) 5 | 6 | The above figure depicts the structure of the DSRC PHY layer including LDPC and MIMO functionality. According to this figure data produced by the sending device is pushed to the PHY layer. The PHY layer prepares the data to be transmitted through the air medium. There are several steps in the PHY layer at the transmitter side which are FEC Coding, Signal Modulation, OFDM Modulation, and MIMO Transmitter. The FEC Coding portion converts the data bits into codeword bits using a specified coding scheme and coding rate. This project uses LDPC Coding shceme and two coding rates are available which are 1/3 and 1/2. Then the coded data is passed through the Signal Modulation portion where the codeword bits are modulated using a specified modulation technique. This project uses QPSK modulation technique. After that, the modulated data is passed through the OFDM Modulation step where modulated data symbols are prepared to combat against interference caused by multipath fading in the air medium. OFDM Modulation and Demodulation segments are configured based on IEEE 802.11p specifications. Then, the OFDM modulated data symbols are sent through the 10 MHz channel using MIMO. This project uses two MIMO configurations which are 2x2 (two transmitting antennas and two receiving antennas) configuration and 4x4 (four transmitting antennas and four receiving antennas) configuration. MIMO Receiver block uses Minimum Mean Squared Error (MMSE) equalization method. On the receiver side, similar demodulation and decoding techniques are applied to the received data to get the best approximation of the transmitted data. The simulation results are evaluated based on two metrics which are Bit Error Rate (BER) and Throughput. 7 | 8 | Associated files--> 9 | 10 | * Experimental_Simulation.m -> Runs the simulation as a complete package 11 | * System_Parameter.m -> Defines the simulation parameters 12 | * System_Initialize.m -> Initializes the simulation objects and necessary variables 13 | * LDPC_and_MIMOinDSRC -> Contains the simulations steps shown in the above figure 14 | * Pilot_Generator.m -> Generates pilot symbols 15 | * Ideal_Channel_Estimation.m -> Measures channel response for equalization purpose 16 | * MMSE_Equalize.m -> Contains implementation for MMSE equalization 17 | 18 | N.B.: If you take help from this project, please cite the following papers: 19 | * U. K. Dey, R. Akl, and R. Chataut, “Throughput Improvement in Vehicular Communication by Using Low Density Parity Check (LDPC),” in *The IEEE 12th Annual Computing and Communication Workshop and Conference (CCWC),* 2022. 20 | * U. K. Dey, R. Akl, and R. Chataut, “High Throughput Vehicular Communication Using Spatial Multiplexing MIMO,” in *2020 10th Annual Computing and Communication Workshop and Conference (CCWC), pp. 0110-0115,* 2020. 21 | -------------------------------------------------------------------------------- /Ideal_Channel_Estimation.m: -------------------------------------------------------------------------------- 1 | function channel_estimation_matrix = Ideal_Channel_Estimation(channel_estimation_parameter) 2 | 3 | %%% Initializing FFT object 4 | persistent dft; 5 | if isempty(dft) 6 | dft = dsp.FFT('FFTImplementation','FFTW'); 7 | end 8 | %%% Initializing FFT object 9 | 10 | %%% Getting the parameter values 11 | number_of_resource_block = channel_estimation_parameter.number_of_resource_block; 12 | number_of_data_subcarrier = channel_estimation_parameter.number_of_data_subcarrier; 13 | number_of_symbol = channel_estimation_parameter.number_of_symbol; 14 | number_of_transmit_antenna = channel_estimation_parameter.number_of_transmit_antenna; 15 | number_of_receive_antenna = channel_estimation_parameter.number_of_receive_antenna; 16 | fft_length = channel_estimation_parameter.fft_length; 17 | cyclic_prefix_length = channel_estimation_parameter.cyclic_prefix_length; 18 | path_delay = channel_estimation_parameter.path_delay; 19 | sampling_frequency = channel_estimation_parameter.sampling_frequency; 20 | channel_path_gain = channel_estimation_parameter.channel_path_gain; 21 | number_of_paths = channel_estimation_parameter.number_of_paths; 22 | data_subcarrier_indices = channel_estimation_parameter.data_subcarrier_indices; 23 | %%% Getting the parameter values 24 | 25 | slot_length = fft_length + cyclic_prefix_length; %% Defining the slot length 26 | 27 | sample_index = round(path_delay/(1/sampling_frequency)) + 1; %% Defining sample locations 28 | 29 | H = complex(zeros(number_of_resource_block * number_of_data_subcarrier, number_of_symbol, number_of_transmit_antenna, number_of_receive_antenna)); 30 | for i= 1:number_of_transmit_antenna 31 | for j = 1:number_of_receive_antenna 32 | link_path_gain = channel_path_gain(:, :, i, j); 33 | %%% Splitting the path gain per OFDM symbol 34 | g = complex(zeros(number_of_symbol, number_of_paths)); 35 | for m = 1:number_of_symbol 36 | index=(m-1)*slot_length + (1:slot_length); 37 | g(m, :) = mean(link_path_gain(index, :), 1); 38 | end 39 | hImp = complex(zeros(number_of_symbol, fft_length)); 40 | hImp(:, sample_index) = g; %% Setting path gains at sample locations 41 | 42 | %%% FFT processing 43 | h = dft(hImp.'); 44 | h2=fftshift(h,1); 45 | %%% FFT processing 46 | 47 | sc=h2(data_subcarrier_indices,:); %% Extracting the channel estimation values according to data subcarrier indices 48 | H(:,:,i,j) = sc; 49 | end 50 | end 51 | 52 | %%% Putting the channel estimation values in channel estimation matrix 53 | channel_estimation_matrix=complex(zeros(number_of_resource_block * number_of_data_subcarrier * number_of_symbol, number_of_transmit_antenna, number_of_receive_antenna)); 54 | for n=1:number_of_receive_antenna 55 | for m=1:number_of_transmit_antenna 56 | tmp=H(:,:,m,n); 57 | tmp = reshape(tmp, number_of_resource_block * number_of_data_subcarrier * number_of_symbol, 1); 58 | channel_estimation_matrix(:,m,n)=tmp; 59 | end 60 | end 61 | %%% Putting the channel estimation values in channel estimation matrix 62 | 63 | end -------------------------------------------------------------------------------- /Experimental_Simulation.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | 4 | %%%%%------------------------------1x1 MIMO-------------------------------%%%%%% 5 | System_Parameter; 6 | number_of_transmit_antenna = 1; 7 | number_of_receive_antenna = 1; 8 | equalizer_mode = 2; 9 | System_Initialize; 10 | fprintf('numTx: %d; numRx: %d; Doppler: %d; Equalizer: %d\n', number_of_transmit_antenna, ... 11 | number_of_receive_antenna, doppler_effect, equalizer_mode); 12 | 13 | LDPC_and_MIMOinDSRC; 14 | 15 | overall_throughput = ((number_of_bits_per_frame * (total_frame_count - total_error_frame_count)) / (1e-3 * total_frame_count))/1e6; 16 | fprintf('Throughput (SM) 1x1 with %4.4f LDPC Code = %4.4f \n', coding_rate, overall_throughput); 17 | fprintf('\n\n'); 18 | 19 | error_rate_1x1_ldpc = error_rate; 20 | throughput_1x1_ldpc = throughput; 21 | %%%%%------------------------------1x1 MIMO-------------------------------%%%%%% 22 | 23 | 24 | %%%%%------------------------------2x2 MIMO-------------------------------%%%%%% 25 | System_Parameter; 26 | number_of_transmit_antenna = 2; 27 | number_of_receive_antenna = 2; 28 | equalizer_mode = 2; 29 | System_Initialize; 30 | fprintf('numTx: %d; numRx: %d; Doppler: %d; Equalizer: %d\n', number_of_transmit_antenna, ... 31 | number_of_receive_antenna, doppler_effect, equalizer_mode); 32 | 33 | LDPC_and_MIMOinDSRC; 34 | 35 | overall_throughput = ((number_of_bits_per_frame * (total_frame_count - total_error_frame_count)) / (1e-3 * total_frame_count))/1e6; 36 | fprintf('Throughput (SM) 2x2 with %4.4f LDPC Code = %4.4f \n', coding_rate, overall_throughput); 37 | fprintf('\n\n'); 38 | 39 | error_rate_2x2_ldpc = error_rate; 40 | throughput_2x2_ldpc = throughput; 41 | %%%%%------------------------------2x2 MIMO-------------------------------%%%%%% 42 | 43 | 44 | %%%%%------------------------------4x4 MIMO-------------------------------%%%%%% 45 | System_Parameter; 46 | number_of_transmit_antenna = 4; 47 | number_of_receive_antenna = 4; 48 | equalizer_mode = 2; 49 | System_Initialize; 50 | fprintf('numTx: %d; numRx: %d; Doppler: %d; Equalizer: %d\n', number_of_transmit_antenna, ... 51 | number_of_receive_antenna, doppler_effect, equalizer_mode); 52 | 53 | LDPC_and_MIMOinDSRC; 54 | 55 | overall_throughput = ((number_of_bits_per_frame * (total_frame_count - total_error_frame_count)) / (1e-3 * total_frame_count))/1e6; 56 | fprintf('Throughput (SM) 4x4 with %4.4f LDPC Code = %4.4f \n', coding_rate, overall_throughput); 57 | fprintf('\n\n'); 58 | 59 | error_rate_4x4_ldpc = error_rate; 60 | throughput_4x4_ldpc = throughput; 61 | %%%%%------------------------------4x4 MIMO-------------------------------%%%%%% 62 | 63 | 64 | %%%%%%---------------------------Displaying Bit Error Rate---------------------------%%%%%% 65 | figure('Name','Bit Error Rate','NumberTitle','off','Position', ... 66 | [200, 80, 900, 550]); % Naming the figure and setting the position 67 | subplot(1,1,1); 68 | semilogy(EbNo, error_rate_1x1_ldpc, 'ko-', 'LineWidth', 2); 69 | hold on; 70 | semilogy(EbNo, error_rate_2x2_ldpc, 'ro-', 'LineWidth', 2); 71 | hold on; 72 | semilogy(EbNo, error_rate_4x4_ldpc, 'bo-', 'LineWidth', 2); 73 | hold off; 74 | grid on; 75 | xlabel('SNR (dB)'); 76 | ylabel('BER'); 77 | legend('Conventional DSRC', 'DSRC with 2x2 MIMO', 'DSRC with 4x4 MIMO'); 78 | %%%%%%---------------------------Displaying Bit Error Rate---------------------------%%%%%% 79 | 80 | 81 | %%%%%%-----------------------------Displaying Throughput------------------------------%%%%%% 82 | figure('Name','Throughput','NumberTitle','off','Position', ... 83 | [200, 80, 900, 550]); % Naming the figure and setting the position 84 | subplot(1,1,1); 85 | semilogy(EbNo, throughput_1x1_ldpc, 'ko-', 'LineWidth', 2); 86 | hold on; 87 | semilogy(EbNo, throughput_2x2_ldpc, 'ro-', 'LineWidth', 2); 88 | hold on; 89 | semilogy(EbNo, throughput_4x4_ldpc, 'bo-', 'LineWidth', 2); 90 | hold off; 91 | grid on; 92 | xlabel('SNR (dB)'); 93 | ylabel('Throughput'); 94 | legend('Conventional DSRC', 'DSRC with 2x2 MIMO', 'DSRC with 4x4 MIMO', 'Location','southeast'); 95 | %%%%%%-----------------------------Displaying Throughput------------------------------%%%%%% -------------------------------------------------------------------------------- /System_Initialize.m: -------------------------------------------------------------------------------- 1 | %%% Initializing the resource block parameters based on channel bandwidth 2 | if channel_bandwidth == 10e6 3 | subcarrier_spacing = 156.25e3; %% Initializing the subcarrier spacing in Hz 4 | symbol_duration = 1/subcarrier_spacing; %% Initializing symbol duration 5 | cyclic_prefix_duration = symbol_duration * 0.0703125; %% Initializing cyclic prefix duration 6 | number_of_symbol_per_subcarrier = floor((1 * 1000e-6) / (symbol_duration + cyclic_prefix_duration)); %% Initializing the number of symbols per subcarrier 7 | guard_bandwidth = 2.500e6; %% Initializing the guard bandwidth [20% of channel bandwidth] 8 | guard_interval = 1/guard_bandwidth; %% Initializing guard interval 9 | number_of_resource_block = (channel_bandwidth - guard_bandwidth) / (number_of_data_subcarrier * subcarrier_spacing); %% Initializing the number of resource block 10 | sampling_frequency = subcarrier_spacing * number_of_total_subcarrier * number_of_resource_block; %% Initializing sampling frequency 11 | fft_length = 64; %% Initializing FFT length 12 | cyclic_prefix_length = ceil(fft_length * 0.0703125); %% Initializing cyclic prefix length [7.03125% of fft length] 13 | guard_band = [floor(fft_length * 0.10); floor(fft_length * 0.10)]; %% Initializing guard band 14 | end 15 | %%% Initializing the resource block parameters based on channel bandwidth 16 | 17 | %%% Preparing data subcarrier indices and pilot subcarrier indices for multiple resource blocks in a frame 18 | margin = (fft_length - sum(guard_band) - (number_of_resource_block * number_of_total_subcarrier)) / 2; 19 | index = guard_band(1) + margin; 20 | for resource_block = 1:number_of_resource_block 21 | if resource_block == 1 22 | data_subcarrier_indices = data_subcarrier_indices_per_symbol + index; 23 | pilot_subcarrier_indices = pilot_subcarrier_indices_per_symbol + index; 24 | else 25 | data_subcarrier_indices = [data_subcarrier_indices, data_subcarrier_indices_per_symbol + index]; 26 | pilot_subcarrier_indices = [pilot_subcarrier_indices; pilot_subcarrier_indices_per_symbol + index]; 27 | end 28 | index = data_subcarrier_indices(end); 29 | end 30 | %%% Preparing data subcarrier indices and pilot subcarrier indices for multiple resource blocks in a frame 31 | 32 | %%% Initializing OFDM Modulator and Demodulator 33 | ofdm_mod = comm.OFDMModulator('FFTLength' , fft_length, 'NumGuardBandCarriers', guard_band, ... 34 | 'PilotInputPort', true, 'PilotCarrierIndices', pilot_subcarrier_indices, ... 35 | 'CyclicPrefixLength', cyclic_prefix_length, 'NumSymbols', number_of_symbol_per_subcarrier,... 36 | 'NumTransmitAntennas', number_of_transmit_antenna); 37 | 38 | ofdm_demod = comm.OFDMDemodulator('FFTLength' , fft_length, 'NumGuardBandCarriers', guard_band, ... 39 | 'PilotOutputPort', true, 'PilotCarrierIndices', pilot_subcarrier_indices, ... 40 | 'CyclicPrefixLength', cyclic_prefix_length, 'NumSymbols', number_of_symbol_per_subcarrier, ... 41 | 'NumReceiveAntennas', number_of_receive_antenna); 42 | %%% Initializing OFDM Modulator and Demodulator 43 | 44 | %%% Initializing modulation parameters 45 | if modulation_type == 1 %% Initializing modulation parameters for QPSK modulation 46 | number_of_bits_per_symbol = 2; 47 | modulator = comm.PSKModulator('ModulationOrder', 4, 'BitInput', true,... 48 | 'PhaseOffset', pi/4, 'SymbolMapping', 'Custom', 'CustomSymbolMapping', [0 2 3 1]); 49 | demodulator_hard = comm.PSKDemodulator('ModulationOrder', 4, 'BitOutput',true, ... 50 | 'PhaseOffset', pi/4, 'SymbolMapping', 'Custom', 'CustomSymbolMapping', [0 2 3 1], ... 51 | 'DecisionMethod','Hard decision'); 52 | demodulator_soft = comm.PSKDemodulator('ModulationOrder', 4, 'BitOutput',true, ... 53 | 'PhaseOffset', pi/4, 'SymbolMapping', 'Custom', 'CustomSymbolMapping', [0 2 3 1], ... 54 | 'DecisionMethod','Log-likelihood ratio'); 55 | end 56 | %%% Initializing modulation parameters 57 | 58 | %%% Initializing Channel Models 59 | delay_spread = cyclic_prefix_length - 1; %% Initializing delay spread in the channel 60 | number_of_paths= 5; %% Initializing number of paths for fading 61 | path_delay = floor(linspace(0, delay_spread, number_of_paths))*(1/sampling_frequency); %% Initializing path delay for each path 62 | path_gain = zeros(size(path_delay)); 63 | for i=2:number_of_paths 64 | path_gain(i) = path_gain(i - 1) - abs(randn); %% Initializing path gain for each path 65 | end 66 | 67 | mimo_fading_channel = comm.MIMOChannel('SampleRate', sampling_frequency, 'MaximumDopplerShift', doppler_effect, ... 68 | 'PathDelays', path_delay, 'AveragePathGains', path_gain,... 69 | 'TransmitCorrelationMatrix', eye(number_of_transmit_antenna),... 70 | 'ReceiveCorrelationMatrix', eye(number_of_receive_antenna),... 71 | 'PathGainsOutputPort', true, 'NormalizePathGains', true, 'NormalizeChannelOutputs', true); 72 | 73 | awgn_channel = comm.AWGNChannel('NoiseMethod', 'Variance', 'VarianceSource', 'Input port'); 74 | %%% Initializing Channel Models 75 | 76 | %%% Initializing encoder and decoder based on coding rate 77 | ldpc_encoder = comm.LDPCEncoder(dvbs2ldpc(coding_rate)); 78 | ldpc_decoder = comm.LDPCDecoder(dvbs2ldpc(coding_rate)); 79 | ldpc_config = ldpcEncoderConfig(dvbs2ldpc(coding_rate)); 80 | ldpc_num_bits = ldpc_config.NumInformationBits; 81 | %%% Initializing encoder and decoder based on coding rate 82 | 83 | %%% Initializing parameters for 24 bit Cyclic Redundancy Check (CRC) error detection 84 | crc_24_generator = comm.CRCGenerator('Polynomial',[1 1 zeros(1, 16) 1 1 0 0 0 1 1]); 85 | crc_bit = 24; 86 | crc_24_detector = comm.CRCDetector('Polynomial',[1 1 zeros(1, 16) 1 1 0 0 0 1 1]); 87 | %%% Initializing parameters for 24 bit Cyclic Redundancy Check (CRC) error detection 88 | 89 | 90 | number_of_bits_per_frame = (((number_of_resource_block * number_of_data_subcarrier * number_of_symbol_per_subcarrier * number_of_bits_per_symbol * number_of_transmit_antenna)) ... 91 | * coding_rate) - crc_bit; %% Initializing number of bits per frame 92 | -------------------------------------------------------------------------------- /LDPC_and_MIMOinDSRC.m: -------------------------------------------------------------------------------- 1 | error_rate = zeros(1, length(EbNo)); %% Declaring variable to store BER for each SNR value 2 | throughput = zeros(1, length(EbNo)); %% Declaring variable to store cummulative Throughput for each SNR value 3 | 4 | total_frame_count = 0; %% Declaring variable to count total number of transferred frames 5 | total_error_frame_count = 0; %% Declaring variable to count total number of transferred frame which contains error 6 | 7 | for ebno = 1:length(EbNo) %% Running loop to run simulation for each SNR value 8 | 9 | snr_dB = EbNo(ebno); %% Getting one SNR value in each iteration 10 | 11 | error_rate_calculator = comm.ErrorRate; %%% Declaring object to calculate BER for each SNR value 12 | 13 | number_of_bits = 0; 14 | 15 | while number_of_bits < maximum_number_of_bits %%% Running loop to process one frame in each iteration 16 | 17 | raw_data = logical(randi([0 1], number_of_bits_per_frame, 1)); %% Generating random data bits 18 | 19 | crc_coded_data = step(crc_24_generator, raw_data); %% Adding CRC bits for error checking 20 | 21 | ldpc_extra_bits = ldpc_num_bits - length(crc_coded_data); 22 | 23 | ldpc_data = [crc_coded_data; logical(randi([0 1], ldpc_extra_bits, 1))]; 24 | 25 | ldpc_encoded_data = ldpc_encoder(ldpc_data); 26 | 27 | modulated_data = modulator(ldpc_encoded_data); %% Modulating the encoded data bits 28 | 29 | modulated_data_length = length(modulated_data); 30 | block_length = number_of_resource_block * number_of_data_subcarrier * number_of_symbol_per_subcarrier * number_of_transmit_antenna; 31 | number_of_turn = ceil(modulated_data_length / block_length); 32 | modulated_data = [modulated_data; complex(zeros(((block_length * number_of_turn) - modulated_data_length), 1))]; 33 | 34 | reshaped_equalized_data = []; 35 | for turn = 1:number_of_turn 36 | reshaped_modulated_data = reshape(modulated_data((((turn - 1) * block_length) + 1):(turn * block_length), 1), number_of_resource_block * number_of_data_subcarrier, number_of_symbol_per_subcarrier, number_of_transmit_antenna); 37 | reshaped_modulated_data = [complex(zeros(margin, number_of_symbol_per_subcarrier, number_of_transmit_antenna)); reshaped_modulated_data; complex(zeros(margin, number_of_symbol_per_subcarrier, number_of_transmit_antenna))]; 38 | 39 | %%% Generating pilot symbols 40 | for resource_block = 1:number_of_resource_block 41 | if resource_block == 1 42 | pilot_data = Pilot_Generator(number_of_symbol_per_subcarrier,number_of_transmit_antenna); 43 | else 44 | pilot_data = [pilot_data; Pilot_Generator(number_of_symbol_per_subcarrier,number_of_transmit_antenna)]; 45 | end 46 | end 47 | %%% Generating pilot symbols 48 | 49 | ofdm_modulated_data = ofdm_mod(reshaped_modulated_data, pilot_data); %% OFDM modulation 50 | 51 | [faded_data, channel_path_gain] = mimo_fading_channel(ofdm_modulated_data); %% Adding fading effect on the data symbols 52 | 53 | transmitted_data = faded_data; 54 | 55 | signal_power = 10*log10(var(transmitted_data)); %% Calculating signal power 56 | noise_variance = (10.^(0.1.*(signal_power - snr_dB))) * noise_factor; %% Calculating noise variance 57 | 58 | recevied_data = awgn_channel(transmitted_data, noise_variance); %% Passing the transmitted data symbols through AWGN channel 59 | 60 | %%% OFDM Demodulation 61 | ofdm_demodulated_data = ofdm_demod(recevied_data); 62 | [len, ~, ~] = size(ofdm_demodulated_data); 63 | ofdm_demodulated_data = ofdm_demodulated_data((margin + 1):(len - margin), :, :); 64 | %%% OFDM Demodulation 65 | 66 | %%% Initializing channel estimation parameter 67 | channel_estimation_parameter.number_of_resource_block = number_of_resource_block; 68 | channel_estimation_parameter.number_of_data_subcarrier = number_of_data_subcarrier; 69 | channel_estimation_parameter.number_of_symbol = number_of_symbol_per_subcarrier; 70 | channel_estimation_parameter.number_of_transmit_antenna = number_of_transmit_antenna; 71 | channel_estimation_parameter.number_of_receive_antenna = number_of_receive_antenna; 72 | channel_estimation_parameter.fft_length = fft_length; 73 | channel_estimation_parameter.cyclic_prefix_length = cyclic_prefix_length; 74 | channel_estimation_parameter.path_delay = path_delay; 75 | channel_estimation_parameter.sampling_frequency = sampling_frequency; 76 | channel_estimation_parameter.channel_path_gain = channel_path_gain; 77 | channel_estimation_parameter.number_of_paths = number_of_paths; 78 | channel_estimation_parameter.data_subcarrier_indices = data_subcarrier_indices; 79 | %%% Initializing channel estimation parameter 80 | 81 | channel_estimation_matrix = Ideal_Channel_Estimation(channel_estimation_parameter); %% Getting channel estimation matrix 82 | 83 | %%% Preparing the ofdm demodulated data symbols for equalization purpose 84 | processed_ofdm_demodulated_data = complex(zeros(number_of_resource_block * number_of_data_subcarrier * number_of_symbol_per_subcarrier, number_of_receive_antenna)); 85 | for i=1:number_of_receive_antenna 86 | tmp = ofdm_demodulated_data(:, :, i); 87 | tmp = reshape(tmp, number_of_resource_block * number_of_data_subcarrier * number_of_symbol_per_subcarrier, 1); 88 | processed_ofdm_demodulated_data(:, i) = tmp; 89 | end 90 | %%% Preparing the ofdm demodulated data symbols for equalization purpose 91 | 92 | 93 | equalized_data = MMSE_Equalize(processed_ofdm_demodulated_data, channel_estimation_matrix, noise_variance); 94 | 95 | reshaped_equalized_data = [reshaped_equalized_data; equalized_data(:)]; 96 | end 97 | 98 | reshaped_equalized_data = reshaped_equalized_data(1:modulated_data_length, 1); %% Collapsing OFDM demodulated data symbols 99 | 100 | demodulated_data = demodulator_soft(reshaped_equalized_data); %% Demodulating 101 | 102 | ldpc_decoded_data = ldpc_decoder(demodulated_data); %% Decoding the data bits using convolutional decoder 103 | 104 | ldpc_useful_data = ldpc_decoded_data(1:length(crc_coded_data), 1); %% Filtering the decoded data bits 105 | 106 | [crc_decoded_data, frame_error] = step(crc_24_detector, ldpc_useful_data); %% Detecting frame error using CRC detector 107 | 108 | %%% Counting error frames as well as total frames 109 | if frame_error == 1 110 | total_error_frame_count = total_error_frame_count + 1; 111 | end 112 | total_frame_count = total_frame_count + 1; 113 | %%% Counting error frames as well as total frames 114 | 115 | measured_error_rate = error_rate_calculator(raw_data, crc_decoded_data); %% Calculating error rate 116 | 117 | error_rate(ebno) = measured_error_rate(1); %% Storing BER for each SNR value 118 | 119 | number_of_bits = measured_error_rate(3); %% Counting number of bits transmitted per SNR value 120 | 121 | end 122 | 123 | throughput(ebno) = ((number_of_bits_per_frame * (total_frame_count - total_error_frame_count)) / (1e-3 * total_frame_count))/1e6; %% Calculating Throughput 124 | 125 | end --------------------------------------------------------------------------------