diff --git a/targets/PROJECTS/TDDREC/v4_CH_EST/f_ch_est.m b/targets/PROJECTS/TDDREC/v4_CH_EST/f_ch_est.m new file mode 100644 index 0000000000000000000000000000000000000000..e488b505eec6548b2cd67fcf953ae71f0508fdac --- /dev/null +++ b/targets/PROJECTS/TDDREC/v4_CH_EST/f_ch_est.m @@ -0,0 +1,45 @@ + +% PURPOSE : channel estimation using least square method +%% ARGUMENTS : +% +% m_sym_T : transmitted symbol, d_N_f x d_N_ofdm x d_N_ant_act x d_N_meas +% m_sym_R : received symbol, d_N_f x d_N_ofdm x d_N_ant_act x d_N_meas +% d_N_meas : number of measurements +% +% OUTPUTS : +% +% m_H_est : estimation of sub-channels, d_N_antR x d_N_antT x d_N_f x d_N_meas +% +%********************************************************************************************** +% EURECOM - All rights reserved +% +% AUTHOR : Xiwen JIANG, Florian Kaltenberger +% +% DEVELOPMENT HISTORY : +% +% Date Name(s) Version Description +% ----------- ------------- ------- ------------------------------------------------------ +% Apr-29-2014 X. JIANG 0.1 creation of code +% +% REFERENCES/NOTES/COMMENTS : +% +% - Based on the function "runmeas_full_duplex" created by Mirsad Cirkic, Florian Kaltenberger. +% +%********************************************************************************************** +function m_H_est = f_ch_est(m_sym_T, m_sym_R) + +%% ** initialisation ** +[d_N_f,d_N_OFDM,d_N_antT,d_N_meas] = size(m_sym_T); +d_N_antR = size(m_sym_R,3); +m_H_est = zeros(d_N_antR,d_N_antT,d_N_f,d_N_meas); + +%% ** estimate the subband channel for each measurement and antenna ** +for d_n_meas = 1:d_N_meas + for d_n_f = 1:d_N_f + m_y = reshape(m_sym_R(d_n_f,:,:,d_n_meas),d_N_OFDM,d_N_antR).'; % squeeze: problem for antenna number = 1 case + m_s = reshape(m_sym_T(d_n_f,:,:,d_n_meas),d_N_OFDM,d_N_antT).'; + m_H_est(:,:,d_n_f,d_n_meas) = m_y*m_s'/(m_s*m_s'); % LS channel estimation + end +end + +end diff --git a/targets/PROJECTS/TDDREC/v4_CH_EST/f_ofdm_rx.m b/targets/PROJECTS/TDDREC/v4_CH_EST/f_ofdm_rx.m new file mode 100644 index 0000000000000000000000000000000000000000..ede1c646657e8bf1d94c611259530a9c53bf8845 --- /dev/null +++ b/targets/PROJECTS/TDDREC/v4_CH_EST/f_ofdm_rx.m @@ -0,0 +1,46 @@ +% +% PURPOSE : OFDM Receiver +% +% ARGUMENTS : +% +% m_sig_R : received signal with dimension ((d_N_FFT+d_N_CP)*d_N_ofdm) x d_N +% d_N_FFT : total carrier number +% d_N_CP : extented cyclic prefix +% d_N_OFDM : OFDM symbol number per frame +% v_active_rf : active RF antenna indicator +% +% OUTPUTS : +% +% m_sym_R : transmitted signal before IFFT with dimension d_N_f x d_N_ofdm x d_N_ant_act +% +%********************************************************************************************** +% EURECOM - All rights reserved +% +% AUTHOR : Xiwen JIANG, Florian Kaltenberger +% +% DEVELOPMENT HISTORY : +% +% Date Name(s) Version Description +% ----------- ------------- ------- ------------------------------------------------------ +% Apr-29-2014 X. JIANG 0.1 creation of code +% +% REFERENCES/NOTES/COMMENTS : +% +% - Based on the function "genrandpskseq" created by Mirsad Cirkic, Florian Kaltenberger. +% +%********************************************************************************************** +function m_sym_R = f_ofdm_rx(m_sig_R, d_N_FFT, d_N_CP, d_N_OFDM, v_active_rf) + +d_N_ant_act = sum(v_active_rf); +m_sig_R_eff = m_sig_R(:,find(v_active_rf)); +m_sig_R_f = reshape(m_sig_R_eff,(d_N_FFT+d_N_CP),d_N_OFDM,d_N_ant_act); + +%** delete the CP ** +m_sig_R_noCP = m_sig_R_f(d_N_CP+1:end,:,:); + +%** fft ** +m_sym_R_fft = 1/sqrt(d_N_FFT)*fft(m_sig_R_noCP,d_N_FFT,1); +%m_sym_R_fft = fft(m_sig_R_noCP,d_N_FFT,1); +m_sym_R = m_sym_R_fft([363:512 2:151],:,:); + +end diff --git a/targets/PROJECTS/TDDREC/v4_CH_EST/f_ofdm_tx.m b/targets/PROJECTS/TDDREC/v4_CH_EST/f_ofdm_tx.m new file mode 100644 index 0000000000000000000000000000000000000000..73e1fc656cfc2297c35957d4c55ed0c6363c04f7 --- /dev/null +++ b/targets/PROJECTS/TDDREC/v4_CH_EST/f_ofdm_tx.m @@ -0,0 +1,59 @@ +% +% PURPOSE : OFDM Transmitter +% +% ARGUMENTS : +% +% d_M : modulation order +% d_N_f : carrier number carrying data +% d_N_FFT : total carrier number +% d_N_CP : extented cyclic prefix +% d_N_OFDM : OFDM symbol number per frame +% v_active_rf : active RF antenna indicator +% d_amp : amplitude +% +% OUTPUTS : +% +% m_sym_T : transmitted signal before IFFT with dimension d_N_f x d_N_OFDM x d_N_ant_act +% m_sig_T : OFDM signal with dimension ((d_N_FFT+d_N_CP)*d_N_OFDM) x d_N_ant +% +%********************************************************************************************** +% EURECOM - All rights reserved +% +% AUTHOR : Xiwen JIANG, Florian Kaltenberger +% +% DEVELOPMENT HISTORY : +% +% Date Name(s) Version Description +% ----------- ------------- ------- ------------------------------------------------------ +% Apr-29-2014 X. JIANG 0.1 creation of code +% +% REFERENCES/NOTES/COMMENTS : +% +% - Based on the function "genrandpskseq" created by Mirsad Cirkic, Florian Kaltenberger. +% +%********************************************************************************************** +function [m_sym_T, m_sig_T] = f_ofdm_tx(d_M, d_N_f, d_N_FFT, d_N_CP, d_N_OFDM, v_active_rf, d_amp) + +d_N_ant_act = sum(v_active_rf); + +%** constellation table ** +v_MPSK = exp(sqrt(-1)*([1:d_M]*2*pi/d_M+pi/d_M)); +%** transmitted symbol ** +%v_state = [1;2;3;4]; +%rand("state",v_state); +m_sym_T = v_MPSK(ceil(rand(d_N_f, d_N_OFDM, d_N_ant_act)*d_M)); + +%** mapping useful data to favorable carriers ** +m_sym_T_ext = zeros(d_N_FFT,d_N_OFDM,d_N_ant_act); +m_sym_T_ext(2:151,:,:) = m_sym_T(151:300,:,:); +m_sym_T_ext(363:512,:,:) = m_sym_T(1:150,:,:); + +%** ifft ** +m_sig_T_ = sqrt(d_N_FFT)*ifft(m_sym_T_ext,d_N_FFT,1); + +%** add cyclic prefix ** +m_sig_T_ = [m_sig_T_(end-d_N_CP+1:end,:,:); m_sig_T_]; +d_L = (d_N_FFT+d_N_CP)*d_N_OFDM; +m_sig_T = floor(reshape(m_sig_T_,d_L,d_N_ant_act)*d_amp); + +end diff --git a/targets/PROJECTS/TDDREC/v4_CH_EST/s_H_est.m b/targets/PROJECTS/TDDREC/v4_CH_EST/s_H_est.m new file mode 100644 index 0000000000000000000000000000000000000000..dae3a7830b3ff709c1a3f9d899f9023ad001cb1a --- /dev/null +++ b/targets/PROJECTS/TDDREC/v4_CH_EST/s_H_est.m @@ -0,0 +1,110 @@ +% +% SCRIPT ID : s_H_est +% +% PROJECT NAME : TDD Recoprocity +% +% PURPOSE : full transmission and receive train for calibration channel estimation +% +%********************************************************************************************** +% Eurecom - All rights reserved +% +% AUTHOR(s) : Xiwen JIANG, Florian Kaltenberger +% +% DEVELOPMENT HISTORY : +% +% Date Name(s) Version Description +% ----------- ------------- ------- ------------------------------------------------------ +% May-11-2015 X. JIANG 0.1 script creation v0.1 +% +% REFERENCES/NOTES/COMMENTS : +% +%********************************************************************************************** + +%% ** initialisation ** +clc +close all +clear all +s_init_params; + +d_M = 4; % modulation order, e.g. 4 means QPSK + +%%** frequency ** +d_N_f = 300; % carrier number carrying data +d_N_FFT = 512; % total carrier number +d_N_CP = 128; % extented cyclic prefix +%%** time ** +d_N_OFDM = 120; % number of ofdm symbol per frame +d_N_meas = 10; % measuement number +%%** antenna ** +d_N_antA = 4; % antenna number at site a +d_N_antB = 4; % antenna number at site b +v_indA = find(v_active_rfA); % active antenna index at site a +v_indB = find(v_active_rfB); % active antenna index at site b +d_amp = pow2(12); +%% ---------------------------------------------------- +m_sym_TA = zeros(d_N_f,d_N_OFDM,length(v_indA),d_N_meas); +m_sym_TB = zeros(d_N_f,d_N_OFDM,length(v_indA),d_N_meas); +m_sym_RB = zeros(d_N_f,d_N_OFDM,length(v_indB),d_N_meas); +m_sig_TA = zeros((d_N_CP+d_N_FFT)*d_N_OFDM,d_N_antA); +m_sig_TB = zeros((d_N_CP+d_N_FFT)*d_N_OFDM,d_N_antB); + +%** simulation** + +for d_n_meas = 1:d_N_meas + %% -------- tx -------- + %** tx of site A ** + [m_sym_TA(:,:,:,d_n_meas), m_sig_TA_] = f_ofdm_tx(d_M, d_N_f, d_N_FFT, d_N_CP, d_N_OFDM, v_active_rfA, d_amp); + + %% -------- channel -------- + %** Transmission from A to B ** + m_sig_TA(:,v_indA)= m_sig_TA_*2; %affect the LSB to 0 to set on Tx mode + m_sig_TB(:,v_indB)= 1+1i*ones(size(m_sig_TB,1),length(v_indB)); %affect the LSB to 1 to set on Rx mode + oarf_send_frame(cardB,m_sig_TB,d_n_bit); + oarf_send_frame(cardA,m_sig_TA,d_n_bit); + m_sig_R = oarf_get_frame(cardA); + m_sig_RB = m_sig_R(1:d_N_OFDM*(d_N_FFT+d_N_CP),d_N_antA+1:d_N_antA+d_N_antB); + sleep(0.1); + %% -------- rx -------- + m_sym_RB(:,:,:,d_n_meas) = f_ofdm_rx(m_sig_RB, d_N_FFT, d_N_CP, d_N_OFDM, v_active_rfB); + +end +%keyboard; + +%** channel estimation ** +m_H_est_A2B_f = f_ch_est(m_sym_TA, m_sym_RB); %dimension: d_N_antR x d_N_antT x d_N_f x d_N_meas +m_H_est_A2B_ = zeros(length(v_indB),length(v_indA),d_N_FFT,d_N_meas); +m_H_est_A2B_(:,:,[2:151 363:512],:) = m_H_est_A2B_f(:,:,[151:300 1:150],:); +m_H_est_A2B_t = ifft(m_H_est_A2B_,[],3); + +%% -------- plot -------- + +%** channel estimation in frequency domain ** + m_H_A2B_draw_f = squeeze(m_H_est_A2B_f(1,:,:,1)).'; + m_H_A2B_draw_t = squeeze(m_H_est_A2B_t(1,:,:,1)).'; + + figure(1) + plot(real(m_sig_RB(1:1000,v_indB)),'b-'); + title('received signal at site B (time domain)') + + figure(2) + plot(m_sym_RB(100,:,1,1),'*') + title('Demodulated symboles at site B') + + figure(3) + plot(abs(m_H_A2B_draw_t)) + title('Impulse Response') + + figure(4) + subplot(2,1,1) + plot(20*log10(abs(m_H_A2B_draw_f)),'-'); + title('|h| vs. freq (A2B)') + xlabel('freq') + ylabel('|h|') + ylim([0 100]) + + subplot(2,1,2) + plot(angle(m_H_A2B_draw_f),'-'); + title('angle(h) vs. freq (A2B)') + xlabel('freq') + ylabel('angle(h)') + diff --git a/targets/PROJECTS/TDDREC/v4_CH_EST/s_init_params.m b/targets/PROJECTS/TDDREC/v4_CH_EST/s_init_params.m new file mode 100644 index 0000000000000000000000000000000000000000..31838d44592126ffa57f15e32521fc8a9783dc20 --- /dev/null +++ b/targets/PROJECTS/TDDREC/v4_CH_EST/s_init_params.m @@ -0,0 +1,57 @@ +clear all +close all +addpath([getenv('OPENAIR_TARGETS') '/ARCH/EXMIMO/USERSPACE/OCTAVE']); + +%% -------- ExpressMIMO2 configuration -------- +limeparms; + +cardA = 0; +cardB = 1; + +v_active_rfA = [1 0 0 0]; +v_active_rfB = [1 0 0 0]; + +fc = 1907600000; %3500000000; %fc = 859.5e6; %fc = 2660000000; +freq_rxA = fc*v_active_rfA; +freq_txA = freq_rxA; %+1.92e6; +freq_rxB = fc*v_active_rfB; +freq_txB = freq_rxB; %+1.92e6; + +tdd_config = DUPLEXMODE_FDD+TXRXSWITCH_LSB; %we need the LSB switching for the woduplex script, otherwise we don't receive anything +rx_gainA = 10*v_active_rfA;%[0 0 0 3]; +tx_gainA = 10*v_active_rfA;%[20 20 20 20] +rx_gainB = 10*v_active_rfB; +tx_gainB = 10*v_active_rfB; +syncmodeA = SYNCMODE_MASTER; +syncmodeB = SYNCMODE_SLAVE; +eNB_flag = 0; +resampling_factorA = [2 2 2 2];%2*v_active_rfA; +resampling_factorB = [2 2 2 2];%2*v_active_rfB; + +rf_modeA = (TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_TX+TXEN+DMAMODE_RX+RXEN) * v_active_rfA; +rf_rxdcA = rf_rxdc*v_active_rfA; +rf_vcocalA = rf_vcocal_19G*v_active_rfA; +rf_local = [8254744 8255063 8257340 8257340]; %eNB2tx 1.9GHz +rffe_rxg_lowA = 31*v_active_rfA; +rffe_rxg_finalA = 63*v_active_rfA; +rffe_bandA = B19G_TDD*v_active_rfA; +autocal_modeA = v_active_rfA; +oarf_stop(cardA); +%oarf_stop_without_reset(cardA); +sleep(0.1); +oarf_config_exmimo(cardA,freq_rxA,freq_txA,tdd_config,syncmodeA,rx_gainA,tx_gainA,eNB_flag,rf_modeA,rf_rxdcA,rf_local,rf_vcocalA,rffe_rxg_lowA,rffe_rxg_finalA,rffe_bandA,autocal_modeA,resampling_factorA); + +rf_modeB = (TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_TX+TXEN+DMAMODE_RX+RXEN) * v_active_rfB; +rf_rxdcB = rf_rxdc*v_active_rfB; +rf_vcocalB = rf_vcocal_19G*v_active_rfB; +rffe_rxg_lowB = 31*v_active_rfB; +rffe_rxg_finalB = 63*v_active_rfB; +rffe_bandB = B19G_TDD*v_active_rfB; +autocal_modeB = v_active_rfB; +oarf_stop(cardB); +%oarf_stop_without_reset(cardB); +sleep(0.1); +oarf_config_exmimo(cardB,freq_rxB,freq_txB,tdd_config,syncmodeB,rx_gainB,tx_gainB,eNB_flag,rf_modeB,rf_rxdcB,rf_local,rf_vcocalB,rffe_rxg_lowB,rffe_rxg_finalB,rffe_bandB,autocal_modeB,resampling_factorB); + +d_n_bit = 16; +