From 658b47d917210fbc8a351d3c5d1086b40821e9a3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 11:08:11 +0200 Subject: [PATCH] Added NR PUSCH and PUCCH decoder in gnb_ul --- .../srsran/phy/ch_estimation/dmrs_pucch.h | 4 - lib/include/srsran/phy/gnb/gnb_ul.h | 3 +- lib/include/srsran/srsran.h | 1 + lib/src/phy/ch_estimation/dmrs_pucch.c | 46 ++++---- lib/src/phy/gnb/gnb_ul.c | 105 +++++++++++++++++- lib/src/phy/phch/test/pucch_nr_test.c | 6 +- srsenb/hdr/phy/nr/slot_worker.h | 1 + srsenb/src/phy/nr/slot_worker.cc | 31 ++++-- 8 files changed, 152 insertions(+), 45 deletions(-) diff --git a/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h b/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h index e8ef7f5d5..56f83466e 100644 --- a/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h +++ b/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h @@ -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, diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h index 7fa392c17..6440a4512 100644 --- a/lib/include/srsran/phy/gnb/gnb_ul.h +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -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); diff --git a/lib/include/srsran/srsran.h b/lib/include/srsran/srsran.h index 0e379a2dc..7588caf18 100644 --- a/lib/include/srsran/srsran.h +++ b/lib/include/srsran/srsran.h @@ -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" diff --git a/lib/src/phy/ch_estimation/dmrs_pucch.c b/lib/src/phy/ch_estimation/dmrs_pucch.c index 2d036e9f7..7a045c325 100644 --- a/lib/src/phy/ch_estimation/dmrs_pucch.c +++ b/lib/src/phy/ch_estimation/dmrs_pucch.c @@ -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]; } } diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index 616dae751..ab85c3df9 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -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; } \ No newline at end of file diff --git a/lib/src/phy/phch/test/pucch_nr_test.c b/lib/src/phy/phch/test/pucch_nr_test.c index 455787cf7..5b99ab0c8 100644 --- a/lib/src/phy/phch/test/pucch_nr_test.c +++ b/lib/src/phy/phch/test/pucch_nr_test.c @@ -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, diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h index dd5fd3985..ec079f4a2 100644 --- a/srsenb/hdr/phy/nr/slot_worker.h +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -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 tx_buffer; ///< Baseband transmit buffers std::vector rx_buffer; ///< Baseband receive buffers }; diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 411e319e8..9b73a73ed 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -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; }