Multiple PHY fixes and NR-PHY configuration refactor

This commit is contained in:
Xavier Arteaga 2021-01-29 16:43:40 +01:00 committed by Xavier Arteaga
parent 7e6a35a9f7
commit 2421f2cd99
27 changed files with 512 additions and 302 deletions

View File

@ -47,12 +47,12 @@ typedef struct {
/**
* @brief Computes the symbol indexes carrying DMRS and stores them in symbols_idx
* @param pdsch_cfg PDSCH configuration provided by upper layers
* @param dmrs_cfg DMRS configuration
* @param grant PDSCH information provided by a DCI
* @param symbols_idx is the destination pointer where the symbols indexes are stored
* @return It returns the number of symbols if inputs are valid, otherwise, it returns SRSLTE_ERROR code.
*/
SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* pdsch_cfg,
SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_dmrs_sch_cfg_t* dmrs_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t symbols_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS]);
@ -69,11 +69,11 @@ SRSLTE_API int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint
/**
* @brief Calculates the number of resource elements taken by a PDSCH-DMRS for a given PDSCH transmission
* @param pdsch_cfg PDSCH configuration provided by upper layers
* @param dmrs_cfg PDSCH-DMRS configuration
* @param grant PDSCH information provided by a DCI
* @return it returns the number of resource elements if the configuration is valid, otherwise it returns SRSLTE_ERROR
*/
SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant);
SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant);
/**
* @brief Stringifies the PDSCH DMRS configuration

View File

@ -130,15 +130,26 @@ typedef enum SRSLTE_API {
*/
typedef enum SRSLTE_API { srslte_sch_mapping_type_A = 0, srslte_sch_mapping_type_B } srslte_sch_mapping_type_t;
/**
* @brief Search spaces
* @remark Described in TS 38.213 V15.10.0 Section 10.1 UE procedure for determining physical downlink control channel
* assignment
*/
typedef enum SRSLTE_API {
srslte_search_space_type_common = 0,
srslte_search_space_type_common_0,
srslte_search_space_type_common_0A,
srslte_search_space_type_common_1,
srslte_search_space_type_common_2,
srslte_search_space_type_ue,
srslte_search_space_type_common_0 = 0, ///< configured by pdcch-ConfigSIB1 in MIB or by searchSpaceSIB1 in
///< PDCCH-ConfigCommon or by searchSpaceZero in PDCCH-ConfigCommon
srslte_search_space_type_common_0A, ///< configured by searchSpaceOtherSystemInformation in PDCCH-ConfigCommon
srslte_search_space_type_common_1, ///< configured by ra-SearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_common_2, ///< configured by pagingSearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_common_3, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = common
srslte_search_space_type_ue, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = ue-Specific
} srslte_search_space_type_t;
/**
* @brief Helper macro to get if a search space type is common or not
*/
#define SRSLTE_SEARCH_SPACE_IS_COMMON(SS_TYPE) ((SS_TYPE) < srslte_search_space_type_ue)
/**
* @brief Indicates the MCS table the UE shall use for PDSCH and/or PUSCH without transform precoding
*/
@ -160,7 +171,7 @@ typedef enum SRSLTE_API {
srslte_rnti_type_tc,
srslte_rnti_type_cs,
srslte_rnti_type_sp_csi,
srslte_rnti_type_mcs_crnti,
srslte_rnti_type_mcs_c,
} srslte_rnti_type_t;
/**
@ -321,6 +332,17 @@ SRSLTE_API srslte_mcs_table_t srslte_mcs_table_from_str(const char* str);
*/
SRSLTE_API uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb);
/**
* @brief Computes the time in seconds between two symbols in a slot
* @note l0 is expected to be smaller than l1
* @remark All symbol size reference and values are taken from TS 38.211 section 5.3 OFDM baseband signal generation
* @param l0 First symbol index within the slot
* @param l1 Second symbol index within the slot
* @param numerology NR Carrier numerology
* @return Returns the time in seconds between the two symbols if the condition above is satisfied, 0 seconds otherwise
*/
SRSLTE_API float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology);
#ifdef __cplusplus
}
#endif

View File

@ -20,6 +20,7 @@
typedef struct SRSLTE_API {
srslte_dci_location_t location;
srslte_search_space_type_t search_space;
uint32_t coreset_id;
uint8_t payload[50];
srslte_rnti_type_t rnti_type;
uint32_t nof_bits;
@ -28,11 +29,12 @@ typedef struct SRSLTE_API {
} srslte_dci_msg_nr_t;
typedef struct SRSLTE_API {
uint16_t rnti;
srslte_rnti_type_t rnti_type;
srslte_dci_format_nr_t format;
srslte_dci_location_t location;
srslte_search_space_t search_space;
uint16_t rnti;
srslte_rnti_type_t rnti_type;
srslte_dci_format_nr_t format;
srslte_dci_location_t location;
srslte_search_space_type_t search_space;
uint32_t coreset_id;
// Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment

View File

@ -114,7 +114,7 @@ typedef struct SRSLTE_API {
srslte_sch_mapping_type_t mapping;
/// Frequency domain resources
bool prb_idx[SRSLTE_MAX_PRB_NR];
bool prb_idx[SRSLTE_MAX_PRB_NR];
uint32_t nof_prb;
/// Number of DMRS groups without data
@ -144,21 +144,48 @@ typedef struct SRSLTE_API {
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config
*/
typedef struct SRSLTE_API {
srslte_dmrs_sch_typeA_pos_t typeA_pos;
bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
srslte_dmrs_sch_cfg_t dmrs_typeA;
srslte_dmrs_sch_cfg_t dmrs_typeB;
srslte_sch_grant_nr_t grant;
struct {
srslte_dmrs_sch_type_t type;
srslte_dmrs_sch_add_pos_t additional_pos;
srslte_dmrs_sch_len_t length;
bool scrambling_id0_present;
uint32_t scrambling_id0;
bool scrambling_id1_present;
uint32_t scrambling_id1;
} dmrs_typeA;
bool dmrs_typeA_present;
srslte_dmrs_sch_cfg_t dmrs_typeB;
bool dmrs_typeB_present;
srslte_pdsch_time_ra_t common_pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_common_pdsch_time_ra;
bool pdsch_time_is_default; ///< Set to true if pdsch_time_ra contains the configuration from pdsch-ConfigCommon or
///< pdsch-Config
srslte_pdsch_time_ra_t pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_pdsch_time_ra;
bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2)
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters
} srslte_pdsch_cfg_nr_t;
/**
* @brief Common NR-SCH (PDSCH and PUSCH for NR) configuration
*/
typedef struct SRSLTE_API {
bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
srslte_dmrs_sch_cfg_t dmrs;
srslte_sch_grant_nr_t grant;
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters
/// Uplink params
bool enable_transform_precoder;

View File

@ -36,13 +36,15 @@
* @param pdsch_cfg Flattened PDSCH configuration provided from higher layers
* @param rnti_type Type of the RNTI of the corresponding DCI
* @param ss_type Type of the SS for PDCCH
* @param coreset_id CORESET identifier associated with the PDCCH transmission
* @param m Time domain resource assignment field value m provided in DCI
* @param[out] Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* pdsch_cfg,
SRSLTE_API int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant);
@ -65,12 +67,12 @@ srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_type
*
* @remark Defined by TS 38.214 V15.10.0 5.1.6.1.3 CSI-RS for mobility
*
* @param pdsch_cfg PDSCH NR configuration by upper layers
* @param cfg PDSCH-DMRS NR configuration by upper layers
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_sch_cfg_nr_t* pdsch_cfg,
srslte_sch_grant_nr_t* grant);
SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_dmrs_sch_cfg_t* cfg,
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the PDSCH frequency resource allocation and stores it in the provided PDSCH NR grant.
@ -80,12 +82,11 @@ SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const
* @param cfg PDSCH NR configuration by upper layers
* @param dci_dl Unpacked DCI used to schedule the PDSCH grant
* @param[out] grant Provides grant pointer to fill
* @return
* @return SRSLTE_SUCCESS if the provided data is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant);
SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant);
#endif // SRSLTE_RA_DL_NR_H

View File

@ -95,9 +95,10 @@ SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
* @param pdsch_grant Generated PDSCH grant
* @return 0 on success, -1 on error
*/
SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* pdsch_grant);
SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* pdsch_grant);
#endif // SRSLTE_RA_NR_H

View File

@ -48,10 +48,10 @@ typedef struct SRSLTE_API {
srslte_search_space_t search_space[SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
bool search_space_present[SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
uint32_t ra_rnti; ///< Deduced from the PRACH configuration
uint32_t ra_search_space_id;
uint32_t ra_search_space_present;
} srslte_ue_dl_nr_pdcch_cfg_t;
uint16_t ra_rnti; ///< Needs to be deduced from the PRACH configuration
srslte_search_space_t ra_search_space;
bool ra_search_space_present;
} srslte_ue_dl_nr_cfg_t;
typedef struct SRSLTE_API {
uint32_t max_prb;
@ -59,8 +59,8 @@ typedef struct SRSLTE_API {
float pdcch_dmrs_corr_thr;
float pdcch_dmrs_epre_thr;
srslte_carrier_nr_t carrier;
srslte_ue_dl_nr_pdcch_cfg_t cfg;
srslte_carrier_nr_t carrier;
srslte_ue_dl_nr_cfg_t cfg;
srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
@ -79,7 +79,7 @@ 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_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_pdcch_cfg_t* cfg);
SRSLTE_API int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_cfg_t* cfg);
SRSLTE_API void srslte_ue_dl_nr_free(srslte_ue_dl_nr_t* q);

View File

@ -12,6 +12,7 @@
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/common/sequence.h"
#include <complex.h>
#include <srslte/phy/utils/debug.h>
#define SRSLTE_DMRS_SCH_TYPEA_SINGLE_DURATION_MIN 3
@ -163,13 +164,12 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q,
uint32_t delta,
cf_t* symbols)
{
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB;
uint32_t prb_count = 0; // Counts consecutive used PRB
uint32_t prb_start = 0; // Start consecutive used PRB
uint32_t prb_skip = 0; // Number of PRB to skip
uint32_t nof_pilots_x_prb = dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4;
uint32_t pilot_count = 0;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
uint32_t prb_count = 0; // Counts consecutive used PRB
uint32_t prb_start = 0; // Start consecutive used PRB
uint32_t prb_skip = 0; // Number of PRB to skip
uint32_t nof_pilots_x_prb = dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4;
uint32_t pilot_count = 0;
// Initialise sequence
srslte_sequence_state_t sequence_state = {};
@ -209,8 +209,7 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q,
}
if (prb_count > 0) {
pilot_count += srslte_dmrs_put_pilots(
q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, &symbols[prb_start * SRSLTE_NRE]);
pilot_count += srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols);
}
return pilot_count;
@ -350,7 +349,7 @@ static int srslte_dmrs_sch_get_symbols_idx_mapping_type_A_double(const srslte_dm
return count;
}
int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* cfg,
int srslte_dmrs_sch_get_symbols_idx(const srslte_dmrs_sch_cfg_t* dmrs_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS])
{
@ -363,9 +362,6 @@ int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* cfg,
ld = grant->S + grant->L;
}
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
switch (grant->mapping) {
case srslte_sch_mapping_type_A:
// The case dmrs-AdditionalPosition equals to 'pos3' is only supported when dmrs-TypeA-Position is equal to 'pos2'
@ -417,11 +413,8 @@ int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint32_t max_co
return count;
}
int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant)
int srslte_dmrs_sch_get_N_prb(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant)
{
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
if (grant->nof_dmrs_cdm_groups_without_data < 1 || grant->nof_dmrs_cdm_groups_without_data > 3) {
ERROR("Invalid number if DMRS CDM groups without data (%d). Valid values: 1, 2 , 3\n",
grant->nof_dmrs_cdm_groups_without_data);
@ -434,7 +427,7 @@ int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_g
// Get number of symbols used for DMRS
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int ret = srslte_dmrs_sch_get_symbols_idx(cfg, grant, symbols);
int ret = srslte_dmrs_sch_get_symbols_idx(dmrs_cfg, grant, symbols);
if (ret < SRSLTE_SUCCESS) {
ERROR("Error getting PDSCH DMRS symbol indexes\n");
return SRSLTE_ERROR;
@ -449,8 +442,7 @@ static uint32_t srslte_dmrs_sch_seed(const srslte_carrier_nr_t* carrier,
uint32_t slot_idx,
uint32_t symbol_idx)
{
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
slot_idx = slot_idx % SRSLTE_NSLOTS_PER_FRAME_NR(carrier->numerology);
@ -570,7 +562,7 @@ int srslte_dmrs_sch_put_sf(srslte_dmrs_sch_t* q,
// Get symbols indexes
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols);
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols);
if (nof_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -595,8 +587,7 @@ static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q,
const cf_t* symbols,
cf_t* least_square_estimates)
{
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
uint32_t prb_count = 0; // Counts consecutive used PRB
uint32_t prb_start = 0; // Start consecutive used PRB
@ -635,28 +626,16 @@ static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q,
}
// Get contiguous pilots
pilot_count += srslte_dmrs_get_lse(q,
&sequence_state,
dmrs_cfg->type,
prb_start,
prb_count,
delta,
&symbols[prb_start * SRSLTE_NRE],
&least_square_estimates[pilot_count]);
pilot_count += srslte_dmrs_get_lse(
q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]);
// Reset counter
prb_count = 0;
}
if (prb_count > 0) {
pilot_count += srslte_dmrs_get_lse(q,
&sequence_state,
dmrs_cfg->type,
prb_start,
prb_count,
delta,
&symbols[prb_start * SRSLTE_NRE],
&least_square_estimates[pilot_count]);
pilot_count += srslte_dmrs_get_lse(
q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]);
}
return pilot_count;
@ -675,15 +654,14 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
return SRSLTE_ERROR_INVALID_INPUTS;
}
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
cf_t* ce = q->temp;
uint32_t symbol_sz = q->carrier.nof_prb * SRSLTE_NRE; // Symbol size in resource elements
// Get symbols indexes
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols);
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols);
if (nof_symbols <= SRSLTE_SUCCESS) {
ERROR("Error getting symbol indexes\n");
return SRSLTE_ERROR;
@ -706,17 +684,19 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
}
}
float rsrp = 0.0f;
float epre = 0.0f;
// Perform Power measurements
float rsrp = 0.0f;
float epre = 0.0f;
cf_t corr[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
for (uint32_t i = 0; i < nof_symbols; i++) {
cf_t corr =
corr[i] =
srslte_vec_acc_cc(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol) / nof_pilots_x_symbol;
rsrp += __real__ corr * __real__ corr + __imag__ corr * __imag__ corr;
rsrp += __real__ corr[i] * __real__ corr[i] + __imag__ corr[i] * __imag__ corr[i];
epre += srslte_vec_avg_power_cf(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol);
}
rsrp /= nof_symbols;
epre /= nof_symbols;
rsrp = SRSLTE_MIN(rsrp, epre);
rsrp = SRSLTE_MIN(rsrp, epre - epre * 1e-7);
chest_res->rsrp = rsrp;
chest_res->rsrp_dbm = srslte_convert_power_to_dB(chest_res->rsrp);
@ -726,8 +706,17 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
chest_res->snr_db = chest_res->rsrp_dbm - chest_res->noise_estimate_dbm;
// Perform measurements here
// ...
// Measure CFO if more than one symbol is used
float cfo_avg = 0.0;
for (uint32_t i = 0; i < nof_symbols - 1; i++) {
float time_diff = srslte_symbol_distance_s(symbols[i], symbols[i + 1], q->carrier.numerology);
float phase_diff = cargf(corr[i + 1] * conjf(corr[i]));
if (isnormal(time_diff)) {
cfo_avg += phase_diff / (2.0f * M_PI * time_diff * (nof_symbols - 1));
}
}
chest_res->cfo = cfo_avg;
// Average over time, only if more than one DMRS symbol
for (uint32_t i = 1; i < nof_symbols; i++) {

View File

@ -143,7 +143,7 @@ int main(int argc, char** argv)
for (coreset.duration = 1; coreset.duration <= 3; coreset.duration++) {
for (search_space.type = srslte_search_space_type_common; search_space.type <= srslte_search_space_type_ue;
for (search_space.type = srslte_search_space_type_common_0; search_space.type <= srslte_search_space_type_ue;
search_space.type++) {
for (uint32_t i = 0; i < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; i++) {

View File

@ -168,24 +168,24 @@ static int assert_cfg(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_gra
continue;
}
if (pdsch_cfg->dmrs_typeA.typeA_pos != gold[i].typeA_pos) {
if (pdsch_cfg->dmrs.typeA_pos != gold[i].typeA_pos) {
continue;
}
if (pdsch_cfg->dmrs_typeA.additional_pos != gold[i].additional_pos) {
if (pdsch_cfg->dmrs.additional_pos != gold[i].additional_pos) {
continue;
}
if (pdsch_cfg->dmrs_typeA.length != gold[i].max_length) {
if (pdsch_cfg->dmrs.length != gold[i].max_length) {
continue;
}
if (pdsch_cfg->dmrs_typeA.type != gold[i].type) {
if (pdsch_cfg->dmrs.type != gold[i].type) {
continue;
}
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols);
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols);
TESTASSERT(nof_symbols == gold[i].nof_symbols);
@ -194,7 +194,7 @@ static int assert_cfg(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_gra
}
uint32_t sc[SRSLTE_NRE] = {};
srslte_dmrs_sch_get_sc_idx(&pdsch_cfg->dmrs_typeA, SRSLTE_NRE, sc);
srslte_dmrs_sch_get_sc_idx(&pdsch_cfg->dmrs, SRSLTE_NRE, sc);
for (uint32_t j = 0; j < gold[i].nof_sc; j++) {
TESTASSERT(sc[j] == gold[i].sc_idx[j]);
@ -274,33 +274,32 @@ int main(int argc, char** argv)
srslte_dmrs_sch_type_t type_begin = srslte_dmrs_sch_type_1;
srslte_dmrs_sch_type_t type_end = srslte_dmrs_sch_type_2;
for (pdsch_cfg.dmrs_typeA.type = type_begin; pdsch_cfg.dmrs_typeA.type <= type_end; pdsch_cfg.dmrs_typeA.type++) {
for (pdsch_cfg.dmrs.type = type_begin; pdsch_cfg.dmrs.type <= type_end; pdsch_cfg.dmrs.type++) {
srslte_dmrs_sch_typeA_pos_t typeA_pos_begin = srslte_dmrs_sch_typeA_pos_2;
srslte_dmrs_sch_typeA_pos_t typeA_pos_end = srslte_dmrs_sch_typeA_pos_3;
for (pdsch_cfg.dmrs_typeA.typeA_pos = typeA_pos_begin; pdsch_cfg.dmrs_typeA.typeA_pos <= typeA_pos_end;
pdsch_cfg.dmrs_typeA.typeA_pos++) {
for (pdsch_cfg.dmrs.typeA_pos = typeA_pos_begin; pdsch_cfg.dmrs.typeA_pos <= typeA_pos_end;
pdsch_cfg.dmrs.typeA_pos++) {
srslte_dmrs_sch_add_pos_t add_pos_begin = srslte_dmrs_sch_add_pos_2;
srslte_dmrs_sch_add_pos_t add_pos_end = srslte_dmrs_sch_add_pos_3;
if (pdsch_cfg.dmrs_typeA.typeA_pos == srslte_dmrs_sch_typeA_pos_3) {
if (pdsch_cfg.dmrs.typeA_pos == srslte_dmrs_sch_typeA_pos_3) {
add_pos_end = srslte_dmrs_sch_add_pos_1;
}
for (pdsch_cfg.dmrs_typeA.additional_pos = add_pos_begin; pdsch_cfg.dmrs_typeA.additional_pos <= add_pos_end;
pdsch_cfg.dmrs_typeA.additional_pos++) {
for (pdsch_cfg.dmrs.additional_pos = add_pos_begin; pdsch_cfg.dmrs.additional_pos <= add_pos_end;
pdsch_cfg.dmrs.additional_pos++) {
srslte_dmrs_sch_len_t max_len_begin = srslte_dmrs_sch_len_1;
srslte_dmrs_sch_len_t max_len_end = srslte_dmrs_sch_len_2;
// Only single DMRS symbols can have additional positions 2 and 3
if (pdsch_cfg.dmrs_typeA.additional_pos == srslte_dmrs_sch_add_pos_2 ||
pdsch_cfg.dmrs_typeA.additional_pos == srslte_dmrs_sch_add_pos_3) {
if (pdsch_cfg.dmrs.additional_pos == srslte_dmrs_sch_add_pos_2 ||
pdsch_cfg.dmrs.additional_pos == srslte_dmrs_sch_add_pos_3) {
max_len_end = srslte_dmrs_sch_len_1;
}
for (pdsch_cfg.dmrs_typeA.length = max_len_begin; pdsch_cfg.dmrs_typeA.length <= max_len_end;
pdsch_cfg.dmrs_typeA.length++) {
for (pdsch_cfg.dmrs.length = max_len_begin; pdsch_cfg.dmrs.length <= max_len_end; pdsch_cfg.dmrs.length++) {
for (uint32_t bw = 1; bw <= carrier.nof_prb; bw++) {
@ -312,21 +311,15 @@ int main(int argc, char** argv)
grant.nof_dmrs_cdm_groups_without_data++) {
// Load default type A grant
srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &grant);
// Copy configuration
pdsch_cfg.dmrs_typeB = pdsch_cfg.dmrs_typeA;
srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &grant);
int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res);
if (n == SRSLTE_SUCCESS) {
test_passed++;
} else {
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant.mapping == srslte_sch_mapping_type_A ? &pdsch_cfg.dmrs_typeA : &pdsch_cfg.dmrs_typeB;
char str[64] = {};
srslte_dmrs_sch_cfg_to_str(dmrs_cfg, str, 64);
srslte_dmrs_sch_cfg_to_str(&pdsch_cfg.dmrs, str, 64);
ERROR("Test %d failed. %s.\n", test_counter, str);
}

View File

@ -96,3 +96,29 @@ uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb)
return 0;
}
float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology)
{
// l0 must be smaller than l1
if (l0 >= l1) {
return 0.0f;
}
// Count number of symbols in between
uint32_t count = l1 - l0;
// Compute at what symbol there is a longer CP
uint32_t cp_boundary = 7U << numerology;
// Select whether extra CP shall be added
uint32_t extra_cp = 0;
if (l0 < cp_boundary && l1 >= cp_boundary) {
extra_cp = 16;
}
// Compute reference FFT size
uint32_t N = (2048 + 144) * count + extra_cp;
// Return symbol distance in microseconds
return (N << numerology) * SRSLTE_LTE_TS;
}

View File

@ -57,7 +57,7 @@ int srslte_enb_dl_nr_init(srslte_enb_dl_nr_t* q, cf_t* output[SRSLTE_MAX_PORTS],
srslte_ofdm_cfg_t fft_cfg = {};
fft_cfg.nof_prb = args->nof_max_prb;
fft_cfg.symbol_sz = srslte_symbol_sz(args->nof_max_prb);
fft_cfg.symbol_sz = srslte_min_symbol_sz_rb(args->nof_max_prb);
fft_cfg.keep_dc = true;
for (uint32_t i = 0; i < q->nof_tx_antennas; i++) {
@ -118,8 +118,13 @@ int srslte_enb_dl_nr_set_carrier(srslte_enb_dl_nr_t* q, const srslte_carrier_nr_
}
if (carrier->nof_prb != q->carrier.nof_prb) {
srslte_ofdm_cfg_t fft_cfg = {};
fft_cfg.nof_prb = carrier->nof_prb;
fft_cfg.symbol_sz = srslte_min_symbol_sz_rb(carrier->nof_prb);
for (uint32_t i = 0; i < q->nof_tx_antennas; i++) {
srslte_ofdm_tx_set_prb(&q->fft[i], SRSLTE_CP_NORM, carrier->nof_prb);
fft_cfg.in_buffer = q->sf_symbols[i];
srslte_ofdm_tx_init_cfg(&q->fft[i], &fft_cfg);
}
}

View File

@ -42,7 +42,8 @@ int srslte_dci_nr_pack(const srslte_carrier_nr_t* carrier,
{
// Copy DCI MSG fields
msg->location = dci->location;
msg->search_space = dci->search_space.type;
msg->search_space = dci->search_space;
msg->coreset_id = dci->coreset_id;
msg->rnti_type = dci->rnti_type;
msg->rnti = dci->rnti;
msg->format = dci->format;
@ -180,11 +181,12 @@ int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrier,
srslte_rnti_type_t rnti_type = msg->rnti_type;
// Copy DCI MSG fields
dci->location = msg->location;
dci->search_space.type = msg->search_space;
dci->rnti_type = msg->rnti_type;
dci->rnti = msg->rnti;
dci->format = msg->format;
dci->location = msg->location;
dci->search_space = msg->search_space;
dci->coreset_id = msg->coreset_id;
dci->rnti_type = msg->rnti_type;
dci->rnti = msg->rnti;
dci->format = msg->format;
if (msg->nof_bits != srslte_dci_nr_format_1_0_sizeof(carrier, coreset, rnti_type)) {
ERROR("Invalid number of bits %d, expected %d\n",

View File

@ -282,8 +282,7 @@ static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q,
{
uint32_t count = 0;
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
switch (dmrs_cfg->type) {
case srslte_dmrs_sch_type_1:
@ -355,7 +354,7 @@ static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q,
uint32_t dmrs_l_count = 0;
// Get symbol indexes carrying DMRS
int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(cfg, grant, dmrs_l_idx);
int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx);
if (nof_dmrs_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -678,12 +677,23 @@ static uint32_t srslte_pdsch_nr_grant_info(const srslte_sch_cfg_nr_t* cfg,
uint32_t len = 0;
len = srslte_print_check(str, str_len, len, "rnti=0x%x", grant->rnti);
char freq_str[SRSLTE_MAX_PRB_NR + 1] = {};
for (uint32_t i = 0, nof_prb = 0; i < SRSLTE_MAX_PRB_NR && nof_prb < grant->nof_prb; i++) {
if (grant->prb_idx[i]) {
freq_str[i] = '1';
nof_prb++;
} else {
freq_str[i] = '0';
}
}
// Append time-domain resource mapping
len = srslte_print_check(str,
str_len,
len,
",k0=%d,S=%d,L=%d,mapping=%s",
",k0=%d,freq=%s,symb=%d:%d,mapping=%s",
grant->k0,
freq_str,
grant->S,
grant->L,
srslte_sch_mapping_type_to_str(grant->mapping));
@ -748,7 +758,7 @@ uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q,
}
if (q->meas_time_en) {
len = srslte_print_check(str, str_len, len, ", t=%d us\n", q->meas_time_us);
len = srslte_print_check(str, str_len, len, ", t=%d us", q->meas_time_us);
}
return len;

View File

@ -281,8 +281,7 @@ static uint32_t srslte_pusch_nr_cp_dmrs(const srslte_pusch_nr_t* q,
{
uint32_t count = 0;
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
switch (dmrs_cfg->type) {
case srslte_dmrs_sch_type_1:
@ -354,7 +353,7 @@ static int srslte_pusch_nr_cp(const srslte_pusch_nr_t* q,
uint32_t dmrs_l_count = 0;
// Get symbol indexes carrying DMRS
int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(cfg, grant, dmrs_l_idx);
int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx);
if (nof_dmrs_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}

View File

@ -12,16 +12,16 @@
#include "srslte/phy/phch/ra_dl_nr.h"
#include "srslte/phy/utils/debug.h"
static void sliv_to_s_and_l(uint32_t sliv, uint32_t* S, uint32_t* L)
static void compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L)
{
// S values can be 0 to 3
uint32_t low = sliv % 14;
if (low < 7) {
uint32_t low = v % N;
uint32_t high = v / N;
if (high + 1 + low <= N) {
*S = low;
*L = sliv / 14 + 1;
*L = high + 1;
} else {
*S = 14 - 1 - low;
*L = 14 - sliv / 14 + 1;
*S = N - 1 - low;
*L = N - high + 1;
}
}
@ -128,14 +128,16 @@ int srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_
void srslte_ra_dl_nr_time_hl(const srslte_pdsch_time_ra_t* hl_ra_cfg, srslte_sch_grant_nr_t* grant)
{
// Compute S and L from SLIV from higher layers
sliv_to_s_and_l(hl_ra_cfg->sliv, &grant->S, &grant->L);
compute_s_and_l(SRSLTE_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L);
grant->k0 = hl_ra_cfg->k0;
grant->mapping = hl_ra_cfg->mapping_type;
}
int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* cfg,
int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant)
{
@ -149,40 +151,72 @@ int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* cfg,
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Determine which PDSCH Time domain RA configuration to apply (Table 5.1.2.1.1-1)
if (cfg->pdsch_time_is_default) {
// Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1
srslte_ra_dl_nr_time_default_A(m, cfg->dmrs_typeA.typeA_pos, grant);
// Determine which PDSCH Time domain RA configuration to apply (TS 38.214 Table 5.1.2.1.1-1)
if (rnti_type == srslte_rnti_type_si && ss_type == srslte_search_space_type_common_0) {
// Row 1
ERROR("Row not implemented");
} else if (rnti_type == srslte_rnti_type_si && ss_type == srslte_search_space_type_common_0A) {
// Row 2
ERROR("Row not implemented");
} else if ((rnti_type == srslte_rnti_type_ra || rnti_type == srslte_rnti_type_tc) &&
ss_type == srslte_search_space_type_common_1) {
// Row 3
if (cfg->nof_common_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant);
} else {
// Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else if (rnti_type == srslte_rnti_type_p && ss_type == srslte_search_space_type_common_2) {
// Row 4
ERROR("Row not implemented");
} else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c ||
rnti_type == srslte_rnti_type_cs) &&
SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) {
// Row 5
if (cfg->nof_common_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant);
} else {
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c ||
rnti_type == srslte_rnti_type_cs) &&
((SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id != 0) || ss_type == srslte_search_space_type_ue)) {
// Row 6
if (cfg->nof_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->pdsch_time_ra[m], grant);
} else if (cfg->nof_common_pdsch_time_ra > 0) {
srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant);
} else {
srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else {
srslte_ra_dl_nr_time_hl(&cfg->pdsch_time_ra[m], grant);
ERROR("Unhandled case");
}
// Validate S and L parameters
if (!srslte_ra_dl_nr_time_validate(grant)) {
ERROR("Invalid Time RA\n");
ERROR("Invalid Time RA S=%d; L=%d; m=%d\n", grant->S, grant->L, m);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_sch_cfg_nr_t* pdsch_cfg,
srslte_sch_grant_nr_t* grant)
int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_dmrs_sch_cfg_t* cfg,
srslte_sch_grant_nr_t* grant)
{
if (pdsch_cfg == NULL || grant == NULL) {
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB;
/* According to TS 38.214 V15.10.0 5.1.6.1.3 CSI-RS for mobility:
* When receiving PDSCH scheduled by DCI format 1_0, the UE shall assume the number of DM-RS CDM groups without data
* is 1 which corresponds to CDM group 0 for the case of PDSCH with allocation duration of 2 symbols, and the UE shall
* assume that the number of DM-RS CDM groups without data is 2 which corresponds to CDM group {0,1} for all other
* cases.
* is 1 which corresponds to CDM group 0 for the case of PDSCH with allocation duration of 2 symbols, and the UE
* shall assume that the number of DM-RS CDM groups without data is 2 which corresponds to CDM group {0,1} for all
* other cases.
*/
if (dmrs_cfg->length == srslte_dmrs_sch_len_2) {
if (cfg->length == srslte_dmrs_sch_len_2) {
grant->nof_dmrs_cdm_groups_without_data = 1;
} else {
grant->nof_dmrs_cdm_groups_without_data = 2;
@ -205,10 +239,10 @@ uint32_t srslte_ra_dl_nr_type0_P(uint32_t bwp_size, bool config_is_1)
}
}
static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
{
uint32_t P = srslte_ra_dl_nr_type0_P(carrier->nof_prb, cfg->rbg_size_cfg_1);
@ -234,10 +268,42 @@ static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
return 0;
}
int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
static int
ra_freq_type1(const srslte_carrier_nr_t* carrier, const srslte_dci_dl_nr_t* dci_dl, srslte_sch_grant_nr_t* grant)
{
uint32_t riv = dci_dl->freq_domain_assigment;
uint32_t N_bwp_size = carrier->nof_prb;
uint32_t start = 0;
uint32_t len = 0;
compute_s_and_l(N_bwp_size, riv, &start, &len);
if (start + len > N_bwp_size) {
ERROR("RIV 0x%x for BWP size %d resulted in freq=%d:%d\n", riv, N_bwp_size, start, len);
return SRSLTE_ERROR;
}
for (uint32_t i = 0; i < start; i++) {
grant->prb_idx[i] = false;
}
for (uint32_t i = start; i < start + len; i++) {
grant->prb_idx[i] = true;
}
for (uint32_t i = start + len; i < SRSLTE_MAX_PRB_NR; i++) {
grant->prb_idx[i] = false;
}
grant->nof_prb = len;
return SRSLTE_SUCCESS;
}
int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL || dci_dl == NULL) {
@ -246,11 +312,11 @@ int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
// RA scheme
if (dci_dl->format == srslte_dci_format_nr_1_0) {
ra_freq_type0(carrier, cfg, dci_dl, grant);
} else {
ERROR("Only DCI Format 1_0 is supported\n");
return SRSLTE_ERROR;
// when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used.
return ra_freq_type1(carrier, dci_dl, grant);
}
return SRSLTE_SUCCESS;
ra_freq_type0(carrier, cfg, dci_dl, grant);
ERROR("Only DCI Format 1_0 is supported\n");
return SRSLTE_ERROR;
}

View File

@ -139,7 +139,7 @@ static ra_nr_table_t ra_nr_select_table_pusch_noprecoding(srslte_mcs_table_t
// - the UE is configured with MCS-C-RNTI, and
// - the PUSCH is scheduled by a PDCCH with
// - CRC scrambled by MCS-C-RNTI,
if (mcs_c_rnti && dci_format != srslte_dci_format_nr_rar && rnti_type == srslte_rnti_type_mcs_crnti) {
if (mcs_c_rnti && dci_format != srslte_dci_format_nr_rar && rnti_type == srslte_rnti_type_mcs_c) {
return ra_nr_table_3;
}
@ -275,7 +275,7 @@ int srslte_ra_dl_nr_slot_nof_re(const srslte_sch_cfg_nr_t* pdsch_cfg, const srsl
int n_sh_symb = grant->L;
// the number of REs for DM-RS per PRB in the scheduled duration
int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(pdsch_cfg, grant);
int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(&pdsch_cfg->dmrs, grant);
if (n_prb_dmrs < SRSLTE_SUCCESS) {
ERROR("Invalid number of DMRS RE\n");
return SRSLTE_ERROR;
@ -455,40 +455,79 @@ int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
return SRSLTE_SUCCESS;
}
int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* pdsch_grant)
static int ra_dl_dmrs(const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg,
srslte_sch_grant_nr_t* pdsch_grant,
srslte_dmrs_sch_cfg_t* dmrs_cfg)
{
// Time domain resource allocation
if (srslte_ra_dl_nr_time(
pdsch_cfg, dci_dl->rnti_type, dci_dl->search_space.type, dci_dl->time_domain_assigment, pdsch_grant) <
SRSLTE_SUCCESS) {
const bool dedicated_dmrs_present = (pdsch_grant->mapping == srslte_sch_mapping_type_A)
? pdsch_hl_cfg->dmrs_typeA_present
: pdsch_hl_cfg->dmrs_typeB_present;
if (pdsch_grant->dci_format == srslte_dci_format_nr_1_0 || !dedicated_dmrs_present) {
if (pdsch_grant->mapping == srslte_sch_mapping_type_A) {
// Absent default values are defined is TS 38.331 - DMRS-DownlinkConfig
dmrs_cfg->additional_pos = srslte_dmrs_sch_add_pos_2;
dmrs_cfg->type = srslte_dmrs_sch_type_1;
dmrs_cfg->length = srslte_dmrs_sch_len_1;
dmrs_cfg->scrambling_id0_present = false;
dmrs_cfg->scrambling_id1_present = false;
if (pdsch_grant->dci_format == srslte_dci_format_nr_1_0) {
if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(dmrs_cfg, pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups\n");
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
}
ERROR("Unsupported configuration\n");
return SRSLTE_ERROR;
}
return SRSLTE_ERROR;
}
int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* pdsch_cfg,
srslte_sch_grant_nr_t* pdsch_grant)
{
// 5.2.1.1 Resource allocation in time domain
if (srslte_ra_dl_nr_time(pdsch_hl_cfg,
dci_dl->rnti_type,
dci_dl->search_space,
dci_dl->coreset_id,
dci_dl->time_domain_assigment,
pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error computing time domain resource allocation\n");
return SRSLTE_ERROR;
}
// Frequency domain resource allocation
if (srslte_ra_dl_nr_freq(carrier, pdsch_cfg, dci_dl, pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error computing time domain resource allocation\n");
// 5.1.2.2 Resource allocation in frequency domain
if (srslte_ra_dl_nr_freq(carrier, pdsch_hl_cfg, dci_dl, pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error computing frequency domain resource allocation\n");
return SRSLTE_ERROR;
}
//???
if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(pdsch_cfg, pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups\n");
return SRSLTE_ERROR;
}
// 5.1.2.3 Physical resource block (PRB) bundling
// ...
pdsch_grant->nof_layers = 1;
pdsch_grant->dci_format = dci_dl->format;
pdsch_grant->rnti = dci_dl->rnti;
pdsch_grant->rnti_type = dci_dl->rnti_type;
for (uint32_t i = 0; i < carrier->nof_prb; i++) {
pdsch_grant->prb_idx[i] = true;
// 5.1.6.2 DM-RS reception procedure
if (ra_dl_dmrs(pdsch_hl_cfg, pdsch_grant, &pdsch_cfg->dmrs) < SRSLTE_SUCCESS) {
ERROR("Error selecting DMRS configuration");
return SRSLTE_ERROR;
}
// Compute TB size
// 5.1.3 Modulation order, target code rate, redundancy version and transport block size determination
if (srslte_ra_nr_fill_tb(pdsch_cfg, pdsch_grant, dci_dl->mcs, &pdsch_grant->tb[0]) < SRSLTE_SUCCESS) {
ERROR("Error filing tb\n");
return SRSLTE_ERROR;

View File

@ -153,13 +153,13 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}
// Load number of DMRS CDM groups without data
if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg, &pdsch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg.dmrs, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups without data\n");
goto clean_exit;
}

View File

@ -132,7 +132,7 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}

View File

@ -137,4 +137,4 @@ float srslte_cfo_est_corr_cp(cf_t* input_buffer, uint32_t nof_prb)
float cfo = (float)(-1 * carg(cfo_estimated) / (float)(2 * M_PI * tFFT));
srslte_vec_apply_cfo(input_buffer, (float)(1 / (nFFT * 15e3)) * ((-15e3 / 2.0) - cfo), input_buffer, sf_n_samples);
return cfo;
}
}

View File

@ -163,7 +163,7 @@ int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t*
return SRSLTE_SUCCESS;
}
int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_pdcch_cfg_t* cfg)
int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_cfg_t* cfg)
{
if (q == NULL || cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
@ -259,22 +259,19 @@ static int ue_dl_nr_find_dci_ncce(srslte_ue_dl_nr_t* q,
return SRSLTE_SUCCESS;
}
static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
uint32_t search_space_id,
uint16_t rnti,
srslte_rnti_type_t rnti_type,
srslte_dci_dl_nr_t* dci_dl_list,
uint32_t nof_dci_msg)
static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_search_space_t* search_space,
uint16_t rnti,
srslte_rnti_type_t rnti_type,
srslte_dci_dl_nr_t* dci_dl_list,
uint32_t nof_dci_msg)
{
// Check inputs
if (q == NULL || slot_cfg == NULL || dci_dl_list == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Select Search space
srslte_search_space_t* search_space = &q->cfg.search_space[search_space_id];
// Select CORESET
uint32_t coreset_id = search_space->coreset_id;
if (coreset_id >= SRSLTE_UE_DL_NR_MAX_NOF_CORESET || !q->cfg.coreset_present[coreset_id]) {
@ -317,6 +314,7 @@ static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q,
dci_msg.location.L = L;
dci_msg.location.ncce = candidates[ncce_idx];
dci_msg.search_space = search_space->type;
dci_msg.coreset_id = search_space->coreset_id;
dci_msg.rnti_type = rnti_type;
dci_msg.rnti = rnti;
dci_msg.format = dci_format;
@ -357,16 +355,9 @@ int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q,
// If the UE looks for a RAR and RA search space is provided, search for it
if (q->cfg.ra_search_space_present && rnti == q->cfg.ra_rnti) {
// Check if the RA search space is valid
uint32_t ra_ss_id = q->cfg.ra_search_space_id;
if (ra_ss_id >= SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE || !q->cfg.search_space_present[ra_ss_id]) {
ERROR("Invalid RA Search Space ID (%d)", ra_ss_id);
return SRSLTE_ERROR;
}
// Find DCIs in the RA search space
return ue_dl_nr_find_dl_dci_ss(
q, slot_cfg, ra_ss_id, rnti, srslte_rnti_type_ra, &dci_dl_list[count], nof_dci_msg - count);
q, slot_cfg, &q->cfg.ra_search_space, rnti, srslte_rnti_type_ra, &dci_dl_list[count], nof_dci_msg - count);
}
// Iterate all possible search spaces
@ -377,8 +368,8 @@ int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q,
}
// Find DCIs in the selected search space
int ret =
ue_dl_nr_find_dl_dci_ss(q, slot_cfg, i, rnti, srslte_rnti_type_c, &dci_dl_list[count], nof_dci_msg - count);
int ret = ue_dl_nr_find_dl_dci_ss(
q, slot_cfg, &q->cfg.search_space[i], rnti, srslte_rnti_type_c, &dci_dl_list[count], nof_dci_msg - count);
if (ret < SRSLTE_SUCCESS) {
ERROR("Error searching DCI");
return SRSLTE_ERROR;
@ -422,11 +413,11 @@ int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
{
int len = 0;
// Append channel estimator info
// ...
// Append PDSCH info
len += srslte_pdsch_nr_rx_info(&q->pdsch, cfg, &cfg->grant, res, &str[len], str_len - len);
// Append channel estimator info
len = srslte_print_check(str, str_len, len, ",SNR=%+.1f", q->chest.snr_db);
return len;
}

View File

@ -99,7 +99,7 @@ static int work_gnb_dl(srslte_enb_dl_nr_t* enb_dl,
dci_dl->format = srslte_dci_format_nr_1_0;
dci_dl->rnti_type = srslte_rnti_type_c;
dci_dl->location = *dci_location;
dci_dl->search_space = *search_space;
dci_dl->search_space = search_space->type;
dci_dl->rnti = rnti;
// Put actual DCI
@ -189,7 +189,7 @@ int main(int argc, char** argv)
goto clean_exit;
}
srslte_ue_dl_nr_pdcch_cfg_t pdcch_cfg = {};
srslte_ue_dl_nr_cfg_t pdcch_cfg = {};
// Configure CORESET
srslte_coreset_t* coreset = &pdcch_cfg.coreset[0];
@ -264,7 +264,7 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}

View File

@ -38,7 +38,7 @@ typedef struct {
} phy_nr_args_t;
typedef struct {
srslte_sch_cfg_nr_t pdsch;
srslte_pdsch_cfg_nr_t pdsch;
} phy_nr_cfg_t;
class phy_nr_state

View File

@ -24,8 +24,8 @@
namespace srsenb {
namespace nr {
cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& logger, phy_nr_state* phy_state_) :
cc_idx(cc_idx_), phy_state(phy_state_), logger(logger)
cc_worker::cc_worker(uint32_t cc_idx_, srslte::log* log, phy_nr_state* phy_state_) :
cc_idx(cc_idx_), phy_state(phy_state_), log_h(log)
{
cf_t* buffer_c[SRSLTE_MAX_PORTS] = {};
@ -118,8 +118,8 @@ int cc_worker::encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants,
return SRSLTE_ERROR;
}
if (logger.info.enabled()) {
logger.info("PDCCH: cc=%d, ...", cc_idx);
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
log_h->info("PDCCH: cc=%d, ...", cc_idx);
}
}
@ -132,10 +132,11 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui
// Get PHY config for UE
// ...
srslte_sch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch;
srslte_pdsch_cfg_nr_t pdsch_hl_cfg = {};
srslte_sch_cfg_nr_t pdsch_cfg = {};
// Compute DL grant
if (srslte_ra_dl_dci_to_grant_nr(&enb_dl.carrier, &pdsch_cfg, &grants[i].dci, &pdsch_cfg.grant)) {
if (srslte_ra_dl_dci_to_grant_nr(&enb_dl.carrier, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant)) {
ERROR("Computing DL grant");
}
@ -150,10 +151,10 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui
}
// Logging
if (logger.info.enabled()) {
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
char str[512];
srslte_enb_dl_nr_pdsch_info(&enb_dl, &pdsch_cfg, str, sizeof(str));
logger.info("PDSCH: cc=%d, %s", cc_idx, str);
log_h->info("PDSCH: cc=%d, %s", cc_idx, str);
}
}

View File

@ -98,8 +98,7 @@ void sf_worker::work_imp()
}
// Configure user
phy_state->cfg.pdsch.rbg_size_cfg_1 = false;
phy_state->cfg.pdsch.pdsch_time_is_default = true;
phy_state->cfg.pdsch.rbg_size_cfg_1 = false;
// Fill grant (this comes from the scheduler)
srslte_dl_slot_cfg_t dl_cfg = {};
@ -117,10 +116,8 @@ void sf_worker::work_imp()
grants.pdsch[0].dci.time_domain_assigment = 0;
grants.pdsch[0].dci.mcs = 27;
grants.pdsch[0].dci.search_space.type = srslte_search_space_type_ue;
for (uint32_t L = 0; L < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
grants.pdsch[0].dci.search_space.nof_candidates[L] = 1;
}
grants.pdsch[0].dci.search_space = srslte_search_space_type_ue;
grants.pdsch[0].dci.coreset_id = 1;
grants.pdsch[0].dci.location.L = 0;
grants.pdsch[0].dci.location.ncce = 0;

View File

@ -37,17 +37,18 @@ typedef struct {
} phy_nr_args_t;
typedef struct {
srslte_sch_cfg_nr_t pdsch;
srslte_prach_cfg_t prach;
srslte_ue_dl_nr_pdcch_cfg_t pdcch;
srslte_pdsch_cfg_nr_t pdsch;
srslte_prach_cfg_t prach;
srslte_ue_dl_nr_cfg_t pdcch;
} phy_nr_cfg_t;
class phy_nr_state
{
public:
srslte_carrier_nr_t carrier = {};
phy_nr_args_t args = {};
phy_nr_cfg_t cfg = {};
srslte_carrier_nr_t carrier = {};
phy_nr_args_t args = {};
phy_nr_cfg_t cfg = {};
int32_t test_rnti = 0x1234; // Fix PDSCH RNTI for testing
phy_nr_state()
{
@ -106,20 +107,40 @@ public:
// searchSpaceType: common (0)
// common
// dci-Format0-0-AndFormat1-0
cfg.pdcch.search_space[1].id = 1;
cfg.pdcch.search_space[1].coreset_id = 1;
cfg.pdcch.search_space[1].nof_candidates[0] = 0;
cfg.pdcch.search_space[1].nof_candidates[1] = 0;
cfg.pdcch.search_space[1].nof_candidates[2] = 1;
cfg.pdcch.search_space[1].nof_candidates[3] = 0;
cfg.pdcch.search_space[1].nof_candidates[4] = 0;
cfg.pdcch.search_space[1].type = srslte_search_space_type_common;
cfg.pdcch.search_space_present[1] = true;
srslte_search_space_t search_space1 = {};
search_space1.id = 1;
search_space1.coreset_id = 1;
search_space1.nof_candidates[0] = 0;
search_space1.nof_candidates[1] = 0;
search_space1.nof_candidates[2] = 1;
search_space1.nof_candidates[3] = 0;
search_space1.nof_candidates[4] = 0;
search_space1.type = srslte_search_space_type_common_3;
cfg.pdcch.search_space[1] = search_space1;
cfg.pdcch.search_space_present[1] = true;
// ra-SearchSpace: 1
cfg.pdcch.ra_rnti = 0x16; //< Supposed to be deduced from PRACH configuration
cfg.pdcch.ra_search_space_id = 1;
cfg.pdcch.ra_search_space = search_space1;
cfg.pdcch.ra_search_space.type = srslte_search_space_type_common_1;
cfg.pdcch.ra_search_space_present = true;
// pdsch-ConfigCommon: setup (1)
// setup
// pdsch-TimeDomainAllocationList: 2 items
// Item 0
// PDSCH-TimeDomainResourceAllocation
// mappingType: typeA (0)
// startSymbolAndLength: 40
// Item 1
// PDSCH-TimeDomainResourceAllocation
// mappingType: typeA (0)
// startSymbolAndLength: 57
cfg.pdsch.common_pdsch_time_ra[0].mapping_type = srslte_sch_mapping_type_A;
cfg.pdsch.common_pdsch_time_ra[0].sliv = 40;
cfg.pdsch.common_pdsch_time_ra[1].mapping_type = srslte_sch_mapping_type_A;
cfg.pdsch.common_pdsch_time_ra[1].sliv = 57;
cfg.pdsch.nof_common_pdsch_time_ra = 2;
}
};
@ -152,9 +173,6 @@ private:
// Temporal attributes
srslte_softbuffer_rx_t softbuffer_rx = {};
std::vector<uint8_t> data;
// Current rnti
uint16_t rnti = 0;
};
} // namespace nr

View File

@ -79,8 +79,7 @@ bool cc_worker::set_carrier(const srslte_carrier_nr_t* carrier)
}
// Set default PDSCH config
phy_state->cfg.pdsch.rbg_size_cfg_1 = false;
phy_state->cfg.pdsch.pdsch_time_is_default = true;
phy_state->cfg.pdsch.rbg_size_cfg_1 = false;
return true;
}
@ -106,64 +105,86 @@ uint32_t cc_worker::get_buffer_len()
bool cc_worker::work_dl()
{
srslte_dci_dl_nr_t dci_dl = {};
srslte_sch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch;
std::array<srslte_pdsch_res_nr_t, SRSLTE_MAX_CODEWORDS> pdsch_res = {};
srslte_pdsch_cfg_nr_t pdsch_hl_cfg = phy_state->cfg.pdsch;
// Run FFT
srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg);
// Set rnti
rnti = phy_state->cfg.pdcch.ra_rnti;
// Initialise grants
std::array<srslte_dci_dl_nr_t, 5> dci_dl_rx = {};
uint32_t nof_found_dci = 0;
// if (dl_slot_cfg.idx % 10 ==1) {
// printf("a=");srslte_vec_fprint_c(stdout, rx_buffer[0], 512);
// }
srslte_dci_dl_nr_t dci_dl_rx = {};
int nof_found_dci = srslte_ue_dl_nr_find_dl_dci(&ue_dl, &dl_slot_cfg, rnti, &dci_dl_rx, 1);
if (nof_found_dci < SRSLTE_SUCCESS) {
ERROR("Error decoding");
return SRSLTE_ERROR;
// Search for RA DCI
if (phy_state->cfg.pdcch.ra_search_space_present) {
int n_ra = srslte_ue_dl_nr_find_dl_dci(&ue_dl,
&dl_slot_cfg,
phy_state->cfg.pdcch.ra_rnti,
&dci_dl_rx[nof_found_dci],
(uint32_t)dci_dl_rx.size() - nof_found_dci);
if (n_ra < SRSLTE_SUCCESS) {
ERROR("Error decoding");
return false;
}
nof_found_dci += n_ra;
}
if (nof_found_dci < 1) {
// ERROR("Error DCI not found");
return true;
// Search for test RNTI
if (phy_state->test_rnti > 0) {
int n_test = srslte_ue_dl_nr_find_dl_dci(&ue_dl,
&dl_slot_cfg,
(uint16_t)phy_state->test_rnti,
&dci_dl_rx[nof_found_dci],
(uint32_t)dci_dl_rx.size() - nof_found_dci);
if (n_test < SRSLTE_SUCCESS) {
ERROR("Error decoding");
return false;
}
nof_found_dci += n_test;
}
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
char str[512];
srslte_dci_nr_to_str(&dci_dl_rx, str, sizeof(str));
log_h->info("PDCCH: cc=%d, %s", cc_idx, str);
}
// Notify MAC about PDCCH found grants
// ...
dci_dl.rnti = 0x1234;
dci_dl.format = srslte_dci_format_nr_1_0;
// Iterate over all received grants
for (uint32_t i = 0; i < nof_found_dci; i++) {
// Select Received DCI
const srslte_dci_dl_nr_t* dci_dl = &dci_dl_rx[i];
dci_dl.freq_domain_assigment = 0x1FFF;
dci_dl.time_domain_assigment = 0;
dci_dl.mcs = 27;
// Log found DCI
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
std::array<char, 512> str;
srslte_dci_nr_to_str(dci_dl, str.data(), str.size());
log_h->info("PDCCH: cc=%d, %s", cc_idx, str.data());
}
// Compute DL grant
if (srslte_ra_dl_dci_to_grant_nr(&ue_dl.carrier, &pdsch_cfg, &dci_dl, &pdsch_cfg.grant)) {
ERROR("Computing DL grant");
}
// Compute DL grant
srslte_sch_cfg_nr_t pdsch_cfg = {};
if (srslte_ra_dl_dci_to_grant_nr(&ue_dl.carrier, &pdsch_hl_cfg, dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) {
ERROR("Computing DL grant");
return false;
}
pdsch_res[0].payload = data.data();
pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(pdsch_cfg.grant.tb[0].softbuffer.rx);
// Initialise PDSCH Result
std::array<srslte_pdsch_res_nr_t, SRSLTE_MAX_CODEWORDS> pdsch_res = {};
pdsch_res[0].payload = data.data();
pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(pdsch_cfg.grant.tb[0].softbuffer.rx);
if (srslte_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, pdsch_res.data()) < SRSLTE_SUCCESS) {
ERROR("Error decoding PDSCH");
return false;
}
// Decode actual PDSCH transmission
if (srslte_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, pdsch_res.data()) < SRSLTE_SUCCESS) {
ERROR("Error decoding PDSCH");
return false;
}
// Logging
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
char str[512];
srslte_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, pdsch_res.data(), str, sizeof(str));
log_h->info("PDSCH: cc=%d, %s", cc_idx, str);
// Notify MAC about PDSCH decoding result
// ...
// Logging
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
std::array<char, 512> str;
srslte_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, pdsch_res.data(), str.data(), str.size());
log_h->info("PDSCH: cc=%d, %s", cc_idx, str.data());
}
}
return true;