srsLTE/srslte/lib/ch_estimation/test/chest_test_dl_mex.c

247 lines
7.1 KiB
C
Raw Normal View History

2014-12-17 12:52:58 -08:00
/**
*
* \section COPYRIGHT
*
2015-05-08 08:05:40 -07:00
* Copyright 2013-2015 The srsLTE Developers. See the
2014-12-17 12:52:58 -08:00
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
2014-12-17 12:52:58 -08:00
*
* srsLTE is free software: you can redistribute it and/or modify
2015-05-08 08:05:40 -07:00
* it under the terms of the GNU Affero General Public License as
2014-12-17 12:52:58 -08:00
* 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,
2014-11-05 05:19:35 -08:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-05-08 08:05:40 -07:00
* GNU Affero General Public License for more details.
2014-12-17 12:52:58 -08:00
*
2015-05-08 08:05:40 -07:00
* A copy of the GNU Affero General Public License can be found in
2014-12-17 12:52:58 -08:00
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
2014-11-05 05:19:35 -08:00
*/
#include <string.h>
#include "srslte/srslte.h"
#include "srslte/mex/mexutils.h"
2014-11-05 05:19:35 -08:00
/** MEX function to be called from MATLAB to test the channel estimator
*/
#define CELLID prhs[0]
#define PORTS prhs[1]
#define INPUT prhs[2]
2014-11-11 10:20:09 -08:00
#define FREQ_FILTER prhs[3]
#define TIME_FILTER prhs[4]
#define NOF_INPUTS 5
#define SFIDX prhs[5]
2014-11-05 05:19:35 -08:00
void help()
{
mexErrMsgTxt
("[estChannel, avg_refs, output] = srslte_chest(cell_id, nof_ports, inputSignal,[sf_idx|freq_filter],"
"[time_filter])\n\n"
2014-11-05 05:19:35 -08:00
" Returns a matrix of size equal to the inputSignal matrix with the channel estimates\n "
"for each resource element in inputSignal. The inputSignal matrix is the received Grid\n"
"of size nof_resource_elements x nof_ofdm_symbols.\n"
"The sf_idx is the subframe index only used if inputSignal is 1 subframe length.\n"
"Returns the averaged references and output signal after ZF/MMSE equalization\n"
);
2014-11-05 05:19:35 -08:00
}
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int i;
2015-03-18 05:41:50 -07:00
srslte_cell_t cell;
srslte_chest_dl_t chest;
2015-03-18 11:14:24 -07:00
srslte_precoding_t cheq;
2015-03-18 05:59:29 -07:00
cf_t *input_signal = NULL, *output_signal[SRSLTE_MAX_LAYERS];
cf_t *output_signal2 = NULL;
2015-03-18 05:41:50 -07:00
cf_t *ce[SRSLTE_MAX_PORTS];
double *outr0=NULL, *outi0=NULL;
double *outr1=NULL, *outi1=NULL;
double *outr2=NULL, *outi2=NULL;
2014-11-11 10:20:09 -08:00
2014-11-05 05:19:35 -08:00
if (!mxIsDouble(CELLID) && mxGetN(CELLID) != 1 &&
!mxIsDouble(PORTS) && mxGetN(PORTS) != 1 &&
mxGetM(CELLID) != 1) {
help();
return;
}
cell.id = (uint32_t) *((double*) mxGetPr(CELLID));
2015-03-18 05:59:29 -07:00
cell.nof_prb = mxGetM(INPUT)/SRSLTE_NRE;
2014-11-05 05:19:35 -08:00
cell.nof_ports = (uint32_t) *((double*) mxGetPr(PORTS));
if ((mxGetN(INPUT)%14) == 0) {
2015-04-05 07:32:35 -07:00
cell.cp = SRSLTE_CP_NORM;
2014-11-05 05:19:35 -08:00
} else if ((mxGetN(INPUT)%12)!=0) {
2015-04-05 07:32:35 -07:00
cell.cp = SRSLTE_CP_EXT;
2014-11-05 05:19:35 -08:00
} else {
2014-11-11 10:20:09 -08:00
mexErrMsgTxt("Invalid number of symbols\n");
2014-11-05 05:19:35 -08:00
help();
return;
}
2015-03-18 05:41:50 -07:00
if (srslte_chest_dl_init(&chest, cell)) {
2014-11-05 05:19:35 -08:00
mexErrMsgTxt("Error initiating channel estimator\n");
return;
}
2014-11-11 10:20:09 -08:00
2014-11-05 05:19:35 -08:00
int nsubframes;
2015-04-05 07:32:35 -07:00
if (cell.cp == SRSLTE_CP_NORM) {
2014-11-05 05:19:35 -08:00
nsubframes = mxGetN(INPUT)/14;
} else {
nsubframes = mxGetN(INPUT)/12;
}
uint32_t sf_idx=0;
if (nsubframes == 1) {
if (nrhs != NOF_INPUTS+1) {
2014-11-11 10:20:09 -08:00
mexErrMsgTxt("Received 1 subframe. Need to provide subframe index.\n");
2014-11-05 05:19:35 -08:00
help();
return;
}
sf_idx = (uint32_t) *((double*) mxGetPr(SFIDX));
}
2014-11-11 10:20:09 -08:00
if (nrhs > 5) {
uint32_t filter_len = 0;
float *filter;
double *f;
filter_len = mxGetNumberOfElements(FREQ_FILTER);
filter = malloc(sizeof(float) * filter_len);
f = (double*) mxGetPr(FREQ_FILTER);
for (i=0;i<filter_len;i++) {
filter[i] = (float) f[i];
}
srslte_chest_dl_set_filter_freq(&chest, filter, filter_len);
filter_len = mxGetNumberOfElements(TIME_FILTER);
filter = malloc(sizeof(float) * filter_len);
f = (double*) mxGetPr(TIME_FILTER);
for (i=0;i<filter_len;i++) {
filter[i] = (float) f[i];
}
srslte_chest_dl_set_filter_time(&chest, filter, filter_len);
}
2014-11-11 10:20:09 -08:00
2014-11-05 05:19:35 -08:00
double *inr=(double *)mxGetPr(INPUT);
double *ini=(double *)mxGetPi(INPUT);
/** Allocate input buffers */
2015-03-18 05:59:29 -07:00
int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
2015-03-18 05:41:50 -07:00
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
2015-03-18 11:14:24 -07:00
ce[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
2014-11-05 05:19:35 -08:00
}
2015-03-18 11:14:24 -07:00
input_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
2015-03-18 05:41:50 -07:00
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
2015-03-18 11:14:24 -07:00
output_signal[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
}
2015-03-18 11:14:24 -07:00
output_signal2 = srslte_vec_malloc(nof_re * sizeof(cf_t));
2015-03-18 11:14:24 -07:00
srslte_precoding_init(&cheq, nof_re);
2014-11-05 05:19:35 -08:00
/* Create output values */
if (nlhs >= 1) {
plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
2014-11-05 05:19:35 -08:00
outr0 = mxGetPr(plhs[0]);
outi0 = mxGetPi(plhs[0]);
}
2014-11-11 10:20:09 -08:00
if (nlhs >= 2) {
2015-03-18 05:41:50 -07:00
plhs[1] = mxCreateDoubleMatrix(SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)*nsubframes, cell.nof_ports, mxCOMPLEX);
2014-11-05 05:19:35 -08:00
outr1 = mxGetPr(plhs[1]);
outi1 = mxGetPi(plhs[1]);
}
if (nlhs >= 3) {
plhs[2] = mxCreateDoubleMatrix(nof_re * nsubframes, 1, mxCOMPLEX);
outr2 = mxGetPr(plhs[2]);
outi2 = mxGetPi(plhs[2]);
}
2014-12-01 13:15:32 -08:00
2014-11-05 05:19:35 -08:00
for (int sf=0;sf<nsubframes;sf++) {
/* Convert input to C complex type */
for (i=0;i<nof_re;i++) {
__real__ input_signal[i] = (float) *inr;
if (ini) {
__imag__ input_signal[i] = (float) *ini;
}
inr++;
ini++;
}
if (nsubframes != 1) {
sf_idx = sf%10;
}
2015-03-18 05:41:50 -07:00
if (srslte_chest_dl_estimate(&chest, input_signal, ce, sf_idx)) {
2014-11-05 05:19:35 -08:00
mexErrMsgTxt("Error running channel estimator\n");
return;
}
2015-01-17 21:33:28 -08:00
if (cell.nof_ports == 1) {
2015-03-18 11:14:24 -07:00
srslte_predecoding_single(&cheq, input_signal, ce[0], output_signal2, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
} else {
2015-03-18 11:14:24 -07:00
srslte_predecoding_diversity(&cheq, input_signal, ce, output_signal, cell.nof_ports, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
2015-03-18 08:05:38 -07:00
srslte_layerdemap_diversity(output_signal, output_signal2, cell.nof_ports, nof_re/cell.nof_ports);
}
2014-11-11 10:20:09 -08:00
2014-11-05 05:19:35 -08:00
if (nlhs >= 1) {
for (int j=0;j<cell.nof_ports;j++) {
for (i=0;i<nof_re;i++) {
*outr0 = (double) crealf(ce[j][i]);
if (outi0) {
*outi0 = (double) cimagf(ce[j][i]);
}
outr0++;
outi0++;
}
}
2014-11-05 05:19:35 -08:00
}
2014-11-11 10:20:09 -08:00
if (nlhs >= 2) {
2014-11-05 05:19:35 -08:00
for (int j=0;j<cell.nof_ports;j++) {
2015-03-18 05:41:50 -07:00
for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) {
2014-11-11 10:20:09 -08:00
*outr1 = (double) crealf(chest.pilot_estimates_average[j][i]);
2014-11-05 05:19:35 -08:00
if (outi1) {
2014-11-11 10:20:09 -08:00
*outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]);
2014-11-05 05:19:35 -08:00
}
outr1++;
outi1++;
}
}
}
if (nlhs >= 3) {
for (i=0;i<nof_re;i++) {
*outr2 = (double) crealf(output_signal2[i]);
if (outi2) {
*outi2 = (double) cimagf(output_signal2[i]);
}
outr2++;
outi2++;
}
}
2014-11-05 05:19:35 -08:00
}
2014-12-01 13:15:32 -08:00
if (nlhs >= 4) {
2015-05-19 11:22:58 -07:00
plhs[3] = mxCreateDoubleScalar(srslte_chest_dl_get_noise_estimate(&chest));
2014-12-01 13:15:32 -08:00
}
2015-01-17 21:33:28 -08:00
if (nlhs >= 5) {
2015-05-19 11:22:58 -07:00
plhs[4] = mxCreateDoubleScalar(srslte_chest_dl_get_rsrp(&chest));
2015-01-17 21:33:28 -08:00
}
2015-03-18 05:41:50 -07:00
srslte_chest_dl_free(&chest);
2015-03-18 11:14:24 -07:00
srslte_precoding_free(&cheq);
2014-12-01 13:15:32 -08:00
2014-11-05 05:19:35 -08:00
return;
}