srsLTE/srslte/lib/ue/src/ue_ul.c

229 lines
7.4 KiB
C
Raw Normal View History

/**
*
* \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 <complex.h>
#include <math.h>
2015-03-06 04:24:24 -08:00
#include <string.h>
#include "srslte/ue/ue_ul.h"
2015-03-18 05:59:29 -07:00
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
#define CURRENT_SFLEN SRSLTE_SF_LEN(CURRENT_FFTSIZE)
2015-03-18 05:59:29 -07:00
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
2015-03-18 11:14:24 -07:00
int srslte_ue_ul_init(srslte_ue_ul_t *q,
2015-03-18 05:41:50 -07:00
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
2015-03-18 05:59:29 -07:00
srslte_cell_isvalid(&cell))
{
ret = SRSLTE_ERROR;
2015-03-18 11:14:24 -07:00
bzero(q, sizeof(srslte_ue_ul_t));
q->cell = cell;
2015-03-18 11:14:24 -07:00
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
2015-03-18 11:14:24 -07:00
srslte_ofdm_set_freq_shift(&q->fft, 0.5);
srslte_ofdm_set_normalize(&q->fft, true);
2015-03-11 09:42:36 -07:00
q->normalize_en = true;
2015-03-18 11:14:24 -07:00
if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) {
fprintf(stderr, "Error creating CFO object\n");
goto clean_exit;
}
2015-03-18 11:14:24 -07:00
if (srslte_pusch_init(&q->pusch, q->cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
2015-03-18 11:14:24 -07:00
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
if (srslte_harq_init(&q->harq_process[i], q->cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
goto clean_exit;
}
}
2015-03-18 05:41:50 -07:00
if (srslte_refsignal_ul_init(&q->drms, cell)) {
fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
goto clean_exit;
}
2015-03-18 11:14:24 -07:00
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
2015-03-18 11:14:24 -07:00
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
if (!q->refsignal) {
perror("malloc");
goto clean_exit;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
clean_exit:
if (ret == SRSLTE_ERROR) {
2015-03-18 11:14:24 -07:00
srslte_ue_ul_free(q);
}
return ret;
}
2015-03-18 11:14:24 -07:00
void srslte_ue_ul_free(srslte_ue_ul_t *q) {
if (q) {
2015-03-18 11:14:24 -07:00
srslte_ofdm_tx_free(&q->fft);
srslte_pusch_free(&q->pusch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
srslte_harq_free(&q->harq_process[i]);
}
2015-03-18 11:14:24 -07:00
srslte_cfo_free(&q->cfo);
2015-03-18 05:41:50 -07:00
srslte_refsignal_ul_free(&q->drms);
if (q->sf_symbols) {
free(q->sf_symbols);
}
if (q->refsignal) {
free(q->refsignal);
}
2015-03-18 11:14:24 -07:00
bzero(q, sizeof(srslte_ue_ul_t));
}
}
2015-03-18 11:14:24 -07:00
void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) {
q->current_cfo = cur_cfo;
}
2015-03-18 11:14:24 -07:00
void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled)
2015-03-11 09:42:36 -07:00
{
q->normalize_en = enabled;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
2015-03-18 11:14:24 -07:00
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/
2015-03-18 11:14:24 -07:00
void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, uint16_t rnti) {
q->current_rnti = rnti;
2015-03-18 11:14:24 -07:00
srslte_pusch_set_rnti(&q->pusch, rnti);
}
2015-03-18 11:14:24 -07:00
void srslte_ue_ul_reset(srslte_ue_ul_t *q) {
srslte_harq_reset(&q->harq_process[0]);
}
2015-03-18 11:14:24 -07:00
void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, srslte_refsignal_drms_pusch_cfg_t *drms_cfg, srslte_pusch_hopping_cfg_t *pusch_hopping_cfg)
{
2015-03-18 11:14:24 -07:00
memcpy(&q->drms_cfg, drms_cfg, sizeof(srslte_refsignal_drms_pusch_cfg_t));
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
}
2015-03-18 11:14:24 -07:00
int srslte_ue_ul_srslte_pusch_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, cf_t *output_signal)
{
2015-03-18 11:14:24 -07:00
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_ue_ul_srslte_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal);
}
2015-03-18 11:14:24 -07:00
int srslte_ue_ul_srslte_pusch_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, uint16_t rnti, cf_t *output_signal)
{
2015-03-18 11:14:24 -07:00
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return srslte_ue_ul_srslte_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, rnti, output_signal);
}
2015-03-18 11:14:24 -07:00
int srslte_ue_ul_srslte_pusch_uci_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, cf_t *output_signal)
{
2015-03-18 11:14:24 -07:00
return srslte_ue_ul_srslte_pusch_uci_encode_rnti(q, ra_ul, data, uci_data, sf_idx, q->current_rnti, output_signal);
}
2015-03-18 11:14:24 -07:00
int srslte_ue_ul_srslte_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, srslte_uci_data_t uci_data,
uint32_t sf_idx, uint16_t rnti,
cf_t *output_signal)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
ra_ul != NULL &&
data != NULL &&
output_signal != NULL)
{
if (ra_ul->prb_alloc.L_prb == 0) {
fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n");
return ret;
}
ret = SRSLTE_ERROR;
2015-03-06 04:24:24 -08:00
2015-03-18 11:14:24 -07:00
if (srslte_harq_setup_ul(&q->harq_process[0], ra_ul->mcs, ra_ul->rv_idx, sf_idx, &ra_ul->prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return ret;
}
printf("sf_idx: %d, rnti: %d\n", sf_idx, rnti);
2015-03-18 11:14:24 -07:00
if (srslte_pusch_encode_rnti(&q->pusch, &q->harq_process[0], data, rnti, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
return ret;
}
2015-03-17 10:26:23 -07:00
// FIXME: Pregenerate for all possible number of prb
2015-03-18 11:14:24 -07:00
if (srslte_refsignal_dmrs_gen(&q->drms, &q->drms_cfg,
2015-03-17 10:26:23 -07:00
q->harq_process[0].ul_alloc.L_prb, sf_idx, q->refsignal))
{
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret;
}
2015-03-18 11:14:24 -07:00
srslte_refsignal_drms_pusch_put(&q->drms, &q->drms_cfg, q->refsignal,
2015-03-17 10:26:23 -07:00
q->harq_process[0].ul_alloc.L_prb,
q->harq_process[0].ul_alloc.n_prb_tilde,
q->sf_symbols);
2015-03-18 11:14:24 -07:00
srslte_ofdm_rx_sf(&q->fft, q->sf_symbols, output_signal);
2015-03-18 11:14:24 -07:00
//srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
2015-03-11 09:42:36 -07:00
if (q->normalize_en) {
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(q->harq_process[0].ul_alloc.L_prb);
2015-03-18 11:14:24 -07:00
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
2015-03-11 09:42:36 -07:00
}
ret = SRSLTE_SUCCESS;
}
return ret;
}