├── 802_11a_vmodel ├── bench │ └── top.v ├── sim │ └── rtl.f └── ofdm_rtl │ ├── receiver │ └── data_descramble.v │ └── transmitter │ ├── conv_code.v │ └── data_scramble.v ├── 802_11a_mmodel ├── ui_start.fig ├── ui_start.mat ├── tx_conv_encoder.m ├── ui_check_params.m ├── ui_read_options.m ├── ui_start_sim.m ├── rx_bpsk_demod.m ├── tx_diversity.m ├── get_n_antennas.m ├── rx_mr_combiner.m ├── rx_qpsk_demod.m ├── readme.md ├── get_bits_per_symbol.m ├── tx_add_cyclic_prefix.m ├── create_freq_offset.m ├── rx_gen_deintlvr_patt.m ├── rx_gen_chan_amps.m ├── rx_qam16_demod.m ├── tx_gen_intlvr_patt.m ├── get_punc_params.m ├── rx_deinterleave.m ├── tx_make_int_num_ofdm_syms.m ├── rx_phase_tracker.m ├── rx_demodulate.m ├── rx_radon_hurwitz.m ├── tx_add_pilot_syms.m ├── tx_freqd_to_timed.m ├── tx_puncture.m ├── tx_interleaver.m ├── rx_init_viterbi.m ├── single_packet.m ├── tx_radon_hurwitz.m ├── rx_depuncture.m ├── get_channel_ir.m ├── phase_noise_model.m ├── rx_estimate_channel.m ├── set_sim_consts.m ├── rx_frequency_sync.m ├── channel.m ├── rx_fine_time_sync.m ├── rx_viterbi_decode.m ├── rx_qam64_demod.m ├── tx_gen_preamble.m ├── rx_find_packet_edge.m ├── rx_timed_to_freqd.m ├── tx_modulate.m ├── rx_diversity_proc.m ├── receiver.m ├── runsim.m ├── transmitter.m ├── rx_pilot_phase_est.m ├── tx_power_amplifier.m ├── main.m └── ui_start.m └── README.md /802_11a_vmodel/bench/top.v: -------------------------------------------------------------------------------- 1 | 'timescale 1ns/1ps 2 | 3 | `define BT_TEST 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /802_11a_mmodel/ui_start.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhao127jl/ofdm_ieee80211a/HEAD/802_11a_mmodel/ui_start.fig -------------------------------------------------------------------------------- /802_11a_mmodel/ui_start.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhao127jl/ofdm_ieee80211a/HEAD/802_11a_mmodel/ui_start.mat -------------------------------------------------------------------------------- /802_11a_mmodel/tx_conv_encoder.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhao127jl/ofdm_ieee80211a/HEAD/802_11a_mmodel/tx_conv_encoder.m -------------------------------------------------------------------------------- /802_11a_mmodel/ui_check_params.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhao127jl/ofdm_ieee80211a/HEAD/802_11a_mmodel/ui_check_params.m -------------------------------------------------------------------------------- /802_11a_mmodel/ui_read_options.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhao127jl/ofdm_ieee80211a/HEAD/802_11a_mmodel/ui_read_options.m -------------------------------------------------------------------------------- /802_11a_mmodel/ui_start_sim.m: -------------------------------------------------------------------------------- 1 | function ui_run_sim 2 | 3 | sim_options = ui_read_options; 4 | feval('runsim', sim_options); 5 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_bpsk_demod.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function soft_bits = rx_bpsk_demod(rx_symbols) 4 | 5 | soft_bits = real(rx_symbols); 6 | 7 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_diversity.m: -------------------------------------------------------------------------------- 1 | function div_ofdm_syms = tx_diversity(ofdm_symbols, sim_options) 2 | 3 | if sim_options.UseTxDiv 4 | % Radon-Hurwitz or Alamouti tx diversity 5 | div_ofdm_syms = tx_radon_hurwitz(ofdm_symbols); 6 | else 7 | % No diversity 8 | div_ofdm_syms = ofdm_symbols; 9 | end 10 | 11 | -------------------------------------------------------------------------------- /802_11a_mmodel/get_n_antennas.m: -------------------------------------------------------------------------------- 1 | function [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options) 2 | 3 | if sim_options.UseTxDiv 4 | n_tx_antennas = 2; 5 | else 6 | n_tx_antennas = 1; 7 | end 8 | 9 | 10 | if sim_options.UseRxDiv 11 | n_rx_antennas = 2; 12 | else 13 | n_rx_antennas = 1; 14 | end 15 | 16 | 17 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_mr_combiner.m: -------------------------------------------------------------------------------- 1 | function comb_syms = rx_mr_combiner(rx_syms, channel_est, sim_options) 2 | 3 | n_ofdm_syms = size(squeeze(rx_syms(1,:,:)),2); 4 | 5 | comb_syms = repmat(conj(channel_est(:,1)), 1, n_ofdm_syms).*squeeze(rx_syms(1,:,:)) + ... 6 | repmat(conj(channel_est(:,2)), 1, n_ofdm_syms).*squeeze(rx_syms(2,:,:)); 7 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_qpsk_demod.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function soft_bits = rx_qpsk_demod(rx_symbols) 4 | 5 | soft_bits = zeros(2*size(rx_symbols,1),size(rx_symbols,2)); 6 | 7 | bit0 = real(rx_symbols); 8 | bit1 = imag(rx_symbols); 9 | 10 | soft_bits(1:2:size(soft_bits, 1),:) = bit0; 11 | soft_bits(2:2:size(soft_bits, 1),:) = bit1; 12 | 13 | -------------------------------------------------------------------------------- /802_11a_vmodel/sim/rtl.f: -------------------------------------------------------------------------------- 1 | 2 | ../bench/top.v 3 | 4 | ../ofdm_rtl/transmitter/data_scramble.v 5 | ../ofdm_rtl/transmitter/conv_code.v 6 | ../ofdm_rtl/transmitter/long_training.v 7 | 8 | ../ofdm_rtl/receiver/ 9 | ../ofdm_rtl/receiver/data_descramble.v 10 | ../ofdm_rtl/receiver/data_descramble.v 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /802_11a_vmodel/ofdm_rtl/receiver/data_descramble.v: -------------------------------------------------------------------------------- 1 | //************************************************************************** 2 | // Project : OFDM 3 | // Module : data_descramble.v 4 | // Description : 5 | // Designer : 6 | // Version : 7 | //*************************************************************************** 8 | -------------------------------------------------------------------------------- /802_11a_mmodel/readme.md: -------------------------------------------------------------------------------- 1 | 2 | #### Description 3 | The simulator GUI is started with command 'ui_start' in Matlab command window. 4 | 5 | WLAN simulation starts by clicking the 'Start Simulation' button in the GUI window. 6 | 7 | WLAN simulation can be terminated, before set number of packets have been reached by pressing 'control-C'. 8 | 9 | #### Version updates and bug fixes 10 | January 24th 2002: A bug in file rx_qpsk_demod.m fixed 11 | 12 | -------------------------------------------------------------------------------- /802_11a_mmodel/get_bits_per_symbol.m: -------------------------------------------------------------------------------- 1 | function num_bits = get_bits_per_symbol(mod_order) 2 | 3 | if ~isempty(strmatch(mod_order, 'BPSK ','exact')) 4 | num_bits=1; 5 | elseif ~isempty(strmatch(mod_order, 'QPSK ','exact')) 6 | num_bits=2; 7 | elseif ~isempty(strmatch(mod_order, '16QAM','exact')) 8 | num_bits=4; 9 | elseif ~isempty(strmatch(mod_order, '64QAM','exact')) 10 | num_bits=6; 11 | else 12 | error('Undefined modulation'); 13 | end 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## OFDM_IEEE802_11a - Physical Layer 2 | ### Reference material: the protocal IEEE 802.11a. 3 | 4 | The system of OFDM baseband process include: 5 | 6 | 1. 80211a transmitter: 7 | (1) scramble 8 | (2) convolution code 9 | (3) signal interleaver 10 | (4) constellation mapping 11 | (5) pilot insert 12 | (6) IFFT 13 | (7) cyclic prefix 14 | (8) windowing 15 | 16 | 2. 80211a receiver: 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_add_cyclic_prefix.m: -------------------------------------------------------------------------------- 1 | function time_signal = tx_add_cyclic_prefix(time_syms) 2 | 3 | num_symbols = size(time_syms, 2)/64; 4 | n_antennas = size(time_syms, 1); 5 | time_signal = zeros(n_antennas, num_symbols*80); 6 | 7 | % Add cyclic prefix for each antenna's signal 8 | for antenna = 1:n_antennas 9 | symbols = reshape(time_syms(antenna,:), 64, num_symbols); 10 | tmp_syms = [symbols(49:64,:); symbols]; 11 | time_signal(antenna,:) = tmp_syms(:).'; 12 | end 13 | 14 | 15 | -------------------------------------------------------------------------------- /802_11a_mmodel/create_freq_offset.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function offset_sig = create_freq_offset(input_signal, freq_offset); 4 | 5 | global sim_consts; 6 | 7 | n_signals = size(input_signal,1); 8 | 9 | % create a timebase 10 | time_base = (0:(length(input_signal)-1))/sim_consts.SampFreq; 11 | 12 | % create phase_rotation vector 13 | phase_rotation = repmat(exp(j*2*pi*freq_offset*time_base), n_signals, 1); 14 | 15 | % and apply it to the signal; 16 | offset_sig = input_signal.*phase_rotation; 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_gen_deintlvr_patt.m: -------------------------------------------------------------------------------- 1 | 2 | function idx = rx_gen_deintlvr_patt(interleaver_depth) 3 | 4 | global sim_consts; 5 | 6 | idx = zeros(1, interleaver_depth); 7 | s = max([interleaver_depth/sim_consts.NumDataSubc/2 1]); 8 | 9 | perm_patt = s*floor((0:interleaver_depth-1)/s)+ ... 10 | mod((0:interleaver_depth-1)+floor(16*(0:interleaver_depth-1)/interleaver_depth),s); 11 | 12 | deintlvr_patt = 16*perm_patt - (interleaver_depth-1)*floor(16*perm_patt/interleaver_depth); 13 | 14 | idx = deintlvr_patt + 1; 15 | 16 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_gen_chan_amps.m: -------------------------------------------------------------------------------- 1 | % Channel amplitudes corresponding to bits for Viterbi decoding 2 | 3 | function channel_amps = rx_gen_chan_amps(data_len, channel_est, sim_options) 4 | 5 | global sim_consts; 6 | 7 | bits_per_subc = get_bits_per_symbol(sim_options.Modulation); 8 | amps_mat = repmat(sum(abs(channel_est(sim_consts.DataSubcPatt, :)).^2, 2), bits_per_subc, 1); 9 | amps_mat = amps_mat(:)'; 10 | amps_mat = repmat(amps_mat, 1, ceil(data_len/length(amps_mat))); 11 | channel_amps = amps_mat(1:data_len); 12 | 13 | 14 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_qam16_demod.m: -------------------------------------------------------------------------------- 1 | % 2 | function soft_bits = rx_qam16_demod(rx_symbols) 3 | 4 | soft_bits = zeros(4*size(rx_symbols,1), size(rx_symbols,2)); % Each symbol consists of 4 bits 5 | 6 | bit0 = real(rx_symbols); 7 | bit2 = imag(rx_symbols); 8 | 9 | bit1 = 2/sqrt(10)-(abs(real(rx_symbols))); 10 | bit3 = 2/sqrt(10)-(abs(imag(rx_symbols))); 11 | 12 | soft_bits(1:4:size(soft_bits,1),:) = bit0; 13 | soft_bits(2:4:size(soft_bits,1),:) = bit1; 14 | soft_bits(3:4:size(soft_bits,1),:) = bit2; 15 | soft_bits(4:4:size(soft_bits,1),:) = bit3; 16 | 17 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_gen_intlvr_patt.m: -------------------------------------------------------------------------------- 1 | 2 | function idx = tx_gen_intlvr_patt(interleaver_depth, sim_options) 3 | 4 | global sim_consts; 5 | 6 | n_syms_per_ofdm_sym = sim_consts.NumDataSubc; 7 | idx=zeros(1,interleaver_depth); 8 | 9 | s = max([interleaver_depth/n_syms_per_ofdm_sym/2 1]); 10 | 11 | intlvr_patt = interleaver_depth/16*rem(0:interleaver_depth-1,16) + floor((0:interleaver_depth-1)/16); 12 | 13 | perm_patt = s*floor(intlvr_patt/s)+ ... 14 | mod(intlvr_patt+interleaver_depth-floor(16*intlvr_patt/interleaver_depth),s); 15 | 16 | idx = perm_patt+1; 17 | 18 | -------------------------------------------------------------------------------- /802_11a_mmodel/get_punc_params.m: -------------------------------------------------------------------------------- 1 | function [punc_patt, punc_patt_size] = get_punc_params(code_rate) 2 | 3 | if strcmp(code_rate,'R3/4') 4 | % R=3/4, Puncture pattern: [1 2 3 x x 6], x = punctured 5 | punc_patt=[1 2 3 6]; 6 | punc_patt_size = 6; 7 | elseif strcmp(code_rate, 'R2/3') 8 | % R=2/3, Puncture pattern: [1 2 3 x], x = punctured 9 | punc_patt=[1 2 3]; 10 | punc_patt_size = 4; 11 | elseif strcmp(code_rate, 'R1/2') 12 | % R=1/2, Puncture pattern: [1 2 3 4 5 6], x = punctured 13 | punc_patt=[1 2 3 4 5 6]; 14 | punc_patt_size = 6; 15 | else 16 | error('Undefined convolutional code rate'); 17 | end 18 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_deinterleave.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function out_bits = rx_deinterleave(in_bits, sim_options) 4 | 5 | global sim_consts; 6 | 7 | interleaver_depth = sim_consts.NumDataSubc * get_bits_per_symbol(sim_options.Modulation); 8 | num_symbols = length(in_bits)/interleaver_depth; 9 | 10 | single_deintlvr_patt = rx_gen_deintlvr_patt(interleaver_depth); 11 | 12 | deintlvr_patt = interleaver_depth*ones(interleaver_depth, num_symbols); 13 | deintlvr_patt = deintlvr_patt*diag(0:num_symbols-1); 14 | deintlvr_patt = deintlvr_patt+repmat(single_deintlvr_patt', 1, num_symbols); 15 | deintlvr_patt = deintlvr_patt(:); 16 | 17 | out_bits(deintlvr_patt) = in_bits; 18 | 19 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_make_int_num_ofdm_syms.m: -------------------------------------------------------------------------------- 1 | function out_bits = tx_make_int_num_ofdm_syms(tx_bits, sim_options) 2 | 3 | global sim_consts; 4 | 5 | n_tx_bits = length(tx_bits); 6 | 7 | n_syms = sim_consts.NumDataSubc; 8 | n_bits_per_sym = get_bits_per_symbol(sim_options.Modulation); 9 | n_ofdm_syms = ceil(n_tx_bits/(n_syms*n_bits_per_sym)); 10 | 11 | % if Radon Hurwitz transform is used we need an even number of OFDM symbols 12 | if sim_options.UseTxDiv 13 | if rem(n_ofdm_syms,2) ~= 0 14 | n_ofdm_syms = n_ofdm_syms + 1; 15 | end 16 | end 17 | 18 | pad_bits = randn(1, n_ofdm_syms*n_syms*n_bits_per_sym - n_tx_bits) > 0; 19 | out_bits = [tx_bits pad_bits]; 20 | 21 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_phase_tracker.m: -------------------------------------------------------------------------------- 1 | 2 | function corrected_syms = rx_phase_tracker(freq_data_syms, freq_pilot_syms, channel_est, sim_options); 3 | 4 | global sim_consts; 5 | 6 | num_symbols = size(freq_data_syms,2); 7 | corrected_syms = zeros(sim_consts.NumDataSubc, num_symbols); 8 | 9 | if sim_options.PilotPhaseTracking 10 | % estimate the phase change using the pilots 11 | correction_phases = rx_pilot_phase_est(freq_pilot_syms, channel_est, sim_options); 12 | 13 | % correct symbol using the phase estimate of this one OFDM symbol, 14 | corrected_syms = exp(-j*correction_phases).*freq_data_syms; 15 | else 16 | corrected_syms = freq_data_syms; 17 | end 18 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_demodulate.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function [soft_bits_out] = rx_demodulate(rx_symbols, sim_options) 4 | 5 | 6 | % We make 'soft' bit estimation for viterbi. 7 | if ~isempty(findstr(sim_options.Modulation, 'BPSK')) 8 | soft_bits = rx_bpsk_demod(rx_symbols); 9 | elseif ~isempty(findstr(sim_options.Modulation, 'QPSK')) 10 | soft_bits = rx_qpsk_demod(rx_symbols); 11 | elseif ~isempty(findstr(sim_options.Modulation, '16QAM')) 12 | soft_bits = rx_qam16_demod(rx_symbols); 13 | elseif ~isempty(findstr(sim_options.Modulation, '64QAM')) 14 | soft_bits = rx_qam64_demod(rx_symbols); 15 | else 16 | error('Undefined modulation'); 17 | end 18 | 19 | soft_bits_out = soft_bits(:)'; 20 | 21 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_radon_hurwitz.m: -------------------------------------------------------------------------------- 1 | function decoupled_syms = rx_radon_hurwitz(rh_syms, channel_est) 2 | 3 | n_syms = size(rh_syms,2); 4 | 5 | % remove the possible extra symbol 6 | if rem(n_syms,2) ~= 0 7 | rh_syms(:,n_syms) = []; 8 | n_syms = n_syms - 1; 9 | end 10 | 11 | decoupled_syms = zeros(size(rh_syms)); 12 | 13 | decoupled_syms(:,1:2:n_syms) = repmat(conj(channel_est(:,1)),1, n_syms/2).*rh_syms(:,1:2:n_syms) + ... 14 | repmat(channel_est(:,2),1,n_syms/2).*conj(rh_syms(:,2:2:n_syms)); 15 | 16 | decoupled_syms(:,2:2:n_syms) = repmat(conj(channel_est(:,2)),1, n_syms/2).*rh_syms(:,1:2:n_syms) - ... 17 | repmat(channel_est(:,1),1,n_syms/2).*conj(rh_syms(:,2:2:n_syms)); 18 | 19 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_add_pilot_syms.m: -------------------------------------------------------------------------------- 1 | function mod_ofdm_syms = tx_add_pilot_syms(mod_syms, sim_options) 2 | 3 | global sim_consts; 4 | 5 | n_mod_syms = size(mod_syms,2); 6 | n_ofdm_syms = n_mod_syms/sim_consts.NumDataSubc; 7 | 8 | %pilot scrambling pattern 9 | scramble_patt = repmat(sim_consts.PilotScramble,1,ceil(n_ofdm_syms/length(sim_consts.PilotScramble))); 10 | scramble_patt = scramble_patt(1:n_ofdm_syms); 11 | 12 | mod_ofdm_syms = zeros(sim_consts.NumSubc, n_ofdm_syms); 13 | mod_ofdm_syms(sim_consts.DataSubcPatt,:) = reshape(mod_syms, sim_consts.NumDataSubc, n_ofdm_syms); 14 | 15 | mod_ofdm_syms(sim_consts.PilotSubcPatt,:) = repmat(scramble_patt, sim_consts.NumPilotSubc,1).* ... 16 | repmat(sim_consts.PilotSubcSymbols, 1, n_ofdm_syms); 17 | 18 | mod_ofdm_syms = mod_ofdm_syms(:).'; 19 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_freqd_to_timed.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function time_syms = tx_freqd_to_timed(mod_ofdm_syms) 4 | 5 | global sim_consts; 6 | 7 | num_symbols = size(mod_ofdm_syms, 2)/sim_consts.NumSubc; 8 | n_antennas = size(mod_ofdm_syms, 1); 9 | 10 | resample_patt=[33:64 1:32]; 11 | time_syms = zeros(n_antennas, num_symbols*64); 12 | 13 | % Convert each antenna's signal to time domain 14 | for antenna = 1:n_antennas 15 | syms_into_ifft = zeros(64, num_symbols); 16 | syms_into_ifft(sim_consts.UsedSubcIdx,:) = reshape(mod_ofdm_syms(antenna,:), ... 17 | sim_consts.NumSubc, num_symbols); 18 | 19 | syms_into_ifft(resample_patt,:) = syms_into_ifft; 20 | 21 | % Convert to time domain 22 | ifft_out = ifft(syms_into_ifft); 23 | time_syms(antenna,:) = ifft_out(:).'; 24 | end 25 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_puncture.m: -------------------------------------------------------------------------------- 1 | % puncturing 2 | 3 | function punctured_bits = tx_puncture(in_bits, code_rate) 4 | 5 | [punc_patt, punc_patt_size] = get_punc_params(code_rate); 6 | 7 | % Remainder bits are the bits in the end of the packet that are not integer multiple of the puncture window size 8 | num_rem_bits = rem(length(in_bits), punc_patt_size); 9 | 10 | puncture_table = reshape(in_bits(1:length(in_bits)-num_rem_bits), punc_patt_size, fix(length(in_bits)/punc_patt_size)); 11 | tx_table = puncture_table(punc_patt,:); 12 | 13 | %puncture the remainder bits 14 | rem_bits = in_bits(length(in_bits)-num_rem_bits+1:length(in_bits)); 15 | rem_punc_patt = find(punc_patt<=num_rem_bits); 16 | rem_punc_bits = rem_bits(rem_punc_patt)'; 17 | 18 | punctured_bits = [tx_table(:)' rem_punc_bits]; 19 | 20 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_interleaver.m: -------------------------------------------------------------------------------- 1 | % Interleaver 2 | 3 | function interleaved_bits = tx_interleaver(in_bits, sim_options) 4 | 5 | global sim_consts; 6 | 7 | interleaver_depth = sim_consts.NumDataSubc * get_bits_per_symbol(sim_options.Modulation); 8 | 9 | num_symbols = length(in_bits)/interleaver_depth; 10 | 11 | % Get interleaver pattern for symbols 12 | single_intlvr_patt = tx_gen_intlvr_patt(interleaver_depth, sim_options); 13 | 14 | % Generate intereleaver pattern for the whole packet 15 | intlvr_patt = interleaver_depth*ones(interleaver_depth, num_symbols); 16 | intlvr_patt = intlvr_patt*diag(0:num_symbols-1); 17 | intlvr_patt = intlvr_patt+repmat(single_intlvr_patt', 1, num_symbols); 18 | intlvr_patt = intlvr_patt(:); 19 | 20 | % Perform interleaving 21 | interleaved_bits(intlvr_patt) = in_bits; 22 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_init_viterbi.m: -------------------------------------------------------------------------------- 1 | function rx_init_viterbi 2 | 3 | global sim_consts; 4 | 5 | global prev_state; 6 | global prev_state_outbits; 7 | 8 | prev_state = zeros(64, 2); 9 | prev_state_outbits = zeros(64, 2, 2); 10 | 11 | for state = 0:63 12 | state_bits = de2bi(state, 6); 13 | input_bit = state_bits(1); 14 | for transition = 0:1 15 | prev_state_bits = [state_bits(2:6) transition]; 16 | prev_state(state+1, transition+1) = bi2de(prev_state_bits); 17 | 18 | prev_state_outbits(state+1, transition+1, 1) = 2*(rem(sum(sim_consts.ConvCodeGenPoly(1,:).* ... 19 | [input_bit prev_state_bits]),2)) - 1; 20 | prev_state_outbits(state+1, transition+1, 2) = 2*(rem(sum(sim_consts.ConvCodeGenPoly(2,:).* ... 21 | [input_bit prev_state_bits]),2)) - 1; 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /802_11a_mmodel/single_packet.m: -------------------------------------------------------------------------------- 1 | 2 | function [inf_bits_cnt, inf_bit_errs, raw_bits_cnt, raw_bit_errs] = single_packet(sim_options) 3 | 4 | % Generate channel impulse response 5 | cir = get_channel_ir(sim_options); 6 | 7 | % Generate tx signal, returns also information bits and raw bits 8 | [txsignal, tx_inf_bits, tx_raw_bits] = transmitter(sim_options); 9 | 10 | % Channel model 11 | rxsignal = channel(txsignal, cir, sim_options); 12 | 13 | %Receiver, return data bits and undecoded bits 14 | [rx_inf_bits, rx_raw_bits] = receiver(rxsignal, cir, sim_options); 15 | 16 | % Calculate bit errors 17 | raw_bit_errs = sum(abs(rx_raw_bits(1:length(tx_raw_bits))-tx_raw_bits)); 18 | raw_bits_cnt = length(tx_raw_bits); 19 | 20 | inf_bit_errs = sum(abs(rx_inf_bits(1:length(tx_inf_bits))-tx_inf_bits)); 21 | inf_bits_cnt = length(tx_inf_bits); 22 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_radon_hurwitz.m: -------------------------------------------------------------------------------- 1 | function ofdm_syms_out = tx_radon_hurwitz(mod_ofdm_syms) 2 | 3 | global sim_consts; 4 | 5 | num_symbols = length(mod_ofdm_syms)/sim_consts.NumDataSubc; 6 | mod_syms = reshape(mod_ofdm_syms, sim_consts.NumDataSubc, num_symbols); 7 | 8 | ant1_syms = zeros(sim_consts.NumDataSubc, num_symbols); 9 | ant2_syms = zeros(sim_consts.NumDataSubc, num_symbols); 10 | 11 | % unchanged symbols 12 | ant1_syms(:,1:2:num_symbols) = mod_syms(:,1:2:num_symbols); 13 | ant2_syms(:,1:2:num_symbols) = mod_syms(:,2:2:num_symbols); 14 | 15 | % transformed symbols 16 | ant1_syms(:,2:2:num_symbols) = -conj(mod_syms(:,2:2:num_symbols)); 17 | ant2_syms(:,2:2:num_symbols) = conj(mod_syms(:,1:2:num_symbols)); 18 | 19 | ofdm_syms_out = zeros(2, length(mod_ofdm_syms)); 20 | 21 | ofdm_syms_out(1,:) = ant1_syms(:).'; 22 | ofdm_syms_out(2,:) = ant2_syms(:).'; 23 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_depuncture.m: -------------------------------------------------------------------------------- 1 | function depunctured_bits = rx_depuncture(in_bits, code_rate) 2 | 3 | [punc_patt, punc_patt_size] = get_punc_params(code_rate); 4 | 5 | % Remainder bits are the bits in the and of the packet that are not integer mulitple of the puncture window size 6 | num_rem_bits = rem(length(in_bits), length(punc_patt)); 7 | 8 | depuncture_table = zeros(punc_patt_size, fix(length(in_bits)/length(punc_patt))); 9 | 10 | depunc_bits = reshape(in_bits(1:length(in_bits)-num_rem_bits), length(punc_patt), ... 11 | fix(length(in_bits)/length(punc_patt))); 12 | 13 | depuncture_table(punc_patt,:) = depuncture_table(punc_patt,:) + depunc_bits; 14 | 15 | %puncture the remainder bits 16 | rem_bits = in_bits(length(in_bits)-num_rem_bits+1:length(in_bits)); 17 | rem_depunc_bits = zeros(1,punc_patt_size); 18 | 19 | rem_depunc_bits(punc_patt(1:num_rem_bits)) = rem_depunc_bits(punc_patt(1:num_rem_bits)) + rem_bits; 20 | 21 | depunctured_bits = [depuncture_table(:)' rem_depunc_bits]; 22 | -------------------------------------------------------------------------------- /802_11a_mmodel/get_channel_ir.m: -------------------------------------------------------------------------------- 1 | function cir = get_channel_ir(sim_options); 2 | 3 | global sim_consts; 4 | 5 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 6 | 7 | n_channels = n_tx_antennas*n_rx_antennas; 8 | 9 | if ~isempty(findstr(sim_options.ChannelModel, 'ExponentialDecay')) 10 | if sim_options.ExpDecayTrms == 0 11 | Kmax = 0; 12 | vark = 1; 13 | else 14 | % Calculate the exponential decay envelope 15 | Kmax = ceil( 10 * (sim_options.ExpDecayTrms*(1e-9))*sim_consts.SampFreq); 16 | var0 = (1 - exp( - 1/(sim_consts.SampFreq*(sim_options.ExpDecayTrms*(1e-9))))) / ... 17 | (1 - exp( -1*((Kmax+1)*sim_consts.SampFreq/(sim_options.ExpDecayTrms*(1e-9))))); 18 | k = (0:Kmax); 19 | env = var0 * exp( - k/(sim_consts.SampFreq*(sim_options.ExpDecayTrms*(1e-9)))); 20 | end 21 | 22 | stdDevReOrIm = sqrt(env/2); 23 | cir = repmat(stdDevReOrIm, n_channels,1) .* (randn(n_channels, Kmax+1) + j*randn(n_channels, Kmax+1)); 24 | 25 | elseif ~isempty(findstr(sim_options.ChannelModel, 'AWGN')) 26 | cir = ones(n_channels,1); 27 | else 28 | error('Undefined channel model'); 29 | end 30 | -------------------------------------------------------------------------------- /802_11a_mmodel/phase_noise_model.m: -------------------------------------------------------------------------------- 1 | 2 | function phase_noise = gen_phase_noise(dbc_level, corner_freq, phase_noise_floor, n_samples); 3 | 4 | global sim_consts; 5 | 6 | % Variance of top flat noisd 7 | colored_noise_var = sim_consts.SampFreq*10^(dbc_level/10); 8 | 9 | % Variance of noise floor 10 | noise_floor_var = sim_consts.SampFreq*10^(phase_noise_floor/10); 11 | 12 | % Phase noise power spectrum is created with two filters, 13 | % high pass filter, followed by an ideal integrator 14 | 15 | [b_hpf, a_hpf] = butter(1, corner_freq/(sim_consts.SampFreq/2), 'high'); 16 | 17 | % ...and then an ideal integrator. 18 | tmp = freqz(1,[1 -1],[corner_freq corner_freq+1], sim_consts.SampFreq); 19 | [b_intg] = 1/abs(tmp(1)); % make f = corner frequency gain be 0dB 20 | [a_intg] = [1 -1]; 21 | 22 | % Colored noise 23 | colored_noise = sqrt(colored_noise_var)*randn(1, n_samples); 24 | 25 | % Noise floor 26 | noise_floor = sqrt(noise_floor_var)*randn(1, n_samples); 27 | 28 | integrator_input = filter(b_hpf, a_hpf, colored_noise); 29 | phase_noise = filter(b_intg, a_intg, integrator_input) + noise_floor; 30 | 31 | % add random initial state between [0, 2*pi] 32 | phase_noise = phase_noise + 2*pi*rand(1); 33 | 34 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_estimate_channel.m: -------------------------------------------------------------------------------- 1 | % 2 | 3 | function channel_estimate = rx_estimate_channel(freq_tr_syms, cir, sim_options) 4 | 5 | global sim_consts; 6 | 7 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 8 | 9 | if sim_options.ChannelEstimation 10 | % Estimate from training symbols 11 | if ~sim_options.UseTxDiv 12 | for rx_ant=1:n_rx_antennas 13 | mean_symbols = mean(squeeze(freq_tr_syms(rx_ant,:,:)).'); 14 | channel_estimate(rx_ant,:) = mean_symbols.*conj(sim_consts.LongTrainingSymbols); 15 | end 16 | channel_estimate = channel_estimate.'; 17 | else 18 | for rx_ant=1:n_rx_antennas 19 | for tx_ant = 1:n_tx_antennas 20 | tr_symbol = squeeze(freq_tr_syms(rx_ant, :, tx_ant)); 21 | channel_estimate((rx_ant-1)*n_tx_antennas+tx_ant,:) = ... 22 | tr_symbol.*conj(sim_consts.LongTrainingSymbols*sqrt(1/2)); 23 | end 24 | end 25 | channel_estimate = channel_estimate.'; 26 | end; 27 | else 28 | % Known channel estimate 29 | channel_estimate = fft([zeros(size(cir,1), abs(sim_options.RxTimingOffset)) cir], 64, 2); 30 | reorder = [33:64 1:32]; 31 | channel_estimate(:,reorder) = channel_estimate; 32 | channel_estimate = channel_estimate(:, sim_consts.UsedSubcIdx).'; 33 | end 34 | -------------------------------------------------------------------------------- /802_11a_mmodel/set_sim_consts.m: -------------------------------------------------------------------------------- 1 | function sim_consts = set_sim_consts 2 | 3 | global sim_consts; 4 | 5 | sim_consts = struct('SampFreq' , 20e6, ... 6 | 'ConvCodeGenPoly', [1 0 1 1 0 1 1;1 1 1 1 0 0 1 ], ... 7 | 'NumSubc', 52, ... 8 | 'UsedSubcIdx', [7:32 34:59]', ... 9 | 'ShortTrainingSymbols', sqrt(13/6)*[0 0 1+j 0 0 0 -1-j 0 0 0 1+j 0 0 0 -1-j 0 0 0 -1-j 0 0 0 1+j 0 0 0 0 0 0 -1-j 0 0 0 -1-j 0 0 0 ... 10 | 1+j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0], ... 11 | 'LongTrainingSymbols', [1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 ... 12 | 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1], ... 13 | 'ExtraNoiseSamples', 500, ... 14 | 'PilotScramble', [1 1 1 1 -1 -1 -1 1 -1 -1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 1 1 -1 1 1 1 1 ... 15 | 1 1 -1 1 1 1 -1 1 1 -1 -1 1 1 1 -1 1 -1 -1 -1 1 -1 1 -1 -1 1 -1 -1 1 1 1 1 1 -1 -1 1 ... 16 | 1 -1 -1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 -1 -1 -1 1 -1 -1 1 -1 1 1 1 1 -1 1 -1 1 -1 1 -1 ... 17 | -1 -1 -1 -1 1 -1 1 1 -1 1 -1 1 1 1 -1 -1 1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 -1 -1], ... 18 | 'NumDataSubc', 48, ... 19 | 'NumPilotSubc' , 4, ... 20 | 'DataSubcIdx', [7:11 13:25 27:32 34:39 41:53 55:59]', ... 21 | 'PilotSubcIdx', [12 26 40 54]', ... 22 | 'PilotSubcPatt', [6 20 33 47]', ... 23 | 'DataSubcPatt', [1:5 7:19 21:26 27:32 34:46 48:52]', ... 24 | 'PilotSubcSymbols' , [1;1;1;-1]); 25 | 26 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_frequency_sync.m: -------------------------------------------------------------------------------- 1 | % Frequency error estimation and correction 2 | function [out_signal, freq_est] = rx_frequency_sync(rxsignal, sim_options) 3 | 4 | global sim_consts; 5 | 6 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 7 | 8 | % Estimate the frequency error 9 | if sim_options.FreqSync 10 | 11 | % allows for error in packet detection 12 | pkt_det_offset = 30; 13 | 14 | % averaging length 15 | rlen = 128; 16 | 17 | % short training symbol periodicity 18 | D = 16; 19 | 20 | phase = rxsignal(:,pkt_det_offset:pkt_det_offset+rlen-D).* ... 21 | conj(rxsignal(:,pkt_det_offset+D:pkt_det_offset+rlen)); 22 | 23 | % add all estimates 24 | phase = sum(phase, 2); 25 | 26 | % with rx diversity combine antennas 27 | phase = sum(phase, 1); 28 | 29 | freq_est = -angle(phase) / (2*D*pi/sim_consts.SampFreq); 30 | 31 | radians_per_sample = 2*pi*freq_est/sim_consts.SampFreq; 32 | else 33 | % Magic number 34 | freq_est = -sim_options.FreqError; 35 | radians_per_sample = 2*pi*freq_est/sim_consts.SampFreq; 36 | end 37 | 38 | % Now create a signal that has the frequency offset in the other direction 39 | siglen=length(rxsignal(1,:)); 40 | time_base=0:siglen-1; 41 | correction_signal=repmat(exp(-j*(radians_per_sample)*time_base),n_rx_antennas,1); 42 | 43 | % And finally apply correction on the signal 44 | out_signal = rxsignal.*correction_signal; 45 | 46 | -------------------------------------------------------------------------------- /802_11a_mmodel/channel.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function rx_signal = channel(tx_signal, cir, sim_options); 4 | 5 | global sim_consts; 6 | 7 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 8 | 9 | % Channel effect 10 | rx_signal = zeros(n_rx_antennas, size(tx_signal,2)+size(cir,2)-1); 11 | for rx_ant = 1:n_rx_antennas 12 | for tx_ant = 1:n_tx_antennas 13 | rx_signal(rx_ant,:) = rx_signal(rx_ant,:) + ... 14 | conv(tx_signal(tx_ant,:), cir((rx_ant-1)*n_tx_antennas+tx_ant,:)); 15 | end 16 | end 17 | 18 | len = size(rx_signal, 2); 19 | 20 | % Add noise 21 | % calculate noise variance 22 | % 64/52 scale factor normalizes the noise with the used subcarrier number 23 | noise_var = 64/52/(10^(sim_options.SNR/10))/2; 24 | 25 | noise = sqrt(noise_var) * (randn(n_rx_antennas, len) + j*randn(n_rx_antennas, len)); 26 | 27 | extra_noise = sqrt(noise_var) * (randn(n_rx_antennas,sim_consts.ExtraNoiseSamples) + ... 28 | j*randn(n_rx_antennas, sim_consts.ExtraNoiseSamples)); 29 | 30 | % end noise is added to prevent simulation from crashing from incorrect timing in receiver 31 | end_noise = sqrt(noise_var) * (randn(n_rx_antennas,170) + j*randn(n_rx_antennas, 170)); 32 | 33 | % add noise 34 | rx_signal = rx_signal+noise; 35 | 36 | % extra noise samples are inserted before the packet to test the packet search algorithm 37 | rx_signal = [extra_noise rx_signal end_noise]; 38 | 39 | %Create frequency offset 40 | rx_signal = create_freq_offset(rx_signal, sim_options.FreqError); 41 | 42 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_fine_time_sync.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function fine_time_est = rx_fine_time_sync(input_signal, sim_options); 4 | 5 | global sim_consts; 6 | 7 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 8 | 9 | if sim_options.FineTimeSync 10 | %timing search window size 11 | start_search=130; 12 | end_search=200; 13 | 14 | % get time domain long training symbols 15 | long_tr_symbols = tx_freqd_to_timed(sim_consts.LongTrainingSymbols); 16 | 17 | if sim_options.UseTxDiv 18 | long_trs = [long_tr_symbols(49:64) long_tr_symbols(1:48)]; 19 | else 20 | long_trs = [long_tr_symbols(33:64) long_tr_symbols(1:32)]; 21 | end 22 | 23 | time_corr_long = zeros(n_rx_antennas,end_search-start_search+1); 24 | 25 | for k=1:n_rx_antennas 26 | % calculate cross correlation 27 | for idx=start_search:end_search 28 | time_corr_long(k,idx-start_search+1) = sum((input_signal(k,idx:idx+63).*conj(long_trs))); 29 | end 30 | end 31 | 32 | % combine, if we had two antennas 33 | time_corr_long = sum(abs(time_corr_long),1); 34 | [max_peak_long,long_search_idx] = max(abs(time_corr_long)); 35 | 36 | if sim_options.UseTxDiv 37 | fine_time_est = start_search-1 + long_search_idx+16; 38 | else 39 | fine_time_est = start_search-1 + long_search_idx+32; 40 | end 41 | 42 | else 43 | % Magic numbers 44 | if ~sim_options.UseTxDiv 45 | fine_time_est = 194; 46 | else 47 | fine_time_est = 194-16; 48 | end 49 | end 50 | 51 | 52 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_viterbi_decode.m: -------------------------------------------------------------------------------- 1 | function out_bits = rx_viterbi_decode(rx_bits) 2 | 3 | global prev_state; 4 | global prev_state_outbits; 5 | 6 | cum_metrics = -1e6*ones(64, 1); 7 | cum_metrics(1) = 0; 8 | 9 | tmp_cum_metrics = zeros(64,1); 10 | max_paths = zeros(64, length(rx_bits)/2); 11 | out_bits = zeros(1, length(rx_bits)/2); 12 | 13 | for data_bit = 1:2:length(rx_bits) 14 | for state = 1:64 15 | tmp_max_cum_metric = -1e7; 16 | 17 | path_metric1 = prev_state_outbits(state, 1, 1)*rx_bits(data_bit) + ... 18 | prev_state_outbits(state, 1, 2)*rx_bits(data_bit+1); 19 | 20 | path_metric2 = prev_state_outbits(state, 2, 1)*rx_bits(data_bit) + ... 21 | prev_state_outbits(state, 2, 2)*rx_bits(data_bit+1); 22 | 23 | if cum_metrics(prev_state(state, 1)+1) + path_metric1 > ... 24 | cum_metrics(prev_state(state, 2)+1) + path_metric2 25 | tmp_cum_metrics(state) = cum_metrics(prev_state(state, 1)+1) + path_metric1; 26 | max_paths(state, (data_bit+1)/2) = 0; 27 | else 28 | tmp_cum_metrics(state) = cum_metrics(prev_state(state, 2)+1) + path_metric2; 29 | max_paths(state, (data_bit+1)/2) = 1; 30 | end 31 | end 32 | 33 | for state = 1:64 34 | cum_metrics(state) = tmp_cum_metrics(state); 35 | end 36 | end 37 | 38 | % trace back 39 | state = 0; 40 | for data_bit = length(rx_bits)/2:-1:1 41 | bit_estimate = rem(state,2); 42 | out_bits(data_bit) = bit_estimate; 43 | state = prev_state(state+1, max_paths(state+1, data_bit)+1); 44 | end 45 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_qam64_demod.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function soft_bits = rx_qam64_demod(rx_symbols) 4 | 5 | soft_bits = zeros(6*size(rx_symbols,1), size(rx_symbols,2)); % Each symbol consists of 6 bits 6 | bit0 = real(rx_symbols); 7 | bit3 = imag(rx_symbols); 8 | 9 | bit1 = 4/sqrt(42)-abs(real(rx_symbols)); 10 | bit4 = 4/sqrt(42)-abs(imag(rx_symbols)); 11 | 12 | 13 | for m=1:size(rx_symbols,2) 14 | for k=1:size(rx_symbols,1) 15 | if abs(4/sqrt(42)-abs(real(rx_symbols(k,m)))) <= 2/sqrt(42) % bit is one 16 | bit2(k,m) = 2/sqrt(42) - abs(4/sqrt(42)-abs(real(rx_symbols(k,m)))); 17 | elseif abs(real(rx_symbols(k,m))) <= 2/sqrt(42) % bit is zero, close to real axis 18 | bit2(k,m) = -2/sqrt(42) + abs(real(rx_symbols(k,m))); 19 | else 20 | bit2(k,m) = 6/sqrt(42)-abs(real(rx_symbols(k,m))); % bit is zero 21 | end; 22 | 23 | if abs(4/sqrt(42)-abs(imag(rx_symbols(k,m)))) <= 2/sqrt(42) % bit is one 24 | bit5(k,m) = 2/sqrt(42) - abs(4/sqrt(42)-abs(imag(rx_symbols(k,m)))); 25 | elseif abs(imag(rx_symbols(k,m))) <= 2/sqrt(42) % bit is zero, close to real axis 26 | bit5(k,m) = -2/sqrt(42) + abs(imag(rx_symbols(k,m))); 27 | else 28 | bit5(k,m) = 6/sqrt(42)-abs(imag(rx_symbols(k,m))); 29 | end; 30 | end; 31 | end; 32 | 33 | soft_bits(1:6:size(soft_bits,1),:) = bit0; 34 | soft_bits(2:6:size(soft_bits,1),:) = bit1; 35 | soft_bits(3:6:size(soft_bits,1),:) = bit2; 36 | soft_bits(4:6:size(soft_bits,1),:) = bit3; 37 | soft_bits(5:6:size(soft_bits,1),:) = bit4; 38 | soft_bits(6:6:size(soft_bits,1),:) = bit5; 39 | 40 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_gen_preamble.m: -------------------------------------------------------------------------------- 1 | 2 | function preamble = tx_gen_preamble(sim_options); 3 | 4 | 5 | global sim_consts; 6 | 7 | %Generate first ten short training symbols 8 | 9 | short_tr = sim_consts.ShortTrainingSymbols; 10 | 11 | % generate four short training symbols 12 | short_tr_symbols = tx_freqd_to_timed(short_tr); 13 | 14 | % Pick one short training symbol 15 | Strs = short_tr_symbols(1:16); 16 | 17 | % extend to ten short training symbols 18 | short_trs=[Strs Strs Strs Strs Strs Strs Strs Strs Strs Strs]; 19 | 20 | short_trs_len=length(short_trs); 21 | 22 | 23 | % next generate the two long training symbols 24 | 25 | long_tr = sim_consts.LongTrainingSymbols; 26 | long_tr_symbol = tx_freqd_to_timed(long_tr); 27 | 28 | if ~sim_options.UseTxDiv 29 | % single antenna preamble 30 | % extend with the 2*guard interval in front and then two long training symbols 31 | long_trs_signal = [long_tr_symbol(64-2*16+1:64) long_tr_symbol long_tr_symbol]; 32 | else 33 | % generate the two antenna preamble, 34 | % long training symbols are not transmitted simultaneously from both antennas to allow 35 | % channel estimation in receiver 36 | long_trs_signal(1,:) = sqrt(2)*[long_tr_symbol(64-16+1:64) long_tr_symbol ... 37 | zeros(1,80)]; 38 | long_trs_signal(2,:) = sqrt(2)*[zeros(1,80) ... 39 | long_tr_symbol(64-16+1:64) long_tr_symbol]; 40 | end 41 | 42 | % concatenate first short training symbols and long training symbols 43 | preamble(1,:) = [short_trs(1,:) long_trs_signal(1,:)]; 44 | 45 | % add the second antenna preamble 46 | if sim_options.UseTxDiv 47 | preamble(2,:) = [short_trs(1,:) long_trs_signal(2,:)]; 48 | end 49 | -------------------------------------------------------------------------------- /802_11a_vmodel/ofdm_rtl/transmitter/conv_code.v: -------------------------------------------------------------------------------- 1 | //********************************************************** 2 | // Project : OFDM-IEEE 802.11a 3 | // DesignModule : conv_code.v 4 | // Description : 5 | // Designer : 6 | // Date : 7 | //********************************************************** 8 | 9 | module conv_code( 10 | input sys_clk, 11 | input sys_rstn, 12 | 13 | input data_in, 14 | input data_valid_i, 15 | 16 | output reg [1:0] data_out, 17 | output reg data_valid_o 18 | ); 19 | 20 | //*************************************************** 21 | // 22 | // Internal Defination 23 | // 24 | //*************************************************** 25 | reg [5:0] shift_reg; 26 | wire [5:0] shift_reg_in = data_valid_i ? {shift_reg[4:0], data_in} : shift_reg;//cyculatory left shift 27 | 28 | assign data_valid_o_in = data_valid_i; 29 | assign data_out_in = data_valid_i ? {shift_reg[5] + shift_reg[2] + shift_reg[1] + shift_reg[0] + data_in, shift_reg[5] + shift_reg[4] + shift_reg[2] + shift_reg[1] + data_in} : data_out; 30 | 31 | //*************************************************** 32 | // 33 | // always 34 | // 35 | //*************************************************** 36 | always @(posedge sys_clk or negedge sys_rstn) 37 | if(!sys_rstn) 38 | begin 39 | shift_reg <= #1 6'd0; 40 | data_valid_o <= #1 1'd0; 41 | end 42 | else 43 | begin 44 | shift_reg <= #1 shift_reg_in; 45 | data_valid_o <= #1 data_valid_o_in; 46 | end 47 | 48 | 49 | 50 | //********************************************************** 51 | // 52 | // END Of Module 53 | // 54 | //********************************************************** 55 | endmodule 56 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_find_packet_edge.m: -------------------------------------------------------------------------------- 1 | function detected_packet = rx_find_packet_edge(rx_signal, sim_options) 2 | 3 | global sim_consts; 4 | 5 | search_win = 800; 6 | D = 16; 7 | 8 | if sim_options.PacketDetection 9 | rx_len = length(rx_signal); 10 | 11 | % Calculate the delayd correlation 12 | delay_xcorr = rx_signal(:,1:search_win+2*D).*conj(rx_signal(:,1*D+1:search_win+3*D)); 13 | 14 | % Moving average of the delayed correlation 15 | ma_delay_xcorr = abs(filter(ones(1,2*D), 1, delay_xcorr, [], 2)); 16 | 17 | % Moving average of received power 18 | ma_rx_pwr = filter(ones(1,2*D), 1, abs(rx_signal(:,1*D+1:search_win+3*D)).^2,[], 2); 19 | 20 | % The decision variable 21 | delay_len = length(ma_delay_xcorr); 22 | ma_M = ma_delay_xcorr(:,1:delay_len)./ma_rx_pwr(:,1:delay_len); 23 | 24 | % remove delay samples 25 | ma_M(:,1:2*D) = []; 26 | 27 | % combine antennas, if rx diversity is used 28 | ma_M = sum(ma_M, 1); 29 | 30 | if ~sim_options.UseRxDiv 31 | threshold = 0.75; 32 | else 33 | threshold = 1.5; 34 | end 35 | 36 | thres_idx = find(ma_M > threshold); 37 | if isempty(thres_idx) 38 | thres_idx = 1; 39 | else 40 | thres_idx = thres_idx(1); 41 | end 42 | 43 | else 44 | thres_idx = sim_consts.ExtraNoiseSamples; 45 | end; 46 | 47 | % check if the packet has been detected too late, 48 | % > sim_consts.extra_noise_samples + 35 index 49 | % is out of range of the fine timing algorithm 50 | % This prevents simulation error for code running out samples 51 | if thres_idx > sim_consts.ExtraNoiseSamples + 35 52 | thres_idx = 1; 53 | end 54 | 55 | detected_packet = rx_signal(:,thres_idx:length(rx_signal)); 56 | 57 | 58 | -------------------------------------------------------------------------------- /802_11a_vmodel/ofdm_rtl/transmitter/data_scramble.v: -------------------------------------------------------------------------------- 1 | //********************************************************** 2 | // Project : OFDM-IEEE 802.11a 3 | // DesignModule : data_scramble.v 4 | // Description : 5 | // Designer : 6 | // Date : 7 | //********************************************************** 8 | 9 | module data_scramble( 10 | input sys_clk, 11 | input sys_rstn, 12 | 13 | input [6:0] scram_seed, 14 | input scram_din, 15 | input scram_load, 16 | input scram_valid_i, 17 | 18 | output reg scram_dout, 19 | output reg scram_valid_o 20 | ); 21 | 22 | //*************************************************** 23 | // 24 | // Internal Defination 25 | // 26 | //*************************************************** 27 | reg [6:0] scramble; 28 | 29 | wire [6:0] scramble_in = scram_load ? scram_seed : // initial scram_seed = 7'b1011101 30 | (scram_valid_i) ? {scramble[5:0], scramble[6] + scramble[3]} : 7'd0; // cyculatory left shift 31 | assign scram_dout_in = scram_valid_i ? scram_din + scramble[6] + scramble[3] : 1'd0; // s(x) = 1 + x^4 + x^7 32 | assign scram_valid_o_in = scram_valid_i ? 1'b1 : 1'd0; 33 | 34 | 35 | //*************************************************** 36 | // 37 | // always 38 | // 39 | //*************************************************** 40 | always @(posedge sys_clk or negedge sys_rstn) 41 | if(!sys_rstn) 42 | begin 43 | scramble <= #1 7'd0; 44 | scram_dout <= #1 1'd0; 45 | scram_valid_o <= #1 1'b0; 46 | end 47 | else 48 | begin 49 | scramble <= #1 scramble_in; 50 | scram_dout <= #1 scram_dout_in; 51 | scram_valid_o <= #1 scram_valid_o_in; 52 | end 53 | 54 | 55 | endmodule 56 | //********************************************************** 57 | // 58 | // END Of Module 59 | // 60 | //********************************************************** 61 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_timed_to_freqd.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function [freq_tr_syms, freq_data_syms, freq_pilot_syms] = rx_timed_to_freqd(time_signal, sim_options) 4 | 5 | global sim_consts; 6 | 7 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 8 | 9 | for rx_ant = 1:n_rx_antennas 10 | % Long Training symbols 11 | 12 | if ~sim_options.UseTxDiv 13 | long_tr_syms = time_signal(rx_ant,1:2*64); 14 | else 15 | long_tr_syms = [time_signal(rx_ant,1:64) time_signal(rx_ant,81:144)]; 16 | end 17 | long_tr_syms = reshape(long_tr_syms, 64, 2); 18 | 19 | % to frequency domain 20 | freq_long_tr = fft(long_tr_syms)/(64/sqrt(52)/sqrt(n_tx_antennas)); 21 | reorder = [33:64 1:32]; 22 | freq_long_tr(reorder,:) = freq_long_tr; 23 | 24 | % Select training carriers 25 | freq_tr_syms = freq_long_tr(sim_consts.UsedSubcIdx,:); 26 | 27 | % Take data symbols 28 | if ~sim_options.UseTxDiv 29 | data_syms = time_signal(rx_ant,129:length(time_signal)); 30 | else 31 | data_syms = time_signal(rx_ant, 145:length(time_signal)); 32 | end 33 | 34 | data_sig_len = length(data_syms); 35 | n_data_syms = floor(data_sig_len/80); 36 | 37 | % Cut to multiple of symbol period 38 | data_syms = data_syms(1:n_data_syms*80); 39 | data_syms = reshape(data_syms, 80, n_data_syms); 40 | % remove guard intervals 41 | data_syms(1:16,:) = []; 42 | 43 | % perform fft 44 | freq_data = fft(data_syms)/(64/sqrt(52)/sqrt(n_tx_antennas)); 45 | 46 | %Reorder pattern is [33:64 1:32] 47 | freq_data(reorder,:) = freq_data; 48 | 49 | %Select data carriers 50 | freq_data_syms = freq_data(sim_consts.DataSubcIdx,:); 51 | 52 | %Select the pilot carriers 53 | freq_pilot_syms = freq_data(sim_consts.PilotSubcIdx,:); 54 | 55 | tmp_freq_tr(rx_ant,:,:) = freq_tr_syms; 56 | tmp_data_syms(rx_ant,:,:) = freq_data_syms; 57 | tmp_pilot_syms(rx_ant,:,:) = freq_pilot_syms; 58 | end 59 | 60 | freq_tr_syms = tmp_freq_tr; 61 | freq_data_syms = tmp_data_syms; 62 | freq_pilot_syms = tmp_pilot_syms; 63 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_modulate.m: -------------------------------------------------------------------------------- 1 | 2 | function mod_symbols = tx_modulate(bits_in, modulation) 3 | 4 | full_len = length(bits_in); 5 | 6 | % BPSK modulation 7 | if ~isempty(findstr(modulation, 'BPSK')) 8 | % Angle [pi/4 -3*pi/4] corresponds to 9 | % Gray code vector [0 1], respectively. 10 | table=exp(j*[0 -pi]); % generates BPSK symbols 11 | table=table([1 0]+1); % Gray code mapping pattern for BPSK symbols 12 | inp=bits_in; 13 | mod_symbols=table(inp+1); % maps transmitted bits into BPSK symbols 14 | 15 | % QPSK modulation 16 | elseif ~isempty(findstr(modulation, 'QPSK')) 17 | % Angle [pi/4 3*pi/4 -3*pi/4 -pi/4] corresponds to 18 | % Gray code vector [00 10 11 01], respectively. 19 | table=exp(j*[-3/4*pi 3/4*pi 1/4*pi -1/4*pi]); % generates QPSK symbols 20 | table=table([0 1 3 2]+1); % Gray code mapping pattern for QPSK symbols 21 | inp=reshape(bits_in,2,full_len/2); 22 | mod_symbols=table([2 1]*inp+1); % maps transmitted bits into QPSK symbols 23 | 24 | % 16-QAM modulation 25 | elseif ~isempty(findstr(modulation, '16QAM')) 26 | % generates 16QAM symbols 27 | m=1; 28 | for k=-3:2:3 29 | for l=-3:2:3 30 | table(m) = (k+j*l)/sqrt(10); % power normalization 31 | m=m+1; 32 | end; 33 | end; 34 | table=table([0 1 3 2 4 5 7 6 12 13 15 14 8 9 11 10]+1); % Gray code mapping pattern for 8-PSK symbols 35 | inp=reshape(bits_in,4,full_len/4); 36 | mod_symbols=table([8 4 2 1]*inp+1); % maps transmitted bits into 16QAM symbols 37 | 38 | % 64-QAM modulation 39 | elseif ~isempty(findstr(modulation, '64QAM')) 40 | % generates 64QAM symbols 41 | m=1; 42 | for k=-7:2:7 43 | for l=-7:2:7 44 | table(m) = (k+j*l)/sqrt(42); % power normalization 45 | m=m+1; 46 | end; 47 | end; 48 | table=table([[ 0 1 3 2 7 6 4 5]... 49 | 8+[ 0 1 3 2 7 6 4 5]... 50 | 24+[ 0 1 3 2 7 6 4 5]... 51 | 16+[ 0 1 3 2 7 6 4 5]... 52 | 56+[ 0 1 3 2 7 6 4 5]... 53 | 48+[ 0 1 3 2 7 6 4 5]... 54 | 32+[ 0 1 3 2 7 6 4 5]... 55 | 40+[ 0 1 3 2 7 6 4 5]]+1); 56 | 57 | inp=reshape(bits_in,6,full_len/6); 58 | 59 | mod_symbols=table([32 16 8 4 2 1]*inp+1); % maps transmitted bits into 64QAM symbol 60 | else 61 | error('Unimplemented modulation'); 62 | end 63 | 64 | 65 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_diversity_proc.m: -------------------------------------------------------------------------------- 1 | function [data_syms_out, pilot_syms_out] = rx_diversity_proc(freq_data_syms, freq_pilot_syms, ... 2 | channel_est, sim_options) 3 | 4 | global sim_consts; 5 | 6 | % remove extra dimension from matrices, if rx diversity is not used 7 | freq_data_syms = squeeze(freq_data_syms); 8 | freq_pilot_syms = squeeze(freq_pilot_syms); 9 | 10 | % tx diversity 11 | if sim_options.UseTxDiv 12 | % Radon-Hurwitz transmit diversity 13 | if ~sim_options.UseRxDiv 14 | freq_data_syms = rx_radon_hurwitz(freq_data_syms, channel_est(sim_consts.DataSubcPatt,:)); 15 | elseif sim_options.UseRxDiv 16 | % Rx R-H performed to both receiver antennas 17 | freq_data_syms(1,:,:) = rx_radon_hurwitz(squeeze(freq_data_syms(1,:,:)), ... 18 | channel_est(sim_consts.DataSubcPatt,1:2)); 19 | freq_data_syms(2,:,:) = rx_radon_hurwitz(squeeze(freq_data_syms(2,:,:)), ... 20 | channel_est(sim_consts.DataSubcPatt,3:4)); 21 | end 22 | end 23 | 24 | % rx diversity 25 | if sim_options.UseRxDiv 26 | if ~sim_options.UseTxDiv 27 | freq_data_syms = rx_mr_combiner(freq_data_syms, channel_est(sim_consts.DataSubcPatt,:), sim_options); 28 | freq_pilot_syms = rx_mr_combiner(freq_pilot_syms, channel_est(sim_consts.PilotSubcPatt,:), sim_options); 29 | elseif sim_options.UseTxDiv 30 | freq_data_syms = squeeze(freq_data_syms(1,:,:) + freq_data_syms(2,:,:)); 31 | freq_pilot_syms = rx_mr_combiner(freq_pilot_syms, channel_est(sim_consts.PilotSubcPatt,:), sim_options); 32 | end 33 | end 34 | 35 | % no diversity 36 | if (~sim_options.UseTxDiv) & (~sim_options.UseRxDiv) 37 | % Data symbols channel correction 38 | chan_corr_mat = repmat(channel_est(sim_consts.DataSubcPatt), 1, size(freq_data_syms,2)); 39 | freq_data_syms = freq_data_syms.*conj(chan_corr_mat); 40 | chan_corr_mat = repmat(channel_est(sim_consts.PilotSubcPatt), 1, size(freq_pilot_syms,2)); 41 | freq_pilot_syms = freq_pilot_syms.*conj(chan_corr_mat); 42 | end 43 | 44 | % Amplitude normalization 45 | chan_sq_amplitude = sum(abs(channel_est(sim_consts.DataSubcPatt,:)).^2, 2); 46 | chan_sq_amplitude_mtx = repmat(chan_sq_amplitude,1, size(freq_data_syms,2)); 47 | 48 | data_syms_out = freq_data_syms./chan_sq_amplitude_mtx; 49 | 50 | chan_sq_amplitude = sum(abs(channel_est(sim_consts.PilotSubcPatt,:)).^2, 2); 51 | chan_sq_amplitude_mtx = repmat(chan_sq_amplitude,1, size(freq_pilot_syms,2)); 52 | pilot_syms_out = freq_pilot_syms./chan_sq_amplitude_mtx; 53 | 54 | 55 | -------------------------------------------------------------------------------- /802_11a_mmodel/receiver.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function [data_bits, raw_bits] = receiver(rx_signal, cir, sim_options); 4 | 5 | global sim_consts; 6 | 7 | [n_tx_antennas, n_rx_antennas] = get_n_antennas(sim_options); 8 | 9 | % Phase noise model 10 | if sim_options.UsePhaseNoise 11 | phase_noise = phase_noise_model(sim_options.PhaseNoisedBcLevel, ... 12 | sim_options.PhaseNoiseCFreq, sim_options.PhaseNoiseFloor, size(rx_signal,2)); 13 | rx_signal = rx_signal.*exp(j*repmat(phase_noise, size(rx_signal,1), 1)); 14 | end 15 | 16 | %packet search 17 | rx_signal = rx_find_packet_edge(rx_signal, sim_options); 18 | 19 | % Frequency error estimation and correction 20 | rx_signal = rx_frequency_sync(rx_signal, sim_options); 21 | 22 | % Fine time synchronization 23 | fine_time_est = rx_fine_time_sync(rx_signal, sim_options); 24 | 25 | % Time synchronized signal 26 | sync_time_signal = rx_signal(:,fine_time_est + sim_options.RxTimingOffset:length(rx_signal(1,:))); 27 | 28 | % Return to frequency domain 29 | [freq_tr_syms, freq_data_syms, freq_pilot_syms] = rx_timed_to_freqd(sync_time_signal, sim_options); 30 | 31 | % Channel estimation 32 | channel_est = rx_estimate_channel(freq_tr_syms, cir, sim_options); 33 | 34 | % Phase tracker, returns phase error corrected symbols 35 | freq_data_syms = rx_phase_tracker(freq_data_syms, freq_pilot_syms, channel_est, sim_options); 36 | 37 | % receiver diversity processing 38 | [freq_data_syms,freq_pilot_syms] = rx_diversity_proc(freq_data_syms, freq_pilot_syms, ... 39 | channel_est, sim_options); 40 | 41 | % Demodulate 42 | soft_bits = rx_demodulate(freq_data_syms, sim_options); 43 | 44 | % Deinterleave if bits were interleaved 45 | if sim_options.InterleaveBits 46 | deint_bits = rx_deinterleave(soft_bits, sim_options); 47 | else 48 | deint_bits = soft_bits; 49 | end 50 | 51 | % hard decision of soft bits, used to measure uncoded BER 52 | raw_bits = deint_bits > 0; 53 | 54 | % depuncture 55 | depunc_bits = rx_depuncture(deint_bits, sim_options.ConvCodeRate); 56 | 57 | % Subcarrier amplitudes are used to weight the soft decisions before Viterbi decoding 58 | channel_amps = rx_gen_chan_amps(length(deint_bits), channel_est, sim_options); 59 | 60 | if sim_options.InterleaveBits 61 | channel_amps = rx_deinterleave(channel_amps, sim_options); 62 | end 63 | channel_amps = rx_depuncture(channel_amps, sim_options.ConvCodeRate); 64 | 65 | % Weight soft decisions by subcarrier amplitudes 66 | viterbi_input = channel_amps(1:(sim_options.PacketLength+6)*2).* ... 67 | depunc_bits(1:(sim_options.PacketLength+6)*2); 68 | 69 | % Vitervi decoding 70 | data_bits = rx_viterbi_decode(viterbi_input); 71 | 72 | -------------------------------------------------------------------------------- /802_11a_mmodel/runsim.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function runsim(sim_options) 4 | 5 | % set constants used in simulation 6 | set_sim_consts; 7 | 8 | % Set Random number generators initial state 9 | % reset random number generators based on current clock value 10 | rand('state',sum(100*clock)); 11 | randn('state',sum(100*clock)); 12 | 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | % Main simulation loop 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | 17 | % Initialize simulation timer 18 | start_time = clock; 19 | 20 | % Initialize trellis tables for Viterbi decoding 21 | rx_init_viterbi; 22 | 23 | % counters for information bits 24 | num_inf_bits = 0; 25 | num_inf_bit_errors = 0; 26 | num_inf_packet_errors = 0; 27 | inf_ber = 0; 28 | inf_per = 0; 29 | 30 | % counters for raw (uncoded) bits 31 | num_raw_bits = 0; 32 | num_raw_bit_errors = 0; 33 | num_raw_packet_errors = 0; 34 | raw_ber = 0; 35 | raw_per = 0; 36 | 37 | % Simulation the number of packets specified 38 | 39 | packet_count = 0; 40 | 41 | while packet_count < sim_options.PktsToSimulate 42 | 43 | packet_count = packet_count + 1; 44 | 45 | packet_start_time = clock; 46 | 47 | % Simulate one packet with the current options 48 | [inf_bit_cnt, inf_bit_errors, raw_bits_cnt, raw_bit_errors] = ... 49 | single_packet(sim_options); 50 | 51 | num_inf_bits = num_inf_bits + inf_bit_cnt; 52 | num_inf_bit_errors = num_inf_bit_errors + inf_bit_errors; 53 | num_inf_packet_errors = num_inf_packet_errors + (inf_bit_errors~=0); 54 | inf_ber = num_inf_bit_errors/num_inf_bits; 55 | inf_per = num_inf_packet_errors/packet_count; 56 | 57 | num_raw_bits = num_raw_bits + raw_bits_cnt; 58 | num_raw_bit_errors = num_raw_bit_errors + raw_bit_errors; 59 | num_raw_packet_errors = num_raw_packet_errors + (raw_bit_errors~=0); 60 | raw_ber = num_raw_bit_errors/num_raw_bits; 61 | raw_per = num_raw_packet_errors/packet_count; 62 | 63 | packet_stop_time = clock; 64 | packet_duration = etime(packet_stop_time, packet_start_time); 65 | 66 | % Display results 67 | fprintf('%8s %8s %9s %10s %8s %10s %10s %9s\n', ... 68 | ' Packet |', ' Time |', 'raw errs |', ' raw BER |', 'data errs |',' data BER |', ' raw PER |', 'data PER'); 69 | fprintf('%7d |%7g | %8d |%10.2e |%10d |%10.2e |%10.2e |%10.2e\n',... 70 | packet_count, packet_duration, raw_bit_errors, raw_ber, inf_bit_errors, inf_ber, raw_per, inf_per); 71 | 72 | % read event queue 73 | drawnow; 74 | end 75 | 76 | stop_time = clock; 77 | elapsed_time = etime(stop_time,start_time); 78 | 79 | fprintf('Simulation duration: %g seconds\n',elapsed_time); 80 | 81 | -------------------------------------------------------------------------------- /802_11a_mmodel/transmitter.m: -------------------------------------------------------------------------------- 1 | % Generates transmitted signal for one packet. 2 | 3 | function [tx_signal, inf_bits, tx_bits] = transmitter(sim_options); 4 | 5 | global sim_consts; 6 | 7 | % Generate the information bits 8 | inf_bits = randn(1, sim_options.PacketLength) > 0; 9 | 10 | % Convolutional encoding 11 | coded_bit_stream = tx_conv_encoder(inf_bits); 12 | 13 | %Puncturing 14 | tx_bits = tx_puncture(coded_bit_stream, sim_options.ConvCodeRate); 15 | 16 | % Generate number bits that is an integer multiple of OFDM symbols 17 | rdy_to_mod_bits = tx_make_int_num_ofdm_syms(tx_bits, sim_options); 18 | 19 | if sim_options.InterleaveBits == 1 20 | %Interleave padded bit stream 21 | rdy_to_mod_bits = tx_interleaver(rdy_to_mod_bits, sim_options); 22 | end 23 | 24 | %Modulate 25 | mod_syms = tx_modulate(rdy_to_mod_bits, sim_options.Modulation); 26 | 27 | % Transmit diversity 28 | mod_syms = tx_diversity(mod_syms, sim_options); 29 | 30 | %Add pilot symbols 31 | if ~sim_options.UseTxDiv 32 | mod_ofdm_syms = tx_add_pilot_syms(mod_syms, sim_options); 33 | else 34 | mod_ofdm_syms(1,:) = tx_add_pilot_syms(mod_syms(1,:), sim_options); 35 | mod_ofdm_syms(2,:) = tx_add_pilot_syms(mod_syms(2,:), sim_options); 36 | end 37 | 38 | % Tx symbols to time domain 39 | time_syms = tx_freqd_to_timed(mod_ofdm_syms); 40 | 41 | % Add cyclic prefix 42 | time_signal = tx_add_cyclic_prefix(time_syms); 43 | 44 | % Construction of the preamble 45 | preamble = tx_gen_preamble(sim_options); 46 | 47 | % Concatenate preamble and data part and normalize the average signal power to 1 48 | tx_signal = [preamble time_signal]*64/sqrt(52)/sqrt(size(time_signal,1)); 49 | 50 | % Model phase noise 51 | if sim_options.UsePhaseNoise 52 | phase_noise = phase_noise_model(sim_options.PhaseNoisedBcLevel, ... 53 | sim_options.PhaseNoiseCFreq, sim_options.PhaseNoiseFloor, size(tx_signal,2)); 54 | tx_signal = tx_signal.*exp(j*repmat(phase_noise,size(tx_signal,1), 1)); 55 | end 56 | 57 | %Power amplifier model 58 | if sim_options.UseTxPA 59 | if ~sim_options.UseTxDiv 60 | [tx_signal, pwr_in, pwr_out] = tx_power_amplifier(tx_signal, 1, 1, 1, 2, size(tx_signal,2)); 61 | % normalize average tx power to one 62 | tx_signal(1,:) = tx_signal(1,:)/sqrt(pwr_out); 63 | else 64 | % first antenna 65 | [tx_signal(1,:), pwr_in, pwr_out] = tx_power_amplifier(tx_signal(1,:), 1, 1, 1, 2, size(tx_signal(1,:),2)); 66 | % normalize average tx power to one 67 | tx_signal(1,:) = tx_signal(1,:)/sqrt(pwr_out); 68 | 69 | % second antenna 70 | [tx_signal(2,:), pwr_in, pwr_out] = tx_power_amplifier(tx_signal(2,:), 1, 1, 1, 2, size(tx_signal(2,:),2)); 71 | % normalize average tx power to one 72 | tx_signal(2,:) = tx_signal(2,:)/sqrt(pwr_out); 73 | end 74 | end 75 | 76 | % Generates passband signal from which the tx power spectrum can be estimated 77 | if sim_options.TxPowerSpectrum 78 | if ~sim_options.UseTxDiv 79 | interp_tx_signal = interp(tx_signal, 16); 80 | else 81 | interp_tx_signal(1,:) = interp(tx_signal(1,:), 16); 82 | interp_tx_signal(2,:) = interp(tx_signal(2,:), 16); 83 | end 84 | 85 | % upconvert, and extract passband signal 86 | rf_tx_signal = interp_tx_signal.*exp(repmat(j*2*pi*4/16* ... 87 | (0:size(interp_tx_signal,2)-1), size(interp_tx_signal, 1), 1)); 88 | rf_tx_signal = real(rf_tx_signal); 89 | end 90 | -------------------------------------------------------------------------------- /802_11a_mmodel/rx_pilot_phase_est.m: -------------------------------------------------------------------------------- 1 | function correction_phases = rx_pilot_phase_est(rx_pilots, channel, sim_options) 2 | 3 | global sim_consts; 4 | 5 | num_symbols = size(rx_pilots, 3); 6 | 7 | % Pilot scrambling pattern 8 | scramble_patt = repmat(sim_consts.PilotScramble, sim_consts.NumPilotSubc,... 9 | ceil(num_symbols/length(sim_consts.PilotScramble))); 10 | scramble_patt = scramble_patt(:,1:num_symbols); 11 | ref_pilots = repmat(sim_consts.PilotSubcSymbols, 1, num_symbols); 12 | 13 | % Estimate the symbol rotation from the pilot subcarriers 14 | % Different Tx and/or Rx diversity options require different processing of the pilot symbols 15 | if (~sim_options.UseTxDiv) & (~sim_options.UseRxDiv) 16 | channel_est = repmat(channel(sim_consts.PilotSubcPatt), 1, num_symbols); 17 | phase_error_est = angle(sum(conj(ref_pilots).*squeeze(rx_pilots).*conj(channel_est).*conj(scramble_patt))); 18 | 19 | correction_phases = zeros(1, sim_consts.NumDataSubc, num_symbols); 20 | correction_phases(1,:,:) = repmat(phase_error_est, sim_consts.NumDataSubc, 1); 21 | elseif (~sim_options.UseTxDiv) & (sim_options.UseRxDiv) 22 | channel_est1 = repmat(channel(sim_consts.PilotSubcPatt, 1), 1, num_symbols); 23 | phase_error_est1 = sum(conj(ref_pilots).*squeeze(rx_pilots(1,:,:)).*conj(channel_est1).*conj(scramble_patt)); 24 | 25 | channel_est2 = repmat(channel(sim_consts.PilotSubcPatt, 2), 1, num_symbols); 26 | phase_error_est2 = sum(conj(ref_pilots).*squeeze(rx_pilots(2,:,:)).*conj(channel_est2).*conj(scramble_patt)); 27 | 28 | phase_error_est = angle(phase_error_est1+phase_error_est2); 29 | 30 | correction_phases = zeros(2, sim_consts.NumDataSubc, num_symbols); 31 | correction_phases(1,:,:) = repmat(phase_error_est, sim_consts.NumDataSubc, 1); 32 | correction_phases(2,:,:) = repmat(phase_error_est, sim_consts.NumDataSubc, 1); 33 | elseif (sim_options.UseTxDiv) & (~sim_options.UseRxDiv) 34 | channel_est1 = repmat(channel(sim_consts.PilotSubcPatt, 1), 1, num_symbols); 35 | channel_est2 = repmat(channel(sim_consts.PilotSubcPatt, 2), 1, num_symbols); 36 | 37 | phase_error_est = sum(conj(channel_est1.*ref_pilots+channel_est2.*ref_pilots).*... 38 | squeeze(rx_pilots(1,:,:)).*conj(scramble_patt)); 39 | 40 | phase_error_est = angle(phase_error_est); 41 | 42 | correction_phases = zeros(1, sim_consts.NumDataSubc, num_symbols); 43 | correction_phases(1,:,:) = repmat(phase_error_est, sim_consts.NumDataSubc, 1); 44 | elseif (sim_options.UseTxDiv) & (sim_options.UseRxDiv) 45 | channel_est1_1 = repmat(channel(sim_consts.PilotSubcPatt, 1), 1, num_symbols); 46 | channel_est1_2 = repmat(channel(sim_consts.PilotSubcPatt, 2), 1, num_symbols); 47 | channel_est2_1 = repmat(channel(sim_consts.PilotSubcPatt, 3), 1, num_symbols); 48 | channel_est2_2 = repmat(channel(sim_consts.PilotSubcPatt, 4), 1, num_symbols); 49 | 50 | 51 | phase_error_est1 = sum(conj(channel_est1_1.*ref_pilots+channel_est1_2.*ref_pilots).*... 52 | squeeze(rx_pilots(1,:,:)).*conj(scramble_patt)); 53 | phase_error_est2 = sum(conj(channel_est2_1.*ref_pilots+channel_est2_2.*ref_pilots).*... 54 | squeeze(rx_pilots(2,:,:)).*conj(scramble_patt)); 55 | 56 | phase_error_est = angle(phase_error_est1+phase_error_est2); 57 | 58 | correction_phases = zeros(2, sim_consts.NumDataSubc, num_symbols); 59 | correction_phases(1,:,:) = repmat(phase_error_est, sim_consts.NumDataSubc, 1); 60 | correction_phases(2,:,:) = repmat(phase_error_est, sim_consts.NumDataSubc, 1); 61 | end 62 | -------------------------------------------------------------------------------- /802_11a_mmodel/tx_power_amplifier.m: -------------------------------------------------------------------------------- 1 | % AMP - Non-linear power amplifier 2 | % 3 | % usage:[out,inPow,outPow,P3,P_I]=tx_power_amplifier(in,one_dB,G,R,s,N); 4 | % [out,inPow,outPow]=tx_power_amplifier(in,1,1,R,s,N,T); 5 | % 6 | % in: Input data stream 7 | % one_dB: Output power at 1 db compression point for amplifier (dBW) 8 | % G: Linear Gain of the amplifier (dB) 9 | % R: Source Impedance 10 | % s: Knee sharpness of limiter 11 | % N: Number of samples in one period for power estimation 12 | % 13 | % out: Output data stream 14 | % inPow: Estimate of input power. (dB) 15 | % outPow: Estimate of output power (dB) 16 | % P3: Estimate of third order intermod products power (dB) 17 | % PI: Estimate of third order intercept power (dB) 18 | function [out,inPow,outPow,P3,P_I]=amp(in,one_dB,G,R,s,N,T); 19 | % 20 | % REFERENCES: 21 | % 22 | % TARGET: 23 | % 24 | % REVISION HISTORY: 25 | % DATE AUTHOR DESCRIPTION STR 26 | % 02-28-97 John D Terry Original Code 27 | % 28 | %******************************************************************************* 29 | [r,q]=size(in); 30 | 31 | if r>q 32 | in=in.'; 33 | L=r; 34 | else 35 | L=q; 36 | end 37 | 38 | if ~(r == 1 | q == 1) 39 | error('input must be a vector'); 40 | end 41 | % 42 | % Compute square of each sample 43 | % 44 | square=in.*conj(in); 45 | % 46 | % Group data into integral number of periods for power estimation 47 | % 48 | integral=reshape(square(1:N*floor(L/N)),N,floor(L/N)); 49 | % 50 | % Compute power estimates 51 | % 52 | P_est=mean(integral'); 53 | % 54 | % Compute average Input Power 55 | % 56 | P_avg=10*log10(mean(P_est'))-10*log10(R); 57 | inPow=P_avg; 58 | if nargin==6 59 | % 60 | % Linear Gain and correction for limiting amplifier's gain 61 | % 62 | G=G+20*log10(.7); 63 | k1=10^(G/20); 64 | % 65 | % Compute coefficient of cubic power needed to meet third order intercept point 66 | % 67 | k3=10^((30*log10(k1)-10*log10(17.33)-one_dB-10*log10(R))/10); 68 | % 69 | % Compute AM/AM modulation distortion for linear region 70 | % 71 | third_order=in*k1-k3*in.^3+1e-38; 72 | % 73 | % Compute AM/AM modulation distortion for linear region 74 | % 75 | if inPow+G > one_dB + 2 76 | g1=10^((G-1)/20); 77 | third_order=g1*in+1e-38; 78 | end 79 | % 80 | % Third order intercept power dBW 81 | % 82 | P_I=10*log10(2/3*k1^3/k3/R); 83 | % 84 | % Third order intermod product power dBW 85 | % 86 | P3=3*P_avg-2*P_I; 87 | % 88 | % Asymptotic output level of limiter 89 | % 90 | LL=10^((one_dB+1)/20)*sqrt(R); 91 | % 92 | % Limiter Output 93 | % 94 | out=LL*sign(third_order)./(1+(.7*LL./abs(third_order)).^s).^inv(s); 95 | elseif nargin==7 96 | % 97 | % Asymptotic output level of limiter 98 | % 99 | LL=10^((max(T(:,2))+4)/20)*sqrt(R); 100 | % 101 | % Spline Fit 102 | % 103 | T=((10*ones(size(T))).^(T/10)*R); 104 | PP=spline(T(:,1),(T(:,2)./T(:,1))); 105 | sqr=(conv(ones(1,N)/N,in.*conj(in))); 106 | out=(sqrt(ppval(PP,sqr(N/2:(N/2-1+length(in)))))).*(in+1e-15*max(in)); 107 | % 108 | % Limiter Output 109 | % 110 | out=LL*sign(out)./(1+(LL./abs(out)).^s).^inv(s); 111 | end 112 | % 113 | % Estimate Output Power 114 | % 115 | OP=out.*conj(out); 116 | sum_out=reshape(OP(1:N*floor(L/N)),N,floor(L/N)); 117 | P_nat=mean(sum_out); 118 | outPow=10*log10(mean(P_nat))-10*log10(R); 119 | -------------------------------------------------------------------------------- /802_11a_mmodel/main.m: -------------------------------------------------------------------------------- 1 | 2 | % ------------------------------------------------------------------ 3 | % Projet : 4 | % Filename : main.m 5 | % Description : This communication system consists of transmitter 6 | % and receiver. 7 | % Author : 8 | % Data : 08/03/2020 9 | % ------------------------------------------------------------------ 10 | clc;clear all; close all; 11 | 12 | global sim_options; 13 | global sim_consts; 14 | 15 | pkt_length = 8* 100; 16 | %conv_code_rate = ['R1/2', 'R2/3', 'R3/4']; 17 | conv_code_rate = 'R1/2'; 18 | interleave_bits = 1; 19 | %modulation = ['BPSK', 'QPSK', '16QAM', '64QAM']; 20 | modulation = 'BPSK'; 21 | use_tx_div = 0; 22 | use_rx_div = 0; 23 | freq_error = 0; 24 | chan_model = 'AWGN'; 25 | exp_decay_trms = 50; 26 | snr = 10; 27 | use_tx_pa = 0; 28 | use_phase_noise = 0; 29 | phase_noise_dbc = -90; 30 | phase_noise_cfreq = 30000; 31 | phase_noise_floor = -140; 32 | packet_detection = 0; 33 | tx_pwr_spectrum_test = 0; 34 | fine_time_sync = 0; 35 | freq_sync = 0; 36 | pilot_phase_tracking = 0; 37 | channel_estimation = 0; 38 | rx_timing_offset = -3; 39 | pkts_per_run = 100; 40 | 41 | sim_options = struct( 'PacketLength', pkt_length, ... 42 | 'ConvCodeRate', conv_code_rate, ... 43 | 'InterleaveBits', interleave_bits, ... 44 | 'Modulation', modulation,... 45 | 'UseTxDiv', use_tx_div, ... 46 | 'UseRxDiv', use_rx_div, ... 47 | 'FreqError', freq_error, ... 48 | 'ChannelModel', chan_model, ... 49 | 'ExpDecayTrms', exp_decay_trms, ... 50 | 'SNR', snr,... 51 | 'UseTxPA', use_tx_pa, ... 52 | 'UsePhaseNoise', use_phase_noise, ... 53 | 'PhaseNoisedBcLevel', phase_noise_dbc, ... 54 | 'PhaseNoiseCFreq', phase_noise_cfreq, ... 55 | 'PhaseNoiseFloor', phase_noise_floor, ... 56 | 'PacketDetection', packet_detection, ... 57 | 'TxPowerSpectrum', tx_pwr_spectrum_test, ... 58 | 'FineTimeSync', fine_time_sync, ... 59 | 'FreqSync', freq_sync, ... 60 | 'PilotPhaseTracking', pilot_phase_tracking, ... 61 | 'ChannelEstimation', channel_estimation, ... 62 | 'RxTimingOffset', rx_timing_offset, ... 63 | 'PktsToSimulate', pkts_per_run); 64 | 65 | sim_consts = struct( 'SampFreq' , 20e6, ... 66 | 'ConvCodeGenPoly', [1 0 1 1 0 1 1;1 1 1 1 0 0 1 ], ... 67 | 'NumSubc', 52, ... 68 | 'UsedSubcIdx', [7:32 34:59]', ... 69 | 'ShortTrainingSymbols', sqrt(13/6)*[0 0 1+j 0 0 0 -1-j 0 0 0 1+j 0 0 0 -1-j 0 0 0 -1-j 0 0 0 1+j 0 0 0 0 0 0 -1-j 0 0 0 -1-j 0 0 0 ... 70 | 1+j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0], ... 71 | 'LongTrainingSymbols', [1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 ... 72 | 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1], ... 73 | 'ExtraNoiseSamples', 500, ... 74 | 'PilotScramble', [1 1 1 1 -1 -1 -1 1 -1 -1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 1 1 -1 1 1 1 1 ... 75 | 1 1 -1 1 1 1 -1 1 1 -1 -1 1 1 1 -1 1 -1 -1 -1 1 -1 1 -1 -1 1 -1 -1 1 1 1 1 1 -1 -1 1 ... 76 | 1 -1 -1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 -1 -1 -1 1 -1 -1 1 -1 1 1 1 1 -1 1 -1 1 -1 1 -1 ... 77 | -1 -1 -1 -1 1 -1 1 1 -1 1 -1 1 1 1 -1 -1 1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 -1 -1], ... 78 | 'NumDataSubc', 48, ... 79 | 'NumPilotSubc' , 4, ... 80 | 'DataSubcIdx', [7:11 13:25 27:32 34:39 41:53 55:59]', ... 81 | 'PilotSubcIdx', [12 26 40 54]', ... 82 | 'PilotSubcPatt', [6 20 33 47]', ... 83 | 'DataSubcPatt', [1:5 7:19 21:26 27:32 34:46 48:52]', ... 84 | 'PilotSubcSymbols' , [1;1;1;-1]); 85 | 86 | % Set Random number generators initial state, reset random number generators based on current clock value 87 | rand('state',sum(100*clock)); 88 | randn('state',sum(100*clock)); 89 | 90 | 91 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 92 | % Main simulation loop 93 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 94 | start_time = clock; 95 | 96 | % Initialize trellis tables for Viterbi decoding 97 | rx_init_viterbi; 98 | 99 | % counters for information bits 100 | num_inf_bits = 0; 101 | num_inf_bit_errors = 0; 102 | num_inf_packet_errors = 0; 103 | inf_ber = 0; 104 | inf_per = 0; 105 | 106 | % counters for raw (uncoded) bits 107 | num_raw_bits = 0; 108 | num_raw_bit_errors = 0; 109 | num_raw_packet_errors = 0; 110 | raw_ber = 0; 111 | raw_per = 0; 112 | 113 | % Simulation the number of packets specified 114 | packet_count = 0; 115 | while packet_count < sim_options.PktsToSimulate 116 | packet_count = packet_count + 1; 117 | 118 | packet_start_time = clock; 119 | 120 | % Simulate one packet with the current options 121 | [inf_bit_cnt, inf_bit_errors, raw_bits_cnt, raw_bit_errors] = single_packet(sim_options); 122 | num_inf_bits = num_inf_bits + inf_bit_cnt; 123 | num_inf_bit_errors = num_inf_bit_errors + inf_bit_errors; 124 | num_inf_packet_errors = num_inf_packet_errors + (inf_bit_errors~=0); 125 | inf_ber = num_inf_bit_errors/num_inf_bits; 126 | inf_per = num_inf_packet_errors/packet_count; 127 | 128 | num_raw_bits = num_raw_bits + raw_bits_cnt; 129 | num_raw_bit_errors = num_raw_bit_errors + raw_bit_errors; 130 | num_raw_packet_errors = num_raw_packet_errors + (raw_bit_errors~=0); 131 | raw_ber = num_raw_bit_errors/num_raw_bits; 132 | raw_per = num_raw_packet_errors/packet_count; 133 | 134 | packet_stop_time = clock; 135 | packet_duration = etime(packet_stop_time, packet_start_time); 136 | 137 | % Display results 138 | fprintf('%8s %8s %9s %10s %8s %10s %10s %9s\n', ... 139 | ' Packet |', ' Time |', 'raw errs |', ' raw BER |', 'data errs |',' data BER |', ' raw PER |', 'data PER'); 140 | fprintf('%7d |%7g | %8d |%10.2e |%10d |%10.2e |%10.2e |%10.2e\n',... 141 | packet_count, packet_duration, raw_bit_errors, raw_ber, inf_bit_errors, inf_ber, raw_per, inf_per); 142 | 143 | % read event queue 144 | drawnow; 145 | end 146 | 147 | stop_time = clock; 148 | elapsed_time = etime(stop_time,start_time); 149 | 150 | fprintf('Simulation duration: %g seconds\n',elapsed_time); 151 | -------------------------------------------------------------------------------- /802_11a_mmodel/ui_start.m: -------------------------------------------------------------------------------- 1 | function fig = ui_start() 2 | % This is the machine-generated representation of a Handle Graphics object 3 | % and its children. Note that handle values may change when these objects 4 | % are re-created. This may cause problems with any callbacks written to 5 | % depend on the value of the handle at the time the object was saved. 6 | % This problem is solved by saving the output as a FIG-file. 7 | % 8 | % To reopen this object, just type the name of the M-file at the MATLAB 9 | % prompt. The M-file and its associated MAT-file must be on your path. 10 | % 11 | % NOTE: certain newer features in MATLAB may not have been saved in this 12 | % M-file due to limitations of this format, which has been superseded by 13 | % FIG-files. Figures which have been annotated using the plot editor tools 14 | % are incompatible with the M-file/MAT-file format, and should be saved as 15 | % FIG-files. 16 | 17 | load ui_start 18 | 19 | h0 = figure('Units','points', ... 20 | 'Color',[0.8 0.8 0.8], ... 21 | 'Colormap',mat0, ... 22 | 'FileName','ui_start.m', ... 23 | 'MenuBar','none', ... 24 | 'Name','WLAN Simulator', ... 25 | 'NumberTitle','off', ... 26 | 'PaperPosition',[18 180 576 432], ... 27 | 'PaperUnits','points', ... 28 | 'Position',[114 277.5 575.25 220.5], ... 29 | 'Resize','on', ... 30 | 'Tag','UIFigure', ... 31 | 'ToolBar','none'); 32 | h1 = uicontrol('Parent',h0, ... 33 | 'Units','points', ... 34 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 35 | 'HorizontalAlignment','left', ... 36 | 'ListboxTop',0, ... 37 | 'Position',[18.75 187.5 93.75 18.75], ... 38 | 'String','Packet Length (Bytes)', ... 39 | 'Style','text', ... 40 | 'Tag','StaticText1'); 41 | h1 = uicontrol('Parent',h0, ... 42 | 'Units','points', ... 43 | 'BackgroundColor',[1 1 1], ... 44 | 'Callback','ui_check_params', ... 45 | 'HorizontalAlignment','left', ... 46 | 'ListboxTop',0, ... 47 | 'Position',[18.75 168.75 93.75 18.75], ... 48 | 'String','100', ... 49 | 'Style','edit', ... 50 | 'Tag','PktLen'); 51 | h1 = uicontrol('Parent',h0, ... 52 | 'Units','points', ... 53 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 54 | 'FontSize',9, ... 55 | 'HorizontalAlignment','left', ... 56 | 'ListboxTop',0, ... 57 | 'Position',[18.75 131.25 168.75 18.75], ... 58 | 'String','Convolutional code rate', ... 59 | 'Style','text', ... 60 | 'Tag','StaticText1'); 61 | h1 = uicontrol('Parent',h0, ... 62 | 'Units','points', ... 63 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 64 | 'ListboxTop',0, ... 65 | 'Position',[112.5 131.25 75 18.75], ... 66 | 'String',['R1/2';'R2/3';'R3/4'], ... 67 | 'Style','popupmenu', ... 68 | 'Tag','ConvCodeRate', ... 69 | 'Value',1); 70 | h1 = uicontrol('Parent',h0, ... 71 | 'Units','points', ... 72 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 73 | 'FontSize',9, ... 74 | 'HorizontalAlignment','left', ... 75 | 'ListboxTop',0, ... 76 | 'Position',[18.75 93.75 168.75 18.75], ... 77 | 'String','Modulation', ... 78 | 'Style','text', ... 79 | 'Tag','StaticText1'); 80 | h1 = uicontrol('Parent',h0, ... 81 | 'Units','points', ... 82 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 83 | 'ListboxTop',0, ... 84 | 'Position',[112.5 93.75 75 18.75], ... 85 | 'String',['BPSK ';'QPSK ';'16QAM';'64QAM'], ... 86 | 'Style','popupmenu', ... 87 | 'Tag','Modulation', ... 88 | 'Value',1); 89 | h1 = uicontrol('Parent',h0, ... 90 | 'Units','points', ... 91 | 'BackgroundColor',[1 1 1], ... 92 | 'Callback','ui_check_params', ... 93 | 'HorizontalAlignment','left', ... 94 | 'ListboxTop',0, ... 95 | 'Position',[206.25 168.75 93.75 18.75], ... 96 | 'String','0', ... 97 | 'Style','edit', ... 98 | 'Tag','FreqError'); 99 | h1 = uicontrol('Parent',h0, ... 100 | 'Units','points', ... 101 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 102 | 'HorizontalAlignment','left', ... 103 | 'ListboxTop',0, ... 104 | 'Position',[206.25 187.5 93.75 18.75], ... 105 | 'String','Frequency Error', ... 106 | 'Style','text', ... 107 | 'Tag','StaticText1'); 108 | h1 = uicontrol('Parent',h0, ... 109 | 'Units','points', ... 110 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 111 | 'HorizontalAlignment','left', ... 112 | 'ListboxTop',0, ... 113 | 'Position',[206.25 150 93.75 13.5], ... 114 | 'String','Channel Model', ... 115 | 'Style','text', ... 116 | 'Tag','StaticText1'); 117 | h1 = uicontrol('Parent',h0, ... 118 | 'Units','points', ... 119 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 120 | 'Callback','ui_check_params', ... 121 | 'ListboxTop',0, ... 122 | 'Position',[206.25 131.25 93.75 18.75], ... 123 | 'String','AWGN', ... 124 | 'Style','radiobutton', ... 125 | 'Tag','AWGN', ... 126 | 'Enable','inactive', ... 127 | 'Value',1); 128 | h1 = uicontrol('Parent',h0, ... 129 | 'Units','points', ... 130 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 131 | 'HorizontalAlignment','left', ... 132 | 'ListboxTop',0, ... 133 | 'Position',[206.25 75 93.75 13.5], ... 134 | 'String','Signal to Noise Ratio (dB)', ... 135 | 'Style','text', ... 136 | 'Tag','StaticText1'); 137 | h1 = uicontrol('Parent',h0, ... 138 | 'Units','points', ... 139 | 'BackgroundColor',[1 1 1], ... 140 | 'Callback','ui_check_params', ... 141 | 'HorizontalAlignment','left', ... 142 | 'ListboxTop',0, ... 143 | 'Position',[206.25 56.25 93.75 18.75], ... 144 | 'String','10', ... 145 | 'Style','edit', ... 146 | 'Tag','SNR'); 147 | h1 = uicontrol('Parent',h0, ... 148 | 'Units','points', ... 149 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 150 | 'FontSize',9, ... 151 | 'HorizontalAlignment','left', ... 152 | 'ListboxTop',0, ... 153 | 'Position',[450 187.5 112.5 18.75], ... 154 | 'String','Synchronization algorithms', ... 155 | 'Style','text', ... 156 | 'Tag','StaticText1'); 157 | h1 = uicontrol('Parent',h0, ... 158 | 'Units','points', ... 159 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 160 | 'Callback','ui_check_params', ... 161 | 'ListboxTop',0, ... 162 | 'Position',[450 168.75 112.5 18.75], ... 163 | 'String','Packet Detection', ... 164 | 'Style','checkbox', ... 165 | 'Tag','PacketDetection'); 166 | h1 = uicontrol('Parent',h0, ... 167 | 'Units','points', ... 168 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 169 | 'Callback','ui_check_params', ... 170 | 'ListboxTop',0, ... 171 | 'Position',[450 150 112.5 18.75], ... 172 | 'String','Fine Time Sync', ... 173 | 'Style','checkbox', ... 174 | 'Tag','FineTimeSync'); 175 | h1 = uicontrol('Parent',h0, ... 176 | 'Units','points', ... 177 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 178 | 'Callback','ui_check_params', ... 179 | 'ListboxTop',0, ... 180 | 'Position',[450 131.25 112.5 18.75], ... 181 | 'String','Frequency Sync', ... 182 | 'Style','checkbox', ... 183 | 'Tag','FreqSync'); 184 | h1 = uicontrol('Parent',h0, ... 185 | 'Units','points', ... 186 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 187 | 'Callback','ui_check_params', ... 188 | 'ListboxTop',0, ... 189 | 'Position',[450 112.5 112.5 18.75], ... 190 | 'String','Pilot Phase Tracking', ... 191 | 'Style','checkbox', ... 192 | 'Tag','PilotPhaseTrack'); 193 | h1 = uicontrol('Parent',h0, ... 194 | 'Units','points', ... 195 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 196 | 'BusyAction','cancel', ... 197 | 'Callback','ui_start_sim', ... 198 | 'Interruptible','off', ... 199 | 'ListboxTop',0, ... 200 | 'Position',[450 18.75 93.75 18.75], ... 201 | 'String','Start Simulation', ... 202 | 'Tag','Pushbutton1'); 203 | h1 = uicontrol('Parent',h0, ... 204 | 'Units','points', ... 205 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 206 | 'Callback','ui_check_params', ... 207 | 'Enable','on', ... 208 | 'ListboxTop',0, ... 209 | 'Position',[206.25 112.5 93.75 18.75], ... 210 | 'String','Exponential decay', ... 211 | 'Style','radiobutton', ... 212 | 'Tag','ExponentialDecay'); 213 | h1 = uicontrol('Parent',h0, ... 214 | 'Units','points', ... 215 | 'BackgroundColor',[1 1 1], ... 216 | 'Callback','ui_check_params', ... 217 | 'HorizontalAlignment','left', ... 218 | 'ListboxTop',0, ... 219 | 'Position',[450 37.5 93.75 18.75], ... 220 | 'String','100', ... 221 | 'Style','edit', ... 222 | 'Tag','PktsToSimulate'); 223 | h1 = uicontrol('Parent',h0, ... 224 | 'Units','points', ... 225 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 226 | 'FontSize',9, ... 227 | 'HorizontalAlignment','left', ... 228 | 'ListboxTop',0, ... 229 | 'Position',[450 75 112.5 18.75], ... 230 | 'String','Rx timing offset', ... 231 | 'Style','text', ... 232 | 'Tag','StaticText1'); 233 | h1 = uicontrol('Parent',h0, ... 234 | 'Units','points', ... 235 | 'BackgroundColor',[1 1 1], ... 236 | 'Callback','ui_check_params', ... 237 | 'HorizontalAlignment','left', ... 238 | 'ListboxTop',0, ... 239 | 'Position',[506.25 75 56.25 18.75], ... 240 | 'String','-3', ... 241 | 'Style','edit', ... 242 | 'Tag','RxTimingOffset'); 243 | h1 = uicontrol('Parent',h0, ... 244 | 'Units','points', ... 245 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 246 | 'Callback','ui_check_params', ... 247 | 'ListboxTop',0, ... 248 | 'Position',[450 93.75 112.5 18.75], ... 249 | 'String','Channel Estimation', ... 250 | 'Style','checkbox', ... 251 | 'Tag','ChannelEst'); 252 | h1 = uicontrol('Parent',h0, ... 253 | 'Units','points', ... 254 | 'BackgroundColor',[1 1 1], ... 255 | 'Callback','ui_check_params', ... 256 | 'HorizontalAlignment','left', ... 257 | 'ListboxTop',0, ... 258 | 'Position',[206.25 93.75 37.5 18.75], ... 259 | 'String','50', ... 260 | 'Style','edit', ... 261 | 'Tag','ExpDecayTrms'); 262 | h1 = uicontrol('Parent',h0, ... 263 | 'Units','points', ... 264 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 265 | 'FontSize',9, ... 266 | 'HorizontalAlignment','left', ... 267 | 'ListboxTop',0, ... 268 | 'Position',[243.75 93.75 56.25 18.75], ... 269 | 'String','T rms (ns)', ... 270 | 'Style','text', ... 271 | 'Tag','StaticText1'); 272 | h1 = uicontrol('Parent',h0, ... 273 | 'Units','points', ... 274 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 275 | 'Callback','ui_check_params', ... 276 | 'ListboxTop',0, ... 277 | 'Position',[18.75 112.5 168.75 18.75], ... 278 | 'String','Interleave Bits', ... 279 | 'Style','checkbox', ... 280 | 'Tag','InterleaveBits', ... 281 | 'Value',1); 282 | h1 = uicontrol('Parent',h0, ... 283 | 'Units','points', ... 284 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 285 | 'HorizontalAlignment','left', ... 286 | 'ListboxTop',0, ... 287 | 'Position',[450 56.25 93.75 13.5], ... 288 | 'String','Packets to simulate', ... 289 | 'Style','text', ... 290 | 'Tag','StaticText1'); 291 | h1 = uicontrol('Parent',h0, ... 292 | 'Units','points', ... 293 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 294 | 'Callback','ui_check_params', ... 295 | 'ListboxTop',0, ... 296 | 'Position',[18.75 56.25 168.75 18.75], ... 297 | 'String','Transmitter diversity', ... 298 | 'Style','checkbox', ... 299 | 'Tag','UseTxDiversity'); 300 | h1 = uicontrol('Parent',h0, ... 301 | 'Units','points', ... 302 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 303 | 'Callback','ui_check_params', ... 304 | 'ListboxTop',0, ... 305 | 'Position',[18.75 37.5 168.75 18.75], ... 306 | 'String','Receiver diversity', ... 307 | 'Style','checkbox', ... 308 | 'Tag','UseRxDiversity'); 309 | h1 = uicontrol('Parent',h0, ... 310 | 'Units','points', ... 311 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 312 | 'Callback','ui_check_params', ... 313 | 'ListboxTop',0, ... 314 | 'Position',[318.75 187.5 112.5 18.75], ... 315 | 'String','Tx Power Amplifier', ... 316 | 'Style','checkbox', ... 317 | 'Tag','UseTxPA'); 318 | h1 = uicontrol('Parent',h0, ... 319 | 'Units','points', ... 320 | 'BackgroundColor',[1 1 1], ... 321 | 'Callback','ui_check_params', ... 322 | 'HorizontalAlignment','left', ... 323 | 'ListboxTop',0, ... 324 | 'Position',[318.75 131.25 37.5 18.75], ... 325 | 'String','-90', ... 326 | 'Style','edit', ... 327 | 'Tag','PhaseNoiseDbcLevel'); 328 | h1 = uicontrol('Parent',h0, ... 329 | 'Units','points', ... 330 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 331 | 'FontSize',9, ... 332 | 'HorizontalAlignment','left', ... 333 | 'ListboxTop',0, ... 334 | 'Position',[356.25 131.25 75 18.75], ... 335 | 'String','dBc level (dB)', ... 336 | 'Style','text', ... 337 | 'Tag','StaticText1'); 338 | h1 = uicontrol('Parent',h0, ... 339 | 'Units','points', ... 340 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 341 | 'Callback','ui_check_params', ... 342 | 'ListboxTop',0, ... 343 | 'Position',[318.75 150 112.5 18.75], ... 344 | 'String','Phase Noise', ... 345 | 'Style','checkbox', ... 346 | 'Tag','UsePhaseNoise'); 347 | h1 = uicontrol('Parent',h0, ... 348 | 'Units','points', ... 349 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 350 | 'FontSize',9, ... 351 | 'HorizontalAlignment','left', ... 352 | 'ListboxTop',0, ... 353 | 'Position',[356.25 112.5 75 18.75], ... 354 | 'String','Corner Frequency (Hz)', ... 355 | 'Style','text', ... 356 | 'Tag','StaticText1'); 357 | h1 = uicontrol('Parent',h0, ... 358 | 'Units','points', ... 359 | 'BackgroundColor',[1 1 1], ... 360 | 'Callback','ui_check_params', ... 361 | 'HorizontalAlignment','left', ... 362 | 'ListboxTop',0, ... 363 | 'Position',[318.75 112.5 37.5 18.75], ... 364 | 'String','30e3', ... 365 | 'Style','edit', ... 366 | 'Tag','PhaseNoiseCornerFreq'); 367 | h1 = uicontrol('Parent',h0, ... 368 | 'Units','points', ... 369 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 370 | 'FontSize',9, ... 371 | 'HorizontalAlignment','left', ... 372 | 'ListboxTop',0, ... 373 | 'Position',[356.25 93.75 75 18.75], ... 374 | 'String','Phase noise floor (dB)', ... 375 | 'Style','text', ... 376 | 'Tag','StaticText1'); 377 | h1 = uicontrol('Parent',h0, ... 378 | 'Units','points', ... 379 | 'BackgroundColor',[1 1 1], ... 380 | 'Callback','ui_check_params', ... 381 | 'HorizontalAlignment','left', ... 382 | 'ListboxTop',0, ... 383 | 'Position',[318.75 93.75 37.5 18.75], ... 384 | 'String','-140', ... 385 | 'Style','edit', ... 386 | 'Tag','PhaseNoiseFloor'); 387 | h1 = uicontrol('Parent',h0, ... 388 | 'Units','points', ... 389 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 390 | 'Callback','ui_check_params', ... 391 | 'ListboxTop',0, ... 392 | 'Position',[318.75 56.25 112.5 18.75], ... 393 | 'String','Tx Spectrum Shape test', ... 394 | 'Style','checkbox', ... 395 | 'Tag','TxSpectrumShape'); 396 | h1 = uicontrol('Parent',h0, ... 397 | 'Units','points', ... 398 | 'BackgroundColor',[0.752941176470588 0.752941176470588 0.752941176470588], ... 399 | 'HorizontalAlignment','left', ... 400 | 'ListboxTop',0, ... 401 | 'Position',[318.75 37.5 112.5 18.75], ... 402 | 'String','16x Oversampling, 4x IF Frequency', ... 403 | 'Style','text', ... 404 | 'Tag','StaticText1'); 405 | if nargout > 0, fig = h0; end 406 | --------------------------------------------------------------------------------