mirror of https://github.com/pvnis/srsRAN_4G.git
DMRS PUSCH estimation working and tested
parent
00c2083c1b
commit
d622d5d19d
@ -0,0 +1,184 @@
|
||||
%% LTE Downlink Channel Estimation and Equalization
|
||||
|
||||
%% Cell-Wide Settings
|
||||
|
||||
clear
|
||||
|
||||
plot_noise_estimation_only=false;
|
||||
|
||||
SNR_values_db=linspace(0,30,5);
|
||||
Nrealizations=1;
|
||||
|
||||
w1=1/3;
|
||||
|
||||
%% UE Configuration
|
||||
ue = lteRMCUL('A3-5');
|
||||
ue.TotSubframes = 2;
|
||||
|
||||
K=ue.NULRB*12;
|
||||
P=K/6;
|
||||
|
||||
%% Channel Model Configuration
|
||||
chs.Seed = 1; % Random channel seed
|
||||
chs.InitTime = 0;
|
||||
chs.NRxAnts = 1; % 1 receive antenna
|
||||
chs.DelayProfile = 'EVA';
|
||||
chs.DopplerFreq = 300; % 120Hz Doppler frequency
|
||||
chs.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
|
||||
chs.NTerms = 16; % Oscillators used in fading model
|
||||
chs.ModelType = 'GMEDS'; % Rayleigh fading model type
|
||||
chs.InitPhase = 'Random'; % Random initial phases
|
||||
chs.NormalizePathGains = 'On'; % Normalize delay profile power
|
||||
chs.NormalizeTxAnts = 'On'; % Normalize for transmit antennas
|
||||
|
||||
%% Channel Estimator Configuration
|
||||
cec = struct; % Channel estimation config structure
|
||||
cec.PilotAverage = 'UserDefined'; % Type of pilot symbol 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
|
||||
|
||||
|
||||
%% Allocate memory
|
||||
Ntests=3;
|
||||
hest=cell(1,Ntests);
|
||||
for i=1:Ntests
|
||||
hest{i}=zeros(K,14);
|
||||
end
|
||||
MSE=zeros(Ntests,Nrealizations,length(SNR_values_db));
|
||||
noiseEst=zeros(Ntests,Nrealizations,length(SNR_values_db));
|
||||
|
||||
legends={'matlab','ls',num2str(w1)};
|
||||
colors={'bo-','rx-','m*-','k+-','c+-'};
|
||||
colors2={'b-','r-','m-','k-','c-'};
|
||||
|
||||
addpath('../../build/srslte/lib/ch_estimation/test')
|
||||
|
||||
offset = -1;
|
||||
for nreal=1:Nrealizations
|
||||
|
||||
%% Signal Generation
|
||||
[txWaveform, txGrid, info] = lteRMCULTool(ue,[1;0;0;1]);
|
||||
|
||||
%% SNR Configuration
|
||||
for snr_idx=1:length(SNR_values_db)
|
||||
SNRdB = SNR_values_db(snr_idx); % Desired SNR in dB
|
||||
SNR = 10^(SNRdB/20); % Linear SNR
|
||||
|
||||
fprintf('SNR=%.1f dB\n',SNRdB)
|
||||
|
||||
%% Fading Channel
|
||||
|
||||
chs.SamplingRate = info.SamplingRate;
|
||||
[rxWaveform, chinfo] = lteFadingChannel(chs,txWaveform);
|
||||
|
||||
%% Additive Noise
|
||||
|
||||
% Calculate noise gain
|
||||
N0 = 1/(sqrt(2.0*double(info.Nfft))*SNR);
|
||||
|
||||
% Create additive white Gaussian noise
|
||||
noise = N0*complex(randn(size(rxWaveform)),randn(size(rxWaveform)));
|
||||
|
||||
% Add noise to the received time domain waveform
|
||||
rxWaveform = rxWaveform + noise;
|
||||
|
||||
%% Synchronization
|
||||
|
||||
% Time offset estimation is done once because depends on channel
|
||||
% model only
|
||||
if (offset==-1)
|
||||
offset = lteULFrameOffset(ue,ue.PUSCH,rxWaveform);
|
||||
end
|
||||
rxWaveform = rxWaveform(1+offset:end);
|
||||
|
||||
%% OFDM Demodulation
|
||||
rxGrid = lteSCFDMADemodulate(ue,rxWaveform);
|
||||
rxGrid = rxGrid(:,1:14);
|
||||
|
||||
%% Perfect channel estimate
|
||||
h=lteULPerfectChannelEstimate(ue,chs,offset);
|
||||
h=h(:,1:14);
|
||||
|
||||
%% Channel Estimation with Matlab
|
||||
[hest{1}, noiseEst(1,nreal,snr_idx)] = lteULChannelEstimate(ue,ue.PUSCH,cec,rxGrid);
|
||||
|
||||
%% LS-Linear estimation with srsLTE
|
||||
[hest{2}, noiseEst(2,nreal,snr_idx)] = srslte_chest_ul(ue,ue.PUSCH,rxGrid);
|
||||
|
||||
%% LS-Linear estimation + averaging with srsLTE
|
||||
[hest{3}, noiseEst(3,nreal,snr_idx)] = srslte_chest_ul(ue,ue.PUSCH,rxGrid,w1);
|
||||
|
||||
%% Compute MSE
|
||||
for i=1:Ntests
|
||||
MSE(i,nreal,snr_idx)=mean(mean(abs(h-hest{i}).^2));
|
||||
fprintf('MSE test %d: %f\n',i, 10*log10(MSE(i,nreal,snr_idx)));
|
||||
end
|
||||
|
||||
%% Plot a single realization
|
||||
if (length(SNR_values_db) == 1)
|
||||
subplot(1,1,1)
|
||||
sym=1;
|
||||
n=1:(K*length(sym));
|
||||
for i=1:Ntests
|
||||
plot(n,abs(reshape(hest{i}(:,sym),1,[])),colors2{i});
|
||||
hold on;
|
||||
end
|
||||
plot(n,abs(reshape(h(:,sym),1,[])),'k');
|
||||
hold off;
|
||||
|
||||
tmp=cell(Ntests+1,1);
|
||||
for i=1:Ntests
|
||||
tmp{i}=legends{i};
|
||||
end
|
||||
tmp{Ntests+1}='Perfect';
|
||||
legend(tmp)
|
||||
|
||||
xlabel('SNR (dB)')
|
||||
ylabel('Channel Gain')
|
||||
grid on;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
%% Compute average MSE and noise estimation
|
||||
mean_mse=mean(MSE,2);
|
||||
mean_snr=10*log10(1./mean(noiseEst,2));
|
||||
|
||||
%disp(mean_snr(3)
|
||||
|
||||
%% Plot average over all SNR values
|
||||
if (length(SNR_values_db) > 1)
|
||||
subplot(1,2,1)
|
||||
for i=1:Ntests
|
||||
plot(SNR_values_db, 10*log10(mean_mse(i,:)),colors{i})
|
||||
hold on;
|
||||
end
|
||||
hold off;
|
||||
legend(legends);
|
||||
grid on
|
||||
xlabel('SNR (dB)')
|
||||
ylabel('MSE (dB)')
|
||||
|
||||
subplot(1,2,2)
|
||||
plot(SNR_values_db, SNR_values_db,'k:')
|
||||
hold on;
|
||||
for i=1:Ntests
|
||||
plot(SNR_values_db, mean_snr(i,:), colors{i})
|
||||
end
|
||||
hold off
|
||||
tmp=cell(Ntests+1,1);
|
||||
tmp{1}='Theory';
|
||||
for i=2:Ntests+1
|
||||
tmp{i}=legends{i-1};
|
||||
end
|
||||
legend(tmp)
|
||||
grid on
|
||||
xlabel('SNR (dB)')
|
||||
ylabel('Estimated SNR (dB)')
|
||||
end
|
||||
|
@ -0,0 +1,253 @@
|
||||
/**
|
||||
*
|
||||
* \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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <complex.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
srslte_cell_t cell = {
|
||||
6, // nof_prb
|
||||
1, // nof_ports
|
||||
0,
|
||||
1000, // cell_id
|
||||
SRSLTE_CP_NORM // cyclic prefix
|
||||
};
|
||||
|
||||
char *output_matlab = NULL;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [recov]\n", prog);
|
||||
|
||||
printf("\t-r nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-e extended cyclic prefix [Default normal]\n");
|
||||
|
||||
printf("\t-c cell_id (1000 tests all). [Default %d]\n", cell.id);
|
||||
|
||||
printf("\t-o output matlab file [Default %s]\n",output_matlab?output_matlab:"None");
|
||||
printf("\t-v increase verbosity\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "recov")) != -1) {
|
||||
switch(opt) {
|
||||
case 'r':
|
||||
cell.nof_prb = atoi(argv[optind]);
|
||||
break;
|
||||
case 'e':
|
||||
cell.cp = SRSLTE_CP_EXT;
|
||||
break;
|
||||
case 'c':
|
||||
cell.id = atoi(argv[optind]);
|
||||
break;
|
||||
case 'o':
|
||||
output_matlab = argv[optind];
|
||||
break;
|
||||
case 'v':
|
||||
srslte_verbose++;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
srslte_chest_ul_t est;
|
||||
cf_t *input = NULL, *ce = NULL, *h = NULL;
|
||||
int i, j, n_port=0, sf_idx=0, cid=0, num_re;
|
||||
int ret = -1;
|
||||
int max_cid;
|
||||
FILE *fmatlab = NULL;
|
||||
|
||||
parse_args(argc,argv);
|
||||
|
||||
if (output_matlab) {
|
||||
fmatlab=fopen(output_matlab, "w");
|
||||
if (!fmatlab) {
|
||||
perror("fopen");
|
||||
goto do_exit;
|
||||
}
|
||||
}
|
||||
|
||||
num_re = 2 * cell.nof_prb * SRSLTE_NRE * SRSLTE_CP_NSYMB(cell.cp);
|
||||
|
||||
input = srslte_vec_malloc(num_re * sizeof(cf_t));
|
||||
if (!input) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto do_exit;
|
||||
}
|
||||
h = srslte_vec_malloc(num_re * sizeof(cf_t));
|
||||
if (!h) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto do_exit;
|
||||
}
|
||||
ce = srslte_vec_malloc(num_re * sizeof(cf_t));
|
||||
if (!ce) {
|
||||
perror("srslte_vec_malloc");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
if (cell.id == 1000) {
|
||||
cid = 0;
|
||||
max_cid = 504;
|
||||
} else {
|
||||
cid = cell.id;
|
||||
max_cid = cell.id;
|
||||
}
|
||||
printf("max_cid=%d, cid=%d, cell.id=%d\n", max_cid, cid, cell.id);
|
||||
while(cid <= max_cid) {
|
||||
cell.id = cid;
|
||||
if (srslte_chest_ul_init(&est, cell)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
for (int n=6;n<=cell.nof_prb;n+=5) {
|
||||
if (srslte_dft_precoding_valid_prb(n)) {
|
||||
for (int delta_ss=29;delta_ss<SRSLTE_NOF_DELTA_SS;delta_ss++) {
|
||||
for (int cshift=7;cshift<SRSLTE_NOF_CSHIFT;cshift++) {
|
||||
for (int t=2;t<3;t++) {
|
||||
|
||||
/* Setup and pregen DMRS reference signals */
|
||||
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
|
||||
|
||||
uint32_t nof_prb = n;
|
||||
pusch_cfg.cyclic_shift = cshift;
|
||||
pusch_cfg.delta_ss = delta_ss;
|
||||
bool group_hopping_en = false;
|
||||
bool sequence_hopping_en = false;
|
||||
|
||||
if (!t) {
|
||||
group_hopping_en = false;
|
||||
sequence_hopping_en = false;
|
||||
} else if (t == 1) {
|
||||
group_hopping_en = false;
|
||||
sequence_hopping_en = true;
|
||||
} else if (t == 2) {
|
||||
group_hopping_en = true;
|
||||
sequence_hopping_en = false;
|
||||
}
|
||||
pusch_cfg.group_hopping_en = group_hopping_en;
|
||||
pusch_cfg.sequence_hopping_en = sequence_hopping_en;
|
||||
srslte_chest_ul_set_cfg(&est, &pusch_cfg, NULL, NULL);
|
||||
|
||||
// Loop through subframe idx and cyclic shifts
|
||||
|
||||
for (int sf_idx=0;sf_idx<10;sf_idx+=3) {
|
||||
for (int cshift_dmrs=0;cshift_dmrs<SRSLTE_NOF_CSHIFT;cshift_dmrs+=5) {
|
||||
|
||||
|
||||
if (SRSLTE_VERBOSE_ISINFO()) {
|
||||
printf("nof_prb: %d, ",nof_prb);
|
||||
printf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
|
||||
printf("cyclic_shift_for_dmrs: %d, ", cshift_dmrs);
|
||||
printf("delta_ss: %d, ",pusch_cfg.delta_ss);
|
||||
printf("SF_idx: %d\n", sf_idx);
|
||||
}
|
||||
|
||||
/* Generate random input */
|
||||
bzero(input, sizeof(cf_t) * num_re);
|
||||
for (i=0;i<num_re;i++) {
|
||||
input[i] = 0.5-rand()/RAND_MAX+I*(0.5-rand()/RAND_MAX);
|
||||
}
|
||||
|
||||
/* Generate channel and pass input through channel */
|
||||
for (i=0;i<2*SRSLTE_CP_NSYMB(cell.cp);i++) {
|
||||
for (j=0;j<cell.nof_prb * SRSLTE_NRE;j++) {
|
||||
float x = -1+(float) i/SRSLTE_CP_NSYMB(cell.cp) + cosf(2 * M_PI * (float) j/cell.nof_prb/SRSLTE_NRE);
|
||||
h[i*cell.nof_prb * SRSLTE_NRE+j] = (3+x) * cexpf(I * x);
|
||||
input[i*cell.nof_prb * SRSLTE_NRE+j] *= h[i*cell.nof_prb * SRSLTE_NRE+j];
|
||||
}
|
||||
}
|
||||
|
||||
// Estimate channel
|
||||
uint32_t prb_idx[2]= {0, 0};
|
||||
srslte_chest_ul_estimate(&est, input, ce, n, sf_idx, cshift_dmrs, prb_idx);
|
||||
|
||||
// Compute MSE
|
||||
float mse = 0;
|
||||
for (i=0;i<num_re;i++) {
|
||||
mse += cabsf(ce[i]-h[i]);
|
||||
}
|
||||
mse /= num_re;
|
||||
INFO("MSE: %f\n", mse);
|
||||
if (mse > 4) {
|
||||
goto do_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cid+=10;
|
||||
printf("cid=%d\n", cid);
|
||||
srslte_chest_ul_free(&est);
|
||||
}
|
||||
|
||||
|
||||
if (fmatlab) {
|
||||
fprintf(fmatlab, "input=");
|
||||
srslte_vec_fprint_c(fmatlab, input, num_re);
|
||||
fprintf(fmatlab, ";\n");
|
||||
fprintf(fmatlab, "h=");
|
||||
srslte_vec_fprint_c(fmatlab, h, num_re);
|
||||
fprintf(fmatlab, ";\n");
|
||||
fprintf(fmatlab, "ce=");
|
||||
srslte_vec_fprint_c(fmatlab, ce, num_re);
|
||||
fprintf(fmatlab, ";\n");
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
do_exit:
|
||||
|
||||
if (ce) {
|
||||
free(ce);
|
||||
}
|
||||
if (input) {
|
||||
free(input);
|
||||
}
|
||||
if (h) {
|
||||
free(h);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("OK\n");
|
||||
} else {
|
||||
printf("Error at cid=%d, slot=%d, port=%d\n",cid, sf_idx, n_port);
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
/**
|
||||
*
|
||||
* \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 INPUT prhs[2]
|
||||
#define NOF_INPUTS 3
|
||||
|
||||
void help()
|
||||
{
|
||||
mexErrMsgTxt
|
||||
("[estChannel, noiseEst, eq_output] = srslte_chest_ul(ue_cfg, pusch_cfg, inputSignal, [w_coeff])\n");
|
||||
}
|
||||
|
||||
/* the gateway function */
|
||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
srslte_cell_t cell;
|
||||
srslte_chest_ul_t chest;
|
||||
|
||||
cf_t *input_signal = NULL, *output_signal = NULL;
|
||||
cf_t *ce = NULL;
|
||||
|
||||
if (nrhs < NOF_INPUTS) {
|
||||
help();
|
||||
return;
|
||||
}
|
||||
|
||||
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 NCellID not found in UE config\n");
|
||||
return;
|
||||
}
|
||||
cell.cp = SRSLTE_CP_NORM;
|
||||
cell.nof_ports = 1;
|
||||
|
||||
uint32_t sf_idx=0;
|
||||
if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) {
|
||||
help();
|
||||
return;
|
||||
}
|
||||
|
||||
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
|
||||
pusch_cfg.group_hopping_en = false;
|
||||
pusch_cfg.sequence_hopping_en = false;
|
||||
char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
|
||||
if (tmp) {
|
||||
if (!strcmp(tmp, "Group")) {
|
||||
pusch_cfg.group_hopping_en = true;
|
||||
} else if (!strcmp(tmp, "Sequence")) {
|
||||
pusch_cfg.sequence_hopping_en = true;
|
||||
}
|
||||
mxFree(tmp);
|
||||
}
|
||||
|
||||
|
||||
if (mexutils_read_uint32_struct(UECFG, "SeqGroup", &pusch_cfg.delta_ss)) {
|
||||
pusch_cfg.delta_ss = 0;
|
||||
}
|
||||
if (mexutils_read_uint32_struct(UECFG, "CyclicShift", &pusch_cfg.cyclic_shift)) {
|
||||
pusch_cfg.cyclic_shift = 0;
|
||||
}
|
||||
float *prbset;
|
||||
mxArray *p;
|
||||
p = mxGetField(PUSCHCFG, 0, "PRBSet");
|
||||
if (!p) {
|
||||
mexErrMsgTxt("Error field PRBSet not found in PUSCH config\n");
|
||||
return;
|
||||
}
|
||||
uint32_t nof_prb = mexutils_read_f(p, &prbset);
|
||||
uint32_t n_prb[2];
|
||||
n_prb[0] = prbset[0];
|
||||
n_prb[1] = prbset[0];
|
||||
|
||||
|
||||
uint32_t cyclic_shift_for_dmrs = 0;
|
||||
if (mexutils_read_uint32_struct(PUSCHCFG, "DynCyclicShift", &cyclic_shift_for_dmrs)) {
|
||||
cyclic_shift_for_dmrs = 0;
|
||||
}
|
||||
|
||||
if (srslte_chest_ul_init(&chest, cell)) {
|
||||
mexErrMsgTxt("Error initiating channel estimator\n");
|
||||
return;
|
||||
}
|
||||
|
||||
srslte_chest_ul_set_cfg(&chest, &pusch_cfg, NULL, NULL);
|
||||
|
||||
/** Allocate input buffers */
|
||||
int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
|
||||
ce = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
||||
output_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
||||
|
||||
// Read input signal
|
||||
int insignal_len = mexutils_read_cf(INPUT, &input_signal);
|
||||
if (insignal_len < 0) {
|
||||
mexErrMsgTxt("Error reading input signal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read optional value smooth filter coefficient
|
||||
if (nrhs > NOF_INPUTS) {
|
||||
float w = (float) mxGetScalar(prhs[NOF_INPUTS]);
|
||||
srslte_chest_ul_set_smooth_filter3_coeff(&chest, w);
|
||||
} else {
|
||||
srslte_chest_ul_set_smooth_filter(&chest, NULL, 0);
|
||||
}
|
||||
|
||||
// Perform channel estimation
|
||||
if (srslte_chest_ul_estimate(&chest, input_signal, ce, nof_prb, sf_idx, cyclic_shift_for_dmrs, n_prb)) {
|
||||
mexErrMsgTxt("Error running channel estimator\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get noise power estimation
|
||||
float noise_power = srslte_chest_ul_get_noise_estimate(&chest);
|
||||
|
||||
// Perform channel equalization
|
||||
srslte_predecoding_single(input_signal, ce, output_signal, nof_re, noise_power);
|
||||
|
||||
/* Write output values */
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(ce, &plhs[0], mxGetM(INPUT), mxGetN(INPUT));
|
||||
}
|
||||
if (nlhs >= 2) {
|
||||
plhs[1] = mxCreateDoubleScalar(noise_power);
|
||||
}
|
||||
if (nlhs >= 3) {
|
||||
mexutils_write_cf(output_signal, &plhs[2], mxGetM(INPUT), mxGetN(INPUT));
|
||||
}
|
||||
|
||||
// Free all memory
|
||||
srslte_chest_ul_free(&chest);
|
||||
|
||||
if (ce) {
|
||||
free(ce);
|
||||
}
|
||||
if (input_signal) {
|
||||
free(input_signal);
|
||||
}
|
||||
if (output_signal) {
|
||||
free(output_signal);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue