From daae1da8bced60f3ddf66451530885b9f5d47573 Mon Sep 17 00:00:00 2001 From: ismagom Date: Fri, 13 Feb 2015 11:14:10 +0100 Subject: [PATCH] Added DFT transform precoding --- .../include/liblte/phy/filter/dft_precoding.h | 64 ++++++ lte/phy/lib/filter/src/dft_precoding.c | 116 +++++++++++ lte/phy/lib/phch/test/pusch_encode_test_mex.c | 197 ++++++++++++++++++ matlab/tests/print_m.m | 9 + 4 files changed, 386 insertions(+) create mode 100644 lte/phy/include/liblte/phy/filter/dft_precoding.h create mode 100644 lte/phy/lib/filter/src/dft_precoding.c create mode 100644 lte/phy/lib/phch/test/pusch_encode_test_mex.c create mode 100644 matlab/tests/print_m.m diff --git a/lte/phy/include/liblte/phy/filter/dft_precoding.h b/lte/phy/include/liblte/phy/filter/dft_precoding.h new file mode 100644 index 000000000..cd0f9a514 --- /dev/null +++ b/lte/phy/include/liblte/phy/filter/dft_precoding.h @@ -0,0 +1,64 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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/. + * + */ + + +#ifndef DFTPREC_ +#define DFTPREC_ + +#include "liblte/config.h" +#include "liblte/phy/common/phy_common.h" +#include "liblte/phy/utils/dft.h" + +typedef _Complex float cf_t; + +/* DFT-based Transform Precoding object */ +typedef struct LIBLTE_API { + + uint32_t max_prb; + dft_plan_t dft_plan[MAX_PRB]; + dft_plan_t idft_plan[MAX_PRB]; + +}dft_precoding_t; + +LIBLTE_API int dft_precoding_init(dft_precoding_t *q, + uint32_t max_prb); + +LIBLTE_API void dft_precoding_free(dft_precoding_t *q); + +LIBLTE_API int dft_precoding(dft_precoding_t *q, + cf_t *input, + cf_t *output, + uint32_t nof_prb, + uint32_t nof_symbols); + +LIBLTE_API int dft_predecoding(dft_precoding_t *q, + cf_t *input, + cf_t *output, + uint32_t nof_prb, + uint32_t nof_symbols); + +#endif diff --git a/lte/phy/lib/filter/src/dft_precoding.c b/lte/phy/lib/filter/src/dft_precoding.c new file mode 100644 index 000000000..9d5730740 --- /dev/null +++ b/lte/phy/lib/filter/src/dft_precoding.c @@ -0,0 +1,116 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 +#include +#include +#include +#include +#include +#include + +#include "liblte/phy/common/phy_common.h" +#include "liblte/phy/utils/debug.h" +#include "liblte/phy/utils/vector.h" +#include "liblte/phy/utils/dft.h" +#include "liblte/phy/filter/dft_precoding.h" + +/* Create DFT plans for transform precoding */ +int dft_precoding_init(dft_precoding_t *q, uint32_t max_prb) +{ + int ret = LIBLTE_ERROR_INVALID_INPUTS; + bzero(q, sizeof(dft_precoding_t)); + + if (max_prb >= MAX_PRB) { + ret = LIBLTE_ERROR; + for (uint32_t i=0;idft_plan[i], i*RE_X_RB, FORWARD)) { + fprintf(stderr, "Error: Creating DFT plan %d\n",i); + goto clean_exit; + } + if (dft_plan_c(&q->idft_plan[i], i*RE_X_RB, BACKWARD)) { + fprintf(stderr, "Error: Creating DFT plan %d\n",i); + goto clean_exit; + } + } + } + q->max_prb = max_prb; + ret = LIBLTE_SUCCESS; + } + +clean_exit: + if (ret == LIBLTE_ERROR) { + dft_precoding_free(q); + } + return ret; +} + +/* Free DFT plans for transform precoding */ +void dft_precoding_free(dft_precoding_t *q) +{ + for (uint32_t i=0;imax_prb;i++) { + if((i % 2) == 0 || (i % 3) == 0 || (i % 5) == 0) { + dft_plan_free(&q->dft_plan[i]); + dft_plan_free(&q->idft_plan[i]); + } + } + bzero(q, sizeof(dft_precoding_t)); +} + +int dft_precoding(dft_precoding_t *q, cf_t *input, cf_t *output, + uint32_t nof_prb, uint32_t nof_symbols) +{ + + if ((nof_prb%2) || (nof_prb%3) || (nof_prb%5)) { + fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb); + return LIBLTE_ERROR; + } + + for (uint32_t i=0;idft_plan[nof_prb], &input[i*RE_X_RB*nof_prb], &output[i*RE_X_RB*nof_prb]); + } + + return LIBLTE_SUCCESS; +} + +int dft_predecoding(dft_precoding_t *q, cf_t *input, cf_t *output, + uint32_t nof_prb, uint32_t nof_symbols) +{ + if ((nof_prb%2) || (nof_prb%3) || (nof_prb%5)) { + fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb); + return LIBLTE_ERROR; + } + + for (uint32_t i=0;idft_plan[nof_prb], &input[i*RE_X_RB*nof_prb], &output[i*RE_X_RB*nof_prb]); + } + + return LIBLTE_SUCCESS; + +} \ No newline at end of file diff --git a/lte/phy/lib/phch/test/pusch_encode_test_mex.c b/lte/phy/lib/phch/test/pusch_encode_test_mex.c new file mode 100644 index 000000000..5c468f188 --- /dev/null +++ b/lte/phy/lib/phch/test/pusch_encode_test_mex.c @@ -0,0 +1,197 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2014 The libLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the libLTE library. + * + * libLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libLTE 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 Lesser General Public License for more details. + * + * A copy of the GNU Lesser 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 "liblte/phy/phy.h" +#include "liblte/mex/mexutils.h" + +/** MEX function to be called from MATLAB to test the channel estimator + */ + +#define UECFG prhs[0] +#define PUSCHCFG prhs[1] +#define TRBLKIN prhs[2] +#define CQI prhs[3] +#define RI prhs[4] +#define ACK prhs[5] +#define NOF_INPUTS 3 + +void help() +{ + mexErrMsgTxt + ("sym=liblte_pusch_encode(ue, chs, trblkin, cqi, ri, ack)\n\n"); +} + +/* the gateway function */ +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + int i; + lte_cell_t cell; + pusch_t pusch; + uint32_t sf_idx; + uint8_t *trblkin = NULL; + cf_t *sf_symbols = NULL; + ra_mcs_t mcs; + ra_prb_t prb_alloc; + harq_t harq_process; + uint32_t rv; + uint32_t rnti32; + uci_data_t uci_data; + bzero(&uci_data, sizeof(uci_data_t)); + + if (nrhs != NOF_INPUTS) { + help(); + return; + } + + if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) { + mexErrMsgTxt("Field NCellID not found in pusch config\n"); + return; + } + if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) { + mexErrMsgTxt("Field NCellID not found in pusch config\n"); + return; + } + + if (mexutils_read_uint32_struct(UECFG, "RNTI", &rnti32)) { + mexErrMsgTxt("Field RNTI not found in pusch config\n"); + return; + } + + char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); + + if (!strcmp(mod_str, "QPSK")) { + mcs.mod = LTE_QPSK; + } else if (!strcmp(mod_str, "16QAM")) { + mcs.mod = LTE_QAM16; + } else if (!strcmp(mod_str, "64QAM")) { + mcs.mod = LTE_QAM64; + } else { + mexErrMsgTxt("Unknown modulation\n"); + return; + } + + mxFree(mod_str); + + float *prbset = NULL; + mxArray *p; + p = mxGetField(PUSCHCFG, 0, "PRBSet"); + if (!p) { + mexErrMsgTxt("Error field PRBSet not found\n"); + return; + } + + // Only localized PRB supported + prb_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset); + + for (i=0;i 0) { + uci_data.uci_ri = *tmp; + } + free(tmp); + uci_data.uci_ack_len = mexutils_read_uint8(ACK, &tmp); + if (uci_data.uci_ack_len > 0) { + uci_data.uci_ack = *tmp; + } + free(tmp); + + mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", mcs.tbs, + uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ri_len); + + if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { + mexErrMsgTxt("Field RV not found in pdsch config\n"); + return; + } + + if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &uci_data.beta_cqi)) { + uci_data.beta_cqi = 2.0; + } + if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &uci_data.beta_ri)) { + uci_data.beta_ri = 2.0; + } + if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &uci_data.beta_ack)) { + uci_data.beta_ack = 2.0; + } + mexPrintf("Beta_CQI: %.1f, Beta_ACK: %.1f, Beta_RI: %.1f\n", + uci_data.beta_cqi, uci_data.beta_ack, uci_data.beta_ri); + + sf_symbols = vec_malloc(sizeof(cf_t) * harq_process.nof_re); + if (!sf_symbols) { + mexErrMsgTxt("malloc"); + return; + } + + if (harq_setup_ul(&harq_process, mcs, rv, sf_idx, &prb_alloc)) { + mexErrMsgTxt("Error configuring HARQ process\n"); + return; + } + + int r = pusch_uci_encode(&pusch, &harq_process, trblkin, uci_data, sf_symbols); + if (r < 0) { + mexErrMsgTxt("Error encoding PUSCH\n"); + return; + } + + if (nlhs >= 1) { + mexutils_write_cf(sf_symbols, &plhs[0], harq_process.nof_re, 1); + } + pusch_free(&pusch); + free(trblkin); + free(uci_data.uci_cqi); + free(sf_symbols); + + return; +} + diff --git a/matlab/tests/print_m.m b/matlab/tests/print_m.m new file mode 100644 index 000000000..0aa456902 --- /dev/null +++ b/matlab/tests/print_m.m @@ -0,0 +1,9 @@ +fprintf('static uint8_t M_basis_seq_pucch[20][13]={\n'); +for i=1:20 + fprintf('\t\t{'); + for j=1:12 + fprintf('%d, ',y(i,j)); + end + fprintf('%d},\n',y(i,13)); +end +fprintf('\t\t};\n');