mirror of https://github.com/pvnis/srsRAN_4G.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
17 KiB
C
488 lines
17 KiB
C
11 years ago
|
/**
|
||
|
*
|
||
|
* \section COPYRIGHT
|
||
|
*
|
||
9 years ago
|
* Copyright 2013-2015 Software Radio Systems Limited
|
||
11 years ago
|
*
|
||
|
* \section LICENSE
|
||
|
*
|
||
10 years ago
|
* This file is part of the srsLTE library.
|
||
11 years ago
|
*
|
||
10 years ago
|
* srsLTE is free software: you can redistribute it and/or modify
|
||
10 years ago
|
* it under the terms of the GNU Affero General Public License as
|
||
11 years ago
|
* published by the Free Software Foundation, either version 3 of
|
||
|
* the License, or (at your option) any later version.
|
||
|
*
|
||
10 years ago
|
* srsLTE is distributed in the hope that it will be useful,
|
||
11 years ago
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
10 years ago
|
* GNU Affero General Public License for more details.
|
||
11 years ago
|
*
|
||
10 years ago
|
* A copy of the GNU Affero General Public License can be found in
|
||
11 years ago
|
* the LICENSE file in the top-level directory of this distribution
|
||
|
* and at http://www.gnu.org/licenses/.
|
||
|
*
|
||
|
*/
|
||
|
|
||
10 years ago
|
#include "srslte/ue/ue_dl.h"
|
||
11 years ago
|
|
||
11 years ago
|
#include <complex.h>
|
||
|
#include <math.h>
|
||
9 years ago
|
#include <string.h>
|
||
|
|
||
11 years ago
|
|
||
10 years ago
|
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
|
||
|
#define CURRENT_SFLEN SRSLTE_SF_LEN(CURRENT_FFTSIZE)
|
||
11 years ago
|
|
||
10 years ago
|
#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)
|
||
11 years ago
|
|
||
10 years ago
|
#define MAX_CANDIDATES 64
|
||
11 years ago
|
|
||
9 years ago
|
srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also
|
||
|
const uint32_t nof_ue_formats = 2;
|
||
|
|
||
|
srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C};
|
||
|
const uint32_t nof_common_formats = 2;
|
||
|
|
||
|
|
||
10 years ago
|
int srslte_ue_dl_init(srslte_ue_dl_t *q,
|
||
10 years ago
|
srslte_cell_t cell)
|
||
11 years ago
|
{
|
||
10 years ago
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||
11 years ago
|
|
||
|
if (q != NULL &&
|
||
10 years ago
|
srslte_cell_isvalid(&cell))
|
||
11 years ago
|
{
|
||
10 years ago
|
ret = SRSLTE_ERROR;
|
||
11 years ago
|
|
||
10 years ago
|
bzero(q, sizeof(srslte_ue_dl_t));
|
||
10 years ago
|
|
||
11 years ago
|
q->cell = cell;
|
||
|
q->pkt_errors = 0;
|
||
10 years ago
|
q->pkts_total = 0;
|
||
9 years ago
|
q->pending_ul_dci_rnti = 0;
|
||
9 years ago
|
q->sample_offset = 0;
|
||
11 years ago
|
|
||
10 years ago
|
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
|
||
11 years ago
|
fprintf(stderr, "Error initiating FFT\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
10 years ago
|
if (srslte_chest_dl_init(&q->chest, cell)) {
|
||
11 years ago
|
fprintf(stderr, "Error initiating channel estimator\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
10 years ago
|
if (srslte_regs_init(&q->regs, q->cell)) {
|
||
11 years ago
|
fprintf(stderr, "Error initiating REGs\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
10 years ago
|
if (srslte_pcfich_init(&q->pcfich, &q->regs, q->cell)) {
|
||
11 years ago
|
fprintf(stderr, "Error creating PCFICH object\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
10 years ago
|
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) {
|
||
|
fprintf(stderr, "Error creating PHICH object\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
11 years ago
|
|
||
10 years ago
|
if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) {
|
||
11 years ago
|
fprintf(stderr, "Error creating PDCCH object\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
|
|
||
10 years ago
|
if (srslte_pdsch_init(&q->pdsch, q->cell)) {
|
||
11 years ago
|
fprintf(stderr, "Error creating PDSCH object\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
10 years ago
|
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) {
|
||
10 years ago
|
fprintf(stderr, "Error initiating soft buffer\n");
|
||
|
goto clean_exit;
|
||
11 years ago
|
}
|
||
9 years ago
|
if (srslte_cfo_init(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
|
||
|
fprintf(stderr, "Error initiating SFO correct\n");
|
||
|
goto clean_exit;
|
||
|
}
|
||
9 years ago
|
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
|
||
9 years ago
|
|
||
10 years ago
|
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
||
11 years ago
|
if (!q->sf_symbols) {
|
||
|
perror("malloc");
|
||
|
goto clean_exit;
|
||
|
}
|
||
|
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
|
||
10 years ago
|
q->ce[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
||
11 years ago
|
if (!q->ce[i]) {
|
||
|
perror("malloc");
|
||
|
goto clean_exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
10 years ago
|
ret = SRSLTE_SUCCESS;
|
||
11 years ago
|
} else {
|
||
|
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
|
||
|
cell.id, cell.nof_ports, cell.nof_prb);
|
||
|
}
|
||
|
|
||
|
clean_exit:
|
||
10 years ago
|
if (ret == SRSLTE_ERROR) {
|
||
10 years ago
|
srslte_ue_dl_free(q);
|
||
11 years ago
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
10 years ago
|
void srslte_ue_dl_free(srslte_ue_dl_t *q) {
|
||
11 years ago
|
if (q) {
|
||
10 years ago
|
srslte_ofdm_rx_free(&q->fft);
|
||
10 years ago
|
srslte_chest_dl_free(&q->chest);
|
||
10 years ago
|
srslte_regs_free(&q->regs);
|
||
|
srslte_pcfich_free(&q->pcfich);
|
||
10 years ago
|
srslte_phich_free(&q->phich);
|
||
10 years ago
|
srslte_pdcch_free(&q->pdcch);
|
||
|
srslte_pdsch_free(&q->pdsch);
|
||
9 years ago
|
srslte_cfo_free(&q->sfo_correct);
|
||
10 years ago
|
srslte_softbuffer_rx_free(&q->softbuffer);
|
||
11 years ago
|
if (q->sf_symbols) {
|
||
|
free(q->sf_symbols);
|
||
|
}
|
||
|
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
|
||
|
if (q->ce[i]) {
|
||
|
free(q->ce[i]);
|
||
|
}
|
||
|
}
|
||
10 years ago
|
bzero(q, sizeof(srslte_ue_dl_t));
|
||
11 years ago
|
}
|
||
|
}
|
||
|
|
||
10 years ago
|
/* 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.
|
||
10 years ago
|
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
|
||
10 years ago
|
*/
|
||
10 years ago
|
void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
|
||
10 years ago
|
srslte_pdsch_set_rnti(&q->pdsch, rnti);
|
||
10 years ago
|
q->current_rnti = rnti;
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
void srslte_ue_dl_reset(srslte_ue_dl_t *q) {
|
||
10 years ago
|
srslte_softbuffer_rx_reset(&q->softbuffer);
|
||
|
bzero(&q->pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
|
||
10 years ago
|
}
|
||
|
|
||
9 years ago
|
void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset) {
|
||
|
q->sample_offset = sample_offset;
|
||
|
}
|
||
|
|
||
10 years ago
|
/** Applies the following operations to a subframe of synchronized samples:
|
||
|
* - OFDM demodulation
|
||
|
* - Channel estimation
|
||
|
* - PCFICH decoding
|
||
10 years ago
|
* - PDCCH decoding: Find DCI for RNTI given by previous call to srslte_ue_dl_set_rnti()
|
||
|
* - PDSCH decoding: Decode TB scrambling with RNTI given by srslte_ue_dl_set_rnti()
|
||
10 years ago
|
*/
|
||
10 years ago
|
int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx) {
|
||
|
return srslte_ue_dl_decode_rnti_rv(q, input, data, sf_idx, q->current_rnti, 0);
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti) {
|
||
|
return srslte_ue_dl_decode_rnti_rv(q, input, data, sf_idx, rnti, 0);
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) {
|
||
10 years ago
|
if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
|
||
10 years ago
|
|
||
|
/* Run FFT for all subframe data */
|
||
10 years ago
|
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols);
|
||
9 years ago
|
|
||
9 years ago
|
/* Correct SFO multiplying by complex exponential in the time domain */
|
||
9 years ago
|
if (q->sample_offset) {
|
||
9 years ago
|
struct timeval t[3];
|
||
|
gettimeofday(&t[1], NULL);
|
||
9 years ago
|
for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) {
|
||
|
srslte_cfo_correct(&q->sfo_correct,
|
||
9 years ago
|
&q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE],
|
||
|
&q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE],
|
||
|
q->sample_offset / q->fft.symbol_sz);
|
||
9 years ago
|
}
|
||
9 years ago
|
gettimeofday(&t[2], NULL);
|
||
|
get_time_interval(t);
|
||
9 years ago
|
}
|
||
|
|
||
9 years ago
|
return srslte_ue_dl_decode_estimate(q, sf_idx, cfi);
|
||
|
} else {
|
||
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *cfi) {
|
||
|
float cfi_corr;
|
||
|
if (q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
|
||
|
|
||
10 years ago
|
/* Get channel estimates for each port */
|
||
10 years ago
|
srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx);
|
||
10 years ago
|
|
||
10 years ago
|
/* First decode PCFICH and obtain CFI */
|
||
10 years ago
|
if (srslte_pcfich_decode(&q->pcfich, q->sf_symbols, q->ce,
|
||
10 years ago
|
srslte_chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi, &cfi_corr)<0) {
|
||
10 years ago
|
fprintf(stderr, "Error decoding PCFICH\n");
|
||
10 years ago
|
return SRSLTE_ERROR;
|
||
10 years ago
|
}
|
||
|
|
||
9 years ago
|
INFO("Decoded CFI=%d with correlation %.2f, sf_idx=%d\n", *cfi, cfi_corr, sf_idx);
|
||
10 years ago
|
|
||
10 years ago
|
if (srslte_regs_set_cfi(&q->regs, *cfi)) {
|
||
10 years ago
|
fprintf(stderr, "Error setting CFI\n");
|
||
10 years ago
|
return SRSLTE_ERROR;
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
return SRSLTE_SUCCESS;
|
||
10 years ago
|
} else {
|
||
10 years ago
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||
10 years ago
|
}
|
||
|
}
|
||
|
|
||
9 years ago
|
|
||
9 years ago
|
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx)
|
||
10 years ago
|
{
|
||
9 years ago
|
return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx);
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint8_t *data,
|
||
10 years ago
|
uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
|
||
|
{
|
||
10 years ago
|
int ret = SRSLTE_ERROR;
|
||
10 years ago
|
|
||
10 years ago
|
q->nof_detected++;
|
||
10 years ago
|
|
||
10 years ago
|
/* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */
|
||
9 years ago
|
if (srslte_ue_dl_cfg_grant(q, grant, cfi, sf_idx, rvidx)) {
|
||
10 years ago
|
return SRSLTE_ERROR;
|
||
10 years ago
|
}
|
||
10 years ago
|
|
||
10 years ago
|
if (q->pdsch_cfg.rv == 0) {
|
||
9 years ago
|
srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant->mcs.tbs);
|
||
10 years ago
|
}
|
||
10 years ago
|
|
||
9 years ago
|
// Uncoment next line to do ZF by default in pdsch_ue example
|
||
|
//float noise_estimate = 0;
|
||
10 years ago
|
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
|
||
|
|
||
10 years ago
|
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
|
||
|
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,
|
||
10 years ago
|
q->sf_symbols, q->ce,
|
||
|
noise_estimate,
|
||
|
rnti, data);
|
||
10 years ago
|
|
||
10 years ago
|
if (ret == SRSLTE_ERROR) {
|
||
10 years ago
|
q->pkt_errors++;
|
||
10 years ago
|
} else if (ret == SRSLTE_ERROR_INVALID_INPUTS) {
|
||
10 years ago
|
fprintf(stderr, "Error calling srslte_pdsch_decode()\n");
|
||
10 years ago
|
} else if (ret == SRSLTE_SUCCESS) {
|
||
10 years ago
|
if (SRSLTE_VERBOSE_ISDEBUG()) {
|
||
10 years ago
|
INFO("Decoded Message: ", 0);
|
||
10 years ago
|
srslte_vec_fprint_hex(stdout, data, q->pdsch_cfg.grant.mcs.tbs);
|
||
10 years ago
|
}
|
||
|
}
|
||
|
q->pkts_total++;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
10 years ago
|
int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti)
|
||
10 years ago
|
{
|
||
10 years ago
|
srslte_dci_location_t locations[MAX_CANDIDATES];
|
||
|
uint32_t nof_locations = srslte_pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
|
||
10 years ago
|
uint16_t crc_rem = 0;
|
||
9 years ago
|
|
||
|
if (rnti) {
|
||
|
/* Do not search if an UL DCI is already pending */
|
||
9 years ago
|
|
||
9 years ago
|
if (q->pending_ul_dci_rnti == rnti) {
|
||
|
q->pending_ul_dci_rnti = 0;
|
||
|
memcpy(dci_msg, &q->pending_ul_dci_msg, sizeof(srslte_dci_msg_t));
|
||
|
return 1;
|
||
10 years ago
|
}
|
||
9 years ago
|
|
||
|
for (uint32_t i=0;i<nof_locations && crc_rem != rnti;i++) {
|
||
|
if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &locations[i], SRSLTE_DCI_FORMAT0, &crc_rem)) {
|
||
|
fprintf(stderr, "Error decoding DCI msg\n");
|
||
|
return SRSLTE_ERROR;
|
||
|
}
|
||
|
if (dci_msg->data[0] != 0) {
|
||
|
crc_rem = 0;
|
||
|
}
|
||
|
DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
|
||
9 years ago
|
if (crc_rem == rnti) {
|
||
|
memcpy(&q->last_location, &locations[i], sizeof(srslte_dci_location_t));
|
||
|
}
|
||
9 years ago
|
}
|
||
|
if (crc_rem == rnti) {
|
||
|
return 1;
|
||
|
} else {
|
||
|
return 0;
|
||
10 years ago
|
}
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) {
|
||
|
return q->last_n_cce;
|
||
|
}
|
||
|
|
||
10 years ago
|
int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti)
|
||
10 years ago
|
{
|
||
|
srslte_rnti_type_t rnti_type;
|
||
|
if (rnti == SRSLTE_SIRNTI) {
|
||
|
rnti_type = SRSLTE_RNTI_SI;
|
||
|
} else if (rnti == SRSLTE_PRNTI) {
|
||
|
rnti_type = SRSLTE_RNTI_PCH;
|
||
|
} else if (rnti <= SRSLTE_RARNTI_END) {
|
||
|
rnti_type = SRSLTE_RNTI_RAR;
|
||
|
} else {
|
||
|
rnti_type = SRSLTE_RNTI_USER;
|
||
|
}
|
||
|
return srslte_ue_dl_find_dl_dci_type(q, dci_msg, cfi, sf_idx, rnti, rnti_type);
|
||
|
}
|
||
|
|
||
|
int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx,
|
||
|
uint16_t rnti, srslte_rnti_type_t rnti_type)
|
||
10 years ago
|
{
|
||
10 years ago
|
srslte_dci_location_t locations[MAX_CANDIDATES];
|
||
11 years ago
|
uint32_t nof_locations;
|
||
10 years ago
|
uint32_t nof_formats;
|
||
10 years ago
|
srslte_dci_format_t *formats = NULL;
|
||
11 years ago
|
|
||
10 years ago
|
/* Generate PDCCH candidates */
|
||
10 years ago
|
if (rnti_type == SRSLTE_RNTI_SI || rnti_type == SRSLTE_RNTI_PCH || rnti_type == SRSLTE_RNTI_RAR) {
|
||
10 years ago
|
nof_locations = srslte_pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, q->cfi);
|
||
10 years ago
|
formats = common_formats;
|
||
|
nof_formats = nof_common_formats;
|
||
10 years ago
|
} else {
|
||
10 years ago
|
nof_locations = srslte_pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, q->cfi, rnti);
|
||
10 years ago
|
formats = ue_formats;
|
||
|
nof_formats = nof_ue_formats;
|
||
10 years ago
|
}
|
||
10 years ago
|
|
||
|
uint16_t crc_rem = 0;
|
||
|
for (int f=0;f<nof_formats && crc_rem != rnti;f++) {
|
||
|
for (int i=0;i<nof_locations && crc_rem != rnti;i++) {
|
||
9 years ago
|
DEBUG("Trying format %s (nbits=%d), location L=%d, ncce=%d\n", srslte_dci_format_string(formats[f]),
|
||
9 years ago
|
srslte_dci_format_sizeof_lut(formats[f], q->cell.nof_prb), locations[i].L, locations[i].ncce);
|
||
10 years ago
|
q->last_n_cce = locations[i].ncce;
|
||
10 years ago
|
if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &locations[i], formats[f], &crc_rem)) {
|
||
10 years ago
|
fprintf(stderr, "Error decoding DCI msg\n");
|
||
10 years ago
|
return SRSLTE_ERROR;
|
||
10 years ago
|
}
|
||
9 years ago
|
if (crc_rem == rnti) {
|
||
9 years ago
|
INFO("Found DCI nCCE: %d, L: %d, n_bits=%d\n", locations[i].ncce, locations[i].L, srslte_dci_format_sizeof_lut(formats[f], q->cell.nof_prb));
|
||
9 years ago
|
memcpy(&q->last_location, &locations[i], sizeof(srslte_dci_location_t));
|
||
|
}
|
||
9 years ago
|
if (crc_rem == rnti && formats[f] == SRSLTE_DCI_FORMAT1A && dci_msg->data[0] != 1) {
|
||
|
/* Save Format 0 msg. Recovered next call to srslte_ue_dl_find_ul_dci() */
|
||
|
q->pending_ul_dci_rnti = crc_rem;
|
||
|
memcpy(&q->pending_ul_dci_msg, dci_msg, sizeof(srslte_dci_msg_t));
|
||
|
crc_rem = 0;
|
||
10 years ago
|
}
|
||
10 years ago
|
DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem);
|
||
11 years ago
|
}
|
||
10 years ago
|
}
|
||
10 years ago
|
if (crc_rem == rnti) {
|
||
|
return 1;
|
||
|
} else {
|
||
9 years ago
|
INFO("Couldn't find any DCI for RNTI=0x%x\n", rnti);
|
||
10 years ago
|
return 0;
|
||
|
}
|
||
10 years ago
|
}
|
||
|
|
||
|
|
||
|
int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
|
||
|
{
|
||
|
srslte_dci_msg_t dci_msg;
|
||
10 years ago
|
srslte_ra_dl_dci_t dci_unpacked;
|
||
|
srslte_ra_dl_grant_t grant;
|
||
10 years ago
|
int ret = SRSLTE_ERROR;
|
||
|
|
||
|
if ((ret = srslte_ue_dl_decode_fft_estimate(q, input, sf_idx, &q->cfi)) < 0) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if (srslte_pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, 0, sf_idx, q->cfi)) {
|
||
|
fprintf(stderr, "Error extracting LLRs\n");
|
||
|
return SRSLTE_ERROR;
|
||
|
}
|
||
|
|
||
9 years ago
|
int found_dci = srslte_ue_dl_find_dl_dci(q, &dci_msg, q->cfi, sf_idx, rnti);
|
||
10 years ago
|
if (found_dci == 1) {
|
||
10 years ago
|
|
||
|
if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, &dci_unpacked, &grant)) {
|
||
|
fprintf(stderr, "Error unpacking DCI\n");
|
||
|
return SRSLTE_ERROR;
|
||
|
}
|
||
|
|
||
|
ret = srslte_ue_dl_decode_rnti_rv_packet(q, &grant, data, q->cfi, sf_idx, rnti, rvidx);
|
||
11 years ago
|
}
|
||
10 years ago
|
|
||
10 years ago
|
if (found_dci == 1 && ret == SRSLTE_SUCCESS) {
|
||
10 years ago
|
return q->pdsch_cfg.grant.mcs.tbs;
|
||
11 years ago
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
11 years ago
|
}
|
||
10 years ago
|
|
||
|
/* Computes n_group and n_seq according to Section 9.1.2 in 36.213 and calls phich processing function */
|
||
|
bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, uint32_t n_dmrs)
|
||
|
{
|
||
|
uint8_t ack_bit;
|
||
|
float distance;
|
||
|
uint32_t Ngroups = srslte_phich_ngroups(&q->phich);
|
||
|
uint32_t ngroup = (n_prb_lowest+n_dmrs)%Ngroups;
|
||
|
uint32_t nseq = ((n_prb_lowest/Ngroups)+n_dmrs)%(2*srslte_phich_nsf(&q->phich));
|
||
10 years ago
|
DEBUG("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d\n",
|
||
10 years ago
|
sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq);
|
||
|
if (!srslte_phich_decode(&q->phich, q->sf_symbols, q->ce, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) {
|
||
|
INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance);
|
||
|
} else {
|
||
|
fprintf(stderr, "Error decoding PHICH\n");
|
||
|
return false;
|
||
|
}
|
||
9 years ago
|
if (ack_bit && distance > 1.5) {
|
||
10 years ago
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
9 years ago
|
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx) {
|
||
|
srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||
9 years ago
|
printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
|
||
9 years ago
|
srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||
|
if (q->cell.nof_ports > 1) {
|
||
|
srslte_vec_save_file("ce1", q->ce[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
|
||
|
}
|
||
|
srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pcfich_symbols", q->pcfich.symbols[0], q->pcfich.nof_symbols*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN*sizeof(float));
|
||
|
|
||
|
srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce*36*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce*36*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce*36*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce*36*sizeof(cf_t));
|
||
|
srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float));
|
||
|
|
||
|
|
||
|
srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t));
|
||
|
srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t));
|
||
|
int cb_len = q->pdsch_cfg.cb_segm.K1;
|
||
|
for (int i=0;i<q->pdsch_cfg.cb_segm.C;i++) {
|
||
|
char tmpstr[64];
|
||
|
snprintf(tmpstr,64,"rmout_%d.dat",i);
|
||
|
srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));
|
||
|
}
|
||
|
printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=%d\n", tti, tti%10, q->cfi,
|
||
|
q->pdsch_cfg.grant.mcs.idx, rv_idx, q->current_rnti);
|
||
|
}
|
||
|
|
||
10 years ago
|
|
||
|
|