Added NR PUSCH and PUCCH decoder in gnb_ul

master
Xavier Arteaga 3 years ago committed by Xavier Arteaga
parent 89994cd5a8
commit 658b47d917

@ -49,7 +49,6 @@ SRSRAN_API int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t*
/**
* @brief Estimates NR-PUCCH format 1 resource elements from their DMRS in the provided resource grid
* @param[in] q NR-PUCCH encoder/decoder object
* @param[in] carrier Carrier configuration
* @param[in] cfg PUCCH common configuration
* @param[in] slot slot configuration
* @param[in] resource PUCCH format 1 resource
@ -58,7 +57,6 @@ SRSRAN_API int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t*
* @return SRSRAN_SUCCESS if successful, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
const srsran_carrier_nr_t* carrier,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_slot_cfg_t* slot,
const srsran_pucch_nr_resource_t* resource,
@ -85,7 +83,6 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q,
/**
* @brief Estimates NR-PUCCH format 2 resource elements from their DMRS in the provided resource grid
* @param[in] q NR-PUCCH encoder/decoder object
* @param[in] carrier Carrier configuration
* @param[in] cfg PUCCH common configuration
* @param[in] slot slot configuration
* @param[in] resource PUCCH format 2 resource
@ -94,7 +91,6 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q,
* @return SRSRAN_SUCCESS if successful, SRSRAN_ERROR code otherwise
*/
int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
const srsran_carrier_nr_t* carrier,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_slot_cfg_t* slot,
const srsran_pucch_nr_resource_t* resource,

@ -34,7 +34,8 @@ typedef struct SRSRAN_API {
srsran_pusch_nr_t pusch;
srsran_pucch_nr_t pucch;
srsran_dmrs_sch_t dmrs;
srsran_chest_dl_res_t chest;
srsran_chest_dl_res_t chest_pusch;
srsran_chest_ul_res_t chest_pucch;
} srsran_gnb_ul_t;
SRSRAN_API int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args_t* args);

@ -118,6 +118,7 @@ extern "C" {
#include "srsran/phy/enb/enb_dl.h"
#include "srsran/phy/enb/enb_ul.h"
#include "srsran/phy/gnb/gnb_dl.h"
#include "srsran/phy/gnb/gnb_ul.h"
#include "srsran/phy/scrambling/scrambling.h"

@ -121,7 +121,7 @@ int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t* q,
uint32_t l = m * 2;
// Get start of the sequence in resource grid
cf_t* slot_symbols_ptr = &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE];
cf_t* slot_symbols_ptr = &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE];
// Get Alpha index
uint32_t alpha_idx = 0;
@ -152,15 +152,13 @@ int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t* q,
}
int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
const srsran_carrier_nr_t* carrier,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_slot_cfg_t* slot,
const srsran_pucch_nr_resource_t* resource,
const cf_t* slot_symbols,
srsran_chest_ul_res_t* res)
{
if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL ||
res == NULL) {
if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || res == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
@ -172,7 +170,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
// Get group sequence
uint32_t u = 0;
uint32_t v = 0;
if (srsran_pucch_nr_group_sequence(carrier, cfg, &u, &v) < SRSRAN_SUCCESS) {
if (srsran_pucch_nr_group_sequence(&q->carrier, cfg, &u, &v) < SRSRAN_SUCCESS) {
ERROR("Error getting group sequence");
return SRSRAN_ERROR;
}
@ -191,11 +189,11 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
// Get start of the sequence in resource grid
const cf_t* slot_symbols_ptr =
&slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE];
&slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE];
// Get Alpha index
uint32_t alpha_idx = 0;
if (srsran_pucch_nr_alpha_idx(carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, 0, &alpha_idx) <
if (srsran_pucch_nr_alpha_idx(&q->carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, 0, &alpha_idx) <
SRSRAN_SUCCESS) {
ERROR("Calculating alpha");
}
@ -247,9 +245,9 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
// Compute Time Aligment error in microseconds
if (isnormal(ta_err)) {
ta_err /= 15e3f * (float)(1U << carrier->scs); // Convert from normalized frequency to seconds
ta_err *= 1e6f; // Convert to micro-seconds
ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second
ta_err /= 15e3f * (float)(1U << q->carrier.scs); // Convert from normalized frequency to seconds
ta_err *= 1e6f; // Convert to micro-seconds
ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second
res->ta_us = ta_err;
} else {
res->ta_us = 0.0f;
@ -264,7 +262,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
// Interpolates between DMRS symbols
for (uint32_t m = 0; m < n_pucch; m++) {
uint32_t l = m * 2 + 1;
cf_t* ce_ptr = &res->ce[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE];
cf_t* ce_ptr = &res->ce[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE];
if (m != n_pucch - 1) {
// If it is not the last symbol with DMRS, average between
@ -313,8 +311,8 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q,
uint32_t l_start = resource->start_symbol_idx;
uint32_t l_end = resource->start_symbol_idx + resource->nof_symbols;
uint32_t k_start = SRSRAN_MIN(carrier->nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1;
uint32_t k_end = SRSRAN_MIN(carrier->nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE;
uint32_t k_start = SRSRAN_MIN(q->carrier.nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1;
uint32_t k_end = SRSRAN_MIN(q->carrier.nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE;
for (uint32_t l = l_start; l < l_end; l++) {
// Compute sequence initial state
uint32_t cinit = dmrs_pucch_format2_cinit(carrier, cfg, slot, l);
@ -330,22 +328,20 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q,
// Put sequence in k = 3 * m + 1
for (uint32_t k = k_start, i = 0; k < k_end; k += 3, i++) {
slot_symbols[l * carrier->nof_prb * SRSRAN_NRE + k] = r_l[i];
slot_symbols[l * q->carrier.nof_prb * SRSRAN_NRE + k] = r_l[i];
}
}
return SRSRAN_SUCCESS;
}
int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
const srsran_carrier_nr_t* carrier,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_slot_cfg_t* slot,
const srsran_pucch_nr_resource_t* resource,
const cf_t* slot_symbols,
srsran_chest_ul_res_t* res)
{
if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL ||
res == NULL) {
if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || res == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
@ -358,12 +354,12 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
uint32_t l_start = resource->start_symbol_idx;
uint32_t l_end = resource->start_symbol_idx + resource->nof_symbols;
uint32_t k_start = SRSRAN_MIN(carrier->nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1;
uint32_t k_end = SRSRAN_MIN(carrier->nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE;
uint32_t k_start = SRSRAN_MIN(q->carrier.nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1;
uint32_t k_end = SRSRAN_MIN(q->carrier.nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE;
uint32_t nof_ref = 4 * resource->nof_prb;
for (uint32_t l = l_start, j = 0; l < l_end; l++, j++) {
// Compute sequence initial state
uint32_t cinit = dmrs_pucch_format2_cinit(carrier, cfg, slot, l);
uint32_t cinit = dmrs_pucch_format2_cinit(&q->carrier, cfg, slot, l);
srsran_sequence_state_t sequence = {};
srsran_sequence_state_init(&sequence, cinit);
@ -376,7 +372,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
// Put sequence in k = 3 * m + 1
for (uint32_t k = k_start, i = 0; k < k_end; k += 3, i++) {
ce[j][i] = slot_symbols[l * carrier->nof_prb * SRSRAN_NRE + k];
ce[j][i] = slot_symbols[l * q->carrier.nof_prb * SRSRAN_NRE + k];
}
srsran_vec_prod_conj_ccc(ce[j], r_l, ce[j], nof_ref);
@ -409,9 +405,9 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
// Compute Time Aligment error in microseconds
if (isnormal(ta_err)) {
ta_err /= 15e3f * (float)(1U << carrier->scs) * 3; // Convert from normalized frequency to seconds
ta_err *= 1e6f; // Convert to micro-seconds
ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second
ta_err /= 15e3f * (float)(1U << q->carrier.scs) * 3; // Convert from normalized frequency to seconds
ta_err *= 1e6f; // Convert to micro-seconds
ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second
res->ta_us = ta_err;
} else {
res->ta_us = 0.0f;
@ -423,7 +419,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
// Zero order hold
for (uint32_t l = l_start, j = 0; l < l_end; l++, j++) {
for (uint32_t k = k_start - 1, i = 0; k < k_end; k++, i++) {
res->ce[l * carrier->nof_prb * SRSRAN_NRE + k] = ce[j][i / 3];
res->ce[l * q->carrier.nof_prb * SRSRAN_NRE + k] = ce[j][i / 3];
}
}

@ -11,6 +11,7 @@
*/
#include "srsran/phy/gnb/gnb_ul.h"
#include "srsran/phy/ch_estimation/dmrs_pucch.h"
/**
* @brief Shifts FFT window a fraction of the cyclic prefix. Set to 0.0f for disabling.
@ -24,8 +25,13 @@ static int gnb_ul_alloc_prb(srsran_gnb_ul_t* q, uint32_t new_nof_prb)
if (q->max_prb < new_nof_prb) {
q->max_prb = new_nof_prb;
srsran_chest_dl_res_free(&q->chest);
if (srsran_chest_dl_res_init(&q->chest, q->max_prb) < SRSRAN_SUCCESS) {
srsran_chest_dl_res_free(&q->chest_pusch);
if (srsran_chest_dl_res_init(&q->chest_pusch, q->max_prb) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
srsran_chest_ul_res_free(&q->chest_pucch);
if (srsran_chest_ul_res_init(&q->chest_pucch, q->max_prb) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
@ -90,7 +96,8 @@ void srsran_gnb_ul_free(srsran_gnb_ul_t* q)
srsran_pusch_nr_free(&q->pusch);
srsran_pucch_nr_free(&q->pucch);
srsran_dmrs_sch_free(&q->dmrs);
srsran_chest_dl_res_free(&q->chest);
srsran_chest_dl_res_free(&q->chest_pusch);
srsran_chest_ul_res_free(&q->chest_pucch);
if (q->sf_symbols[0] != NULL) {
free(q->sf_symbols[0]);
@ -157,13 +164,101 @@ int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q,
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (srsran_dmrs_sch_estimate(&q->dmrs, slot_cfg, cfg, grant, q->sf_symbols[0], &q->chest) < SRSRAN_SUCCESS) {
if (srsran_dmrs_sch_estimate(&q->dmrs, slot_cfg, cfg, grant, q->sf_symbols[0], &q->chest_pusch) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest, q->sf_symbols, data) < SRSRAN_SUCCESS) {
if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest_pusch, q->sf_symbols, data) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
static int gnb_ul_decode_pucch_format1(srsran_gnb_ul_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_pucch_nr_resource_t* resource,
const srsran_uci_cfg_nr_t* uci_cfg,
srsran_uci_value_nr_t* uci_value)
{
uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {};
// Set ACK bits
uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_cfg->o_ack);
// Set SR bits
// For a positive SR transmission using PUCCH format 1, the UE transmits the PUCCH as described in [4, TS
// 38.211] by setting b ( 0 ) = 0 .
if (nof_bits == 0 && uci_cfg->o_sr > 0) {
nof_bits = 1;
}
if (srsran_dmrs_pucch_format1_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) <
SRSRAN_SUCCESS) {
ERROR("Error in PUCCH format 1 estimation");
return SRSRAN_ERROR;
}
if (srsran_pucch_nr_format1_decode(
&q->pucch, cfg, slot_cfg, resource, &q->chest_pucch, q->sf_symbols[0], b, nof_bits) < SRSRAN_SUCCESS) {
ERROR("Error in PUCCH format 1 decoding");
return SRSRAN_ERROR;
}
// De-multiplex ACK bits
for (uint32_t i = 0; i < nof_bits; i++) {
uci_value->ack[i] = b[i];
}
return SRSRAN_SUCCESS;
}
static int gnb_ul_decode_pucch_format2(srsran_gnb_ul_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_pucch_nr_resource_t* resource,
const srsran_uci_cfg_nr_t* uci_cfg,
srsran_uci_value_nr_t* uci_value)
{
if (srsran_dmrs_pucch_format2_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) <
SRSRAN_SUCCESS) {
ERROR("Error in PUCCH format 2 estimation");
return SRSRAN_ERROR;
}
if (srsran_pucch_nr_format_2_3_4_decode(
&q->pucch, cfg, slot_cfg, resource, uci_cfg, &q->chest_pucch, q->sf_symbols[0], uci_value) < SRSRAN_SUCCESS) {
ERROR("Error in PUCCH format 2 decoding");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_pucch_nr_common_cfg_t* cfg,
const srsran_pucch_nr_resource_t* resource,
const srsran_uci_cfg_nr_t* uci_cfg,
srsran_uci_value_nr_t* uci_value)
{
if (q == NULL || slot_cfg == NULL || cfg == NULL || resource == NULL || uci_cfg == NULL || uci_value == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Estimate channel
switch (resource->format) {
case SRSRAN_PUCCH_NR_FORMAT_1:
return gnb_ul_decode_pucch_format1(q, slot_cfg, cfg, resource, uci_cfg, uci_value);
case SRSRAN_PUCCH_NR_FORMAT_2:
return gnb_ul_decode_pucch_format2(q, slot_cfg, cfg, resource, uci_cfg, uci_value);
case SRSRAN_PUCCH_NR_FORMAT_0:
case SRSRAN_PUCCH_NR_FORMAT_3:
case SRSRAN_PUCCH_NR_FORMAT_4:
case SRSRAN_PUCCH_NR_FORMAT_ERROR:
ERROR("Invalid or not implemented PUCCH-NR format %d", (int)resource->format);
}
return SRSRAN_ERROR;
}

@ -130,7 +130,7 @@ static int test_pucch_format1(srsran_pucch_nr_t* pucch,
// Estimate channel
TESTASSERT(srsran_dmrs_pucch_format1_estimate(
pucch, &carrier, cfg, &slot, &resource, slot_symbols, chest_res) == SRSRAN_SUCCESS);
pucch, cfg, &slot, &resource, slot_symbols, chest_res) == SRSRAN_SUCCESS);
TESTASSERT(fabsf(chest_res->rsrp_dBfs - 0.0f) < 3.0f);
TESTASSERT(fabsf(chest_res->epre_dBfs - 0.0f) < 3.0f);
@ -215,8 +215,8 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch,
&awgn, slot_symbols, slot_symbols, carrier.nof_prb * SRSRAN_NRE * SRSRAN_NSYMB_PER_SLOT_NR);
// Estimate channel
TESTASSERT(srsran_dmrs_pucch_format2_estimate(
pucch, &carrier, cfg, &slot, &resource, slot_symbols, chest_res) == SRSRAN_SUCCESS);
TESTASSERT(srsran_dmrs_pucch_format2_estimate(pucch, cfg, &slot, &resource, slot_symbols, chest_res) ==
SRSRAN_SUCCESS);
INFO("RSRP=%+.2f; EPRE=%+.2f; SNR=%+.2f;",
chest_res->rsrp_dBfs,
chest_res->epre_dBfs,

@ -80,6 +80,7 @@ private:
srsran_pdcch_cfg_nr_t pdcch_cfg = {};
srsran::rf_timestamp_t tx_time = {};
srsran_gnb_dl_t gnb_dl = {};
srsran_gnb_ul_t gnb_ul = {};
std::vector<cf_t*> tx_buffer; ///< Baseband transmit buffers
std::vector<cf_t*> rx_buffer; ///< Baseband receive buffers
};

@ -18,9 +18,7 @@ namespace nr {
slot_worker::slot_worker(srsran::phy_common_interface& common_,
stack_interface_phy_nr& stack_,
srslog::basic_logger& logger_) :
common(common_),
stack(stack_),
logger(logger_)
common(common_), stack(stack_), logger(logger_)
{
// Do nothing
}
@ -62,15 +60,34 @@ bool slot_worker::init(const args_t& args)
dl_args.nof_tx_antennas = args.nof_tx_ports;
dl_args.nof_max_prb = args.carrier.nof_prb;
// Initialise DL
// Initialise DL
if (srsran_gnb_dl_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) {
logger.error("Error gNb PHY init");
logger.error("Error gNb DL init");
return false;
}
// Set gNb carrier
// Set gNb DL carrier
if (srsran_gnb_dl_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) {
logger.error("Error setting carrier");
logger.error("Error setting DL carrier");
return false;
}
// Prepare UL arguments
srsran_gnb_ul_args_t ul_args = {};
ul_args.pusch.measure_time = true;
ul_args.pusch.max_layers = args.carrier.max_mimo_layers;
ul_args.pusch.max_prb = args.carrier.nof_prb;
ul_args.nof_max_prb = args.carrier.nof_prb;
// Initialise UL
if (srsran_gnb_ul_init(&gnb_ul, rx_buffer[0], &ul_args) < SRSRAN_SUCCESS) {
logger.error("Error gNb DL init");
return false;
}
// Set gNb UL carrier
if (srsran_gnb_ul_set_carrier(&gnb_ul, &args.carrier) < SRSRAN_SUCCESS) {
logger.error("Error setting UL carrier");
return false;
}

Loading…
Cancel
Save