Multiple PHY fixes and NR-PHY configuration refactor

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 7e6a35a9f7
commit 2421f2cd99

@ -47,12 +47,12 @@ typedef struct {
/** /**
* @brief Computes the symbol indexes carrying DMRS and stores them in symbols_idx * @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 grant PDSCH information provided by a DCI
* @param symbols_idx is the destination pointer where the symbols indexes are stored * @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. * @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, const srslte_sch_grant_nr_t* grant,
uint32_t symbols_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS]); 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 * @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 * @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 * @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 * @brief Stringifies the PDSCH DMRS configuration

@ -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; 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 { typedef enum SRSLTE_API {
srslte_search_space_type_common = 0, srslte_search_space_type_common_0 = 0, ///< configured by pdcch-ConfigSIB1 in MIB or by searchSpaceSIB1 in
srslte_search_space_type_common_0, ///< PDCCH-ConfigCommon or by searchSpaceZero in PDCCH-ConfigCommon
srslte_search_space_type_common_0A, srslte_search_space_type_common_0A, ///< configured by searchSpaceOtherSystemInformation in PDCCH-ConfigCommon
srslte_search_space_type_common_1, srslte_search_space_type_common_1, ///< configured by ra-SearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_common_2, srslte_search_space_type_common_2, ///< configured by pagingSearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_ue, 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; } 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 * @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_tc,
srslte_rnti_type_cs, srslte_rnti_type_cs,
srslte_rnti_type_sp_csi, srslte_rnti_type_sp_csi,
srslte_rnti_type_mcs_crnti, srslte_rnti_type_mcs_c,
} srslte_rnti_type_t; } 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); 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 #ifdef __cplusplus
} }
#endif #endif

@ -20,6 +20,7 @@
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_dci_location_t location; srslte_dci_location_t location;
srslte_search_space_type_t search_space; srslte_search_space_type_t search_space;
uint32_t coreset_id;
uint8_t payload[50]; uint8_t payload[50];
srslte_rnti_type_t rnti_type; srslte_rnti_type_t rnti_type;
uint32_t nof_bits; uint32_t nof_bits;
@ -32,7 +33,8 @@ typedef struct SRSLTE_API {
srslte_rnti_type_t rnti_type; srslte_rnti_type_t rnti_type;
srslte_dci_format_nr_t format; srslte_dci_format_nr_t format;
srslte_dci_location_t location; srslte_dci_location_t location;
srslte_search_space_t search_space; srslte_search_space_type_t search_space;
uint32_t coreset_id;
// Common fields // Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment uint32_t freq_domain_assigment; ///< Frequency domain resource assignment

@ -144,21 +144,48 @@ typedef struct SRSLTE_API {
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config * @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config
*/ */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_dmrs_sch_typeA_pos_t typeA_pos;
bool scrambling_id_present; bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023) uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
srslte_dmrs_sch_cfg_t dmrs_typeA; 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; srslte_dmrs_sch_cfg_t dmrs_typeB;
srslte_sch_grant_nr_t grant; 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]; 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) bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2)
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters 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 /// Uplink params
bool enable_transform_precoder; bool enable_transform_precoder;

@ -36,13 +36,15 @@
* @param pdsch_cfg Flattened PDSCH configuration provided from higher layers * @param pdsch_cfg Flattened PDSCH configuration provided from higher layers
* @param rnti_type Type of the RNTI of the corresponding DCI * @param rnti_type Type of the RNTI of the corresponding DCI
* @param ss_type Type of the SS for PDCCH * @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 m Time domain resource assignment field value m provided in DCI
* @param[out] Provides grant pointer to fill * @param[out] Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code * @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_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type, const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m, const uint8_t m,
srslte_sch_grant_nr_t* grant); srslte_sch_grant_nr_t* grant);
@ -65,11 +67,11 @@ 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 * @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 * @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code * @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_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); srslte_sch_grant_nr_t* 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 cfg PDSCH NR configuration by upper layers
* @param dci_dl Unpacked DCI used to schedule the PDSCH grant * @param dci_dl Unpacked DCI used to schedule the PDSCH grant
* @param[out] grant Provides grant pointer to fill * @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, SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg, const srslte_pdsch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl, const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant); srslte_sch_grant_nr_t* grant);
#endif // SRSLTE_RA_DL_NR_H #endif // SRSLTE_RA_DL_NR_H

@ -96,8 +96,9 @@ SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, 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_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_dci_dl_nr_t* dci_dl, const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* pdsch_grant); srslte_sch_grant_nr_t* pdsch_grant);
#endif // SRSLTE_RA_NR_H #endif // SRSLTE_RA_NR_H

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

@ -12,6 +12,7 @@
#include "srslte/phy/ch_estimation/dmrs_sch.h" #include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/common/sequence.h" #include "srslte/phy/common/sequence.h"
#include <complex.h>
#include <srslte/phy/utils/debug.h> #include <srslte/phy/utils/debug.h>
#define SRSLTE_DMRS_SCH_TYPEA_SINGLE_DURATION_MIN 3 #define SRSLTE_DMRS_SCH_TYPEA_SINGLE_DURATION_MIN 3
@ -163,8 +164,7 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q,
uint32_t delta, uint32_t delta,
cf_t* symbols) cf_t* symbols)
{ {
const srslte_dmrs_sch_cfg_t* dmrs_cfg = const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
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_count = 0; // Counts consecutive used PRB
uint32_t prb_start = 0; // Start consecutive used PRB uint32_t prb_start = 0; // Start consecutive used PRB
uint32_t prb_skip = 0; // Number of PRB to skip uint32_t prb_skip = 0; // Number of PRB to skip
@ -209,8 +209,7 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q,
} }
if (prb_count > 0) { if (prb_count > 0) {
pilot_count += srslte_dmrs_put_pilots( pilot_count += srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols);
q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, &symbols[prb_start * SRSLTE_NRE]);
} }
return pilot_count; return pilot_count;
@ -350,7 +349,7 @@ static int srslte_dmrs_sch_get_symbols_idx_mapping_type_A_double(const srslte_dm
return count; 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, const srslte_sch_grant_nr_t* grant,
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS]) 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; 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) { switch (grant->mapping) {
case srslte_sch_mapping_type_A: case srslte_sch_mapping_type_A:
// The case dmrs-AdditionalPosition equals to 'pos3' is only supported when dmrs-TypeA-Position is equal to 'pos2' // 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; 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) { 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", ERROR("Invalid number if DMRS CDM groups without data (%d). Valid values: 1, 2 , 3\n",
grant->nof_dmrs_cdm_groups_without_data); 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 // Get number of symbols used for DMRS
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; 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) { if (ret < SRSLTE_SUCCESS) {
ERROR("Error getting PDSCH DMRS symbol indexes\n"); ERROR("Error getting PDSCH DMRS symbol indexes\n");
return SRSLTE_ERROR; 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 slot_idx,
uint32_t symbol_idx) uint32_t symbol_idx)
{ {
const srslte_dmrs_sch_cfg_t* dmrs_cfg = const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
slot_idx = slot_idx % SRSLTE_NSLOTS_PER_FRAME_NR(carrier->numerology); 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 // Get symbols indexes
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; 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) { if (nof_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -595,8 +587,7 @@ static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q,
const cf_t* symbols, const cf_t* symbols,
cf_t* least_square_estimates) cf_t* least_square_estimates)
{ {
const srslte_dmrs_sch_cfg_t* dmrs_cfg = const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
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_count = 0; // Counts consecutive used PRB
uint32_t prb_start = 0; // Start 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 // Get contiguous pilots
pilot_count += srslte_dmrs_get_lse(q, pilot_count += srslte_dmrs_get_lse(
&sequence_state, q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]);
dmrs_cfg->type,
prb_start,
prb_count,
delta,
&symbols[prb_start * SRSLTE_NRE],
&least_square_estimates[pilot_count]);
// Reset counter // Reset counter
prb_count = 0; prb_count = 0;
} }
if (prb_count > 0) { if (prb_count > 0) {
pilot_count += srslte_dmrs_get_lse(q, pilot_count += srslte_dmrs_get_lse(
&sequence_state, q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]);
dmrs_cfg->type,
prb_start,
prb_count,
delta,
&symbols[prb_start * SRSLTE_NRE],
&least_square_estimates[pilot_count]);
} }
return pilot_count; return pilot_count;
@ -675,15 +654,14 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
const srslte_dmrs_sch_cfg_t* dmrs_cfg = const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB;
cf_t* ce = q->temp; cf_t* ce = q->temp;
uint32_t symbol_sz = q->carrier.nof_prb * SRSLTE_NRE; // Symbol size in resource elements uint32_t symbol_sz = q->carrier.nof_prb * SRSLTE_NRE; // Symbol size in resource elements
// Get symbols indexes // Get symbols indexes
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; 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) { if (nof_symbols <= SRSLTE_SUCCESS) {
ERROR("Error getting symbol indexes\n"); ERROR("Error getting symbol indexes\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -706,17 +684,19 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
} }
} }
// Perform Power measurements
float rsrp = 0.0f; float rsrp = 0.0f;
float epre = 0.0f; float epre = 0.0f;
cf_t corr[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
for (uint32_t i = 0; i < nof_symbols; i++) { 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; 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); epre += srslte_vec_avg_power_cf(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol);
} }
rsrp /= nof_symbols; rsrp /= nof_symbols;
epre /= 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 = rsrp;
chest_res->rsrp_dbm = srslte_convert_power_to_dB(chest_res->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; 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 // Average over time, only if more than one DMRS symbol
for (uint32_t i = 1; i < nof_symbols; i++) { for (uint32_t i = 1; i < nof_symbols; i++) {

@ -143,7 +143,7 @@ int main(int argc, char** argv)
for (coreset.duration = 1; coreset.duration <= 3; coreset.duration++) { 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++) { search_space.type++) {
for (uint32_t i = 0; i < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; i++) { for (uint32_t i = 0; i < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; i++) {

@ -168,24 +168,24 @@ static int assert_cfg(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_gra
continue; continue;
} }
if (pdsch_cfg->dmrs_typeA.typeA_pos != gold[i].typeA_pos) { if (pdsch_cfg->dmrs.typeA_pos != gold[i].typeA_pos) {
continue; continue;
} }
if (pdsch_cfg->dmrs_typeA.additional_pos != gold[i].additional_pos) { if (pdsch_cfg->dmrs.additional_pos != gold[i].additional_pos) {
continue; continue;
} }
if (pdsch_cfg->dmrs_typeA.length != gold[i].max_length) { if (pdsch_cfg->dmrs.length != gold[i].max_length) {
continue; continue;
} }
if (pdsch_cfg->dmrs_typeA.type != gold[i].type) { if (pdsch_cfg->dmrs.type != gold[i].type) {
continue; continue;
} }
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; 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); 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] = {}; 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++) { for (uint32_t j = 0; j < gold[i].nof_sc; j++) {
TESTASSERT(sc[j] == gold[i].sc_idx[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_begin = srslte_dmrs_sch_type_1;
srslte_dmrs_sch_type_t type_end = srslte_dmrs_sch_type_2; 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_begin = srslte_dmrs_sch_typeA_pos_2;
srslte_dmrs_sch_typeA_pos_t typeA_pos_end = srslte_dmrs_sch_typeA_pos_3; 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; for (pdsch_cfg.dmrs.typeA_pos = typeA_pos_begin; pdsch_cfg.dmrs.typeA_pos <= typeA_pos_end;
pdsch_cfg.dmrs_typeA.typeA_pos++) { 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_begin = srslte_dmrs_sch_add_pos_2;
srslte_dmrs_sch_add_pos_t add_pos_end = srslte_dmrs_sch_add_pos_3; 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; 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; for (pdsch_cfg.dmrs.additional_pos = add_pos_begin; pdsch_cfg.dmrs.additional_pos <= add_pos_end;
pdsch_cfg.dmrs_typeA.additional_pos++) { 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_begin = srslte_dmrs_sch_len_1;
srslte_dmrs_sch_len_t max_len_end = srslte_dmrs_sch_len_2; srslte_dmrs_sch_len_t max_len_end = srslte_dmrs_sch_len_2;
// Only single DMRS symbols can have additional positions 2 and 3 // Only single DMRS symbols can have additional positions 2 and 3
if (pdsch_cfg.dmrs_typeA.additional_pos == srslte_dmrs_sch_add_pos_2 || if (pdsch_cfg.dmrs.additional_pos == srslte_dmrs_sch_add_pos_2 ||
pdsch_cfg.dmrs_typeA.additional_pos == srslte_dmrs_sch_add_pos_3) { pdsch_cfg.dmrs.additional_pos == srslte_dmrs_sch_add_pos_3) {
max_len_end = srslte_dmrs_sch_len_1; 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; for (pdsch_cfg.dmrs.length = max_len_begin; pdsch_cfg.dmrs.length <= max_len_end; pdsch_cfg.dmrs.length++) {
pdsch_cfg.dmrs_typeA.length++) {
for (uint32_t bw = 1; bw <= carrier.nof_prb; bw++) { 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++) { grant.nof_dmrs_cdm_groups_without_data++) {
// Load default type A grant // Load default type A grant
srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &grant); srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &grant);
// Copy configuration
pdsch_cfg.dmrs_typeB = pdsch_cfg.dmrs_typeA;
int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res); int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res);
if (n == SRSLTE_SUCCESS) { if (n == SRSLTE_SUCCESS) {
test_passed++; test_passed++;
} else { } 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] = {}; 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); ERROR("Test %d failed. %s.\n", test_counter, str);
} }

@ -96,3 +96,29 @@ uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb)
return 0; 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;
}

@ -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 = {}; srslte_ofdm_cfg_t fft_cfg = {};
fft_cfg.nof_prb = args->nof_max_prb; 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; fft_cfg.keep_dc = true;
for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { 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) { 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++) { 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);
} }
} }

@ -42,7 +42,8 @@ int srslte_dci_nr_pack(const srslte_carrier_nr_t* carrier,
{ {
// Copy DCI MSG fields // Copy DCI MSG fields
msg->location = dci->location; 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_type = dci->rnti_type;
msg->rnti = dci->rnti; msg->rnti = dci->rnti;
msg->format = dci->format; msg->format = dci->format;
@ -181,7 +182,8 @@ int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrier,
// Copy DCI MSG fields // Copy DCI MSG fields
dci->location = msg->location; dci->location = msg->location;
dci->search_space.type = msg->search_space; dci->search_space = msg->search_space;
dci->coreset_id = msg->coreset_id;
dci->rnti_type = msg->rnti_type; dci->rnti_type = msg->rnti_type;
dci->rnti = msg->rnti; dci->rnti = msg->rnti;
dci->format = msg->format; dci->format = msg->format;

@ -282,8 +282,7 @@ static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q,
{ {
uint32_t count = 0; uint32_t count = 0;
const srslte_dmrs_sch_cfg_t* dmrs_cfg = const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
switch (dmrs_cfg->type) { switch (dmrs_cfg->type) {
case srslte_dmrs_sch_type_1: 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; uint32_t dmrs_l_count = 0;
// Get symbol indexes carrying DMRS // 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) { if (nof_dmrs_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR; 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; uint32_t len = 0;
len = srslte_print_check(str, str_len, len, "rnti=0x%x", grant->rnti); 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 // Append time-domain resource mapping
len = srslte_print_check(str, len = srslte_print_check(str,
str_len, str_len,
len, len,
",k0=%d,S=%d,L=%d,mapping=%s", ",k0=%d,freq=%s,symb=%d:%d,mapping=%s",
grant->k0, grant->k0,
freq_str,
grant->S, grant->S,
grant->L, grant->L,
srslte_sch_mapping_type_to_str(grant->mapping)); 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) { 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; return len;

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

@ -12,16 +12,16 @@
#include "srslte/phy/phch/ra_dl_nr.h" #include "srslte/phy/phch/ra_dl_nr.h"
#include "srslte/phy/utils/debug.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 = v % N;
uint32_t low = sliv % 14; uint32_t high = v / N;
if (low < 7) { if (high + 1 + low <= N) {
*S = low; *S = low;
*L = sliv / 14 + 1; *L = high + 1;
} else { } else {
*S = 14 - 1 - low; *S = N - 1 - low;
*L = 14 - sliv / 14 + 1; *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) 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 // 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->k0 = hl_ra_cfg->k0;
grant->mapping = hl_ra_cfg->mapping_type; 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_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type, const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m, const uint8_t m,
srslte_sch_grant_nr_t* grant) 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; return SRSLTE_ERROR_INVALID_INPUTS;
} }
// Determine which PDSCH Time domain RA configuration to apply (Table 5.1.2.1.1-1) // Determine which PDSCH Time domain RA configuration to apply (TS 38.214 Table 5.1.2.1.1-1)
if (cfg->pdsch_time_is_default) { 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 // 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); 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 { } 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); 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 {
ERROR("Unhandled case");
} }
// Validate S and L parameters // Validate S and L parameters
if (!srslte_ra_dl_nr_time_validate(grant)) { 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_ERROR;
} }
return SRSLTE_SUCCESS; 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, 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) srslte_sch_grant_nr_t* grant)
{ {
if (pdsch_cfg == NULL || grant == NULL) { if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS; 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: /* 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 * 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 * is 1 which corresponds to CDM group 0 for the case of PDSCH with allocation duration of 2 symbols, and the UE
* assume that the number of DM-RS CDM groups without data is 2 which corresponds to CDM group {0,1} for all other * shall assume that the number of DM-RS CDM groups without data is 2 which corresponds to CDM group {0,1} for all
* cases. * 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; grant->nof_dmrs_cdm_groups_without_data = 1;
} else { } else {
grant->nof_dmrs_cdm_groups_without_data = 2; grant->nof_dmrs_cdm_groups_without_data = 2;
@ -206,7 +240,7 @@ 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, static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg, const srslte_pdsch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl, const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant) srslte_sch_grant_nr_t* grant)
{ {
@ -234,8 +268,40 @@ static int ra_freq_type0(const srslte_carrier_nr_t* carrier,
return 0; return 0;
} }
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, int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg, const srslte_pdsch_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl, const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant) srslte_sch_grant_nr_t* grant)
{ {
@ -246,11 +312,11 @@ int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
// RA scheme // RA scheme
if (dci_dl->format == srslte_dci_format_nr_1_0) { if (dci_dl->format == srslte_dci_format_nr_1_0) {
// 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);
}
ra_freq_type0(carrier, cfg, dci_dl, grant); ra_freq_type0(carrier, cfg, dci_dl, grant);
} else {
ERROR("Only DCI Format 1_0 is supported\n"); ERROR("Only DCI Format 1_0 is supported\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
return SRSLTE_SUCCESS;
}

@ -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 UE is configured with MCS-C-RNTI, and
// - the PUSCH is scheduled by a PDCCH with // - the PUSCH is scheduled by a PDCCH with
// - CRC scrambled by MCS-C-RNTI, // - 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; 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; int n_sh_symb = grant->L;
// the number of REs for DM-RS per PRB in the scheduled duration // 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) { if (n_prb_dmrs < SRSLTE_SUCCESS) {
ERROR("Invalid number of DMRS RE\n"); ERROR("Invalid number of DMRS RE\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -455,40 +455,79 @@ int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
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)
{
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, int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg,
const srslte_dci_dl_nr_t* dci_dl, const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* pdsch_cfg,
srslte_sch_grant_nr_t* pdsch_grant) srslte_sch_grant_nr_t* pdsch_grant)
{ {
// Time domain resource allocation // 5.2.1.1 Resource allocation in time domain
if (srslte_ra_dl_nr_time( if (srslte_ra_dl_nr_time(pdsch_hl_cfg,
pdsch_cfg, dci_dl->rnti_type, dci_dl->search_space.type, dci_dl->time_domain_assigment, pdsch_grant) < dci_dl->rnti_type,
SRSLTE_SUCCESS) { 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"); ERROR("Error computing time domain resource allocation\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
// Frequency domain resource allocation // 5.1.2.2 Resource allocation in frequency domain
if (srslte_ra_dl_nr_freq(carrier, pdsch_cfg, dci_dl, pdsch_grant) < SRSLTE_SUCCESS) { if (srslte_ra_dl_nr_freq(carrier, pdsch_hl_cfg, dci_dl, pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error computing time domain resource allocation\n"); ERROR("Error computing frequency domain resource allocation\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
//??? // 5.1.2.3 Physical resource block (PRB) bundling
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;
}
pdsch_grant->nof_layers = 1; pdsch_grant->nof_layers = 1;
pdsch_grant->dci_format = dci_dl->format; pdsch_grant->dci_format = dci_dl->format;
pdsch_grant->rnti = dci_dl->rnti; pdsch_grant->rnti = dci_dl->rnti;
pdsch_grant->rnti_type = dci_dl->rnti_type;
for (uint32_t i = 0; i < carrier->nof_prb; i++) { // 5.1.6.2 DM-RS reception procedure
pdsch_grant->prb_idx[i] = true; 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) { if (srslte_ra_nr_fill_tb(pdsch_cfg, pdsch_grant, dci_dl->mcs, &pdsch_grant->tb[0]) < SRSLTE_SUCCESS) {
ERROR("Error filing tb\n"); ERROR("Error filing tb\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;

@ -153,13 +153,13 @@ int main(int argc, char** argv)
} }
// Use grant default A time resources with m=0 // 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"); ERROR("Error loading default grant\n");
goto clean_exit; goto clean_exit;
} }
// Load number of DMRS CDM groups without data // 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"); ERROR("Error loading number of DMRS CDM groups without data\n");
goto clean_exit; goto clean_exit;
} }

@ -132,7 +132,7 @@ int main(int argc, char** argv)
} }
// Use grant default A time resources with m=0 // 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"); ERROR("Error loading default grant\n");
goto clean_exit; goto clean_exit;
} }

@ -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; 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) { if (q == NULL || cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
@ -261,7 +261,7 @@ static int ue_dl_nr_find_dci_ncce(srslte_ue_dl_nr_t* q,
static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q, 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_dl_slot_cfg_t* slot_cfg,
uint32_t search_space_id, const srslte_search_space_t* search_space,
uint16_t rnti, uint16_t rnti,
srslte_rnti_type_t rnti_type, srslte_rnti_type_t rnti_type,
srslte_dci_dl_nr_t* dci_dl_list, srslte_dci_dl_nr_t* dci_dl_list,
@ -272,9 +272,6 @@ static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q,
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
// Select Search space
srslte_search_space_t* search_space = &q->cfg.search_space[search_space_id];
// Select CORESET // Select CORESET
uint32_t coreset_id = search_space->coreset_id; uint32_t coreset_id = search_space->coreset_id;
if (coreset_id >= SRSLTE_UE_DL_NR_MAX_NOF_CORESET || !q->cfg.coreset_present[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.L = L;
dci_msg.location.ncce = candidates[ncce_idx]; dci_msg.location.ncce = candidates[ncce_idx];
dci_msg.search_space = search_space->type; dci_msg.search_space = search_space->type;
dci_msg.coreset_id = search_space->coreset_id;
dci_msg.rnti_type = rnti_type; dci_msg.rnti_type = rnti_type;
dci_msg.rnti = rnti; dci_msg.rnti = rnti;
dci_msg.format = dci_format; 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 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) { 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 // Find DCIs in the RA search space
return ue_dl_nr_find_dl_dci_ss( 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 // 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 // Find DCIs in the selected search space
int ret = int ret = ue_dl_nr_find_dl_dci_ss(
ue_dl_nr_find_dl_dci_ss(q, slot_cfg, i, rnti, srslte_rnti_type_c, &dci_dl_list[count], nof_dci_msg - count); 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) { if (ret < SRSLTE_SUCCESS) {
ERROR("Error searching DCI"); ERROR("Error searching DCI");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -422,11 +413,11 @@ int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
{ {
int len = 0; int len = 0;
// Append channel estimator info
// ...
// Append PDSCH info // Append PDSCH info
len += srslte_pdsch_nr_rx_info(&q->pdsch, cfg, &cfg->grant, res, &str[len], str_len - len); 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; return len;
} }

@ -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->format = srslte_dci_format_nr_1_0;
dci_dl->rnti_type = srslte_rnti_type_c; dci_dl->rnti_type = srslte_rnti_type_c;
dci_dl->location = *dci_location; dci_dl->location = *dci_location;
dci_dl->search_space = *search_space; dci_dl->search_space = search_space->type;
dci_dl->rnti = rnti; dci_dl->rnti = rnti;
// Put actual DCI // Put actual DCI
@ -189,7 +189,7 @@ int main(int argc, char** argv)
goto clean_exit; goto clean_exit;
} }
srslte_ue_dl_nr_pdcch_cfg_t pdcch_cfg = {}; srslte_ue_dl_nr_cfg_t pdcch_cfg = {};
// Configure CORESET // Configure CORESET
srslte_coreset_t* coreset = &pdcch_cfg.coreset[0]; 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 // 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"); ERROR("Error loading default grant\n");
goto clean_exit; goto clean_exit;
} }

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

@ -24,8 +24,8 @@
namespace srsenb { namespace srsenb {
namespace nr { namespace nr {
cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& logger, phy_nr_state* phy_state_) : cc_worker::cc_worker(uint32_t cc_idx_, srslte::log* log, phy_nr_state* phy_state_) :
cc_idx(cc_idx_), phy_state(phy_state_), logger(logger) cc_idx(cc_idx_), phy_state(phy_state_), log_h(log)
{ {
cf_t* buffer_c[SRSLTE_MAX_PORTS] = {}; 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; return SRSLTE_ERROR;
} }
if (logger.info.enabled()) { if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
logger.info("PDCCH: cc=%d, ...", cc_idx); 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 // 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 // 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"); ERROR("Computing DL grant");
} }
@ -150,10 +151,10 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui
} }
// Logging // Logging
if (logger.info.enabled()) { if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
char str[512]; char str[512];
srslte_enb_dl_nr_pdsch_info(&enb_dl, &pdsch_cfg, str, sizeof(str)); 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);
} }
} }

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

@ -37,9 +37,9 @@ typedef struct {
} phy_nr_args_t; } phy_nr_args_t;
typedef struct { typedef struct {
srslte_sch_cfg_nr_t pdsch; srslte_pdsch_cfg_nr_t pdsch;
srslte_prach_cfg_t prach; srslte_prach_cfg_t prach;
srslte_ue_dl_nr_pdcch_cfg_t pdcch; srslte_ue_dl_nr_cfg_t pdcch;
} phy_nr_cfg_t; } phy_nr_cfg_t;
class phy_nr_state class phy_nr_state
@ -48,6 +48,7 @@ public:
srslte_carrier_nr_t carrier = {}; srslte_carrier_nr_t carrier = {};
phy_nr_args_t args = {}; phy_nr_args_t args = {};
phy_nr_cfg_t cfg = {}; phy_nr_cfg_t cfg = {};
int32_t test_rnti = 0x1234; // Fix PDSCH RNTI for testing
phy_nr_state() phy_nr_state()
{ {
@ -106,20 +107,40 @@ public:
// searchSpaceType: common (0) // searchSpaceType: common (0)
// common // common
// dci-Format0-0-AndFormat1-0 // dci-Format0-0-AndFormat1-0
cfg.pdcch.search_space[1].id = 1; srslte_search_space_t search_space1 = {};
cfg.pdcch.search_space[1].coreset_id = 1; search_space1.id = 1;
cfg.pdcch.search_space[1].nof_candidates[0] = 0; search_space1.coreset_id = 1;
cfg.pdcch.search_space[1].nof_candidates[1] = 0; search_space1.nof_candidates[0] = 0;
cfg.pdcch.search_space[1].nof_candidates[2] = 1; search_space1.nof_candidates[1] = 0;
cfg.pdcch.search_space[1].nof_candidates[3] = 0; search_space1.nof_candidates[2] = 1;
cfg.pdcch.search_space[1].nof_candidates[4] = 0; search_space1.nof_candidates[3] = 0;
cfg.pdcch.search_space[1].type = srslte_search_space_type_common; 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; cfg.pdcch.search_space_present[1] = true;
// ra-SearchSpace: 1 // ra-SearchSpace: 1
cfg.pdcch.ra_rnti = 0x16; //< Supposed to be deduced from PRACH configuration 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; 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 // Temporal attributes
srslte_softbuffer_rx_t softbuffer_rx = {}; srslte_softbuffer_rx_t softbuffer_rx = {};
std::vector<uint8_t> data; std::vector<uint8_t> data;
// Current rnti
uint16_t rnti = 0;
}; };
} // namespace nr } // namespace nr

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

Loading…
Cancel
Save