Added Matlab tests to verify PDSCH BLER

master
ismagom 9 years ago
parent fb1d2d32c4
commit 75357c8526

@ -4,44 +4,24 @@ pdschConfig=struct('Modulation','64QAM','RV',1,'TxScheme','Port0','NTurboDecIts'
addpath('../../build/srslte/lib/phch/test')
%TBs=18336;
TBs=18336;
i=1;
e_bits=3450*6;
%error=zeros(size(TBs));
%for i=1:length(TBs)
%trblkin=randi(2,TBs(i),1)-1;
trblkin=read_uchar('../../build/data_in');
fprintf('e_bits=%d, trblkin=%d\n',e_bits,length(trblkin));
error=zeros(size(TBs));
for i=1:length(TBs)
trblkin=randi(2,TBs(i),1)-1;
[mat, info]=lteDLSCH(enbConfig,pdschConfig,e_bits,trblkin);
lib=srslte_dlsch_encode(enbConfig,pdschConfig,e_bits,trblkin);
error(i)=mean(abs(double(mat)-double(lib)));
mat(mat==0)=-1;
mat=mat*10;
rec = lteRateRecoverTurbo(mat,length(trblkin),pdschConfig.RV);
rec2 = reshape(reshape(rec{1},[],3)',[],1);
out = lteTurboDecode(rec{1});
x=read_int16('../../build/rmout_0.dat');
subplot(2,1,1)
plot(abs(double(x)-double(rec2)));
t=1:100;
%plot(t,double(x(t)),t,double(rec2(t)))
subplot(2,1,2)
llr=read_int16('../../build/llr.dat');
plot(abs(double(mat)-double(llr)))
end
[data, crc,state] = lteDLSCHDecode(enbConfig, pdschConfig, length(trblkin), mat);
disp(crc)
%end
%
% if (length(TBs) == 1)
% %disp(info)
% disp(error)
% n=1:length(mat);
% plot(abs(double(mat)-double(lib)))
% else
% plot(error)
% end
if (length(TBs) == 1)
disp(info)
disp(error)
n=1:length(mat);
plot(abs(double(mat)-double(lib)))
else
plot(error)
end

@ -1,158 +1,108 @@
%% PDSCH decoding based on RMC channels
%% Cell-Wide Settings
% A structure |enbConfig| is used to configure the eNodeB.
%clear12
recordedSignal=[];
Npackets = 20;
SNR_values = linspace(2,6,10);
Lp=12;
N=256;
K=180;
rstart=(N-K)/2;
P=K/6;
Rhphp=zeros(P,P);
Rhhp=zeros(K,P);
Rhh=zeros(K,K);
t=0:Lp-1;
alfa=log(2*Lp)/Lp;
c_l=exp(-t*alfa);
c_l=c_l/sum(c_l);
C_l=diag(1./c_l);
prows=rstart+(1:6:K);
F=dftmtx(N);
F_p=F(prows,1:Lp);
F_l=F((rstart+1):(K+rstart),1:Lp);
Wi=(F_p'*F_p+C_l*0.01)^(-1);
W2=F_l*Wi*F_p';
w2=reshape(transpose(W2),1,[]);
%% Choose RMC
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.0',[1;0;0;1]);
waveform = sum(waveform,2);
if ~isempty(recordedSignal)
rmccFgOut = struct('CellRefP',1,'NDLRB',100,'DuplexMode','FDD','CyclicPrefix','Normal');
rmccFgOut.PDSCH.RNTI = 1234;
rmccFgOut.PDSCH.PRBSet = repmat(transpose(0:rmccFgOut.NDLRB-1),1,2);
rmccFgOut.PDSCH.TxScheme = 'Port0';
rmccFgOut.PDSCH.NLayers = 1;
rmccFgOut.PDSCH.NTurboDecIts = 5;
rmccFgOut.PDSCH.Modulation = {'64QAM'};
trblklen=75376;
rmccFgOut.PDSCH.TrBlkSizes = trblklen*ones(10,1);
rmccFgOut.PDSCH.RV = 0;
end
flen=rmccFgOut.SamplingRate/1000;
Nsf = 9;
%% Setup Fading channel model
cfg.Seed = 0; % 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
cfg.SamplingRate = rmccFgOut.SamplingRate;
% 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
%% Plot PDSCH BLER vs SNR for PDSCH without equalization
clear
transportBlkSize=75376;
modulation='64QAM';
rvValues=[0 2 3 1];
SNR=linspace(-2.9,-2.0,8);
Nblocks=30;
addpath('../../build/srslte/lib/phch/test')
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*rmccFgOut.CellRefP*double(rmccFgOut.Nfft))*SNR);
Rhphp=zeros(30,30);
Rhhp=zeros(180,30);
for i=1:Npackets
if isempty(recordedSignal)
% Subframe configuration
enbConfig.NCellID = 100;
enbConfig.CyclicPrefix = 'Normal';
enbConfig.NSubframe = 1;
enbConfig.CellRefP = 1;
enbConfig.NDLRB = 100;
enbConfig.CFI = 1;
enbConfig.DuplexMode='FDD';
% Transmission mode configuration for PDSCH
pdschConfig.NLayers = 1;
pdschConfig.TxScheme = 'Port0';
pdschConfig.Modulation = {modulation};
pdschConfig.RNTI = 100;
pdschConfig.NTurboDecIts = 5;
pdschConfig.PRBSet = (0:enbConfig.NDLRB-1)';
switch (modulation)
case 'QPSK'
bitsPerSym = 2;
case '16QAM'
bitsPerSym = 4;
case '64QAM'
bitsPerSym = 6;
end
noiseVarfactor = sqrt(2*bitsPerSym);
snr = 10.^(SNR/10);
%% Fading
%rxWaveform = lteFadingChannel(cfg,waveform);
rxWaveform = waveform;
nErrors_mat = zeros(length(SNR),length(rvValues));
nErrors_srs = zeros(length(SNR),length(rvValues));
%% Noise Addition
noise = N0*complex(randn(size(rxWaveform)), randn(size(rxWaveform))); % Generate noise
rxWaveform = rxWaveform + noise;
else
rxWaveform = recordedSignal;
for k = 1:length(SNR);
subframe=cell(length(rvValues));
pdschIdx=ltePDSCHIndices(enbConfig,pdschConfig,pdschConfig.PRBSet);
for i=1:length(rvValues)
subframe{i} = lteDLResourceGrid(enbConfig);
end
blkCounter = 0;
for l = 1:Nblocks;
% DL-SCH data bits
dlschBits = randi([0 1],transportBlkSize,1);
softBuffer = {};
for rvIndex = 1:length(rvValues)
% DLSCH transport channel
pdschConfig.RV = rvValues(rvIndex);
pdschPayload = lteDLSCH(enbConfig, pdschConfig, length(pdschIdx)*bitsPerSym, dlschBits);
% PDSCH modulated symbols
pdschSymbols = ltePDSCH(enbConfig, pdschConfig, pdschPayload);
pdschSize = size(pdschSymbols);
% Addition of noise
noise = (1/noiseVarfactor)*sqrt(1/snr(k))*complex(randn(pdschSize),randn(pdschSize));
noisySymbols = pdschSymbols + noise;
subframe{rvIndex}(pdschIdx)=noisySymbols;
% PDSCH Rx-side
rxCW = ltePDSCHDecode(enbConfig, pdschConfig, noisySymbols);
% DL-SCH turbo decoding
[rxBits, blkCRCerr, softBuffer] = lteDLSCHDecode(enbConfig, pdschConfig, transportBlkSize, rxCW{1}, softBuffer);
% Add errors to previous error counts
nErrors_mat(k,rvIndex) = nErrors_mat(k,rvIndex)+blkCRCerr;
end
%% Demodulate
frame_rx = lteOFDMDemodulate(rmccFgOut, rxWaveform);
for sf_idx=0:Nsf-1
% sf_idx=9;
subframe_rx=frame_rx(:,sf_idx*14+1:(sf_idx+1)*14);
rmccFgOut.NSubframe=sf_idx;
rmccFgOut.TotSubframes=1;
% Perform channel estimation
[hest, nest,estimates] = lteDLChannelEstimate2(rmccFgOut, cec, subframe_rx);
[cws,symbols] = ltePDSCHDecode(rmccFgOut,rmccFgOut.PDSCH,subframe_rx,hest,nest);
[trblkout,blkcrc,dstate] = lteDLSCHDecode(rmccFgOut,rmccFgOut.PDSCH, ...
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1),cws);
decoded(snr_idx) = decoded(snr_idx) + ~blkcrc;
%% Same with srsLTE
if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0)
[dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ...
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ...
subframe_rx);
else
dec2 = 1;
end
if (~dec2)
fprintf('Error in sf=%d\n',sf_idx);
end
decoded_srslte(snr_idx) = decoded_srslte(snr_idx)+dec2;
end
% Same with srsLTE
[okSRSLTE, data, pdschRx, pdschSymbols, cws] = srslte_pdsch(enbConfig, pdschConfig, ...
transportBlkSize, subframe, ones(size(subframe{1})), 0);
if ~isempty(recordedSignal)
recordedSignal = recordedSignal(flen*10+1:end);
end
nErrors_srs(k,rvIndex) = nErrors_srs(k,rvIndex)+~okSRSLTE;
end
fprintf('SNR: %.1f. Decoded: %d-%d\n',SNRdB, decoded(snr_idx), decoded_srslte(snr_idx))
fprintf('SNR=%.1f dB, BLER_mat=%f, BLER_srs=%f\n',SNR(k),nErrors_mat(k,rvIndex)/Nblocks, nErrors_srs(k,rvIndex)/Nblocks);
end
if (length(SNR_values)>1)
semilogy(SNR_values,1-decoded/Npackets/(Nsf),'bo-',...
SNR_values,1-decoded_srslte/Npackets/(Nsf), 'ro-')
grid on;
legend('Matlab','srsLTE')
xlabel('SNR (dB)')
ylabel('BLER')
axis([min(SNR_values) max(SNR_values) 1/Npackets/(Nsf+1) 1])
PDSCHBLER_MAT = nErrors_mat./Nblocks;
PDSCHBLER_MAT(PDSCHBLER_MAT==0)=10^-10;
PDSCHBLER_SRS = nErrors_srs./Nblocks;
PDSCHBLER_SRS(PDSCHBLER_SRS==0)=10^-10;
if (Nblocks == 1 && length(SNR) == 1)
else
fprintf('Matlab: %d OK\nsrsLTE: %d OK\n',decoded, decoded_srslte);
semilogy(SNR,PDSCHBLER_MAT,SNR,PDSCHBLER_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
legend(leg);
axis([min(SNR) max(SNR) 10^-4 1])
end

@ -1,22 +0,0 @@
nof_cb=11;
TBS=61664;
K=5632; % Only supporting 1 K for now
rv=0;
chs.Modulation='64QAM';
chs.NLayers=1;
% cws must be a vector of size TBS in workspace containing the output of the
% descrambler
rmout_mat=lteRateRecoverTurbo(cws{1},TBS,rv,chs);
scale=700;
%path='../../build/srslte/lib/phch/test';
path='.';
error=zeros(nof_cb,3*K+12);
rmout_lib=zeros(nof_cb,3*K+12);
for i=0:nof_cb-1
filename=sprintf('%s/rmout_%d.dat',path,i);
x=read_int16(filename);
rmout_lib(i+1,:) = reshape(reshape(x,3,[])',[],1);
error(i+1,:)=abs(transpose(rmout_mat{i+1})-rmout_lib(i+1,:)/scale);
end
plot(reshape(error',1,[]))

@ -1,63 +0,0 @@
enb=struct('NCellID',16,'NDLRB',6,'NSubframe',5,'CFI',3,'CyclicPrefix','Normal','CellRefP',1,'Ng','One','PHICHDuration','Normal','DuplexMode','FDD');
RNTI=65535;
addpath('../../build/srslte/lib/phch/test')
cec.PilotAverage = 'UserDefined'; % Type of pilot averaging
cec.FreqWindow = 9; % Frequency window size
cec.TimeWindow = 9; % Time window size
cec.InterpType = 'cubic'; % 2D interpolation type
cec.InterpWindow = 'Centered'; % Interpolation window type
cec.InterpWinSize = 1; % Interpolation window size
subframe_rx=lteOFDMDemodulate(enb,inputSignal);
[hest,nest] = lteDLChannelEstimate(enb, cec, subframe_rx);
% Search PDCCH
pdcchIndices = ltePDCCHIndices(enb);
[pdcchRx, pdcchHest] = lteExtractResources(pdcchIndices, subframe_rx, hest);
[dciBits, pdcchSymbols] = ltePDCCHDecode(enb, pdcchRx, pdcchHest, nest);
pdcch = struct('RNTI', RNTI);
dci = ltePDCCHSearch(enb, pdcch, dciBits); % Search PDCCH for DCI
if ~isempty(dci)
dci = dci{1};
disp(dci);
% Get the PDSCH configuration from the DCI
[pdsch, trblklen] = hPDSCHConfiguration(enb, dci, pdcch.RNTI);
pdsch.NTurboDecIts = 5;
fprintf('PDSCH settings after DCI decoding:\n');
disp(pdsch);
fprintf('Decoding PDSCH...\n\n');
% Get PDSCH indices
[pdschIndices,pdschIndicesInfo] = ltePDSCHIndices(enb, pdsch, pdsch.PRBSet);
[pdschRx, pdschHest] = lteExtractResources(pdschIndices, subframe_rx, hest);
% Decode PDSCH
[dlschBits,pdschSymbols] = ltePDSCHDecode(enb, pdsch, pdschRx, pdschHest, nest);
[sib1, crc] = lteDLSCHDecode(enb, pdsch, trblklen, dlschBits);
[dec2, data, pdschRx2, pdschSymbols2, e_bits, indices] = srslte_pdsch(enb, pdsch, ...
trblklen, ...
subframe_rx);
scatter(real(pdschSymbols{1}),imag(pdschSymbols{1}))
if crc == 0
fprintf('PDSCH OK.\n\n');
else
fprintf('PDSCH ERROR.\n\n');
end
else
% indicate that DCI decoding failed
fprintf('DCI decoding failed.\n\n');
end
indices=indices+1;
plot(t,indices(t),t,pdschIndices(t))

@ -43,6 +43,12 @@
SRSLTE_API bool mexutils_isScalar(const mxArray *ptr);
SRSLTE_API bool mexutils_isCell(const mxArray *ptr);
SRSLTE_API int mexutils_getLength(const mxArray *ptr);
SRSLTE_API mxArray* mexutils_getCellArray(const mxArray *ptr, int idx);
SRSLTE_API int mexutils_read_cell(const mxArray *ptr,
srslte_cell_t *cell);

@ -35,6 +35,20 @@ bool mexutils_isScalar(const mxArray *ptr) {
return mxGetM(ptr) == 1 && mxGetN(ptr) == 1;
}
bool mexutils_isCell(const mxArray *ptr) {
return mxIsCell(ptr);
}
int mexutils_getLength(const mxArray *ptr) {
const mwSize *dims;
dims = mxGetDimensions(ptr);
return dims[0];
}
mxArray* mexutils_getCellArray(const mxArray *ptr, int idx) {
return mxGetCell(ptr, idx);
}
char *mexutils_get_char_struct(const mxArray *ptr, const char *field_name) {
mxArray *p;
p = mxGetField(ptr, 0, field_name);
@ -98,6 +112,8 @@ int mexutils_read_cf(const mxArray *ptr, cf_t **buffer) {
__real__ tmp[i] = (float) inr[i];
if (ini) {
__imag__ tmp[i] = (float) ini[i];
} else {
__imag__ tmp[i] = 0;
}
}
*buffer = tmp;

@ -650,6 +650,25 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32
return SRSLTE_ERROR;
}
// Check if RA procedure by PDCCH order
if (*y == 0) {
int nof_bits = riv_nbits(nof_prb);
int i=0;
while(i<nof_bits && y[1+i] == 1)
i++;
if (i == nof_bits) {
printf("Warning check me: could this be a RA PDCCH order??\n");
i=1+10+nof_bits;
while(i<msg->nof_bits-1 && y[i] == 0) {
i++;
}
if (i == msg->nof_bits-1) {
printf("Received a Format1A RA PDCCH order. Not implemented!\n");
return SRSLTE_ERROR;
}
}
}
data->alloc_type = SRSLTE_RA_ALLOC_TYPE2;
data->type2_alloc.mode = *y++;

@ -426,6 +426,14 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
*/
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
/*
printf("WARNING REMOVE ME!\n");
int16_t *e=q->e;
for (int i=0;i<cfg->nbits.nof_bits;i++) {
e[i] = e[i]>0?10:-10;
}
*/
/* descramble */
if (rnti != q->rnti) {
srslte_sequence_t seq;

@ -229,13 +229,6 @@ static int encode_tb_off(srslte_sch_t *q,
parity[0] = (par&(0xff<<16))>>16;
parity[1] = (par&(0xff<<8))>>8;
parity[2] = par&0xff;
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("DATA: ", 0);
srslte_vec_fprint_byte(stdout, data, cb_segm->tbs/8);
DEBUG("PARITY: ", 0);
srslte_vec_fprint_byte(stdout, parity, 3);
}
}
wp = 0;
@ -425,7 +418,7 @@ static int decode_tb(srslte_sch_t *q,
srslte_tdec_decision_byte(&q->decoder, q->cb_in, cb_len);
/* Check Codeblock CRC and stop early if incorrect */
/* Check Codeblock CRC and stop early if correct */
if (!srslte_crc_checksum_byte(crc_ptr, q->cb_in, len_crc)) {
early_stop = true;
}
@ -448,6 +441,10 @@ static int decode_tb(srslte_sch_t *q,
memcpy(parity, &q->cb_in[(rlen - 24)/8], 3 * sizeof(uint8_t));
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
early_stop = true;
}
/* Set read/write pointers */
wp += rlen;
rp += n_e;

@ -45,6 +45,8 @@ void help()
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[])
{
@ -63,7 +65,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
srslte_verbose = SRSLTE_VERBOSE_INFO;
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
bzero(&cfg, sizeof(srslte_pdsch_cfg_t));
if (mexutils_read_cell(ENBCFG, &cell)) {
@ -174,9 +176,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
/** Allocate input buffers */
if (mexutils_read_cf(INPUT, &input_fft) < 0) {
mexErrMsgTxt("Error reading input signal\n");
return;
int nof_retx=1;
if (mexutils_isCell(INPUT)) {
nof_retx = mexutils_getLength(INPUT);
}
cf_t *ce[SRSLTE_MAX_PORTS];
@ -184,39 +186,55 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
}
if (nrhs > NOF_INPUTS) {
cf_t *cearray = NULL;
int nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
cf_t *cearray_ptr = cearray;
for (i=0;i<cell.nof_ports;i++) {
for (int j=0;j<nof_re/cell.nof_ports;j++) {
ce[i][j] = *cearray;
cearray++;
}
}
if (cearray_ptr)
free(cearray_ptr);
} else {
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
}
float noise_power;
if (nrhs > NOF_INPUTS + 1) {
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
} else {
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
}
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
if (!data_bytes) {
return;
}
srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations);
int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes);
int r=-1;
for (int rvIdx=0;rvIdx<nof_retx && r != 0;rvIdx++) {
free(data_bytes);
mxArray *tmp = (mxArray*) INPUT;
if (mexutils_isCell(INPUT)) {
tmp = mexutils_getCellArray(INPUT, rvIdx);
if (nof_retx > 1) {
cfg.rv = rv_seq[rvIdx%4];
}
}
if (mexutils_read_cf(tmp, &input_fft) < 0) {
mexErrMsgTxt("Error reading input signal\n");
return;
}
if (nrhs > NOF_INPUTS) {
cf_t *cearray = NULL;
int nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
cf_t *cearray_ptr = cearray;
for (i=0;i<cell.nof_ports;i++) {
for (int j=0;j<nof_re/cell.nof_ports;j++) {
ce[i][j] = *cearray;
cearray++;
}
}
if (cearray_ptr)
free(cearray_ptr);
} else {
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
}
float noise_power;
if (nrhs > NOF_INPUTS + 1) {
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
} else {
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
}
r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes);
free(input_fft);
}
uint8_t *data = malloc(grant.mcs.tbs);
srslte_bit_unpack_vector(data_bytes, data, grant.mcs.tbs);
@ -237,14 +255,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1);
}
srslte_softbuffer_rx_free(&softbuffer);
srslte_chest_dl_free(&chest);
srslte_pdsch_free(&pdsch);
for (i=0;i<cell.nof_ports;i++) {
free(ce[i]);
}
free(data_bytes);
free(data);
free(input_fft);
return;
}

Loading…
Cancel
Save