|
id | following:sounding:http:LICENSE:http: (id Implicit,[sounding] use beamweights computed in step2 License,[http] c SOURCE,[LICENSE] id,[http] id all) |
|
Scale for Tx | waveform ([0:1]) % OFDM params SC_IND_PILOTS |
|
id | N_ZPAD_POST () |
|
Number of data | symbols (one per data-bearing subcarrier per OFDM symbol) N_DATA_SC |
|
Modulation | order (2/4/16/64=BSPK/QPSK/16-QAM/64-QAM) % Rx processing params RECIP_PLOT=0 |
|
Number of CP samples to use in | FFT (on average) %% Define the preamble % LTS for fine CFO and channel estimation lts_f |
|
| ceil (N_BS_NODE/2) |
|
| bs_index (REF_ANT) |
|
| rx_cal_data_start (REF_ANT) |
|
if WIRED_UE | pilot_data_start (:) |
|
| dl_data_start (:) |
|
| rx_cal_data_start (:) |
|
end | precoding_in_mat (SC_IND_DATA, N_PILOTS_SYMS+1:end) |
|
| precoding_in_mat (SC_IND_PILOTS, N_PILOTS_SYMS+1:end) |
|
| recip_tx (nid+(nid >=REF_ANT), first:last) |
|
| recip_tx (REF_ANT, first:last) |
|
| uplink_pilot_tx (start_index+1:start_index+N_SYM_SAMP) |
|
initialize UE node_bs | sdrsync () |
|
Synchronize delays only for BS node_bs | sdrrxsetup () |
|
node_bs | sdr_setupbeacon () |
|
Burn beacon to the BS RAM node_ue | sdr_configgainctrl () |
|
end node_bs | set_tddconfig_single (1, schedule, i) |
|
configure the N_ZPAD_PRE | recip_tx (i, :) zeros(1 |
|
node_bs | sdrtx_single (tx_signal, i) |
|
Burn data to the UE RAM end node_bs | sdr_activate_rx () |
|
| rx_cal_data_start (ibs) |
|
| cal_mat (nid, :) |
|
end node_bs | set_tddconfig (1, schedule) |
|
end node_ue | set_tddconfig (WIRED_UE, ue_ul_sched) |
|
configure the N_ZPAD_PRE uplink_pilot_tx | zeros (1, N_ZPAD_POST)] |
|
node_ue | sdrtx_single (tx_signal, 1) |
|
Burn data to the UE RAM if ~WIRED_UE node_ue | sdr_setcorr () |
|
if ~WIRED_UE node_ue | sdr_unsetcorr () |
|
| plot (lts_corr) |
|
'UPLINK PILOT COLLECTION:No LTS Correlation Peaks Found!\n' | fprintf () |
|
Get sSecond peak | pilot_data_start (ibs) |
|
| corr_peak_all (ibs) |
|
if curr_offset< 0 rx_mat_calibrated_tmp(ibs, 1+abs(curr_offset):end)=rx_vec_pilot(ibs, 1:end-abs(curr_offset));elseif curr_offset > | rx_mat_calibrated_tmp (ibs, 1:end-curr_offset) |
|
else | rx_mat_calibrated_tmp (ibs, :) |
|
if pilotEnd | length (rx_vec_pilot) display('Bad Uplink Pilot(RX)') |
|
end | uplink_pilot_rx (ibs, :) |
|
| rx_fft (irp, :) |
|
end | uplink_pilot_csi (ibs, :) |
|
| tx_pilot_mat (ibs, :) |
|
| tx_payload_mat (ibs, :, isym-N_PILOTS_SYMS) |
|
Add preamble to one antenna for | sync (workaround to offset from beamformed preamble) syncSeq |
|
| syncSeq (1, :) |
|
| plot (abs(tx_vec_iris)) node_bs.sdrtx_single(tx_vec_iris |
|
activate reading stream node_bs | sdrtrigger () |
|
read data | rx_vec_dl (:, :) |
|
| fprintf ('Downlink Beacon Successful at UE %d \n', j) |
|
else | fprintf ('WARNING:NO Downlink Beacon Detected at UE %d \n', j) |
|
end end | if (all_ue_rx==N_UE_NODE) rx_vec_downlink |
|
use size of lts_t Stop if no valid correlation peak was found | if (isempty(lts_second_peak_index)) bad_cnt |
|
| fprintf ('DOWNLINK TRAINING:No LTS Correlation Peaks Found! Count:%d \n', bad_cnt) |
|
| fprintf ('CORR. PEAK AT:%d, PILOT STARTS AT:%d \n', offset-1, dl_pilot_start) |
|
end Another correlation | method (similar performance to code above)... if 0 lts_rep_dl |
|
lts | length () |
|
| fprintf ('CORR. ALT. PEAK AT:%d \n', max_idx_dl) |
|
|
if ~isloaded pyversion usr bin python py print() %weird bug where py isn 't loaded in an external script end py.importlib.import_module( 'iris_py') % Params Enable writing plots to PNG Iris | params = pyversion |
|
| WIRED_UE = 0 |
|
| TX_FRQ = 3.6e9 |
|
| RX_FRQ = TX_FRQ |
|
| TX_GN = 80 |
|
| RX_GN = 70 |
|
| SMPL_RT = 5e6 |
|
| N_FRM = 1 |
|
| bs_ids = string.empty() |
|
| bs_sched = string.empty() |
|
| ue_sched = string.empty() |
|
Waveform params | TX_SCALE = 1 |
|
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_SYM_SAMP = N_SC + CP_LEN |
|
Number of samples that will go over the air | N_SAMP = 4096 |
|
| N_ZPAD_PRE = 160 |
|
Number of OFDM symbols for | burst |
|
Number of OFDM symbols for it needs to be less than | N_PILOTS_SYMS = 2 |
|
| N_DATA_SYMS = (N_OFDM_SYMS - N_PILOTS_SYMS) |
|
| MOD_ORDER = 4 |
|
| PILOT_PLOT = 1 |
|
| DOWNLINK_PLOT = 1 |
|
| AUTO_OFFSET = 1 |
|
| FFT_OFFSET = 0 |
|
| lts_t = ifft(lts_f, 64) |
|
time domain | lts = [lts_t(49:64) lts_t] |
|
| lts_lcp = [lts_t(33:64) lts_t lts_t] |
|
LTS Init Iris nodes Set up the Iris experiment Create BS Hub and UE objects | Note |
|
else | hub_id = [] |
|
end Last node in list is calibration node | ! bs_ids = ["RF3E000674", "RF3E000704", "RF3E000676", "RF3E000668", "RF3E000157"] |
|
| ue_ids = ["RF3E000119"] |
|
| beacon_node = 0 |
|
set to make all nodes send beacon | ref_calib_sched = "RGPG" |
|
| bs_calib_sched = "PGRG" |
|
| bs_ul_sched_beacon = "BGRG" |
|
| bs_ul_sched = "GGRG" |
|
| ue_ul_sched = "GGPG" |
|
| bs_dl_sched_beacon = "BGPG" |
|
| bs_dl_sched = "GGPG" |
|
| ue_dl_sched = "GGRG" |
|
| N_BS_NODE = length(bs_ids) |
|
| N_UE_NODE = 1 |
|
| REF_ANT = N_BS_NODE |
|
| bs_index = 1:N_BS_NODE |
|
Manually measured offsets for the start of data | rx_cal_data_start = 168 * ones(1, N_BS_NODE) |
|
| pilot_data_start = 150 * ones(1, N_BS_NODE) |
|
| dl_data_start = 305 |
|
end Generate a payload of random integers | tx_data = randi(MOD_ORDER, 1, N_DATA_SC) - 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_DATA_SYMS) |
|
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_DATA_SYMS) |
|
Construct the precoding input matrix | precoding_in_mat = zeros(N_SC, N_OFDM_SYMS) |
|
Insert the data and pilot | values |
|
other subcarriers will remain at for | i |
|
reciprocity calibration tx pilots | N_BS = N_BS_NODE - 1 |
|
| DATA_REP = floor(N_OFDM_SYMS / N_BS) |
|
| lts_rep = repmat(lts, 1, DATA_REP) |
|
| lts_rep_len = DATA_REP * N_SYM_SAMP |
|
| data_len = N_BS * lts_rep_len |
|
| recip_tx = zeros(N_BS_NODE, data_len) |
|
for | nid |
|
| last = nid * lts_rep_len |
|
end uplink tx piltos | UE_DATA_REP = N_OFDM_SYMS |
|
| ue_pilot_len = UE_DATA_REP * N_SYM_SAMP |
|
| uplink_pilot_tx = zeros(1, ue_pilot_len) |
|
for | rp |
|
end Iris nodes parameters | bs_sdr_params |
|
| ue_sdr_params = bs_sdr_params |
|
ue_sdr_params | id = ue_ids |
|
ue_sdr_params | n_sdrs = N_UE_NODE |
|
ue_sdr_params | tdd_sched = ue_sched |
|
ue_sdr_params | is_bs = 0 |
|
| node_bs = iris_py(bs_sdr_params, hub_id) |
|
initialize BS | node_ue = iris_py(ue_sdr_params, []) |
|
Step | __pad4__ |
|
| schedule = bs_calib_sched |
|
configure the | BS |
|
configure the N_ZPAD_PRE | recip_postfix_len |
|
activate reading | stream [rx_vec_iris, ~] = node_bs.sdrrx(N_SAMP) |
|
read data | a = 1 |
|
| unos = ones(size(conj(lts))) |
|
default offsets measured with prefix and | postfix |
|
| v1 = filter(unos, a, abs(rx_vec_iris(ibs, end - DATA_REP * N_SYM_SAMP: end)) .^ 2) |
|
| lts_corr = (abs(v0) .^ 2) ./ v1 |
|
normalized correlation position of the last | peak [~, max_idx] = max(abs(lts_corr)) |
|
| break |
|
end end end | recip_rx = zeros(N_BS_NODE, data_len) |
|
| rx_fft = zeros(N_BS, N_SC) |
|
| rx_fft_ref = zeros(N_BS, N_SC) |
|
| cal_mat = zeros(N_BS_NODE, N_SC) |
|
| first = rx_cal_data_start(REF_ANT) |
|
| recip_rx_ref = rx_vec_iris(REF_ANT, first:last) |
|
| recip_rx_ref_mat = reshape(recip_rx_ref, N_SYM_SAMP, DATA_REP, N_BS) |
|
| recip_ref_fft_mat = fft(recip_rx_ref_mat(CP_LEN+1:N_SYM_SAMP, :, :), N_SC, 1) |
|
| recip_rx_bs = rx_vec_iris(bs_index, 1:lts_rep_len) |
|
| recip_rx_bs_mat = reshape(recip_rx_bs, N_BS, N_SYM_SAMP, DATA_REP) |
|
| recip_bs_fft_mat = fft(recip_rx_bs_mat(:, CP_LEN+1:N_SYM_SAMP, :), N_SC, 2) |
|
end for | sid |
|
end | Step |
|
activate correlator | end [rx_vec_pilot_all, data_len_all] = node_bs.sdrrx(N_SAMP, 0) |
|
read data | pilot_rep = 1 |
|
| rx_vec_pilot = node_bs.get_best_frame(rx_vec_pilot_all, N_SAMP) |
|
| data0_len = length(rx_vec_pilot) |
|
activate correlator end | corr_peak_all = zeros(1, N_BS_NODE) |
|
if AUTO_OFFSET for | ibs |
|
| figure |
|
| lts_peaks = find(lts_corr > 0.8*max(lts_corr)) |
|
| return |
|
end | offset = lts_peaks(lts_second_peak_index(1)) - (2*length(lts)) |
|
| v0 = filter(fliplr(conj(uplink_pilot_tx)), a, rx_vec_pilot(ibs, :)) |
|
| m_filt = (abs(v0) .^ 2) ./ v1 |
|
normalized | correlation [~, max_idx] = max(abs(m_filt)) |
|
In case of bad | correlatons |
|
end end end Sample offset calibration | samp_offset_array = corr_peak_all - corr_peak_all(1) |
|
| rx_mat_calibrated_tmp = zeros(size(rx_vec_pilot)) |
|
end end | uplink_pilot_rx = zeros(N_BS_NODE, ue_pilot_len) |
|
| uplink_pilot_csi = zeros(N_BS_NODE, N_SC) |
|
for | irp |
|
| ifft_in_mat = zeros(N_BS_NODE, N_SC, N_OFDM_SYMS) |
|
for | isc |
|
try | downlink_beam_weights = pinv(squeeze(downlink_pilot_csi(:, isc))) |
|
catch | stop = 1 |
|
end for | isym |
|
end end IFFT | tx_payload_mat = zeros(N_BS_NODE, N_SYM_SAMP, N_DATA_SYMS) |
|
| tx_pilot_mat = zeros(N_BS_NODE, length(lts_t)*2.5) |
|
| pilot2 = squeeze(ifft(ifft_in_mat(ibs, :, 2))) |
|
end end Reshape to a vector | tx_payload_vec = reshape(tx_payload_mat, N_BS_NODE, numel(tx_payload_mat(1, :, :))) |
|
end configure the | UE |
|
Write beamformed signal to all antennas | donwlink_postfix_len = N_SAMP - N_ZPAD_PRE - N_OFDM_SYMS * N_SYM_SAMP |
|
| tx_vec_iris = TX_SCALE .* tx_signal ./ max(abs(tx_signal)) |
|
activate correlator end Transmit beamformed signal from all antennas and receive at UEs | bad_pilot = true |
|
| bad_cnt = 0 |
|
| bad_cnt_max = 1000 |
|
while bad_pilot | rx_vec_dl = zeros(N_UE_NODE, N_SAMP) |
|
| rx_vec_downlink = zeros(N_UE_NODE, N_SAMP) |
|
| all_ue_rx = 0 |
|
for | j |
|
end Process downlink receive signal if AUTO_OFFSET Correlation | lts_rep_dl = repmat(lts_t, 1, N_PILOTS_SYMS) |
|
| dl_pilot_start = offset-(2.5*length(lts_t)) |
|