2015-03-05 09:36:15 -08:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* \section COPYRIGHT
|
|
|
|
*
|
2015-05-08 08:05:40 -07:00
|
|
|
* Copyright 2013-2015 The srsLTE Developers. See the
|
2015-03-05 09:36:15 -08:00
|
|
|
* COPYRIGHT file at the top-level directory of this distribution.
|
|
|
|
*
|
|
|
|
* \section LICENSE
|
|
|
|
*
|
2015-03-20 05:01:08 -07:00
|
|
|
* This file is part of the srsLTE library.
|
2015-03-05 09:36:15 -08:00
|
|
|
*
|
2015-03-20 05:01:08 -07: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
|
2015-03-05 09:36:15 -08:00
|
|
|
* published by the Free Software Foundation, either version 3 of
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
2015-03-20 05:01:08 -07:00
|
|
|
* srsLTE is distributed in the hope that it will be useful,
|
2015-03-05 09:36:15 -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.
|
2015-03-05 09:36:15 -08:00
|
|
|
*
|
2015-05-08 08:05:40 -07:00
|
|
|
* A copy of the GNU Affero General Public License can be found in
|
2015-03-05 09:36:15 -08:00
|
|
|
* 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>
|
2015-03-05 09:36:15 -08:00
|
|
|
|
2015-03-18 05:31:13 -07:00
|
|
|
#include "srslte/ue/ue_ul.h"
|
2015-03-05 10:23:34 -08:00
|
|
|
|
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-05 09:36:15 -08:00
|
|
|
|
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-05 09:36:15 -08:00
|
|
|
|
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
int srslte_ue_ul_init(srslte_ue_ul_t *q,
|
2015-04-27 09:14:28 -07:00
|
|
|
srslte_cell_t cell)
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-03-18 05:31:13 -07:00
|
|
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
2015-03-05 09:36:15 -08:00
|
|
|
|
|
|
|
if (q != NULL &&
|
2015-03-18 05:59:29 -07:00
|
|
|
srslte_cell_isvalid(&cell))
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-03-18 05:31:13 -07:00
|
|
|
ret = SRSLTE_ERROR;
|
2015-03-05 09:36:15 -08:00
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
bzero(q, sizeof(srslte_ue_ul_t));
|
2015-03-05 09:36:15 -08:00
|
|
|
|
|
|
|
q->cell = cell;
|
|
|
|
|
2015-04-08 01:50:01 -07:00
|
|
|
if (srslte_ofdm_tx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
|
2015-03-05 09:36:15 -08:00
|
|
|
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-05 09:36:15 -08:00
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) {
|
2015-03-05 09:36:15 -08:00
|
|
|
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)) {
|
2015-03-05 09:36:15 -08:00
|
|
|
fprintf(stderr, "Error creating PUSCH object\n");
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
2015-04-18 18:13:25 -07:00
|
|
|
if (srslte_pucch_init(&q->pucch, q->cell)) {
|
|
|
|
fprintf(stderr, "Error creating PUSCH object\n");
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
2015-04-27 09:14:28 -07:00
|
|
|
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell)) {
|
|
|
|
fprintf(stderr, "Error initiating soft buffer\n");
|
|
|
|
goto clean_exit;
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
2015-04-15 01:06:40 -07:00
|
|
|
if (srslte_refsignal_ul_init(&q->dmrs, cell)) {
|
2015-03-18 05:41:50 -07:00
|
|
|
fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
|
2015-03-05 09:36:15 -08:00
|
|
|
goto clean_exit;
|
|
|
|
}
|
2015-03-18 11:14:24 -07:00
|
|
|
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
2015-03-05 09:36:15 -08:00
|
|
|
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));
|
2015-03-05 09:36:15 -08:00
|
|
|
if (!q->refsignal) {
|
|
|
|
perror("malloc");
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
|
|
|
|
2015-03-18 05:31:13 -07:00
|
|
|
ret = SRSLTE_SUCCESS;
|
2015-03-05 09:36:15 -08:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
|
|
|
|
cell.id, cell.nof_ports, cell.nof_prb);
|
|
|
|
}
|
|
|
|
|
|
|
|
clean_exit:
|
2015-03-18 05:31:13 -07:00
|
|
|
if (ret == SRSLTE_ERROR) {
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_ue_ul_free(q);
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
void srslte_ue_ul_free(srslte_ue_ul_t *q) {
|
2015-03-05 09:36:15 -08:00
|
|
|
if (q) {
|
2015-04-08 01:50:01 -07:00
|
|
|
srslte_ofdm_rx_free(&q->fft);
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_pusch_free(&q->pusch);
|
2015-04-18 18:13:25 -07:00
|
|
|
srslte_pucch_free(&q->pucch);
|
2015-04-27 09:14:28 -07:00
|
|
|
srslte_softbuffer_tx_free(&q->softbuffer);
|
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_cfo_free(&q->cfo);
|
2015-04-15 01:06:40 -07:00
|
|
|
srslte_refsignal_ul_free(&q->dmrs);
|
2015-03-05 10:23:34 -08:00
|
|
|
|
2015-03-05 09:36:15 -08:00
|
|
|
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-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) {
|
2015-03-05 09:36:15 -08:00
|
|
|
q->current_cfo = cur_cfo;
|
|
|
|
}
|
|
|
|
|
2015-04-14 01:41:17 -07:00
|
|
|
void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q, bool enabled)
|
|
|
|
{
|
|
|
|
q->cfo_en = enabled;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-03-05 09:36:15 -08:00
|
|
|
/* 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-05 09:36:15 -08:00
|
|
|
*/
|
2015-03-18 11:14:24 -07:00
|
|
|
void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, uint16_t rnti) {
|
2015-03-05 09:36:15 -08:00
|
|
|
q->current_rnti = rnti;
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_pusch_set_rnti(&q->pusch, rnti);
|
2015-04-18 18:13:25 -07:00
|
|
|
srslte_pucch_set_crnti(&q->pucch, rnti);
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
|
2015-03-18 11:14:24 -07:00
|
|
|
void srslte_ue_ul_reset(srslte_ue_ul_t *q) {
|
2015-04-27 09:14:28 -07:00
|
|
|
srslte_softbuffer_tx_reset(&q->softbuffer);
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
|
2015-04-18 18:13:25 -07:00
|
|
|
void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
|
2015-04-27 09:14:28 -07:00
|
|
|
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
|
|
|
|
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg,
|
|
|
|
srslte_pucch_cfg_t *pucch_cfg,
|
|
|
|
srslte_pucch_sched_t *pucch_sched)
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-04-16 09:46:04 -07:00
|
|
|
srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg);
|
2015-05-16 14:24:18 -07:00
|
|
|
srslte_refsignal_ul_set_pucch_cfg(&q->dmrs, pucch_cfg);
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
|
2015-04-18 18:13:25 -07:00
|
|
|
srslte_pucch_set_cfg(&q->pucch, pucch_cfg);
|
|
|
|
if (pucch_sched) {
|
|
|
|
memcpy(&q->pucch_sched, pucch_sched, sizeof(srslte_pucch_sched_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal
|
|
|
|
*/
|
|
|
|
int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
|
|
|
|
uint32_t sf_idx,
|
|
|
|
cf_t *output_signal)
|
|
|
|
{
|
|
|
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
|
|
|
|
|
|
|
if (q != NULL &&
|
|
|
|
output_signal != NULL)
|
|
|
|
{
|
|
|
|
|
|
|
|
ret = SRSLTE_ERROR;
|
|
|
|
bzero(q->sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
|
|
|
|
|
|
|
|
srslte_pucch_format_t format;
|
|
|
|
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS];
|
|
|
|
uint8_t pucch2_bits[2];
|
|
|
|
bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
|
|
|
bzero(pucch2_bits, 2*sizeof(uint8_t));
|
|
|
|
|
|
|
|
// 1-bit ACK + SR
|
|
|
|
if (uci_data.uci_ack_len == 1) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_1A;
|
|
|
|
pucch_bits[0] = uci_data.uci_ack;
|
|
|
|
}
|
|
|
|
// 2-bit ACK + SR
|
|
|
|
else if (uci_data.uci_ack_len == 2 && uci_data.scheduling_request) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_1B;
|
|
|
|
pucch_bits[0] = uci_data.uci_ack;
|
|
|
|
pucch_bits[1] = uci_data.uci_ack_2;
|
|
|
|
}
|
|
|
|
// 2-bit ACK with channel selection
|
|
|
|
else if (uci_data.uci_ack_len == 2 && uci_data.channel_selection) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_1B;
|
|
|
|
pucch_bits[0] = uci_data.uci_ack;
|
|
|
|
pucch_bits[1] = uci_data.uci_ack_2;
|
|
|
|
}
|
|
|
|
// scheduling_request
|
|
|
|
else if (uci_data.scheduling_request) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_1;
|
|
|
|
}
|
|
|
|
// CQI and no ack
|
|
|
|
else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 0) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_2;
|
|
|
|
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
|
|
|
}
|
|
|
|
// CQI + 1-bit ACK
|
|
|
|
else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 1) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_2A;
|
|
|
|
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
|
|
|
pucch2_bits[0] = uci_data.uci_ack;
|
|
|
|
}
|
|
|
|
// CQI + 2-bit ACK
|
|
|
|
else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 2) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_2B;
|
|
|
|
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
|
|
|
pucch2_bits[0] = uci_data.uci_ack;
|
|
|
|
pucch2_bits[1] = uci_data.uci_ack_2;
|
|
|
|
}
|
|
|
|
// CQI + 2-bit ACK + cyclic prefix
|
|
|
|
else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 1 && SRSLTE_CP_ISEXT(q->cell.cp)) {
|
|
|
|
format = SRSLTE_PUCCH_FORMAT_2B;
|
|
|
|
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
|
|
|
pucch2_bits[0] = uci_data.uci_ack;
|
|
|
|
pucch2_bits[1] = uci_data.uci_ack_2;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Unsupported combination of UCI parameters\n");
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Choose n_pucch
|
|
|
|
uint32_t n_pucch = 0;
|
|
|
|
if (format == SRSLTE_PUCCH_FORMAT_1) {
|
|
|
|
n_pucch = q->pucch_sched.n_pucch_sr;
|
|
|
|
} else if (format < SRSLTE_PUCCH_FORMAT_2) {
|
|
|
|
if (q->pucch_sched.sps_enabled) {
|
|
|
|
n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4];
|
|
|
|
} else {
|
|
|
|
n_pucch = q->pucch_sched.n_cce + q->pucch_sched.N_pucch_1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
n_pucch = q->pucch_sched.n_pucch_2;
|
|
|
|
}
|
|
|
|
if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) {
|
|
|
|
fprintf(stderr, "Error encoding TB\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (srslte_refsignal_dmrs_pucch_gen(&q->dmrs, format, n_pucch, sf_idx, pucch2_bits, q->refsignal))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srslte_refsignal_dmrs_pucch_put(&q->dmrs, format, n_pucch, q->refsignal, q->sf_symbols);
|
|
|
|
|
2015-05-16 14:24:18 -07:00
|
|
|
|
2015-04-18 18:13:25 -07:00
|
|
|
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
|
|
|
|
|
|
|
|
if (q->cfo_en) {
|
|
|
|
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q->normalize_en) {
|
2015-04-27 09:14:28 -07:00
|
|
|
float norm_factor = (float) q->cell.nof_prb/10;
|
2015-04-18 18:13:25 -07:00
|
|
|
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
|
|
|
|
}
|
|
|
|
ret = SRSLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
|
2015-04-27 09:14:28 -07:00
|
|
|
int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, uint32_t rv, cf_t *output_signal)
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_uci_data_t uci_data;
|
|
|
|
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
2015-04-27 09:14:28 -07:00
|
|
|
return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv, q->current_rnti, output_signal);
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
|
2015-04-27 09:14:28 -07:00
|
|
|
int srslte_ue_ul_pusch_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, uint32_t sf_idx, uint32_t rv, uint16_t rnti, cf_t *output_signal)
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-03-18 11:14:24 -07:00
|
|
|
srslte_uci_data_t uci_data;
|
|
|
|
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
2015-04-27 09:14:28 -07:00
|
|
|
return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv,rnti, output_signal);
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
|
2015-04-27 09:14:28 -07:00
|
|
|
int srslte_ue_ul_pusch_uci_encode(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, uint8_t *data, srslte_uci_data_t uci_data, uint32_t sf_idx, uint32_t rv, cf_t *output_signal)
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-04-27 09:14:28 -07:00
|
|
|
return srslte_ue_ul_pusch_uci_encode_rnti(q, grant, data, uci_data, sf_idx, rv, q->current_rnti, output_signal);
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
|
|
|
|
2015-04-27 09:14:28 -07:00
|
|
|
int srslte_ue_ul_pusch_uci_encode_rnti(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
|
|
|
|
uint8_t *data, srslte_uci_data_t uci_data,
|
|
|
|
uint32_t sf_idx, uint32_t rv, uint16_t rnti,
|
|
|
|
cf_t *output_signal)
|
2015-03-05 09:36:15 -08:00
|
|
|
{
|
2015-03-18 05:31:13 -07:00
|
|
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
2015-03-05 09:36:15 -08:00
|
|
|
|
|
|
|
if (q != NULL &&
|
2015-04-27 09:14:28 -07:00
|
|
|
grant != NULL &&
|
2015-03-05 09:36:15 -08:00
|
|
|
output_signal != NULL)
|
|
|
|
{
|
|
|
|
|
2015-04-27 09:14:28 -07:00
|
|
|
if (grant->L_prb == 0) {
|
2015-03-05 10:23:34 -08:00
|
|
|
fprintf(stderr, "Invalid UL PRB allocation (L_prb=0)\n");
|
2015-03-05 09:36:15 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-03-18 05:31:13 -07:00
|
|
|
ret = SRSLTE_ERROR;
|
2015-03-06 04:24:24 -08:00
|
|
|
|
2015-04-27 09:14:28 -07:00
|
|
|
memcpy(&q->pusch_cfg.grant, grant, sizeof(srslte_ra_ul_grant_t));
|
|
|
|
q->pusch_cfg.sf_idx = sf_idx;
|
|
|
|
q->pusch_cfg.rv = rv;
|
|
|
|
q->pusch_cfg.cp = q->cell.cp;
|
|
|
|
srslte_cbsegm(&q->pusch_cfg.cb_segm, grant->mcs.tbs);
|
|
|
|
|
2015-05-16 14:24:18 -07:00
|
|
|
return srslte_ue_ul_pusch_encode_cfg(q, &q->pusch_cfg, data, uci_data, &q->softbuffer, rnti, output_signal);
|
2015-04-27 09:14:28 -07:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
|
|
|
|
uint8_t *data, srslte_uci_data_t uci_data,
|
2015-05-16 14:24:18 -07:00
|
|
|
srslte_softbuffer_tx_t *softbuffer,
|
2015-04-27 09:14:28 -07:00
|
|
|
uint16_t rnti,
|
|
|
|
cf_t *output_signal)
|
|
|
|
{
|
|
|
|
|
|
|
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
|
|
|
|
|
|
|
if (q != NULL &&
|
|
|
|
cfg != NULL &&
|
|
|
|
output_signal != NULL)
|
|
|
|
{
|
2015-05-16 14:24:18 -07:00
|
|
|
if (srslte_pusch_encode_rnti(&q->pusch, cfg, softbuffer, data, rnti, q->sf_symbols)) {
|
2015-03-05 09:36:15 -08:00
|
|
|
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-04-27 09:14:28 -07:00
|
|
|
if (srslte_refsignal_dmrs_pusch_gen(&q->dmrs, cfg->grant.L_prb, cfg->sf_idx, q->refsignal))
|
2015-03-17 10:26:23 -07:00
|
|
|
{
|
|
|
|
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
|
|
|
|
return ret;
|
2015-03-05 09:36:15 -08:00
|
|
|
}
|
2015-04-16 09:46:04 -07:00
|
|
|
srslte_refsignal_dmrs_pusch_put(&q->dmrs, q->refsignal,
|
2015-04-27 09:14:28 -07:00
|
|
|
cfg->grant.L_prb,
|
|
|
|
cfg->grant.n_prb_tilde,
|
|
|
|
q->sf_symbols);
|
2015-03-05 09:36:15 -08:00
|
|
|
|
2015-04-08 01:50:01 -07:00
|
|
|
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
|
2015-03-05 09:36:15 -08:00
|
|
|
|
2015-04-14 01:41:17 -07:00
|
|
|
if (q->cfo_en) {
|
|
|
|
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) {
|
2015-04-27 09:14:28 -07:00
|
|
|
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(cfg->grant.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
|
|
|
}
|
2015-03-05 09:36:15 -08:00
|
|
|
|
2015-03-18 05:31:13 -07:00
|
|
|
ret = SRSLTE_SUCCESS;
|
2015-03-05 10:23:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|