diff --git a/matlab/tests/phich_bler.m b/matlab/tests/phich_bler.m new file mode 100644 index 000000000..723c8b572 --- /dev/null +++ b/matlab/tests/phich_bler.m @@ -0,0 +1,132 @@ +clear + +%% PHICH encoding/decoding + +%% Setup simulation +Npackets = 80; +SNR_values = linspace(-6,0,6); +enable_fading=false; +addpath('../../debug/srslte/lib/phch/test') + + +%% Cell-Wide Settings +enbConfig.NDLRB = 50; % No of Downlink RBs in total BW +enbConfig.CyclicPrefix = 'Normal'; % CP length +enbConfig.Ng = 'One'; % HICH groups +enbConfig.CellRefP = 1; % 1-antenna ports +enbConfig.NCellID = 36; % Physical layer cell identity +enbConfig.NSubframe = 5; % Subframe number 0 +enbConfig.DuplexMode = 'FDD'; % Frame structure +enbConfig.PHICHDuration = 'Normal'; + +%% Define HI resource +hi_res = [1 1]; +ack_bit = 1; + +%% Setup Fading channel model +if (enable_fading) + cfg.Seed = 8; % Random channel seed + cfg.NRxAnts = 1; % 1 receive antenna + cfg.DelayProfile = 'EPA'; % EVA delay spread + cfg.DopplerFreq = 5; % 120Hz Doppler frequency + cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation + cfg.InitTime = 0; % Initialize at time zero + cfg.NTerms = 16; % Oscillators used in fading model + cfg.ModelType = 'GMEDS'; % Rayleigh fading model type + cfg.InitPhase = 'Random'; % Random initial phases + cfg.NormalizePathGains = 'On'; % Normalize delay profile power + cfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas +end + +% Setup channel equalizer +cec.PilotAverage = 'UserDefined'; % Type of pilot averaging +cec.FreqWindow = 9; % Frequency window size +cec.TimeWindow = 9; % Time window size +cec.InterpType = 'linear'; % 2D interpolation type +cec.InterpWindow = 'Causal'; % Interpolation window type +cec.InterpWinSize = 1; % Interpolation window size + +%% Generate TX subframe +subframe_tx = lteDLResourceGrid(enbConfig); + +%% Genearte PHICH signal +hi_sym_tx = ltePHICH(enbConfig, [hi_res ack_bit]); +hi_indices = ltePHICHIndices(enbConfig); +subframe_tx(hi_indices)=hi_sym_tx; + +%% Add references to subframe +cellRsSym = lteCellRS(enbConfig); +cellRsInd = lteCellRSIndices(enbConfig); +subframe_tx(cellRsInd) = cellRsSym; + +%% Modulate signal +[txWaveform, info] = lteOFDMModulate(enbConfig,subframe_tx); +cfg.SamplingRate = info.SamplingRate; + +%% Start simulation +decoded = zeros(size(SNR_values)); +decoded_srslte = zeros(size(SNR_values)); + +for snr_idx=1:length(SNR_values) + SNRdB = SNR_values(snr_idx); + SNR = 10^(SNRdB/10); % Linear SNR + N0 = 1/(sqrt(2.0*enbConfig.CellRefP*double(info.Nfft))*SNR); + for i=1:Npackets + + %% Fading + rxWaveform = sum(txWaveform,2); + if (enable_fading) + rxWaveform = lteFadingChannel(cfg,rxWaveform); + end + + %% Noise Addition + noise = N0*complex(randn(size(rxWaveform)), randn(size(rxWaveform))); + rxWaveform = rxWaveform + noise; + + %% Demodulate + subframe_rx = lteOFDMDemodulate(enbConfig, rxWaveform); + + %% Channel estimation + if (enable_fading) + [hest, nest] = lteDLChannelEstimate(enbConfig, cec, subframe_rx); + else + hest=ones(size(subframe_rx)); + nest=0; + end + + %% Extract resources + phichSymbolsRx = subframe_rx(hi_indices); + phichSymbolsHest = hest(hi_indices); + + %% PHICH decoding + [hi, hi_symbols] = ltePHICHDecode(enbConfig,hi_res, phichSymbolsRx, phichSymbolsHest, nest); + decoded(snr_idx) = decoded(snr_idx) + (hi == ack_bit); + + %% Same with srsLTE + [hi_srslte, hi_symbols_srslte] = srslte_phich(enbConfig, hi_res, subframe_rx, hest, nest); + decoded_srslte(snr_idx) = decoded_srslte(snr_idx) + (hi_srslte == ack_bit); + end + fprintf('SNR: %.1f\n',SNRdB) +end + +if (Npackets>1) + semilogy(SNR_values,1-decoded/Npackets,'bo-',... + SNR_values,1-decoded_srslte/Npackets, 'ro-') + grid on + legend('Matlab','srsLTE') + xlabel('SNR (dB)') + ylabel('BLER') + axis([min(SNR_values) max(SNR_values) 1/Npackets/10 1]) +else + + scatter(real(hi_symbols),imag(hi_symbols)) + hold on + scatter(real(hi_symbols_srslte),imag(hi_symbols_srslte)) + hold off + grid on; + axis([-2 2 -2 2]) + disp(hi) + disp(hi_srslte) + +end + diff --git a/srslte/lib/phch/test/CMakeLists.txt b/srslte/lib/phch/test/CMakeLists.txt index ea1d14aca..baedda688 100644 --- a/srslte/lib/phch/test/CMakeLists.txt +++ b/srslte/lib/phch/test/CMakeLists.txt @@ -70,6 +70,7 @@ add_test(phich_test_10 phich_test -p 1 -n 10 -e) add_test(phich_test_102 phich_test -p 2 -n 10 -g 2) add_test(phich_test_104 phich_test -p 4 -n 10 -e -l -g 1/2) +BuildMex(MEXNAME phich SOURCES phich_test_mex.c LIBRARIES srslte_static srslte_mex) ######################################################################## # PDCCH TEST diff --git a/srslte/lib/phch/test/pcfich_test_mex.c b/srslte/lib/phch/test/pcfich_test_mex.c index a32c5efc4..183e7330f 100644 --- a/srslte/lib/phch/test/pcfich_test_mex.c +++ b/srslte/lib/phch/test/pcfich_test_mex.c @@ -38,7 +38,7 @@ void help() { mexErrMsgTxt - ("[cfi] = srslte_pdcch(enbConfig, rxWaveform)\n\n"); + ("[cfi] = srslte_pcfich(enbConfig, rxWaveform)\n\n"); } /* the gateway function */ diff --git a/srslte/lib/phch/test/phich_test_mex.c b/srslte/lib/phch/test/phich_test_mex.c new file mode 100644 index 000000000..65e1c0df2 --- /dev/null +++ b/srslte/lib/phch/test/phich_test_mex.c @@ -0,0 +1,173 @@ +/** + * + * \section COPYRIGHT + * +* Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include "srslte/srslte.h" +#include "srslte/mex/mexutils.h" + +/** MEX function to be called from MATLAB to test the channel estimator + */ + +#define ENBCFG prhs[0] +#define HIRES prhs[1] +#define INPUT prhs[2] +#define NOF_INPUTS 3 + +void help() +{ + mexErrMsgTxt + ("[hi, symbols] = srslte_phich(enbConfig, hires, input_signal, [hest, nest])\n\n"); +} + +/* the gateway function */ +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + int i; + srslte_cell_t cell; + srslte_phich_t phich; + srslte_chest_dl_t chest; + srslte_ofdm_t ofdm_rx; + srslte_regs_t regs; + uint32_t sf_idx; + cf_t *input_fft, *input_signal; + + if (nrhs < NOF_INPUTS) { + help(); + return; + } + + if (mexutils_read_cell(ENBCFG, &cell)) { + help(); + return; + } + + if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) { + help(); + return; + } + + if (srslte_chest_dl_init(&chest, cell)) { + mexErrMsgTxt("Error initializing equalizer\n"); + return; + } + + if (srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb)) { + mexErrMsgTxt("Error initializing FFT\n"); + return; + } + + if (srslte_regs_init(®s, cell)) { + mexErrMsgTxt("Error initiating regs\n"); + return; + } + + if (srslte_phich_init(&phich, ®s, cell)) { + mexErrMsgTxt("Error creating PHICH object\n"); + return; + } + +// Read input signal + input_signal = NULL; + int insignal_len = mexutils_read_cf(INPUT, &input_signal); + if (insignal_len < 0) { + mexErrMsgTxt("Error reading input signal\n"); + return; + } + if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) { + input_fft = input_signal; + } else { + input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); + srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft); + free(input_signal); + } + + cf_t *ce[SRSLTE_MAX_PORTS]; + for (i=0;i NOF_INPUTS) { + cf_t *cearray = NULL; + mexutils_read_cf(prhs[NOF_INPUTS], &cearray); + cf_t *cearray_ptr = cearray; + for (i=0;i NOF_INPUTS + 1) { + noise_power = mxGetScalar(prhs[NOF_INPUTS+1]); + } else if (nrhs > NOF_INPUTS) { + noise_power = 0; + } else { + noise_power = srslte_chest_dl_get_noise_estimate(&chest); + } + + // Read hires values + float *hires = NULL; + int nhires = mexutils_read_f(HIRES, &hires); + if (nhires != 2) { + mexErrMsgTxt("Expecting 2 values for hires parameter\n"); + return; + } + uint32_t ngroup = (uint32_t) hires[0]; + uint32_t nseq = (uint32_t) hires[1]; + uint8_t ack; + float corr_res; + int n = srslte_phich_decode(&phich, input_fft, ce, noise_power, ngroup, nseq, sf_idx, &ack, &corr_res); + + if (nlhs >= 1) { + if (n < 0) { + plhs[0] = mxCreateDoubleScalar(-1); + } else { + plhs[0] = mxCreateDoubleScalar(ack); + } + } + if (nlhs >= 2) { + mexutils_write_cf(phich.z, &plhs[1], 1, SRSLTE_PHICH_NBITS); + } + + srslte_chest_dl_free(&chest); + srslte_ofdm_rx_free(&ofdm_rx); + srslte_phich_free(&phich); + srslte_regs_free(®s); + + for (i=0;i 1.5) { + if (ack_bit) { return true; } else { return false;