srsLTE/lib/src/phy/phch/pdsch_nr.c

634 lines
19 KiB
C
Raw Normal View History

/**
2022-04-29 00:28:44 -07:00
* Copyright 2013-2022 Software Radio Systems Limited
2020-10-20 02:59:59 -07:00
*
2021-04-22 01:59:40 -07:00
* This file is part of srsRAN.
2020-10-20 02:59:59 -07:00
*
2021-04-22 01:59:40 -07:00
* srsRAN is free software: you can redistribute it and/or modify
2021-03-28 14:12:42 -07:00
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
2021-04-22 01:59:40 -07:00
* srsRAN is distributed in the hope that it will be useful,
2021-03-28 14:12:42 -07:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
2020-10-20 02:59:59 -07:00
*
2021-03-28 14:12:42 -07:00
* A copy of the GNU Affero 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/.
2020-10-20 02:59:59 -07:00
*
*/
2021-03-19 03:45:56 -07:00
#include "srsran/phy/phch/pdsch_nr.h"
#include "srsran/phy/ch_estimation/csi_rs.h"
2021-03-19 03:45:56 -07:00
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/mimo/layermap.h"
#include "srsran/phy/mimo/precoding.h"
#include "srsran/phy/modem/demod_soft.h"
static int pdsch_nr_alloc(srsran_pdsch_nr_t* q, uint32_t max_mimo_layers, uint32_t max_prb)
{
// Reallocate symbols if necessary
if (q->max_layers < max_mimo_layers || q->max_prb < max_prb) {
q->max_layers = max_mimo_layers;
q->max_prb = max_prb;
// Free current allocations
for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) {
if (q->x[i] != NULL) {
free(q->x[i]);
}
}
// Allocate for new sizes
for (uint32_t i = 0; i < q->max_layers; i++) {
q->x[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb));
if (q->x[i] == NULL) {
ERROR("Malloc");
return SRSRAN_ERROR;
}
}
}
return SRSRAN_SUCCESS;
}
2021-03-19 03:45:56 -07:00
int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args)
2020-11-10 11:04:12 -08:00
{
SRSRAN_MEM_ZERO(q, srsran_pdsch_nr_t, 1);
2021-03-19 03:45:56 -07:00
for (srsran_mod_t mod = SRSRAN_MOD_BPSK; mod < SRSRAN_MOD_NITEMS; mod++) {
if (srsran_modem_table_lte(&q->modem_tables[mod], mod) < SRSRAN_SUCCESS) {
ERROR("Error initialising modem table for %s", srsran_mod_string(mod));
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2020-11-11 07:13:25 -08:00
if (args->measure_evm) {
2021-03-19 03:45:56 -07:00
srsran_modem_table_bytes(&q->modem_tables[mod]);
2020-11-11 07:13:25 -08:00
}
2020-11-10 11:04:12 -08:00
}
if (pdsch_nr_alloc(q, args->max_layers, args->max_prb) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
int srsran_pdsch_nr_init_enb(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args)
2020-11-10 11:04:12 -08:00
{
if (q == NULL) {
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR_INVALID_INPUTS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
if (pdsch_nr_init_common(q, args) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
if (srsran_sch_nr_init_tx(&q->sch, &args->sch)) {
ERROR("Initialising SCH");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
int srsran_pdsch_nr_init_ue(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args)
2020-11-10 11:04:12 -08:00
{
2020-11-11 07:13:25 -08:00
if (q == NULL || args == NULL) {
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR_INVALID_INPUTS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
if (pdsch_nr_init_common(q, args) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
if (srsran_sch_nr_init_rx(&q->sch, &args->sch)) {
ERROR("Initialising SCH");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2020-11-11 07:13:25 -08:00
if (args->measure_evm) {
2021-03-19 03:45:56 -07:00
q->evm_buffer = srsran_evm_buffer_alloc(8);
2020-11-11 07:13:25 -08:00
if (q->evm_buffer == NULL) {
ERROR("Initialising EVM");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-11 07:13:25 -08:00
}
}
2020-11-20 03:12:29 -08:00
q->meas_time_en = args->measure_time;
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
int srsran_pdsch_nr_set_carrier(srsran_pdsch_nr_t* q, const srsran_carrier_nr_t* carrier)
2020-11-10 11:04:12 -08:00
{
// Set carrier
q->carrier = *carrier;
if (pdsch_nr_alloc(q, carrier->max_mimo_layers, carrier->nof_prb) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
// Allocate code words according to table 7.3.1.3-1
uint32_t max_cw = (q->max_layers > 5) ? 2 : 1;
if (q->max_cw < max_cw) {
q->max_cw = max_cw;
for (uint32_t i = 0; i < max_cw; i++) {
if (q->b[i] == NULL) {
2021-03-19 03:45:56 -07:00
q->b[i] = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR);
2020-11-10 11:04:12 -08:00
if (q->b[i] == NULL) {
ERROR("Malloc");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
}
if (q->d[i] == NULL) {
2021-03-19 03:45:56 -07:00
q->d[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_MAX_LEN_RE_NR);
2020-11-10 11:04:12 -08:00
if (q->d[i] == NULL) {
ERROR("Malloc");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
}
}
}
// Set carrier in SCH
2021-03-19 03:45:56 -07:00
if (srsran_sch_nr_set_carrier(&q->sch, carrier) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2020-11-11 07:13:25 -08:00
if (q->evm_buffer != NULL) {
2021-03-19 03:45:56 -07:00
srsran_evm_buffer_resize(q->evm_buffer, SRSRAN_SLOT_LEN_RE_NR(q->max_prb) * SRSRAN_MAX_QM);
2020-11-11 07:13:25 -08:00
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
void srsran_pdsch_nr_free(srsran_pdsch_nr_t* q)
2020-11-10 11:04:12 -08:00
{
if (q == NULL) {
return;
}
2021-03-19 03:45:56 -07:00
for (uint32_t cw = 0; cw < SRSRAN_MAX_CODEWORDS; cw++) {
2020-11-10 11:04:12 -08:00
if (q->b[cw]) {
free(q->b[cw]);
}
if (q->d[cw]) {
free(q->d[cw]);
}
}
2021-03-19 03:45:56 -07:00
srsran_sch_nr_free(&q->sch);
2020-11-10 11:04:12 -08:00
2021-03-19 03:45:56 -07:00
for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) {
2020-11-10 11:04:12 -08:00
if (q->x[i]) {
free(q->x[i]);
}
}
2021-03-19 03:45:56 -07:00
for (srsran_mod_t mod = SRSRAN_MOD_BPSK; mod < SRSRAN_MOD_NITEMS; mod++) {
srsran_modem_table_free(&q->modem_tables[mod]);
2020-11-10 11:04:12 -08:00
}
2020-11-11 07:13:25 -08:00
if (q->evm_buffer != NULL) {
2021-03-19 03:45:56 -07:00
srsran_evm_free(q->evm_buffer);
2020-11-11 07:13:25 -08:00
}
SRSRAN_MEM_ZERO(q, srsran_pdsch_nr_t, 1);
}
static inline uint32_t pdsch_nr_put_rb(cf_t* dst, cf_t* src, bool* rvd_mask)
{
uint32_t count = 0;
for (uint32_t i = 0; i < SRSRAN_NRE; i++) {
if (!rvd_mask[i]) {
dst[i] = src[count++];
}
}
return count;
}
static inline uint32_t pdsch_nr_get_rb(cf_t* dst, cf_t* src, bool* rvd_mask)
{
uint32_t count = 0;
for (uint32_t i = 0; i < SRSRAN_NRE; i++) {
if (!rvd_mask[i]) {
dst[count++] = src[i];
}
}
2020-10-20 02:59:59 -07:00
return count;
}
2021-03-19 03:45:56 -07:00
static int srsran_pdsch_nr_cp(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
2020-10-20 02:59:59 -07:00
{
uint32_t count = 0;
2020-10-20 02:59:59 -07:00
for (uint32_t l = grant->S; l < grant->S + grant->L; l++) {
// Initialise reserved RE mask to all false
bool rvd_mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
2020-10-20 02:59:59 -07:00
// Reserve DMRS
if (srsran_re_pattern_to_symbol_mask(&q->dmrs_re_pattern, l, rvd_mask) < SRSRAN_SUCCESS) {
ERROR("Error generating DMRS reserved RE mask");
return SRSRAN_ERROR;
}
2020-11-11 03:43:18 -08:00
// Reserve RE from configuration
if (srsran_re_pattern_list_to_symbol_mask(&cfg->rvd_re, l, rvd_mask) < SRSRAN_SUCCESS) {
ERROR("Error generating reserved RE mask");
return SRSRAN_ERROR;
2020-10-20 02:59:59 -07:00
}
// Actual copy
for (uint32_t rb = 0; rb < q->carrier.nof_prb; rb++) {
// Skip PRB if not available in grant
if (!grant->prb_idx[rb]) {
continue;
}
// Calculate RE index at the begin of the symbol
uint32_t re_idx = (q->carrier.nof_prb * l + rb) * SRSRAN_NRE;
// Put or get
if (put) {
count += pdsch_nr_put_rb(&sf_symbols[re_idx], &symbols[count], &rvd_mask[rb * SRSRAN_NRE]);
} else {
2021-04-19 02:24:25 -07:00
count += pdsch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]);
}
2020-10-20 02:59:59 -07:00
}
}
return count;
}
2021-03-19 03:45:56 -07:00
static int srsran_pdsch_nr_put(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
2020-10-20 02:59:59 -07:00
{
2021-03-19 03:45:56 -07:00
return srsran_pdsch_nr_cp(q, cfg, grant, symbols, sf_symbols, true);
2020-10-20 02:59:59 -07:00
}
2021-03-19 03:45:56 -07:00
static int srsran_pdsch_nr_get(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
2020-11-10 11:04:12 -08:00
{
2021-03-19 03:45:56 -07:00
return srsran_pdsch_nr_cp(q, cfg, grant, symbols, sf_symbols, false);
2020-11-10 11:04:12 -08:00
}
static uint32_t
2021-03-19 03:45:56 -07:00
pdsch_nr_cinit(const srsran_carrier_nr_t* carrier, const srsran_sch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx)
{
2021-04-16 05:22:26 -07:00
uint32_t n_id = carrier->pci;
2021-03-19 03:45:56 -07:00
if (cfg->scrambling_id_present && SRSRAN_RNTI_ISUSER(rnti)) {
n_id = cfg->scambling_id;
}
uint32_t cinit = (((uint32_t)rnti) << 15U) + (cw_idx << 14U) + n_id;
INFO("PDSCH: RNTI=%d (0x%x); nid=%d; cinit=%d (0x%x);", rnti, rnti, n_id, cinit, cinit);
return cinit;
}
2021-03-19 03:45:56 -07:00
static inline int pdsch_nr_encode_codeword(srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_tb_t* tb,
const uint8_t* data,
uint16_t rnti)
2020-11-10 11:04:12 -08:00
{
// Early return if TB is not enabled
if (!tb->enabled) {
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
// Check codeword index
if (tb->cw_idx >= q->max_cw) {
ERROR("Unsupported codeword index %d", tb->cw_idx);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
// Check modulation
2021-03-19 03:45:56 -07:00
if (tb->mod >= SRSRAN_MOD_NITEMS) {
ERROR("Invalid modulation %s", srsran_mod_string(tb->mod));
return SRSRAN_ERROR_OUT_OF_BOUNDS;
2020-11-10 11:04:12 -08:00
}
// Encode SCH
2021-03-19 03:45:56 -07:00
if (srsran_dlsch_nr_encode(&q->sch, &cfg->sch_cfg, tb, data, q->b[tb->cw_idx]) < SRSRAN_SUCCESS) {
ERROR("Error in DL-SCH encoding");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
if (SRSRAN_DEBUG_ENABLED && get_srsran_verbose_level() >= SRSRAN_VERBOSE_DEBUG && !is_handler_registered()) {
DEBUG("b=");
2021-03-19 03:45:56 -07:00
srsran_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
2020-11-11 03:43:18 -08:00
}
2020-11-10 11:04:12 -08:00
// 7.3.1.1 Scrambling
uint32_t cinit = pdsch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx);
2021-03-19 03:45:56 -07:00
srsran_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit);
2020-11-10 11:04:12 -08:00
// 7.3.1.2 Modulation
2021-03-19 03:45:56 -07:00
srsran_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits);
2020-11-10 11:04:12 -08:00
if (SRSRAN_DEBUG_ENABLED && get_srsran_verbose_level() >= SRSRAN_VERBOSE_DEBUG && !is_handler_registered()) {
DEBUG("d=");
2021-03-19 03:45:56 -07:00
srsran_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
2020-11-11 03:43:18 -08:00
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
int srsran_pdsch_nr_encode(srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
uint8_t* data[SRSRAN_MAX_TB],
cf_t* sf_symbols[SRSRAN_MAX_PORTS])
2020-11-10 11:04:12 -08:00
{
// Check input pointers
if (!q || !cfg || !grant || !data || !sf_symbols) {
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR_INVALID_INPUTS;
2020-11-10 11:04:12 -08:00
}
2020-11-20 03:12:29 -08:00
struct timeval t[3];
if (q->meas_time_en) {
gettimeofday(&t[1], NULL);
}
2020-11-10 11:04:12 -08:00
// Check number of layers
if (q->max_layers < grant->nof_layers) {
ERROR("Error number of layers (%d) exceeds configured maximum (%d)", grant->nof_layers, q->max_layers);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
// Compute DMRS pattern
if (srsran_dmrs_sch_rvd_re_pattern(&cfg->dmrs, grant, &q->dmrs_re_pattern) < SRSRAN_SUCCESS) {
ERROR("Error computing DMRS pattern");
return SRSRAN_ERROR;
}
2020-11-10 11:04:12 -08:00
// 7.3.1.1 and 7.3.1.2
2020-11-20 03:12:29 -08:00
uint32_t nof_cw = 0;
2021-03-19 03:45:56 -07:00
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
2020-11-10 11:04:12 -08:00
nof_cw += grant->tb[tb].enabled ? 1 : 0;
2021-03-19 03:45:56 -07:00
if (pdsch_nr_encode_codeword(q, cfg, &grant->tb[tb], data[tb], grant->rnti) < SRSRAN_SUCCESS) {
ERROR("Error encoding TB %d", tb);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
}
// 7.3.1.3 Layer mapping
cf_t** x = q->d;
if (grant->nof_layers > 1) {
x = q->x;
2021-03-19 03:45:56 -07:00
srsran_layermap_nr(q->d, nof_cw, x, grant->nof_layers, grant->nof_layers);
2020-11-10 11:04:12 -08:00
}
// 7.3.1.4 Antenna port mapping
// ... Not implemented
// 7.3.1.5 Mapping to virtual resource blocks
// ... Not implemented
// 7.3.1.6 Mapping from virtual to physical resource blocks
2021-03-19 03:45:56 -07:00
int n = srsran_pdsch_nr_put(q, cfg, grant, x[0], sf_symbols[0]);
if (n < SRSRAN_SUCCESS) {
ERROR("Putting NR PDSCH resources");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
}
if (n != grant->tb[0].nof_re) {
ERROR("Unmatched number of RE (%d != %d)", n, grant->tb[0].nof_re);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
}
2020-11-10 11:04:12 -08:00
2020-11-20 03:12:29 -08:00
if (q->meas_time_en) {
gettimeofday(&t[2], NULL);
get_time_interval(t);
q->meas_time_us = (uint32_t)t[0].tv_usec;
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
static inline int pdsch_nr_decode_codeword(srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_tb_t* tb,
srsran_pdsch_res_nr_t* res,
uint16_t rnti)
2020-10-20 03:00:37 -07:00
{
2020-11-10 11:04:12 -08:00
// Early return if TB is not enabled
if (!tb->enabled) {
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
// Check codeword index
if (tb->cw_idx >= q->max_cw) {
ERROR("Unsupported codeword index %d", tb->cw_idx);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
// Check modulation
2021-03-19 03:45:56 -07:00
if (tb->mod >= SRSRAN_MOD_NITEMS) {
ERROR("Invalid modulation %s", srsran_mod_string(tb->mod));
return SRSRAN_ERROR_OUT_OF_BOUNDS;
2020-11-10 11:04:12 -08:00
}
if (SRSRAN_DEBUG_ENABLED && get_srsran_verbose_level() >= SRSRAN_VERBOSE_DEBUG && !is_handler_registered()) {
DEBUG("d=");
2021-03-19 03:45:56 -07:00
srsran_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
2020-11-11 03:43:18 -08:00
}
2020-11-10 11:04:12 -08:00
// Demodulation
2020-11-11 03:43:18 -08:00
int8_t* llr = (int8_t*)q->b[tb->cw_idx];
if (srsran_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) {
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2020-11-11 07:13:25 -08:00
// EVM
if (q->evm_buffer != NULL) {
res->evm[tb->cw_idx] =
srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
2020-11-11 07:13:25 -08:00
}
// Change LLR sign and set to zero the LLR that are not used
srsran_vec_neg_bb(llr, llr, tb->nof_bits);
2020-11-10 11:04:12 -08:00
// Descrambling
2021-03-19 03:45:56 -07:00
srsran_sequence_apply_c(llr, llr, tb->nof_bits, pdsch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
2020-11-10 11:04:12 -08:00
if (SRSRAN_DEBUG_ENABLED && get_srsran_verbose_level() >= SRSRAN_VERBOSE_DEBUG && !is_handler_registered()) {
DEBUG("b=");
2021-03-19 03:45:56 -07:00
srsran_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
2020-11-11 03:43:18 -08:00
}
2020-11-10 11:04:12 -08:00
// Decode SCH
if (srsran_dlsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, &res->tb[tb->cw_idx]) < SRSRAN_SUCCESS) {
ERROR("Error in DL-SCH encoding");
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-10 11:04:12 -08:00
}
2021-03-19 03:45:56 -07:00
int srsran_pdsch_nr_decode(srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
srsran_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSRAN_MAX_PORTS],
srsran_pdsch_res_nr_t* data)
2020-11-10 11:04:12 -08:00
{
2020-11-20 03:12:29 -08:00
// Check input pointers
if (!q || !cfg || !grant || !data || !sf_symbols || !channel) {
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR_INVALID_INPUTS;
2020-11-20 03:12:29 -08:00
}
struct timeval t[3];
if (q->meas_time_en) {
gettimeofday(&t[1], NULL);
}
// Compute DMRS pattern
if (srsran_dmrs_sch_rvd_re_pattern(&cfg->dmrs, grant, &q->dmrs_re_pattern) < SRSRAN_SUCCESS) {
ERROR("Error computing DMRS pattern");
return SRSRAN_ERROR;
}
2020-11-10 11:04:12 -08:00
uint32_t nof_cw = 0;
2021-03-19 03:45:56 -07:00
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
2020-11-10 11:04:12 -08:00
nof_cw += grant->tb[tb].enabled ? 1 : 0;
}
uint32_t nof_re = grant->tb[0].nof_re;
2020-11-11 03:43:18 -08:00
2020-11-12 03:48:00 -08:00
if (channel->nof_re != nof_re) {
ERROR("Inconsistent number of RE (%d!=%d)", channel->nof_re, nof_re);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-12 03:48:00 -08:00
}
2020-11-10 11:04:12 -08:00
// Demapping from virtual to physical resource blocks
2021-03-19 03:45:56 -07:00
uint32_t nof_re_get = srsran_pdsch_nr_get(q, cfg, grant, q->x[0], sf_symbols[0]);
2020-11-11 03:43:18 -08:00
if (nof_re_get != nof_re) {
ERROR("Inconsistent number of RE (%d!=%d)", nof_re_get, nof_re);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-11 03:43:18 -08:00
}
2020-11-10 11:04:12 -08:00
if (SRSRAN_DEBUG_ENABLED && get_srsran_verbose_level() >= SRSRAN_VERBOSE_DEBUG && !is_handler_registered()) {
DEBUG("ce=");
2021-03-19 03:45:56 -07:00
srsran_vec_fprint_c(stdout, channel->ce[0][0], nof_re);
DEBUG("x=");
2021-03-19 03:45:56 -07:00
srsran_vec_fprint_c(stdout, q->x[0], nof_re);
2020-11-12 03:48:00 -08:00
}
2020-11-10 11:04:12 -08:00
// Demapping to virtual resource blocks
// ... Not implemented
// Antenna port demapping
// ... Not implemented
srsran_predecoding_single(q->x[0], channel->ce[0][0], q->d[0], NULL, nof_re, 1.0f, channel->noise_estimate);
2020-11-10 11:04:12 -08:00
// Layer demapping
if (grant->nof_layers > 1) {
2021-03-19 03:45:56 -07:00
srsran_layerdemap_nr(q->d, nof_cw, q->x, grant->nof_layers, nof_re);
2020-11-10 11:04:12 -08:00
}
// SCH decode
2021-03-19 03:45:56 -07:00
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
if (pdsch_nr_decode_codeword(q, cfg, &grant->tb[tb], data, grant->rnti) < SRSRAN_SUCCESS) {
ERROR("Error encoding TB %d", tb);
2021-03-19 03:45:56 -07:00
return SRSRAN_ERROR;
2020-11-10 11:04:12 -08:00
}
}
2020-10-20 02:59:59 -07:00
2020-11-20 03:12:29 -08:00
if (q->meas_time_en) {
gettimeofday(&t[2], NULL);
get_time_interval(t);
q->meas_time_us = (uint32_t)t[0].tv_usec;
}
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
2020-11-11 03:43:18 -08:00
}
2020-11-20 03:12:29 -08:00
static uint32_t pdsch_nr_grant_info(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
const srsran_pdsch_res_nr_t* res,
char* str,
uint32_t str_len)
2020-11-20 03:12:29 -08:00
{
uint32_t len = 0;
2021-03-19 03:45:56 -07:00
uint32_t first_prb = SRSRAN_MAX_PRB_NR;
for (uint32_t i = 0; i < SRSRAN_MAX_PRB_NR && first_prb == SRSRAN_MAX_PRB_NR; i++) {
if (grant->prb_idx[i]) {
first_prb = i;
}
}
// Append RNTI type and id
len =
srsran_print_check(str, str_len, len, "%s-rnti=0x%x ", srsran_rnti_type_str_short(grant->rnti_type), grant->rnti);
2020-11-20 03:12:29 -08:00
// Append time-domain resource mapping
len = srsran_print_check(str,
str_len,
len,
"prb=(%d,%d) symb=(%d,%d) ",
first_prb,
first_prb + grant->nof_prb - 1,
grant->S,
grant->S + grant->L - 1);
2020-11-20 03:12:29 -08:00
// Append TB info
2021-03-19 03:45:56 -07:00
for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) {
len += srsran_sch_nr_tb_info(&grant->tb[i], &res->tb[i], &str[len], str_len - len);
if (res != NULL) {
if (grant->tb[i].enabled && !isnan(res->evm[i])) {
len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]);
}
}
2020-11-20 03:12:29 -08:00
}
return len;
}
2021-03-19 03:45:56 -07:00
uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
const srsran_pdsch_res_nr_t* res,
char* str,
uint32_t str_len)
2020-11-20 03:12:29 -08:00
{
uint32_t len = 0;
len += pdsch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len);
2020-11-20 03:12:29 -08:00
if (q->meas_time_en) {
2021-04-16 10:24:35 -07:00
len = srsran_print_check(str, str_len, len, "t_us=%d ", q->meas_time_us);
2020-11-20 03:12:29 -08:00
}
return len;
}
2021-03-19 03:45:56 -07:00
uint32_t srsran_pdsch_nr_tx_info(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant,
char* str,
uint32_t str_len)
2020-11-20 03:12:29 -08:00
{
return srsran_pdsch_nr_rx_info(q, cfg, grant, NULL, str, str_len);
2020-11-20 03:12:29 -08:00
}