2020-11-26 01:25:22 -08:00
|
|
|
/**
|
2020-10-20 02:59:59 -07:00
|
|
|
*
|
2020-11-26 01:25:22 -08:00
|
|
|
* \section COPYRIGHT
|
2020-10-20 02:59:59 -07:00
|
|
|
*
|
2021-03-19 03:45:56 -07:00
|
|
|
* Copyright 2013-2021 Software Radio Systems Limited
|
2020-10-20 02:59:59 -07:00
|
|
|
*
|
2020-11-26 01:25:22 -08:00
|
|
|
* By using this file, you agree to the terms and conditions set
|
|
|
|
* forth in the LICENSE file which can be found at the top level of
|
|
|
|
* the distribution.
|
2020-10-20 02:59:59 -07:00
|
|
|
*
|
|
|
|
*/
|
2021-01-20 06:46:46 -08:00
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
#include "srsran/phy/phch/pdsch_nr.h"
|
|
|
|
#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"
|
|
|
|
#include "srsran/phy/phch/ra_nr.h"
|
2020-11-10 11:04:12 -08:00
|
|
|
|
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
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
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)) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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)) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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;
|
|
|
|
|
|
|
|
// Reallocate symbols if necessary
|
2020-11-17 08:02:14 -08:00
|
|
|
if (q->max_layers < carrier->max_mimo_layers || q->max_prb < carrier->nof_prb) {
|
|
|
|
q->max_layers = carrier->max_mimo_layers;
|
2020-11-10 11:04:12 -08:00
|
|
|
q->max_prb = carrier->nof_prb;
|
|
|
|
|
|
|
|
// Free current allocations
|
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] != NULL) {
|
|
|
|
free(q->x[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate for new sizes
|
|
|
|
for (uint32_t i = 0; i < q->max_layers; i++) {
|
2021-03-19 03:45:56 -07:00
|
|
|
q->x[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb));
|
2020-11-10 11:04:12 -08:00
|
|
|
if (q->x[i] == NULL) {
|
|
|
|
ERROR("Malloc");
|
2021-03-19 03:45:56 -07:00
|
|
|
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
|
|
|
}
|
2020-12-22 02:45:39 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief copies a number of countiguous Resource Elements
|
|
|
|
* @param sf_symbols slot symbols in frequency domain
|
|
|
|
* @param symbols resource elements
|
|
|
|
* @param count number of resource elements to copy
|
|
|
|
* @param put Direction, symbols are copied into sf_symbols if put is true, otherwise sf_symbols are copied into symbols
|
|
|
|
*/
|
2021-03-19 03:45:56 -07:00
|
|
|
static void srsran_pdsch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count, bool put)
|
2020-12-22 02:45:39 -08:00
|
|
|
{
|
|
|
|
if (put) {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_cf_copy(sf_symbols, symbols, count);
|
2020-12-22 02:45:39 -08:00
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_cf_copy(symbols, sf_symbols, count);
|
2020-12-22 02:45:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2:
|
|
|
|
*
|
|
|
|
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
2021-03-03 10:54:55 -08:00
|
|
|
* | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 |
|
2020-12-22 02:45:39 -08:00
|
|
|
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
* -- k -->
|
|
|
|
*
|
|
|
|
* If the number of DMRS CDM groups without data is set to:
|
|
|
|
* - 1, data is mapped in RE marked as 2
|
|
|
|
* - Otherwise, no data is mapped in this symbol
|
|
|
|
*/
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t srsran_pdsch_nr_cp_dmrs_type1(const srsran_pdsch_nr_t* q,
|
|
|
|
const srsran_sch_grant_nr_t* grant,
|
2020-12-28 09:28:16 -08:00
|
|
|
cf_t* symbols,
|
|
|
|
cf_t* sf_symbols,
|
|
|
|
bool put)
|
2020-12-22 02:45:39 -08:00
|
|
|
{
|
|
|
|
uint32_t count = 0;
|
|
|
|
uint32_t delta = 0;
|
|
|
|
|
|
|
|
if (grant->nof_dmrs_cdm_groups_without_data != 1) {
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
|
|
|
|
if (grant->prb_idx[i]) {
|
2021-03-19 03:45:56 -07:00
|
|
|
for (uint32_t j = 0; j < SRSRAN_NRE; j += 2) {
|
2020-12-22 02:45:39 -08:00
|
|
|
if (put) {
|
2021-03-19 03:45:56 -07:00
|
|
|
sf_symbols[i * SRSRAN_NRE + delta + j + 1] = symbols[count++];
|
2020-12-22 02:45:39 -08:00
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
symbols[count++] = sf_symbols[i * SRSRAN_NRE + delta + j + 1];
|
2020-12-22 02:45:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-20 02:59:59 -07:00
|
|
|
|
2020-12-22 02:45:39 -08:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with groups 2 and 3:
|
|
|
|
*
|
|
|
|
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
* | 1 | 1 | 2 | 2 | 3 | 3 | 1 | 1 | 2 | 2 | 3 | 3 |
|
|
|
|
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
* -- k -->
|
|
|
|
*
|
|
|
|
* If the number of DMRS CDM groups without data is set to:
|
|
|
|
* - 1, data is mapped in RE marked as 2 and 3
|
|
|
|
* - 2, data is mapped in RE marked as 3
|
|
|
|
* - otherwise, no data is mapped in this symbol
|
|
|
|
*/
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t srsran_pdsch_nr_cp_dmrs_type2(const srsran_pdsch_nr_t* q,
|
|
|
|
const srsran_sch_grant_nr_t* grant,
|
2020-12-28 09:28:16 -08:00
|
|
|
cf_t* symbols,
|
|
|
|
cf_t* sf_symbols,
|
|
|
|
bool put)
|
2020-12-22 02:45:39 -08:00
|
|
|
{
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) {
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t re_offset = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 2 : 4;
|
|
|
|
uint32_t re_count = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 4 : 2;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
|
|
|
|
if (grant->prb_idx[i]) {
|
|
|
|
// Copy RE between pilot pairs
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_pdsch_re_cp(&sf_symbols[i * SRSRAN_NRE + re_offset], &symbols[count], re_count, put);
|
2020-12-22 02:45:39 -08:00
|
|
|
count += re_count;
|
|
|
|
|
|
|
|
// Copy RE after second pilot
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_pdsch_re_cp(&sf_symbols[(i + 1) * SRSRAN_NRE - re_count], &symbols[count], re_count, put);
|
2020-12-22 02:45:39 -08:00
|
|
|
count += re_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t srsran_pdsch_nr_cp_dmrs(const srsran_pdsch_nr_t* q,
|
|
|
|
const srsran_sch_cfg_nr_t* cfg,
|
|
|
|
const srsran_sch_grant_nr_t* grant,
|
2020-12-28 09:28:16 -08:00
|
|
|
cf_t* symbols,
|
|
|
|
cf_t* sf_symbols,
|
|
|
|
bool put)
|
2020-12-22 02:45:39 -08:00
|
|
|
{
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
const srsran_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
|
2020-12-22 02:45:39 -08:00
|
|
|
|
|
|
|
switch (dmrs_cfg->type) {
|
2021-03-19 03:45:56 -07:00
|
|
|
case srsran_dmrs_sch_type_1:
|
|
|
|
count = srsran_pdsch_nr_cp_dmrs_type1(q, grant, symbols, sf_symbols, put);
|
2020-12-22 02:45:39 -08:00
|
|
|
break;
|
2021-03-19 03:45:56 -07:00
|
|
|
case srsran_dmrs_sch_type_2:
|
|
|
|
count = srsran_pdsch_nr_cp_dmrs_type2(q, grant, symbols, sf_symbols, put);
|
2020-12-22 02:45:39 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
2020-10-20 02:59:59 -07:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t srsran_pdsch_nr_cp_clean(const srsran_pdsch_nr_t* q,
|
|
|
|
const srsran_sch_grant_nr_t* grant,
|
2020-12-28 09:28:16 -08:00
|
|
|
cf_t* symbols,
|
|
|
|
cf_t* sf_symbols,
|
|
|
|
bool put)
|
2020-10-20 02:59:59 -07:00
|
|
|
{
|
|
|
|
uint32_t count = 0;
|
|
|
|
uint32_t start = 0; // Index of the start of continuous data
|
|
|
|
uint32_t length = 0; // End of continuous RE
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
|
2020-11-03 07:06:47 -08:00
|
|
|
if (grant->prb_idx[i]) {
|
2020-10-20 02:59:59 -07:00
|
|
|
// If fist continuous block, save start
|
|
|
|
if (length == 0) {
|
2021-03-19 03:45:56 -07:00
|
|
|
start = i * SRSRAN_NRE;
|
2020-10-20 02:59:59 -07:00
|
|
|
}
|
2021-03-19 03:45:56 -07:00
|
|
|
length += SRSRAN_NRE;
|
2020-10-20 02:59:59 -07:00
|
|
|
} else {
|
|
|
|
// Consecutive block is finished
|
|
|
|
if (put) {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_cf_copy(&sf_symbols[start], &symbols[count], length);
|
2020-10-20 02:59:59 -07:00
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_cf_copy(&symbols[count], &sf_symbols[start], length);
|
2020-10-20 02:59:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Increase RE count
|
|
|
|
count += length;
|
|
|
|
|
|
|
|
// Reset consecutive block
|
|
|
|
length = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy last contiguous block
|
|
|
|
if (length > 0) {
|
|
|
|
if (put) {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_cf_copy(&sf_symbols[start], &symbols[count], length);
|
2020-10-20 02:59:59 -07:00
|
|
|
} else {
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_cf_copy(&symbols[count], &sf_symbols[start], length);
|
2020-10-20 02:59:59 -07:00
|
|
|
}
|
|
|
|
count += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2020-12-28 09:28:16 -08:00
|
|
|
cf_t* symbols,
|
|
|
|
cf_t* sf_symbols,
|
|
|
|
bool put)
|
2020-10-20 02:59:59 -07:00
|
|
|
{
|
2020-12-28 09:28:16 -08:00
|
|
|
uint32_t count = 0;
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t dmrs_l_idx[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {};
|
2020-12-28 09:28:16 -08:00
|
|
|
uint32_t dmrs_l_count = 0;
|
2020-10-20 02:59:59 -07:00
|
|
|
|
|
|
|
// Get symbol indexes carrying DMRS
|
2021-03-19 03:45:56 -07:00
|
|
|
int32_t nof_dmrs_symbols = srsran_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx);
|
|
|
|
if (nof_dmrs_symbols < SRSRAN_SUCCESS) {
|
|
|
|
return SRSRAN_ERROR;
|
2020-10-20 02:59:59 -07:00
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
2020-12-22 02:45:39 -08:00
|
|
|
DEBUG("dmrs_l_idx=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_i(stdout, (int32_t*)dmrs_l_idx, nof_dmrs_symbols);
|
2020-11-11 03:43:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t l = grant->S; l < grant->S + grant->L; l++) {
|
2020-10-20 02:59:59 -07:00
|
|
|
// Advance DMRS symbol counter until:
|
|
|
|
// - the current DMRS symbol index is greater or equal than current symbol l
|
|
|
|
// - no more DMRS symbols
|
|
|
|
while (dmrs_l_idx[dmrs_l_count] < l && dmrs_l_count < nof_dmrs_symbols) {
|
|
|
|
dmrs_l_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (l == dmrs_l_idx[dmrs_l_count]) {
|
2021-03-19 03:45:56 -07:00
|
|
|
count += srsran_pdsch_nr_cp_dmrs(
|
|
|
|
q, cfg, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], put);
|
2020-12-22 02:45:39 -08:00
|
|
|
} else {
|
|
|
|
count +=
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_pdsch_nr_cp_clean(q, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], put);
|
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,
|
2020-12-28 09:28:16 -08:00
|
|
|
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,
|
2020-12-28 09:28:16 -08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-12-22 02:45:39 -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)
|
2020-12-22 02:45:39 -08:00
|
|
|
{
|
|
|
|
uint32_t n_id = carrier->id;
|
2021-03-19 03:45:56 -07:00
|
|
|
if (cfg->scrambling_id_present && SRSRAN_RNTI_ISUSER(rnti)) {
|
2020-12-22 02:45:39 -08:00
|
|
|
n_id = cfg->scambling_id;
|
|
|
|
}
|
|
|
|
uint32_t cinit = (((uint32_t)rnti) << 15U) + (cw_idx << 14U) + n_id;
|
|
|
|
|
2021-02-10 04:46:25 -08:00
|
|
|
INFO("PDSCH: RNTI=%d (0x%x); nid=%d; cinit=%d (0x%x);", rnti, rnti, n_id, cinit, cinit);
|
2020-12-22 02:45:39 -08:00
|
|
|
|
|
|
|
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,
|
2020-12-28 09:28:16 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
2020-12-22 02:45:39 -08:00
|
|
|
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
|
2020-12-22 02:45:39 -08:00
|
|
|
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
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
2020-12-22 02:45:39 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
ERROR("Putting NR PDSCH resources");
|
2021-03-19 03:45:56 -07:00
|
|
|
return SRSRAN_ERROR;
|
2020-12-15 08:57:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (n != grant->tb[0].nof_re) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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-12-15 08:57:37 -08:00
|
|
|
}
|
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,
|
2020-12-28 09:28:16 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
2020-12-22 02:45:39 -08:00
|
|
|
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];
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) {
|
|
|
|
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) {
|
2021-03-19 03:45:56 -07:00
|
|
|
res->evm = 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
|
|
|
}
|
|
|
|
|
2020-11-11 03:43:18 -08:00
|
|
|
// Change LLR sign
|
|
|
|
for (uint32_t i = 0; i < tb->nof_bits; i++) {
|
|
|
|
llr[i] = -llr[i];
|
|
|
|
}
|
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
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
2020-12-22 02:45:39 -08:00
|
|
|
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
|
2021-03-19 03:45:56 -07:00
|
|
|
if (srsran_dlsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSRAN_SUCCESS) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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[SRSRAN_MAX_TB])
|
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) {
|
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);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
uint32_t nof_re = srsran_ra_dl_nr_slot_nof_re(cfg, grant);
|
2020-11-11 03:43:18 -08:00
|
|
|
|
2020-11-12 03:48:00 -08:00
|
|
|
if (channel->nof_re != nof_re) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
2020-12-22 02:45:39 -08:00
|
|
|
DEBUG("ce=");
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_vec_fprint_c(stdout, channel->ce[0][0], nof_re);
|
2020-12-22 02:45:39 -08:00
|
|
|
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
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_predecoding_type(
|
|
|
|
q->x, channel->ce, q->d, NULL, 1, 1, 1, 0, nof_re, SRSRAN_TXSCHEME_PORT0, 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++) {
|
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_decode_codeword(q, cfg, &grant->tb[tb], &data[tb], grant->rnti) < SRSRAN_SUCCESS) {
|
2021-02-10 04:46:25 -08:00
|
|
|
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
|
|
|
|
2021-03-19 03:45:56 -07:00
|
|
|
static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
|
|
|
|
const srsran_sch_grant_nr_t* grant,
|
2020-12-28 09:28:16 -08:00
|
|
|
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
|
|
|
len = srsran_print_check(str, str_len, len, "rnti=0x%x", grant->rnti);
|
2020-11-20 03:12:29 -08:00
|
|
|
|
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++) {
|
2021-01-29 07:43:40 -08:00
|
|
|
if (grant->prb_idx[i]) {
|
2021-03-12 09:12:41 -08:00
|
|
|
first_prb = i;
|
2021-01-29 07:43:40 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-20 03:12:29 -08:00
|
|
|
// Append time-domain resource mapping
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str,
|
2020-11-20 03:12:29 -08:00
|
|
|
str_len,
|
|
|
|
len,
|
2021-03-12 09:12:41 -08:00
|
|
|
",k0=%d,prb=%d:%d,symb=%d:%d,mapping=%s",
|
2021-02-04 09:33:52 -08:00
|
|
|
grant->k,
|
2021-03-12 09:12:41 -08:00
|
|
|
first_prb,
|
|
|
|
grant->nof_prb,
|
2020-11-20 03:12:29 -08:00
|
|
|
grant->S,
|
|
|
|
grant->L,
|
2021-03-19 03:45:56 -07:00
|
|
|
srsran_sch_mapping_type_to_str(grant->mapping));
|
2020-11-20 03:12:29 -08:00
|
|
|
|
|
|
|
// Skip frequency domain resources...
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// Append spatial resources
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",Nl=%d", grant->nof_layers);
|
2020-11-20 03:12:29 -08:00
|
|
|
|
|
|
|
// Append scrambling ID
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",n_scid=%d,", grant->n_scid);
|
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], &str[len], str_len - len);
|
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[SRSRAN_MAX_CODEWORDS],
|
2020-12-28 09:28:16 -08:00
|
|
|
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
|
|
|
len += srsran_pdsch_nr_grant_info(cfg, grant, &str[len], str_len - len);
|
2020-11-20 03:12:29 -08:00
|
|
|
|
|
|
|
if (q->evm_buffer != NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",evm={", 0);
|
|
|
|
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
|
2020-11-20 03:12:29 -08:00
|
|
|
if (grant->tb[i].enabled && !isnan(res[i].evm)) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, "%.2f", res[i].evm);
|
|
|
|
if (i < SRSRAN_MAX_CODEWORDS - 1) {
|
2020-11-20 03:12:29 -08:00
|
|
|
if (grant->tb[i + 1].enabled) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",", 0);
|
2020-11-20 03:12:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, "}", 0);
|
2020-11-20 03:12:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res != NULL) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",crc={", 0);
|
|
|
|
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
|
2020-11-20 03:12:29 -08:00
|
|
|
if (grant->tb[i].enabled) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, "%s", res[i].crc ? "OK" : "KO");
|
|
|
|
if (i < SRSRAN_MAX_CODEWORDS - 1) {
|
2020-11-20 03:12:29 -08:00
|
|
|
if (grant->tb[i + 1].enabled) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ",", 0);
|
2020-11-20 03:12:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, "}", 0);
|
2020-11-20 03:12:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (q->meas_time_en) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ", t=%d us", 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,
|
2020-12-28 09:28:16 -08:00
|
|
|
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
|
|
|
len += srsran_pdsch_nr_grant_info(cfg, grant, &str[len], str_len - len);
|
2020-11-20 03:12:29 -08:00
|
|
|
|
|
|
|
if (q->meas_time_en) {
|
2021-03-19 03:45:56 -07:00
|
|
|
len = srsran_print_check(str, str_len, len, ", t=%d us", q->meas_time_us);
|
2020-11-20 03:12:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|