mirror of https://github.com/PentHertz/srsLTE.git
Multiple PHY fixes and NR-PHY configuration refactor
This commit is contained in:
parent
7e6a35a9f7
commit
2421f2cd99
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue