|
end | fprintf ("Channel type: %s \n", chan_type) |
|
Modulation | order (2/4/16/64=BSPK/QPSK/16-QAM/64-QAM) TX_SCALE=0.5 |
|
Scale for Tx | waveform ([0:1]) % OFDM params SC_IND_PILOTS = "iris" |
|
Number of data | symbols (one per data-bearing subcarrier per OFDM symbol) per UE N_LTS_SYM |
|
id | FFT_OFFSET () |
|
Number of CP samples to use in | FFT (on average) DO_APPLY_PHASE_ERR_CORRECTION |
|
| repmat (lts_t, N_LTS_SYM, 1)] |
|
other subcarriers will remain at | ifft_in_mat (SC_IND_DATA, :, :) |
|
| ifft_in_mat (SC_IND_PILOTS, :, :) |
|
Insert the cyclic prefix | if (CP_LEN > 0) tx_cp |
|
N_ZPAD_PRE, N_UE | zeros () |
|
| zeros (N_ZPAD_POST, N_UE)] |
|
abs(tx_vecs_iris | max () |
|
| if (N_BS_NODE > 1) b_scheds |
|
| sdr_params (2) |
|
| sdr_params (3) |
|
id | a () |
|
| lts_corr (ibs,:) |
|
Get the indices of N_UE largest corr values | lts_peaks (ibs,:) |
|
end | payload_ind (ibs) |
|
| rx_lts_mat (ibs,:) |
|
| payload_rx (ibs, 1:length(pl_idx) -1) |
|
| plot (lts_corr(sp,:)) |
|
| xlabel ('Samples') |
|
| ylabel (y_label) |
|
end | sgtitle ('LTS correlations accross antennas') end %% Rx processing % Construct a matrix from the received pilots n_plt_samp |
|
| Y_lts (:, iue,:) |
|
else Do nz_sc(j))' *H_hat(Apply nz_sc(j))') *squeeze(Y_data(end | syms_eq (:, nz_sc(j),:) |
|
| channel_condition (nz_sc(j)) |
|
| channel_condition_db (nz_sc(j)) |
|
else Define an empty phase correction | vector (used by plotting code below) pilot_phase_err |
|
id | D: (syms_eq_pc, N_UE,[] reshape) |
|
| figure (cf) |
|
| plot (real(tx_vecs_iris(:, sp))) |
|
| axis ([0 length(tx_vecs_iris(:, sp)) -TX_SCALE TX_SCALE]) grid on |
|
| title (sprintf('UE %d Tx Waveform(I)', sp)) |
|
| subplot (N_UE, 2, 2 *sp) |
|
| plot (imag(tx_vecs_iris(:, sp)), 'color', sec_clr) |
|
| title (sprintf('UE %d Tx Waveform(Q)', sp)) |
|
| plot (real(rx_vec_iris(sp,:))) |
|
| title (sprintf('BS antenna %d Rx Waveform(I)', sp)) |
|
| subplot (N_BS_NODE, 2, 2 *sp) |
|
| plot (imag(rx_vec_iris(sp,:)), 'color', sec_clr) |
|
| title (sprintf('BS antenna %d Rx Waveform(Q)', sp)) |
|
| plot (syms_eq_pc(:, sp), 'o', 'MarkerSize', 1, 'color', sec_clr) |
|
| axis (1.5 *[-1 1 -1 1]) |
|
| plot (tx_syms(:, sp),' *', 'MarkerSize', 10, 'LineWidth', 2, 'color', fst_clr) |
|
| title (sprintf('Equalized Uplink Tx and Rx symbols for stream %d', sp)) |
|
| legend ('Rx', 'Tx', 'Location', 'EastOutside', 'fontsize', 12) |
|
| plot (squeeze(Y_data(sp,:,:)), 'co', 'MarkerSize', 1) |
|
| axis (max(max(max(abs(Y_data)))) *[-1 1 -1 1]) |
|
| title (sprintf('Unequalized received symbols at BS ant. %d', sp)) |
|
| subplot (N_BS_NODE, N_UE, sp) |
|
| bar (bw_span, fftshift(abs(squeeze(H_hat(ibs, iue, :)))), 1, 'LineWidth', 1) |
|
| title (sprintf('UE %d -> BS ant. %d Channel Estimates(Magnitude)', iue, ibs)) xlabel('Baseband Frequency(MHz)') end end subplot(N_BS_NODE+1 |
|
| set (bh, 'FaceColor', cond_clr) |
|
| title ('Channel Condition(dB)') xlabel('Baseband Frequency(MHz)') %% EVM &SNR sym_errs |
|
| evm_mat (:, sp) |
|
| aevms (sp) |
|
| snr_mat (sp) |
|
subplot(2, N_UE, sp) plot(100 *evm_mat( | legend ('Per-Symbol EVM', 'Average EVM', 'Location', 'NorthWest') |
|
| set (h, 'Color',[1 0 0]) set(h |
|
bold | set (h, 'FontSize', 10) set(h |
|
bold | set (h, 'BackgroundColor',[1 1 1]) title(sprintf('Stream from UE %d' |
|
| imagesc (1:N_OFDM_SYM,(SC_IND_DATA - N_SC/2), 100 *fftshift(reshape(evm_mat(:, sp), [], N_OFDM_SYM), 1)) |
|
| set (h, 'LineStyle',':') |
|
grid on | xlabel ('OFDM Symbol Index') |
|
| ylabel ('Subcarrier Index') |
|
| title (sprintf('Stream from UE %d', sp)) |
|
|
| Author (s)[version, executable, isloaded] = pyversion |
|
if ~isloaded pyversion usr bin python py print() %weird bug where py isn 't loaded in an external script end % Params Enable writing plots to PNG | CHANNEL = 11 |
|
Channel to tune Tx and Rx radios | SIM_MOD = 1 |
|
| DEBUG = 0 |
|
if SIM_MOD | chan_type = "rayleigh" |
|
Will use only Rayleigh for simulation | sim_SNR_db = 15 |
|
Iris | params |
|
| N_UE = 2 |
|
| TX_FRQ = 2.5e9 |
|
| RX_FRQ = TX_FRQ |
|
| TX_GN = 45 |
|
| TX_GN_ue = 48 |
|
| RX_GN = 23 |
|
| SMPL_RT = 5e6 |
|
| N_FRM = 50 |
|
| b_ids = string.empty() |
|
| b_scheds = string.empty() |
|
| ue_ids = string.empty() |
|
| ue_scheds = string.empty() |
|
| MIMO_ALG = 'ZF' |
|
MIMO | ALGORITHM |
|
Waveform params | N_OFDM_SYM = 44 |
|
Number of OFDM symbols for | burst |
|
Number of OFDM symbols for it needs to be less than | MOD_ORDER = 16 |
|
Pilot subcarrier indices | SC_IND_DATA = [2:7 9:21 23:27 39:43 45:57 59:64] |
|
Data subcarrier indices | SC_IND_DATA_PILOT = [2:27 39:64]' |
|
| N_SC = 64 |
|
Number of subcarriers | CP_LEN = 16 |
|
Cyclic prefix length | N_DATA_SYMS = N_OFDM_SYM * length(SC_IND_DATA) |
|
Number of | N_SYM_SAMP = N_SC + CP_LEN |
|
Number of samples that will go over the air | N_ZPAD_PRE = 90 |
|
Enable Residual CFO estimation correction Define the preamble LTS for fine CFO and channel estimation | lts_f |
|
| lts_t = ifft(lts_f, N_SC) |
|
| l_pre = length(preamble_common) |
|
| pre_z = zeros(size(preamble_common)) |
|
| preamble = zeros(N_UE * l_pre, N_UE) |
|
for | jp |
|
end Generate a payload of random integers | tx_data = randi(MOD_ORDER, N_DATA_SYMS, N_UE) - 1 |
|
| tx_syms = mod_sym(tx_data, MOD_ORDER) |
|
Reshape the symbol vector to a matrix with one column per OFDM symbol | tx_syms_mat = reshape(tx_syms, length(SC_IND_DATA), N_OFDM_SYM, N_UE) |
|
Define the pilot tone values as BPSK symbols | pilots = [1 1 -1 1].' |
|
Repeat the pilots across all OFDM symbols | pilots_mat = repmat(pilots, 1, N_OFDM_SYM, N_UE) |
|
IFFT Construct the IFFT input matrix | ifft_in_mat = zeros(N_SC, N_OFDM_SYM, N_UE) |
|
Insert the data and pilot | values |
|
Perform the IFFT | tx_payload_mat = ifft(ifft_in_mat, N_SC, 1) |
|
end Reshape to a vector | tx_payload_vecs = reshape(tx_payload_mat, ceil(numel(tx_payload_mat)/N_UE), N_UE) |
|
Leftover from zero | padding |
|
SIMULATION | __pad0__ |
|
SIMULATION | N_BS_NODE |
|
| rx_vec_iris = rx_vec_iris.' |
|
| b_prim_sched = "PGGGGGGGGGGRGGGG" |
|
BS primary node s | schedule |
|
| ue_sched = "GGGGGGGGGGGPGGGG" |
|
for | iu |
|
end number of samples in a frame | n_samp = length(tx_vecs_iris) |
|
Iris nodes parameters | sdr_params |
|
end | l_rx_dec =length(rx_vec_iris) |
|
| unos = ones(size(preamble_common')) |
|
| lts_corr = zeros(N_BS_NODE, length(rx_vec_iris)) |
|
| data_len = (N_OFDM_SYM)*(N_SC +CP_LEN) |
|
| rx_lts_mat = double.empty() |
|
| payload_ind = int32.empty() |
|
| payload_rx = zeros(N_BS_NODE, data_len) |
|
| lts_peaks = zeros(N_BS_NODE, N_UE) |
|
for | ibs |
|
| v1 = filter(unos,a,abs(rx_vec_iris(ibs,:)).^2) |
|
normalized correlation Sort the correlation values | sort_corr = sort(lts_corr(ibs,:), 'descend') |
|
Take the N_UE largest values | rho_max = sort_corr(1:N_UE) |
|
position of the last peak | max_idx = max(lts_peaks(ibs,:)) |
|
In case of bad | correlatons |
|
Real value doesn t matter since we have corrrupt | data |
|
| pream_ind_ibs = payload_ind(ibs) - length(preamble) |
|
| pl_idx = payload_ind(ibs) : payload_ind(ibs) + data_len |
|
end if DEBUG | figure |
|
end if DEBUG for | sp |
|
grid | on |
|
| y_label = sprintf('Anetnna %d',sp) |
|
for | iue |
|
end Take N_SC spamples from each LTS | rx_lts_idx = CP_LEN +1 : N_LTS_SYM * N_SC +CP_LEN |
|
| Y_lts = Y_lts(:,:,rx_lts_idx) |
|
Reshape the matix to have each lts pilot in a different | dimension |
|
Reshape the matix to have each lts pilot in a different | N_LTS_SYM |
|
Take | FFT |
|
Take Construct known pilot matrix to use i next | step |
|
Take Construct known pilot matrix to use i next N_BS_NODE *N_UE | lts_f_mat = reshape(lts_f_mat, [], N_LTS_SYM, N_UE, N_BS_NODE) |
|
Get the channel by dividing by the pilots | G_lts = Y_lts_f ./ lts_f_mat |
|
Estimate the channel by averaging over the two LTS | symbols |
|
| payload_noCP = payload_rx(:,CP_LEN-FFT_OFFSET+(1:N_SC),:) |
|
Take FFT | Y_data = fft(payload_noCP, N_SC, 2) |
|
Apply ZF by multiplying the pseudo inverse of H_hat[N_BS_NODE x NUE] for each | suubcarrier |
|
| channel_condition = double.empty() |
|
| channel_condition_db = double.empty() |
|
for | j |
|
| x = HH_inv*squeeze(Y_data(:,nz_sc(j),:)) |
|
else Do | yourselves |
|
else Do nz_sc(j))' *H_hat(Apply | BF |
|
end | DO_APPLY_PHASE_ERR_CORRECTION |
|
| pilots_f_mat_comp = pilots_f_mat.* permute(pilots_mat, [3 1 2]) |
|
| pilot_phase_err = angle(mean(pilots_f_mat_comp,2)) |
|
end | pilot_phase_err_corr = repmat(pilot_phase_err, 1, N_SC, 1) |
|
| pilot_phase_corr = exp(-1i*(pilot_phase_err_corr)) |
|
Apply the pilot phase correction per symbol | syms_eq_pc = syms_eq.* pilot_phase_corr |
|
Demodulate | rx_data = demod_sym(syms_eq_pc ,MOD_ORDER) |
|
Plot results | cf = 0 |
|
| fst_clr = [0, 0.4470, 0.7410] |
|
| sec_clr = [0.8500, 0.3250, 0.0980] |
|
| clf |
|
| myAxis = axis() |
|
tb | FontWeight = 'bold' |
|
else | sp_rows = ceil(N_BS_NODE/2)+1 |
|
end | sp_cols = ceil(N_BS_NODE/(sp_rows -1)) |
|
axis | square |
|
| cond_clr = [0.8500, 0.250, 0.1980] |
|
| bw_span = (20/N_SC) * (-(N_SC/2):(N_SC/2 - 1)).' |
|
| bh = bar(bw_span, fftshift(channel_condition_db) ,1, 'LineWidth', 1) |
|
| bit_errs = length(find(dec2bin(bitxor(tx_data(:), rx_data(:)),8) == '1')) |
|
| evm_mat = double.empty() |
|
| aevms = zeros(N_UE,1) |
|
| snr_mat = zeros(N_UE,1) |
|
| h = text(round(.05*length(evm_mat(:,sp))), 100*aevms(sp), sprintf('Effective SINR: %.1f dB', snr_mat(sp))) |
|
bold | EdgeColor |
|
hold | off |
|