diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h index 424d068dd..c13f50103 100644 --- a/lib/include/srsran/phy/gnb/gnb_ul.h +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -21,6 +21,7 @@ typedef struct SRSRAN_API { srsran_pusch_nr_args_t pusch; srsran_pucch_nr_args_t pucch; + float pusch_min_snr_dB; ///< Minimum SNR threshold to decode PUSCH, set to 0 for default value uint32_t nof_max_prb; } srsran_gnb_ul_args_t; @@ -36,6 +37,7 @@ typedef struct SRSRAN_API { srsran_dmrs_sch_t dmrs; srsran_chest_dl_res_t chest_pusch; srsran_chest_ul_res_t chest_pucch; + float pusch_min_snr_dB; ///< Minimum measured DMRS SNR, below this threshold PUSCH is not decoded } 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/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index 7e2c48847..13fd7a0cc 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -20,6 +20,11 @@ */ #define GNB_UL_NR_FFT_WINDOW_OFFSET 0.5f +/** + * @brief Minimum PUSCH DMRS measured SINR default value + */ +#define GNB_UL_PUSCH_MIN_SNR_DEFAULT -10.0f + static int gnb_ul_alloc_prb(srsran_gnb_ul_t* q, uint32_t new_nof_prb) { if (q->max_prb < new_nof_prb) { @@ -83,6 +88,12 @@ int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args return SRSRAN_ERROR; } + // Set PUSCH minimum SNR, use default value if the given is NAN, INF or zero + q->pusch_min_snr_dB = GNB_UL_PUSCH_MIN_SNR_DEFAULT; + if (isnormal(args->pusch_min_snr_dB)) { + q->pusch_min_snr_dB = args->pusch_min_snr_dB; + } + return SRSRAN_SUCCESS; } @@ -169,6 +180,15 @@ int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q, return SRSRAN_ERROR; } + // Check PUSCH DMRS minimum SNR and abort PUSCH decoding if it is below the threshold + if (q->dmrs.csi.snr_dB < q->pusch_min_snr_dB) { + // Set PUSCH data as not decoded + data->tb[0].crc = false; + data->tb[0].avg_iter = NAN; + data->uci.valid = false; + return SRSRAN_SUCCESS; + } + if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest_pusch, q->sf_symbols, data) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; } diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h index 3bb515dbe..355f10d26 100644 --- a/srsenb/hdr/phy/nr/slot_worker.h +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -57,6 +57,7 @@ public: uint32_t rf_port = 0; srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_15kHz; uint32_t pusch_max_nof_iter = 10; + float pusch_min_snr_dB = -10.0f; double srate_hz = 0.0; }; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 300c43fc4..f61afbfda 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -103,6 +103,7 @@ public: uint32_t nof_prach_workers = 0; uint32_t prio = 52; uint32_t pusch_max_nof_iter = 10; + float pusch_min_snr_dB = -10; srsran::phy_log_args_t log = {}; }; slot_worker* operator[](std::size_t pos) { return workers.at(pos).get(); } diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index fc835c0b7..bbe96fca7 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -78,6 +78,7 @@ bool slot_worker::init(const args_t& args) ul_args.pusch.max_layers = args.nof_rx_ports; ul_args.pusch.max_prb = args.nof_max_prb; ul_args.nof_max_prb = args.nof_max_prb; + ul_args.pusch_min_snr_dB = args.pusch_min_snr_dB; // Initialise UL if (srsran_gnb_ul_init(&gnb_ul, rx_buffer[0], &ul_args) < SRSRAN_SUCCESS) { diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index 0563c6e1c..e60caca40 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -63,6 +63,7 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li w_args.rf_port = cell_list[cell_index].rf_port; w_args.srate_hz = srate_hz; w_args.pusch_max_nof_iter = args.pusch_max_nof_iter; + w_args.pusch_min_snr_dB = args.pusch_min_snr_dB; if (not w->init(w_args)) { return false;