Added Matlab pusch verification model

master
Ismael Gomez 9 years ago
parent eeed44264c
commit d3ce6e83f0

Binary file not shown.

Binary file not shown.

@ -17,8 +17,6 @@ enbConfig.NDLRB = 100;
enbConfig.CFI = 1; enbConfig.CFI = 1;
enbConfig.DuplexMode='FDD'; enbConfig.DuplexMode='FDD';
lteCQIDecode
% Transmission mode configuration for PDSCH % Transmission mode configuration for PDSCH
pdschConfig.NLayers = 1; pdschConfig.NLayers = 1;
pdschConfig.TxScheme = 'Port0'; pdschConfig.TxScheme = 'Port0';

@ -0,0 +1,188 @@
%% Plot PUSCH BLER vs SNR for PUSCH without equalization
clear
transportBlkSize=904;
modulation='64QAM';
rvValues=0;
SNR=linspace(-5,0.0,8);
Nblocks=30;
addpath('../../build/srslte/lib/phch/test')
% Subframe configuration
ueConfig.NCellID = 100;
ueConfig.CyclicPrefixUL = 'Normal';
ueConfig.NSubframe = 0;
ueConfig.NULRB = 6;
ueConfig.Shortened = 0;
ueConfig.NTxAnts = 1;
ueConfig.RNTI = 1;
ueConfig.DuplexMode='FDD';
ueConfig.Hopping = 'Off';
ueConfig.SeqGroup = 0;
ueConfig.CyclicShift = 0;
ueConfig.Shortened = 0;
% Transmission mode configuration for PUSCH
puschConfig.NLayers = 1;
puschConfig.TxScheme = 'Port0';
puschConfig.Modulation = modulation;
puschConfig.NTurboDecIts = 5;
puschConfig.PRBSet = (0:ueConfig.NULRB-1)';
puschConfig.NBundled = 0;
% Configure control channels
puschConfig.OCQI = 0;
puschConfig.ORI = 0;
puschConfig.OACK = 0;
puschConfig.BetaCQI = 2;
puschConfig.BetaRI = 3;
puschConfig.BetaACK = 1;
info=lteULSCHInfo(ueConfig,puschConfig,transportBlkSize,puschConfig.OCQI,puschConfig.ORI,puschConfig.OACK);
puschConfig.QdACK=info.QdACK;
puschConfig.QdRI=info.QdRI;
puschConfig.QdCQI=info.QdCQI;
switch (modulation)
case 'QPSK'
bitsPerSym = 2;
case '16QAM'
bitsPerSym = 4;
case '64QAM'
bitsPerSym = 6;
end
noiseVarfactor = sqrt(2*bitsPerSym);
snr = 10.^(SNR/10);
nErrors_mat = zeros(length(SNR),length(rvValues));
nErrorsCtrl_mat = zeros(length(SNR),3);
nErrors_srs = zeros(length(SNR),length(rvValues));
nErrorsCtrl_srs = zeros(length(SNR),3);
for k = 1:length(SNR);
subframe=cell(length(rvValues));
puschIdx=ltePUSCHIndices(ueConfig,puschConfig);
for i=1:length(rvValues)
subframe{i} = lteULResourceGrid(ueConfig);
end
blkCounter = 0;
for l = 1:Nblocks;
% UL-SCH data bits
ulschBits = randi([0 1],transportBlkSize,1);
softBuffer = {};
% Control bits
cqi = randi([0 1], puschConfig.OCQI,1);
ri = randi([0 1], puschConfig.ORI,1);
ack = randi([0 1], puschConfig.OACK,1);
for rvIndex = 1:length(rvValues)
% ULSCH transport channel
puschConfig.RV = rvValues(rvIndex);
puschPayload = lteULSCH(ueConfig, puschConfig, ulschBits, cqi, ri, ack);
% PUSCH modulated symbols
puschSymbols = ltePUSCH(ueConfig, puschConfig, puschPayload);
puschSize = size(puschSymbols);
% Addition of noise
noise = (1/noiseVarfactor)*sqrt(1/snr(k))*complex(randn(puschSize),randn(puschSize));
noisySymbols = puschSymbols + noise;
subframe{rvIndex}(puschIdx)=noisySymbols;
% PUSCH Rx-side
[rxCW, puschSymbolsRx] = ltePUSCHDecode(ueConfig, puschConfig, noisySymbols);
if (iscell(rxCW))
rxCW_=rxCW{1};
else
rxCW_=rxCW;
end
% UL-SCH turbo decoding
[rxBits, blkCRCerr, softBuffer,ccqi,cri,cack] = lteULSCHDecode2(ueConfig, puschConfig, ...
transportBlkSize, rxCW_, softBuffer);
% Add errors to previous error counts
nErrors_mat(k,rvIndex) = nErrors_mat(k,rvIndex)+blkCRCerr;
if (rvIndex==1)
ack_rx=lteACKDecode(puschConfig,cack);
ri_rx=lteRIDecode(puschConfig,cri);
cqi_rx=lteCQIDecode(puschConfig,ccqi);
nErrorsCtrl_mat(k,1) = nErrorsCtrl_mat(k,1)+(sum(ack_rx~=ack)>0);
nErrorsCtrl_mat(k,2) = nErrorsCtrl_mat(k,2)+(sum(ri_rx~=ri)>0);
nErrorsCtrl_mat(k,3) = nErrorsCtrl_mat(k,3)+(sum(cqi_rx~=cqi)>0);
end
end
% Same with srsLTE
[okSRSLTE, cqi_rx_srs, ri_rx_srs, ack_rx_srs] = srslte_pusch(ueConfig, puschConfig, ...
transportBlkSize, subframe, ones(size(subframe{1})), 0);
nErrors_srs(k,rvIndex) = nErrors_srs(k,rvIndex)+~okSRSLTE;
if (rvIndex==1)
nErrorsCtrl_srs(k,1) = nErrorsCtrl_srs(k,1)+(sum(ack_rx_srs~=ack)>0);
nErrorsCtrl_srs(k,2) = nErrorsCtrl_srs(k,2)+(sum(ri_rx_srs~=ri)>0);
nErrorsCtrl_srs(k,3) = nErrorsCtrl_srs(k,3)+(sum(cqi_rx_srs~=cqi)>0);
end
end
fprintf('SNR=%.1f dB, BLER_mat=%.2f, BLER_srs=%.2f, BLER_ack=%.2f/%.2f, BLER_ri=%.2f/%.2f, BLER_cqi=%.2f/%.2f\n',...
SNR(k),nErrors_mat(k,rvIndex)/Nblocks, nErrors_srs(k,rvIndex)/Nblocks, ...
nErrorsCtrl_mat(k,1)/Nblocks, nErrorsCtrl_srs(k,1)/Nblocks, ...
nErrorsCtrl_mat(k,3)/Nblocks, nErrorsCtrl_srs(k,2)/Nblocks, ...
nErrorsCtrl_mat(k,2)/Nblocks, nErrorsCtrl_srs(k,3)/Nblocks);
end
puschBLER_mat = nErrors_mat./Nblocks;
puschBLER_mat(puschBLER_mat==0)=10^-10;
puschBLER_srs = nErrors_srs./Nblocks;
puschBLER_srs(puschBLER_srs==0)=10^-10;
puschCtrlBLER_mat = nErrorsCtrl_mat./Nblocks;
puschCtrlBLER_mat(puschCtrlBLER_mat==0)=10^-10;
puschCtrlBLER_srs = nErrorsCtrl_srs./Nblocks;
puschCtrlBLER_srs(puschCtrlBLER_srs==0)=10^-10;
if (Nblocks == 1 && length(SNR) == 1)
else
ctrlplot=1;
if (puschConfig.OCQI+puschConfig.ORI+puschConfig.OACK>0)
ctrlplot=2;
end
subplot(ctrlplot,1,1)
semilogy(SNR,puschBLER_mat,SNR,puschBLER_srs);
grid on
xlabel('Eb/No (dB)')
ylabel('BLER')
leg=[];
for rvIndex = 1:length(rvValues)
leg=strvcat(leg,sprintf('Matlab rv=%d',rvValues(rvIndex)));
end
for rvIndex = 1:length(rvValues)
leg=strvcat(leg,sprintf('srsLTE rv=%d',rvValues(rvIndex)));
end
axis([min(SNR) max(SNR) 10^-4 1])
if (ctrlplot==2)
subplot(2,1,2)
semilogy(SNR,puschCtrlBLER_mat,SNR,puschCtrlBLER_srs)
grid on
xlabel('Eb/No (dB)')
ylabel('BLER')
leg=[];
leg=strvcat(leg,'Matlab ACK','Matlab RI', 'Matlab CQI');
leg=strvcat(leg,'srsLTE ACK','srsLTE RI', 'srsLTE CQI');
legend(leg);
axis([min(SNR) max(SNR) 10^-4 1])
end
end

@ -1,12 +1,12 @@
ueConfig=struct('NCellID',1,'NULRB',50,'CyclicPrefixUL','Normal','NTxAnts',1,'RNTI',64); ueConfig=struct('NCellID',1,'NULRB',6,'CyclicPrefixUL','Normal','NTxAnts',1,'RNTI',64);
puschConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'NBundled',0); puschConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'NBundled',0);
addpath('/home/ismael/work/srsLTE/debug/srslte/lib/phch/test') addpath('../../build//srslte/lib/phch/test')
cqilen=[0 20]; cqilen=[0 4 20];
mods={'64QAM'}; mods={'64QAM'};
rvs=0; rvs=0;
betas=[0 2.0 2.5 5.0, 20.0]; betas=[0 5.0, 20.0];
for p=1:ueConfig.NULRB for p=1:ueConfig.NULRB
for i=0:26 for i=0:26
for m=1:length(mods) for m=1:length(mods)
@ -40,7 +40,6 @@ for p=1:ueConfig.NULRB
ack_bit=[]; ack_bit=[];
end end
if (cqilen(c)>0 || TBs>0) if (cqilen(c)>0 || TBs>0)
[enc, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit); [enc, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
cw_mat=ltePUSCH(ueConfig,puschConfig,enc); cw_mat=ltePUSCH(ueConfig,puschConfig,enc);
@ -49,16 +48,11 @@ for p=1:ueConfig.NULRB
%drs_idx=ltePUSCHDRSIndices(ueConfig,puschConfig); %drs_idx=ltePUSCHDRSIndices(ueConfig,puschConfig);
subframe_mat = lteULResourceGrid(ueConfig); subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=cw_mat; subframe_mat(idx)=cw_mat;
%subframe_mat(drs_idx)=drs;
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
[waveform_lib, subframe_lib, cwlib, bits]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit); [~, subframe_lib, cwlib, bits]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
err=max(abs(waveform-waveform_lib)); err=max(abs(subframe_mat(:)-subframe_lib));
if (err > 10^-5) if (err > 10^-5)
disp(err) plot(abs(subframe_mat(:)-subframe_lib))
t=1:200;
%plot(t,bits(t),t,cw_scram(t))
plot(abs(double(bits)-double(cw_scram)))
error('Error!'); error('Error!');
end end
end end

Binary file not shown.

Binary file not shown.

@ -470,7 +470,7 @@ int srslte_prach_detect(srslte_prach_t *p,
indices != NULL) indices != NULL)
{ {
if(sig_len != p->N_ifft_prach){ if(sig_len != p->N_ifft_prach){
INFO("srslte_prach_detect: Signal is not of length %d", p->N_ifft_prach); fprintf(stderr, "srslte_prach_detect: Signal is not of length %d", p->N_ifft_prach);
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }

@ -133,6 +133,7 @@ target_link_libraries(pusch_test srslte)
BuildMex(MEXNAME ulsch_encode SOURCES ulsch_encode_test_mex.c LIBRARIES srslte_static srslte_mex) BuildMex(MEXNAME ulsch_encode SOURCES ulsch_encode_test_mex.c LIBRARIES srslte_static srslte_mex)
BuildMex(MEXNAME pusch_encode SOURCES pusch_encode_test_mex.c LIBRARIES srslte_static srslte_mex) BuildMex(MEXNAME pusch_encode SOURCES pusch_encode_test_mex.c LIBRARIES srslte_static srslte_mex)
BuildMex(MEXNAME pusch SOURCES pusch_test_mex.c LIBRARIES srslte_static srslte_mex)
add_test(pusch_test pusch_test) add_test(pusch_test pusch_test)
@ -191,6 +192,7 @@ add_test(prach_test_multi_n4 prach_test_multi -n 4)
BuildMex(MEXNAME prach SOURCES prach_test_mex.c LIBRARIES srslte_static srslte_mex) BuildMex(MEXNAME prach SOURCES prach_test_mex.c LIBRARIES srslte_static srslte_mex)
BuildMex(MEXNAME prach_detect SOURCES prach_detect_test_mex.c LIBRARIES srslte_static srslte_mex)
if(UHD_FOUND) if(UHD_FOUND)

@ -0,0 +1,113 @@
/**
*
* \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 <string.h>
#define FORCE_POWER2_FFT
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define UECFG prhs[0]
#define PRACHCFG prhs[1]
#define INPUT prhs[2]
#define NOF_INPUTS 3
void help()
{
mexErrMsgTxt
("[preamble, offset] = srslte_prach(ueConfig, prachConfig, signal)\n\n");
}
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs != NOF_INPUTS) {
help();
return;
}
uint32_t n_ul_rb = 0;
if (mexutils_read_uint32_struct(UECFG, "NULRB", &n_ul_rb)) {
mexErrMsgTxt("Field NULRB not found in UE config\n");
return;
}
int r = srslte_symbol_sz(n_ul_rb);
if (r < 0) {
mexErrMsgTxt("Invalid NULRB\n");
return;
}
uint32_t N_ifft_ul = (uint32_t) r;
uint32_t sf_idx = 0;
mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx);
uint32_t nframe = 0;
mexutils_read_uint32_struct(UECFG, "NFrame", &nframe);
uint32_t preamble_format = 0;
mexutils_read_uint32_struct(PRACHCFG, "Format", &preamble_format);
uint32_t root_seq_idx = 0;
mexutils_read_uint32_struct(PRACHCFG, "SeqIdx", &root_seq_idx);
uint32_t seq_idx = 0;
mexutils_read_uint32_struct(PRACHCFG, "PreambleIdx", &seq_idx);
uint32_t zero_corr_zone = 0;
mexutils_read_uint32_struct(PRACHCFG, "CyclicShiftIdx", &zero_corr_zone);
uint32_t high_speed_flag = 0;
mexutils_read_uint32_struct(PRACHCFG, "HighSpeed", &high_speed_flag);
uint32_t timing_offset = 0;
mexutils_read_uint32_struct(PRACHCFG, "TimingOffset", &timing_offset);
uint32_t frequency_offset = 0;
mexutils_read_uint32_struct(PRACHCFG, "FreqOffset", &frequency_offset);
srslte_prach_t prach;
if (srslte_prach_init(&prach, N_ifft_ul, preamble_format, root_seq_idx, high_speed_flag, zero_corr_zone)) {
mexErrMsgTxt("Error initiating PRACH\n");
return;
}
cf_t *input_signal = NULL;
int nof_samples = mexutils_read_cf(INPUT, &input_signal);
uint32_t preambles[64];
uint32_t nof_detected = 0;
mexPrintf("nof_samples=%d\n", nof_samples);
if (srslte_prach_detect(&prach, frequency_offset, input_signal, nof_samples, preambles, &nof_detected)) {
mexErrMsgTxt("Error detecting PRACH\n");
return;
}
if (nlhs >= 1) {
mexutils_write_int((int*) preambles, &plhs[0], nof_detected, 1);
}
free(input_signal);
srslte_prach_free(&prach);
return;
}

@ -101,7 +101,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Unknown modulation\n"); mexErrMsgTxt("Unknown modulation\n");
return; return;
} }
mxFree(mod_str); mxFree(mod_str);
float *prbset = NULL; float *prbset = NULL;
@ -135,20 +134,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod); grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
if (srslte_pusch_cfg(&pusch, &cfg, &grant, NULL, NULL, NULL, cfg.sf_idx, cfg.rv, 0)) { if (srslte_pusch_cfg(&pusch, &cfg, &grant, NULL, NULL, NULL, cfg.sf_idx, cfg.rv, 0)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PUSCH\n");
exit(-1); exit(-1);
} }
mexPrintf("L_prb: %d, n_prb: %d\n", grant.L_prb, grant.n_prb[0]); mexPrintf("L_prb: %d, n_prb: %d\n", grant.L_prb, grant.n_prb[0]);
srslte_softbuffer_tx_t softbuffer; srslte_softbuffer_tx_t softbuffer;
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) { if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating soft buffer\n"); mexErrMsgTxt("Error initiating soft buffer\n");
return; return;
} }
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp); uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re); cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols) { if (!sf_symbols) {
@ -215,6 +212,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
} }
if (nlhs >= 1) {
cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); cf_t *scfdma = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); bzero(scfdma, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_ofdm_t fft; srslte_ofdm_t fft;
@ -222,12 +222,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_ofdm_set_normalize(&fft, true); srslte_ofdm_set_normalize(&fft, true);
srslte_ofdm_set_freq_shift(&fft, 0.5); srslte_ofdm_set_freq_shift(&fft, 0.5);
srslte_ofdm_tx_sf(&fft, sf_symbols, scfdma); srslte_ofdm_tx_sf(&fft, sf_symbols, scfdma);
// Matlab toolbox expects further normalization // Matlab toolbox expects further normalization
srslte_vec_sc_prod_cfc(scfdma, 1.0/sqrtf(srslte_symbol_sz(cell.nof_prb)), scfdma, SRSLTE_SF_LEN_PRB(cell.nof_prb)); srslte_vec_sc_prod_cfc(scfdma, 1.0/sqrtf(srslte_symbol_sz(cell.nof_prb)), scfdma, SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (nlhs >= 1) {
mexutils_write_cf(scfdma, &plhs[0], SRSLTE_SF_LEN_PRB(cell.nof_prb), 1); mexutils_write_cf(scfdma, &plhs[0], SRSLTE_SF_LEN_PRB(cell.nof_prb), 1);
free(scfdma);
} }
if (nlhs >= 2) { if (nlhs >= 2) {
mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1); mexutils_write_cf(sf_symbols, &plhs[1], nof_re, 1);
@ -239,9 +240,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexutils_write_uint8(pusch.q, &plhs[3], cfg.nbits.nof_bits, 1); mexutils_write_uint8(pusch.q, &plhs[3], cfg.nbits.nof_bits, 1);
} }
srslte_pusch_free(&pusch); srslte_pusch_free(&pusch);
srslte_softbuffer_tx_free(&softbuffer);
free(trblkin); free(trblkin);
free(sf_symbols); free(sf_symbols);
free(scfdma);
return; return;
} }

@ -0,0 +1,308 @@
/**
*
* \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 <string.h>
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define UECFG prhs[0]
#define PUSCHCFG prhs[1]
#define TBS prhs[2]
#define INPUT prhs[3]
#define NOF_INPUTS 4
void help()
{
mexErrMsgTxt
("[decoded_ok, cqi_data, ri_data, ack_data] = srslte_pusch(ueConfig, puschConfig, trblklen, rxWaveform)\n\n");
}
extern int indices[2048];
int rv_seq[4] = {0, 2, 3, 1};
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
srslte_ofdm_t ofdm_tx;
srslte_pusch_t pusch;
srslte_chest_ul_t chest;
cf_t *input_fft;
srslte_softbuffer_rx_t softbuffer;
uint32_t rnti32;
if (nrhs < NOF_INPUTS) {
help();
return;
}
srslte_verbose = SRSLTE_VERBOSE_INFO;
srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1;
if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) {
mexErrMsgTxt("Field NCellID not found in UE config\n");
return;
}
if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) {
mexErrMsgTxt("Field NULRB not found in UE config\n");
return;
}
srslte_pusch_cfg_t cfg;
bzero(&cfg, sizeof(srslte_pusch_cfg_t));
if (mexutils_read_uint32_struct(UECFG, "RNTI", &rnti32)) {
mexErrMsgTxt("Field RNTI not found in pdsch config\n");
return;
}
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &cfg.sf_idx)) {
help();
return;
}
if (srslte_ofdm_rx_init(&ofdm_tx, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n");
return;
}
srslte_ofdm_set_normalize(&ofdm_tx, true);
srslte_ofdm_set_freq_shift(&ofdm_tx, 0.5);
if (srslte_pusch_init(&pusch, cell)) {
mexErrMsgTxt("Error initiating PDSCH\n");
return;
}
srslte_pusch_set_rnti(&pusch, (uint16_t) (rnti32 & 0xffff));
if (srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb)) {
mexErrMsgTxt("Error initiating soft buffer\n");
return;
}
if (srslte_chest_ul_init(&chest, cell)) {
mexErrMsgTxt("Error initializing equalizer\n");
return;
}
srslte_ra_ul_grant_t grant;
bzero(&grant, sizeof(srslte_ra_ul_grant_t));
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) {
grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) {
grant.mcs.mod = SRSLTE_MOD_64QAM;
} else {
mexErrMsgTxt("Unknown modulation\n");
return;
}
mxFree(mod_str);
grant.mcs.tbs = mxGetScalar(TBS);
if (grant.mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n");
return;
}
uint32_t N_srs = 0;
mexutils_read_uint32_struct(PUSCHCFG, "Shortened", &N_srs);
if (N_srs == 1) {
pusch.shortened = true;
}
float *prbset = NULL;
mxArray *p;
p = mxGetField(PUSCHCFG, 0, "PRBSet");
if (!p) {
mexErrMsgTxt("Error field PRBSet not found\n");
return;
}
grant.L_prb = mexutils_read_f(p, &prbset);
grant.n_prb[0] = prbset[0];
grant.n_prb[1] = prbset[0];
free(prbset);
grant.M_sc = grant.L_prb*SRSLTE_NRE;
grant.M_sc_init = grant.M_sc; // FIXME: What should M_sc_init be?
grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
if (srslte_cbsegm(&cfg.cb_segm, grant.mcs.tbs)) {
mexErrMsgTxt("Error computing CB segmentation\n");
return;
}
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) {
mexErrMsgTxt("Field RV not found in pdsch config\n");
return;
}
uint32_t max_iterations = 5;
mexutils_read_uint32_struct(PUSCHCFG, "NTurboDecIts", &max_iterations);
/* Configure rest of pdsch_cfg parameters */
if (srslte_pusch_cfg(&pusch, &cfg, &grant, NULL, NULL, NULL, cfg.sf_idx, cfg.rv, 0)) {
fprintf(stderr, "Error configuring PDSCH\n");
exit(-1);
}
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
mexutils_read_uint32_struct(PUSCHCFG, "OCQI", &uci_data.uci_cqi_len);
mexutils_read_uint32_struct(PUSCHCFG, "ORI", &uci_data.uci_ri_len);
mexutils_read_uint32_struct(PUSCHCFG, "OACK", &uci_data.uci_ack_len);
float beta;
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
cfg.uci_cfg.I_offset_cqi = 7;
} else {
cfg.uci_cfg.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta);
}
if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) {
cfg.uci_cfg.I_offset_ri = 2;
} else {
cfg.uci_cfg.I_offset_ri = srslte_sch_find_Ioffset_ri(beta);
}
if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) {
cfg.uci_cfg.I_offset_ack = 0;
} else {
cfg.uci_cfg.I_offset_ack = srslte_sch_find_Ioffset_ack(beta);
}
mexPrintf("TRBL_len: %d, CQI_len: %2d, ACK_len: %d (%d), RI_len: %d (%d)\n", grant.mcs.tbs,
uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri);
mexPrintf("I_cqi: %2d, I_ri: %2d, I_ack=%2d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack);
mexPrintf("L_prb: %d, n_prb: %d/%d, TBS=%d\n", grant.L_prb, grant.n_prb[0], grant.n_prb[1], grant.mcs.tbs);
/** Allocate input buffers */
int nof_retx=1;
if (mexutils_isCell(INPUT)) {
nof_retx = mexutils_getLength(INPUT);
}
cf_t *ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));;
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
if (!data_bytes) {
return;
}
srslte_sch_set_max_noi(&pusch.dl_sch, max_iterations);
input_fft = NULL;
int r=-1;
for (int rvIdx=0;rvIdx<nof_retx && r != 0;rvIdx++) {
mxArray *tmp = (mxArray*) INPUT;
if (mexutils_isCell(INPUT)) {
tmp = mexutils_getCellArray(INPUT, rvIdx);
if (nof_retx > 1) {
cfg.rv = rv_seq[rvIdx%4];
}
}
// Read input signal
cf_t *input_signal = NULL;
int insignal_len = mexutils_read_cf(tmp, &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;
mexPrintf("Input is after fft\n");
} else {
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
srslte_ofdm_rx_sf(&ofdm_tx, input_signal, input_fft);
mexPrintf("Input is before fft\n");
free(input_signal);
}
if (nrhs > NOF_INPUTS) {
cf_t *cearray = NULL;
mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
cf_t *cearray_ptr = cearray;
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
ce[j] = *cearray_ptr;
cearray_ptr++;
}
if (cearray)
free(cearray);
} else {
srslte_chest_ul_estimate(&chest, input_fft, ce, grant.L_prb, cfg.sf_idx, 0, grant.n_prb);
}
float noise_power;
if (nrhs > NOF_INPUTS + 1) {
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
} else if (nrhs > NOF_INPUTS) {
noise_power = 0;
} else {
noise_power = srslte_chest_ul_get_noise_estimate(&chest);
}
r = srslte_pusch_uci_decode(&pusch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes, &uci_data);
}
uint8_t *data = malloc(grant.mcs.tbs);
srslte_bit_unpack_vector(data_bytes, data, grant.mcs.tbs);
if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(r == 0);
}
if (nlhs >= 2) {
mexutils_write_uint8(uci_data.uci_cqi, &plhs[1], uci_data.uci_cqi_len, 1);
}
if (nlhs >= 3 && uci_data.uci_ri_len <= 1) {
mexutils_write_uint8(&uci_data.uci_ri, &plhs[2], uci_data.uci_ri_len, 1);
}
if (nlhs >= 4 && uci_data.uci_ack_len <= 1) {
mexutils_write_uint8(&uci_data.uci_ack, &plhs[3], uci_data.uci_ack_len, 1);
}
srslte_softbuffer_rx_free(&softbuffer);
srslte_chest_ul_free(&chest);
srslte_pusch_free(&pusch);
srslte_ofdm_rx_free(&ofdm_tx);
free(ce);
free(data_bytes);
free(data);
if (input_fft) {
free(input_fft);
}
return;
}
Loading…
Cancel
Save