diff --git a/lib/include/srslte/phy/ch_estimation/dmrs_pdcch.h b/lib/include/srslte/phy/ch_estimation/dmrs_pdcch.h index ffcff4b60..fbcb0fdf5 100644 --- a/lib/include/srslte/phy/ch_estimation/dmrs_pdcch.h +++ b/lib/include/srslte/phy/ch_estimation/dmrs_pdcch.h @@ -13,14 +13,14 @@ #ifndef SRSLTE_DMRS_PDCCH_H #define SRSLTE_DMRS_PDCCH_H -#ifdef __cplusplus -extern "C" { -#endif - #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/resampling/resampler.h" #include "srslte/srslte.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Puts in the resource grid the DeModulation Reference Signals for decoding PDCCH. * diff --git a/lib/include/srslte/phy/common/phy_common_nr.h b/lib/include/srslte/phy/common/phy_common_nr.h index 331296ddb..67237fc25 100644 --- a/lib/include/srslte/phy/common/phy_common_nr.h +++ b/lib/include/srslte/phy/common/phy_common_nr.h @@ -104,8 +104,8 @@ extern "C" { #define SRSLTE_MAX_NOF_DL_ALLOCATION 16 typedef enum SRSLTE_API { - srslte_coreset_mapping_type_interleaved = 0, - srslte_coreset_mapping_type_non_interleaved, + srslte_coreset_mapping_type_non_interleaved = 0, + srslte_coreset_mapping_type_interleaved, } srslte_coreset_mapping_type_t; typedef enum SRSLTE_API { diff --git a/lib/include/srslte/phy/enb/enb_dl_nr.h b/lib/include/srslte/phy/enb/enb_dl_nr.h index 64c8b0bc9..4eae55cb5 100644 --- a/lib/include/srslte/phy/enb/enb_dl_nr.h +++ b/lib/include/srslte/phy/enb/enb_dl_nr.h @@ -15,6 +15,7 @@ #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/dft/ofdm.h" +#include "srslte/phy/phch/pdcch_nr.h" #include "srslte/phy/phch/pdsch_nr.h" #ifdef __cplusplus @@ -22,21 +23,25 @@ extern "C" { #endif typedef struct SRSLTE_API { - srslte_pdsch_args_t pdsch; - uint32_t nof_tx_antennas; - uint32_t nof_max_prb; + srslte_pdsch_nr_args_t pdsch; + srslte_pdcch_nr_args_t pdcch; + uint32_t nof_tx_antennas; + uint32_t nof_max_prb; } srslte_enb_dl_nr_args_t; typedef struct SRSLTE_API { uint32_t max_prb; uint32_t nof_tx_antennas; srslte_carrier_nr_t carrier; + srslte_coreset_t coreset; srslte_ofdm_t fft[SRSLTE_MAX_PORTS]; cf_t* sf_symbols[SRSLTE_MAX_PORTS]; srslte_pdsch_nr_t pdsch; srslte_dmrs_pdsch_t dmrs; + + srslte_pdcch_nr_t pdcch; } srslte_enb_dl_nr_t; SRSLTE_API int @@ -44,10 +49,19 @@ srslte_enb_dl_nr_init(srslte_enb_dl_nr_t* q, cf_t* output[SRSLTE_MAX_PORTS], con SRSLTE_API int srslte_enb_dl_nr_set_carrier(srslte_enb_dl_nr_t* q, const srslte_carrier_nr_t* carrier); +SRSLTE_API int srslte_enb_dl_nr_set_coreset(srslte_enb_dl_nr_t* q, const srslte_coreset_t* coreset); + SRSLTE_API void srslte_enb_dl_nr_free(srslte_enb_dl_nr_t* q); SRSLTE_API void srslte_enb_dl_nr_gen_signal(srslte_enb_dl_nr_t* q); +SRSLTE_API int srslte_enb_dl_nr_pdcch_put(srslte_enb_dl_nr_t* q, + const srslte_dl_slot_cfg_t* slot_cfg, + const srslte_search_space_t* search_space, + const srslte_dci_dl_nr_t* dci_dl, + const srslte_dci_location_t* dci_location, + uint16_t rnti); + SRSLTE_API int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q, const srslte_dl_slot_cfg_t* slot, const srslte_pdsch_cfg_nr_t* cfg, diff --git a/lib/include/srslte/phy/phch/pdcch_nr.h b/lib/include/srslte/phy/phch/pdcch_nr.h index 39bbeb6b5..1f0669064 100644 --- a/lib/include/srslte/phy/phch/pdcch_nr.h +++ b/lib/include/srslte/phy/phch/pdcch_nr.h @@ -95,6 +95,8 @@ int srslte_pdcch_nr_locations_coreset(const srslte_coreset_t* coreset, uint32_t slot_idx, uint32_t locations[SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR]); +SRSLTE_API int srslte_pdcch_nr_max_candidates_coreset(const srslte_coreset_t* coreset, uint32_t aggregation_level); + SRSLTE_API int srslte_pdcch_nr_init_tx(srslte_pdcch_nr_t* q, const srslte_pdcch_nr_args_t* args); SRSLTE_API int srslte_pdcch_nr_init_rx(srslte_pdcch_nr_t* q, const srslte_pdcch_nr_args_t* args); diff --git a/lib/include/srslte/phy/phch/pdsch_nr.h b/lib/include/srslte/phy/phch/pdsch_nr.h index 9a5110f30..6c40b6567 100644 --- a/lib/include/srslte/phy/phch/pdsch_nr.h +++ b/lib/include/srslte/phy/phch/pdsch_nr.h @@ -35,7 +35,7 @@ typedef struct SRSLTE_API { srslte_sch_nr_args_t sch; bool measure_evm; bool measure_time; -} srslte_pdsch_args_t; +} srslte_pdsch_nr_args_t; /** * @brief PDSCH NR object @@ -64,9 +64,9 @@ typedef struct { float evm; } srslte_pdsch_res_nr_t; -SRSLTE_API int srslte_pdsch_nr_init_enb(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args); +SRSLTE_API int srslte_pdsch_nr_init_enb(srslte_pdsch_nr_t* q, const srslte_pdsch_nr_args_t* args); -SRSLTE_API int srslte_pdsch_nr_init_ue(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args); +SRSLTE_API int srslte_pdsch_nr_init_ue(srslte_pdsch_nr_t* q, const srslte_pdsch_nr_args_t* args); SRSLTE_API void srslte_pdsch_nr_free(srslte_pdsch_nr_t* q); diff --git a/lib/include/srslte/phy/ue/ue_dl_nr.h b/lib/include/srslte/phy/ue/ue_dl_nr.h index de8df64b7..b41e0cba0 100644 --- a/lib/include/srslte/phy/ue/ue_dl_nr.h +++ b/lib/include/srslte/phy/ue/ue_dl_nr.h @@ -13,8 +13,11 @@ #ifndef SRSLTE_UE_DL_NR_H #define SRSLTE_UE_DL_NR_H +#include "srslte/phy/ch_estimation/dmrs_pdcch.h" #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/dft/ofdm.h" +#include "srslte/phy/phch/dci_nr.h" +#include "srslte/phy/phch/pdcch_nr.h" #include "srslte/phy/phch/pdsch_nr.h" #ifdef __cplusplus @@ -22,22 +25,31 @@ extern "C" { #endif typedef struct SRSLTE_API { - srslte_pdsch_args_t pdsch; - uint32_t nof_rx_antennas; - uint32_t nof_max_prb; + srslte_pdsch_nr_args_t pdsch; + srslte_pdcch_nr_args_t pdcch; + uint32_t nof_rx_antennas; + uint32_t nof_max_prb; + float pdcch_dmrs_corr_thr; } srslte_ue_dl_nr_args_t; typedef struct SRSLTE_API { - uint32_t max_prb; - uint32_t nof_rx_antennas; + uint32_t max_prb; + uint32_t nof_rx_antennas; + float pdcch_dmrs_corr_thr; + srslte_carrier_nr_t carrier; + srslte_coreset_t coreset; srslte_ofdm_t fft[SRSLTE_MAX_PORTS]; cf_t* sf_symbols[SRSLTE_MAX_PORTS]; srslte_chest_dl_res_t chest; srslte_pdsch_nr_t pdsch; - srslte_dmrs_pdsch_t dmrs; + srslte_dmrs_pdsch_t dmrs_pdsch; + + srslte_dmrs_pdcch_estimator_t dmrs_pdcch; + srslte_pdcch_nr_t pdcch; + srslte_dmrs_pdcch_ce_t* pdcch_ce; } srslte_ue_dl_nr_t; SRSLTE_API int @@ -45,9 +57,18 @@ srslte_ue_dl_nr_init(srslte_ue_dl_nr_t* q, cf_t* input[SRSLTE_MAX_PORTS], const SRSLTE_API int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t* carrier); +SRSLTE_API int srslte_ue_dl_nr_set_coreset(srslte_ue_dl_nr_t* q, const srslte_coreset_t* coreset); + SRSLTE_API void srslte_ue_dl_nr_free(srslte_ue_dl_nr_t* q); -SRSLTE_API void srslte_ue_dl_nr_estimate_fft(srslte_ue_dl_nr_t* q); +SRSLTE_API void srslte_ue_dl_nr_estimate_fft(srslte_ue_dl_nr_t* q, const srslte_dl_slot_cfg_t* slot_cfg); + +SRSLTE_API int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q, + const srslte_search_space_t* search_space, + const srslte_dl_slot_cfg_t* slot_cfg, + uint16_t rnti, + srslte_dci_dl_nr_t* dci_dl_list, + uint32_t nof_dci_msg); SRSLTE_API int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q, const srslte_dl_slot_cfg_t* slot, diff --git a/lib/src/phy/enb/enb_dl_nr.c b/lib/src/phy/enb/enb_dl_nr.c index dc48e08b0..de72d0de8 100644 --- a/lib/src/phy/enb/enb_dl_nr.c +++ b/lib/src/phy/enb/enb_dl_nr.c @@ -71,6 +71,11 @@ int srslte_enb_dl_nr_init(srslte_enb_dl_nr_t* q, cf_t* output[SRSLTE_MAX_PORTS], return SRSLTE_ERROR; } + if (srslte_pdcch_nr_init_tx(&q->pdcch, &args->pdcch) < SRSLTE_SUCCESS) { + ERROR("Error PDCCH\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; } @@ -91,6 +96,8 @@ void srslte_enb_dl_nr_free(srslte_enb_dl_nr_t* q) srslte_pdsch_nr_free(&q->pdsch); srslte_dmrs_pdsch_free(&q->dmrs); + srslte_pdcch_nr_free(&q->pdcch); + memset(q, 0, sizeof(srslte_enb_dl_nr_t)); } @@ -121,6 +128,21 @@ int srslte_enb_dl_nr_set_carrier(srslte_enb_dl_nr_t* q, const srslte_carrier_nr_ return SRSLTE_SUCCESS; } +int srslte_enb_dl_nr_set_coreset(srslte_enb_dl_nr_t* q, const srslte_coreset_t* coreset) +{ + if (q == NULL || coreset == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + q->coreset = *coreset; + + if (srslte_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, &q->coreset) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} + void srslte_enb_dl_nr_gen_signal(srslte_enb_dl_nr_t* q) { if (q == NULL) { @@ -132,6 +154,50 @@ void srslte_enb_dl_nr_gen_signal(srslte_enb_dl_nr_t* q) } } +int srslte_enb_dl_nr_pdcch_put(srslte_enb_dl_nr_t* q, + const srslte_dl_slot_cfg_t* slot_cfg, + const srslte_search_space_t* search_space, + const srslte_dci_dl_nr_t* dci_dl, + const srslte_dci_location_t* dci_location, + uint16_t rnti) +{ + if (q == NULL || search_space == NULL || slot_cfg == NULL || dci_dl == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + // Hard-coded values + srslte_dci_format_nr_t dci_format = srslte_dci_format_nr_1_0; + srslte_rnti_type_t rnti_type = srslte_rnti_type_c; + + // Put DMRS + if (srslte_dmrs_pdcch_put(&q->carrier, &q->coreset, slot_cfg, dci_location, q->sf_symbols[0]) < SRSLTE_SUCCESS) { + ERROR("Error putting PDCCH DMRS\n"); + return SRSLTE_ERROR; + } + + // Initialise DCI MSG fields + srslte_dci_msg_nr_t dci_msg = {}; + dci_msg.location = *dci_location; + dci_msg.search_space = search_space->type; + dci_msg.rnti_type = rnti_type; + dci_msg.rnti = rnti; + dci_msg.format = dci_format; + + // Pack DCI + if (srslte_dci_nr_format_1_0_pack(&q->carrier, &q->coreset, dci_dl, &dci_msg) < SRSLTE_SUCCESS) { + ERROR("Error packing DL DCI\n"); + return SRSLTE_ERROR; + } + + // PDCCH Encode + if (srslte_pdcch_nr_encode(&q->pdcch, &dci_msg, q->sf_symbols[0]) < SRSLTE_SUCCESS) { + ERROR("Error encoding PDCCH\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} + int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q, const srslte_dl_slot_cfg_t* slot, const srslte_pdsch_cfg_nr_t* cfg, diff --git a/lib/src/phy/phch/dci_nr.c b/lib/src/phy/phch/dci_nr.c index 6e07cf10b..62fdef55e 100644 --- a/lib/src/phy/phch/dci_nr.c +++ b/lib/src/phy/phch/dci_nr.c @@ -140,7 +140,7 @@ int srslte_dci_nr_format_1_0_pack(const srslte_carrier_nr_t* carrier, return SRSLTE_ERROR; } - return SRSLTE_ERROR; + return SRSLTE_SUCCESS; } int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrier, @@ -254,7 +254,7 @@ int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrier, return SRSLTE_ERROR; } - return SRSLTE_ERROR; + return SRSLTE_SUCCESS; } int srslte_dci_nr_format_1_0_sizeof(const srslte_carrier_nr_t* carrier, diff --git a/lib/src/phy/phch/pdcch_nr.c b/lib/src/phy/phch/pdcch_nr.c index 9eafd5abd..531dc9439 100644 --- a/lib/src/phy/phch/pdcch_nr.c +++ b/lib/src/phy/phch/pdcch_nr.c @@ -104,6 +104,21 @@ int srslte_pdcch_nr_locations_coreset(const srslte_coreset_t* coreset, return nof_candidates; } +int srslte_pdcch_nr_max_candidates_coreset(const srslte_coreset_t* coreset, uint32_t aggregation_level) +{ + if (coreset == NULL) { + return SRSLTE_ERROR; + } + + uint32_t coreset_bw = srslte_coreset_get_bw(coreset); + uint32_t nof_cce = (coreset_bw * coreset->duration) / 6; + + uint32_t L = 1U << aggregation_level; + uint32_t nof_candidates = nof_cce / L; + + return SRSLTE_MIN(nof_candidates, SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR); +} + static int pdcch_nr_init_common(srslte_pdcch_nr_t* q, const srslte_pdcch_nr_args_t* args) { if (q == NULL || args == NULL) { diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 4a79b211f..5d4b270d2 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -13,7 +13,7 @@ #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/phch/ra_nr.h" -int pdsch_nr_init_common(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) +int pdsch_nr_init_common(srslte_pdsch_nr_t* q, const srslte_pdsch_nr_args_t* args) { for (srslte_mod_t mod = SRSLTE_MOD_BPSK; mod < SRSLTE_MOD_NITEMS; mod++) { if (srslte_modem_table_lte(&q->modem_tables[mod], mod) < SRSLTE_SUCCESS) { @@ -28,7 +28,7 @@ int pdsch_nr_init_common(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) return SRSLTE_SUCCESS; } -int srslte_pdsch_nr_init_enb(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) +int srslte_pdsch_nr_init_enb(srslte_pdsch_nr_t* q, const srslte_pdsch_nr_args_t* args) { if (q == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; @@ -46,7 +46,7 @@ int srslte_pdsch_nr_init_enb(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* ar return SRSLTE_SUCCESS; } -int srslte_pdsch_nr_init_ue(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) +int srslte_pdsch_nr_init_ue(srslte_pdsch_nr_t* q, const srslte_pdsch_nr_args_t* args) { if (q == NULL || args == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; diff --git a/lib/src/phy/phch/test/pdcch_nr_test.c b/lib/src/phy/phch/test/pdcch_nr_test.c index 10f20732f..20d3f798f 100644 --- a/lib/src/phy/phch/test/pdcch_nr_test.c +++ b/lib/src/phy/phch/test/pdcch_nr_test.c @@ -27,7 +27,8 @@ static srslte_carrier_nr_t carrier = { 0, // cell_id 0, // numerology 50, // nof_prb - 0 // start + 0, // start + 1 // max_mimo_layers }; static uint16_t rnti = 0x1234; @@ -163,25 +164,15 @@ int main(int argc, char** argv) goto clean_exit; } - uint32_t coreset_bw = srslte_coreset_get_bw(&coreset); - uint32_t nof_cce = (coreset_bw * coreset.duration) / 6; - uint32_t max_aggregation_level = (uint32_t)floor(log2(nof_cce)); - max_aggregation_level = SRSLTE_MIN(max_aggregation_level + 1, SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR); - // Fill search space maximum number of candidates - for (uint32_t aggregation_level = 0; aggregation_level < max_aggregation_level; aggregation_level++) { - uint32_t L = 1U << aggregation_level; - uint32_t nof_candidates = nof_cce / L; - nof_candidates = SRSLTE_MIN(nof_candidates, SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR); - search_space.nof_candidates[aggregation_level] = nof_candidates; - } - for (uint32_t aggregation_level = max_aggregation_level; - aggregation_level < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; + for (uint32_t aggregation_level = 0; aggregation_level < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; aggregation_level++) { - search_space.nof_candidates[aggregation_level] = 0; + search_space.nof_candidates[aggregation_level] = + srslte_pdcch_nr_max_candidates_coreset(&coreset, aggregation_level); } - for (uint32_t aggregation_level = 0; aggregation_level < max_aggregation_level; aggregation_level++) { + for (uint32_t aggregation_level = 0; aggregation_level < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; + aggregation_level++) { uint32_t L = 1U << aggregation_level; for (uint32_t slot_idx = 0; slot_idx < SRSLTE_NSLOTS_PER_FRAME_NR(carrier.numerology); slot_idx++) { @@ -194,9 +185,10 @@ int main(int argc, char** argv) ERROR("Error calculating locations in CORESET\n"); goto clean_exit; } + + // Skip if no candidates if (n == 0) { - ERROR("Invalid number of locations (%d)\n", n); - goto clean_exit; + continue; } for (uint32_t ncce_idx = 0; ncce_idx < n; ncce_idx++) { diff --git a/lib/src/phy/phch/test/pdsch_nr_test.c b/lib/src/phy/phch/test/pdsch_nr_test.c index fd7be5589..1efa496b2 100644 --- a/lib/src/phy/phch/test/pdsch_nr_test.c +++ b/lib/src/phy/phch/test/pdsch_nr_test.c @@ -91,9 +91,9 @@ int main(int argc, char** argv) goto clean_exit; } - srslte_pdsch_args_t pdsch_args = {}; - pdsch_args.sch.disable_simd = true; - pdsch_args.measure_evm = true; + srslte_pdsch_nr_args_t pdsch_args = {}; + pdsch_args.sch.disable_simd = true; + pdsch_args.measure_evm = true; if (srslte_pdsch_nr_init_enb(&pdsch_tx, &pdsch_args) < SRSLTE_SUCCESS) { ERROR("Error initiating PDSCH for Tx\n"); diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 3f9f963e8..be5218ec9 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -12,7 +12,9 @@ #include "srslte/phy/ue/ue_dl_nr.h" -static int ue_dl_alloc_prb(srslte_ue_dl_nr_t* q, uint32_t new_nof_prb) +#define UE_DL_NR_PDCCH_CORR_DEFAULT_THR 0.5f + +static int ue_dl_nr_alloc_prb(srslte_ue_dl_nr_t* q, uint32_t new_nof_prb) { if (q->max_prb < new_nof_prb) { q->max_prb = new_nof_prb; @@ -49,13 +51,18 @@ int srslte_ue_dl_nr_init(srslte_ue_dl_nr_t* q, cf_t* input[SRSLTE_MAX_PORTS], co return SRSLTE_ERROR; } - q->nof_rx_antennas = args->nof_rx_antennas; + q->nof_rx_antennas = args->nof_rx_antennas; + q->pdcch_dmrs_corr_thr = args->pdcch_dmrs_corr_thr; if (srslte_pdsch_nr_init_ue(&q->pdsch, &args->pdsch) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } - if (ue_dl_alloc_prb(q, args->nof_max_prb)) { + if (srslte_pdcch_nr_init_rx(&q->pdcch, &args->pdcch)) { + return SRSLTE_ERROR; + } + + if (ue_dl_nr_alloc_prb(q, args->nof_max_prb)) { ERROR("Error allocating\n"); return SRSLTE_ERROR; } @@ -71,11 +78,17 @@ int srslte_ue_dl_nr_init(srslte_ue_dl_nr_t* q, cf_t* input[SRSLTE_MAX_PORTS], co srslte_ofdm_rx_init_cfg(&q->fft[i], &fft_cfg); } - if (srslte_dmrs_pdsch_init(&q->dmrs, true) < SRSLTE_SUCCESS) { + if (srslte_dmrs_pdsch_init(&q->dmrs_pdsch, true) < SRSLTE_SUCCESS) { ERROR("Error DMRS\n"); return SRSLTE_ERROR; } + q->pdcch_ce = SRSLTE_MEM_ALLOC(srslte_dmrs_pdcch_ce_t, 1); + if (q->pdcch_ce == NULL) { + ERROR("Error alloc\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; } @@ -95,7 +108,13 @@ void srslte_ue_dl_nr_free(srslte_ue_dl_nr_t* q) srslte_chest_dl_res_free(&q->chest); srslte_pdsch_nr_free(&q->pdsch); - srslte_dmrs_pdsch_free(&q->dmrs); + srslte_dmrs_pdsch_free(&q->dmrs_pdsch); + srslte_dmrs_pdcch_estimator_free(&q->dmrs_pdcch); + srslte_pdcch_nr_free(&q->pdcch); + + if (q->pdcch_ce) { + free(q->pdcch_ce); + } memset(q, 0, sizeof(srslte_ue_dl_nr_t)); } @@ -106,12 +125,12 @@ int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t* return SRSLTE_ERROR; } - if (srslte_dmrs_pdsch_set_carrier(&q->dmrs, carrier) < SRSLTE_SUCCESS) { + if (srslte_dmrs_pdsch_set_carrier(&q->dmrs_pdsch, carrier) < SRSLTE_SUCCESS) { ERROR("Error DMRS\n"); return SRSLTE_ERROR; } - if (ue_dl_alloc_prb(q, carrier->nof_prb)) { + if (ue_dl_nr_alloc_prb(q, carrier->nof_prb)) { ERROR("Error allocating\n"); return SRSLTE_ERROR; } @@ -127,15 +146,138 @@ int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t* return SRSLTE_SUCCESS; } -void srslte_ue_dl_nr_estimate_fft(srslte_ue_dl_nr_t* q) +int srslte_ue_dl_nr_set_coreset(srslte_ue_dl_nr_t* q, const srslte_coreset_t* coreset) { - if (q == NULL) { + if (q == NULL || coreset == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + q->coreset = *coreset; + + if (srslte_dmrs_pdcch_estimator_init(&q->dmrs_pdcch, &q->carrier, &q->coreset) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + if (srslte_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, &q->coreset) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} + +void srslte_ue_dl_nr_estimate_fft(srslte_ue_dl_nr_t* q, const srslte_dl_slot_cfg_t* slot_cfg) +{ + if (q == NULL || slot_cfg == NULL) { return; } + // OFDM demodulation for (uint32_t i = 0; i < q->nof_rx_antennas; i++) { srslte_ofdm_rx_sf(&q->fft[i]); } + + // Estimate PDCCH channel + srslte_dmrs_pdcch_estimate(&q->dmrs_pdcch, slot_cfg, q->sf_symbols[0]); +} + +static int ue_dl_nr_find_dci_ncce(srslte_ue_dl_nr_t* q, srslte_dci_msg_nr_t* dci_msg, srslte_pdcch_nr_res_t* pdcch_res) +{ + srslte_dmrs_pdcch_measure_t m = {}; + + if (srslte_dmrs_pdcch_get_measure(&q->dmrs_pdcch, &dci_msg->location, &m) < SRSLTE_SUCCESS) { + ERROR("Error getting measure location L=%d, ncce=%d\n", dci_msg->location.L, dci_msg->location.ncce); + return SRSLTE_ERROR; + } + + // If measured RSRP and EPRE is invalid, early return + if (!isnormal(m.rsrp) || !isnormal(m.epre)) { + return SRSLTE_SUCCESS; + } + + // Compare DMRS correlation with threshold + float thr = q->pdcch_dmrs_corr_thr; + if (!isnormal(thr)) { + thr = UE_DL_NR_PDCCH_CORR_DEFAULT_THR; //< Load default threshold if not provided + } + if (m.rsrp / m.epre < thr) { + return SRSLTE_SUCCESS; + } + + // Extract PDCCH channel estimates + if (srslte_dmrs_pdcch_get_ce(&q->dmrs_pdcch, &dci_msg->location, q->pdcch_ce) < SRSLTE_SUCCESS) { + ERROR("Error extracting PDCCH DMRS\n"); + return SRSLTE_ERROR; + } + + // Decode PDCCH + if (srslte_pdcch_nr_decode(&q->pdcch, q->sf_symbols[0], q->pdcch_ce, dci_msg, pdcch_res) < SRSLTE_SUCCESS) { + ERROR("Error decoding PDCCH\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} + +int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q, + const srslte_search_space_t* search_space, + const srslte_dl_slot_cfg_t* slot_cfg, + uint16_t rnti, + srslte_dci_dl_nr_t* dci_dl_list, + uint32_t nof_dci_msg) +{ + uint32_t count = 0; + + // Hard-coded values + srslte_dci_format_nr_t dci_format = srslte_dci_format_nr_1_0; + srslte_rnti_type_t rnti_type = srslte_rnti_type_c; + + // Calculate number of DCI bits + int dci_nof_bits = srslte_dci_nr_format_1_0_sizeof(&q->carrier, &q->coreset, rnti_type); + if (dci_nof_bits <= SRSLTE_SUCCESS) { + ERROR("Error DCI size\n"); + return SRSLTE_ERROR; + } + + // Iterate all possible aggregation levels + for (uint32_t L = 0; L < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR && count < nof_dci_msg; L++) { + // Calculate possible PDCCH DCI candidates + uint32_t candidates[SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {}; + int nof_candidates = + srslte_pdcch_nr_locations_coreset(&q->coreset, search_space, rnti, L, slot_cfg->idx, candidates); + if (nof_candidates < SRSLTE_SUCCESS) { + ERROR("Error calculating DCI candidate location\n"); + return SRSLTE_ERROR; + } + + // Iterate over the candidates + for (int ncce_idx = 0; ncce_idx < nof_candidates && count < nof_dci_msg; ncce_idx++) { + srslte_dci_msg_nr_t dci_msg = {}; + dci_msg.location.L = L; + dci_msg.location.ncce = candidates[ncce_idx]; + dci_msg.search_space = search_space->type; + dci_msg.rnti_type = rnti_type; + dci_msg.rnti = rnti; + dci_msg.format = dci_format; + dci_msg.nof_bits = (uint32_t)dci_nof_bits; + + srslte_pdcch_nr_res_t res = {}; + if (ue_dl_nr_find_dci_ncce(q, &dci_msg, &res) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + if (res.crc) { + if (srslte_dci_nr_format_1_0_unpack(&q->carrier, &q->coreset, &dci_msg, &dci_dl_list[count]) < SRSLTE_SUCCESS) { + ERROR("Error unpacking DCI\n"); + return SRSLTE_ERROR; + } + + INFO("Found DCI in L=%d,ncce=%d\n", dci_msg.location.L, dci_msg.location.ncce); + count++; + } + } + } + + return (int)count; } int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q, @@ -145,7 +287,7 @@ int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q, srslte_pdsch_res_nr_t* res) { - if (srslte_dmrs_pdsch_estimate(&q->dmrs, slot, cfg, grant, q->sf_symbols[0], &q->chest) < SRSLTE_SUCCESS) { + if (srslte_dmrs_pdsch_estimate(&q->dmrs_pdsch, slot, cfg, grant, q->sf_symbols[0], &q->chest) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index fd82d3423..12b86922b 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -34,6 +34,7 @@ static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t mcs = 30; // Set to 30 for steering static srslte_pdsch_cfg_nr_t pdsch_cfg = {}; static srslte_pdsch_grant_nr_t pdsch_grant = {}; +static uint16_t rnti = 0x1234; void usage(char* prog) { @@ -107,12 +108,29 @@ int main(int argc, char** argv) enb_dl_args.pdsch.sch.disable_simd = true; // Set default PDSCH configuration - pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam; - + pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam; if (parse_args(argc, argv) < SRSLTE_SUCCESS) { goto clean_exit; } + srslte_pdsch_nr_args_t pdsch_args = {}; + pdsch_args.sch.disable_simd = true; + pdsch_args.measure_evm = true; + + // Configure CORESET + srslte_coreset_t coreset = {}; + coreset.duration = 2; + for (uint32_t i = 0; i < SRSLTE_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { + coreset.freq_resources[i] = i < carrier.nof_prb; + } + + // Configure Search Space + srslte_search_space_t search_space = {}; + search_space.type = srslte_search_space_type_ue; + for (uint32_t L = 0; L < SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR; L++) { + search_space.nof_candidates[L] = srslte_pdcch_nr_max_candidates_coreset(&coreset, L); + } + if (srslte_ue_dl_nr_init(&ue_dl, &buffer, &ue_dl_args)) { ERROR("Error UE DL\n"); goto clean_exit; @@ -128,11 +146,21 @@ int main(int argc, char** argv) goto clean_exit; } + if (srslte_ue_dl_nr_set_coreset(&ue_dl, &coreset)) { + ERROR("Error setting CORESET\n"); + goto clean_exit; + } + if (srslte_enb_dl_nr_set_carrier(&enb_dl, &carrier)) { ERROR("Error setting SCH NR carrier\n"); goto clean_exit; } + if (srslte_enb_dl_nr_set_coreset(&enb_dl, &coreset)) { + ERROR("Error setting CORESET\n"); + goto clean_exit; + } + for (uint32_t i = 0; i < 1; i++) { data_tx[i] = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR); data_rx[i] = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR); @@ -206,8 +234,33 @@ int main(int argc, char** argv) pdsch_grant.tb[tb].softbuffer.tx = &softbuffer_tx; } + // Compute PDCCH candidate locations + uint32_t L = 0; + uint32_t ncce_candidates[SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {}; + int nof_candidates = + srslte_pdcch_nr_locations_coreset(&coreset, &search_space, rnti, L, slot.idx, ncce_candidates); + if (nof_candidates < SRSLTE_SUCCESS) { + ERROR("Error getting PDCCH candidates\n"); + goto clean_exit; + } + + // Setup DCI location + srslte_dci_location_t dci_location = {}; + dci_location.ncce = ncce_candidates[0]; + dci_location.L = L; + + // Setup DCI + srslte_dci_dl_nr_t dci_dl = {}; + + // Put actual DCI + if (srslte_enb_dl_nr_pdcch_put(&enb_dl, &slot, &search_space, &dci_dl, &dci_location, rnti) < SRSLTE_SUCCESS) { + ERROR("Error putting PDCCH\n"); + goto clean_exit; + } + + // Put PDSCH transmission if (srslte_enb_dl_nr_pdsch_put(&enb_dl, &slot, &pdsch_cfg, &pdsch_grant, data_tx) < SRSLTE_SUCCESS) { - ERROR("Error encoding\n"); + ERROR("Error putting PDSCH\n"); goto clean_exit; } @@ -218,7 +271,19 @@ int main(int argc, char** argv) srslte_softbuffer_rx_reset(pdsch_grant.tb[tb].softbuffer.rx); } - srslte_ue_dl_nr_estimate_fft(&ue_dl); + srslte_ue_dl_nr_estimate_fft(&ue_dl, &slot); + + srslte_dci_dl_nr_t dci_dl_rx = {}; + int nof_found_dci = srslte_ue_dl_nr_find_dl_dci(&ue_dl, &search_space, &slot, rnti, &dci_dl_rx, 1); + if (nof_found_dci < SRSLTE_SUCCESS) { + ERROR("Error decoding\n"); + goto clean_exit; + } + + if (nof_found_dci < 1) { + ERROR("Error DCI not found\n"); + goto clean_exit; + } if (srslte_ue_dl_nr_pdsch_get(&ue_dl, &slot, &pdsch_cfg, &pdsch_grant, pdsch_res) < SRSLTE_SUCCESS) { ERROR("Error decoding\n"); diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 3b7343d55..3e73d6b8e 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -125,7 +125,7 @@ bool cc_worker::work_dl() pdsch_grant.tb[0].softbuffer.rx = &softbuffer_rx; srslte_softbuffer_rx_reset(pdsch_grant.tb[0].softbuffer.rx); - srslte_ue_dl_nr_estimate_fft(&ue_dl); + srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); if (srslte_ue_dl_nr_pdsch_get(&ue_dl, &dl_slot_cfg, &pdsch_cfg, &pdsch_grant, pdsch_res.data()) < SRSLTE_SUCCESS) { ERROR("Error decoding PDSCH\n");