Renaming common UL/DL DMRS related types and initial NR PUSCH implementation

This commit is contained in:
Xavier Arteaga 2020-12-28 18:28:16 +01:00 committed by Ismael Gomez
parent cc5fdb68f3
commit b3200d9ef5
32 changed files with 2024 additions and 575 deletions

View File

@ -10,11 +10,11 @@
*
*/
#ifndef SRSLTE_DMRS_PDSCH_H
#define SRSLTE_DMRS_PDSCH_H
#ifndef SRSLTE_DMRS_SCH_H
#define SRSLTE_DMRS_SCH_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/pdsch_cfg_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#include "srslte/srslte.h"
#include <stdint.h>
@ -22,18 +22,18 @@
extern "C" {
#endif
#define SRSLTE_DMRS_PDSCH_MAX_SYMBOLS 4
#define SRSLTE_DMRS_SCH_MAX_SYMBOLS 4
/**
* @brief PDSCH DMRS estimator object
*
* @note The DMRS PDSCH object has to be initialised and the carrier parameters needs to be set.
*
* @see srslte_dmrs_pdsch_init
* @see srslte_dmrs_pdsch_set_carrier
* @see srslte_dmrs_pdsch_free
* @see srslte_dmrs_pdsch_put_sf
* @see srslte_dmrs_pdsch_estimate
* @see srslte_dmrs_sch_init
* @see srslte_dmrs_sch_set_carrier
* @see srslte_dmrs_sch_free
* @see srslte_dmrs_sch_put_sf
* @see srslte_dmrs_sch_estimate
*/
typedef struct {
bool is_ue;
@ -47,7 +47,7 @@ typedef struct {
cf_t* pilot_estimates; /// Pilots least squares estimates
cf_t* temp; /// Temporal data vector of size SRSLTE_NRE * carrier.nof_prb
} srslte_dmrs_pdsch_t;
} srslte_dmrs_sch_t;
/**
* @brief Computes the symbol indexes carrying DMRS and stores them in symbols_idx
@ -56,9 +56,9 @@ typedef struct {
* @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_pdsch_get_symbols_idx(const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t symbols_idx[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS]);
SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t symbols_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS]);
/**
* @brief Computes the sub-carrier indexes carrying DMRS
@ -69,7 +69,7 @@ SRSLTE_API int srslte_dmrs_pdsch_get_symbols_idx(const srslte_pdsch_cfg_nr_t*
*
* @return It returns the number of sub-carriers if inputs are valid, otherwise, it returns SRSLTE_ERROR code.
*/
SRSLTE_API int srslte_dmrs_pdsch_get_sc_idx(const srslte_pdsch_dmrs_cfg_t* cfg, uint32_t max_count, uint32_t* sc_idx);
SRSLTE_API int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint32_t max_count, uint32_t* sc_idx);
/**
* @brief Calculates the number of resource elements taken by a PDSCH-DMRS for a given PDSCH transmission
@ -77,7 +77,7 @@ SRSLTE_API int srslte_dmrs_pdsch_get_sc_idx(const srslte_pdsch_dmrs_cfg_t* cfg,
* @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_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, const srslte_pdsch_grant_nr_t* grant);
SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant);
/**
* @brief Stringifies the PDSCH DMRS configuration
@ -89,7 +89,7 @@ SRSLTE_API int srslte_dmrs_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, con
* @return It returns the number of characters written in the vector if no error occurs, otherwise it returns
* SRSLTE_ERROR code
*/
SRSLTE_API int srslte_dmrs_pdsch_cfg_to_str(const srslte_pdsch_dmrs_cfg_t* cfg, char* msg, uint32_t max_len);
SRSLTE_API int srslte_dmrs_sch_cfg_to_str(const srslte_dmrs_sch_cfg_t* cfg, char* msg, uint32_t max_len);
/**
* @brief Initialises DMRS PDSCH object
@ -98,14 +98,14 @@ SRSLTE_API int srslte_dmrs_pdsch_cfg_to_str(const srslte_pdsch_dmrs_cfg_t* cfg,
* @param is_ue indicates whethe the object is for a UE (in this case, it shall initialise as an estimator)
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_pdsch_init(srslte_dmrs_pdsch_t* q, bool is_ue);
SRSLTE_API int srslte_dmrs_sch_init(srslte_dmrs_sch_t* q, bool is_ue);
/**
* @brief Frees DMRS PDSCH object
*
* @param q DMRS PDSCH object
*/
SRSLTE_API void srslte_dmrs_pdsch_free(srslte_dmrs_pdsch_t* q);
SRSLTE_API void srslte_dmrs_sch_free(srslte_dmrs_sch_t* q);
/**
* @brief Sets the carrier configuration. if the PDSCH DMRS object is configured as UE, it will resize internal buffers
@ -116,7 +116,7 @@ SRSLTE_API void srslte_dmrs_pdsch_free(srslte_dmrs_pdsch_t* q);
*
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_pdsch_set_carrier(srslte_dmrs_pdsch_t* q, const srslte_carrier_nr_t* carrier);
SRSLTE_API int srslte_dmrs_sch_set_carrier(srslte_dmrs_sch_t* q, const srslte_carrier_nr_t* carrier);
/**
* @brief Puts PDSCH DMRS into a given resource grid
@ -129,11 +129,11 @@ SRSLTE_API int srslte_dmrs_pdsch_set_carrier(srslte_dmrs_pdsch_t* q, const srslt
*
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_pdsch_put_sf(srslte_dmrs_pdsch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* sf_symbols);
SRSLTE_API int srslte_dmrs_sch_put_sf(srslte_dmrs_sch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* sf_symbols);
/**
* @brief Estimates the channel for PDSCH from the DMRS
@ -149,15 +149,15 @@ SRSLTE_API int srslte_dmrs_pdsch_put_sf(srslte_dmrs_pdsch_t* q,
*
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
const cf_t* sf_symbols,
srslte_chest_dl_res_t* chest_res);
SRSLTE_API int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
const cf_t* sf_symbols,
srslte_chest_dl_res_t* chest_res);
#ifdef __cplusplus
}
#endif
#endif // SRSLTE_DMRS_PDSCH_H
#endif // SRSLTE_DMRS_SCH_H

View File

@ -128,7 +128,7 @@ typedef enum SRSLTE_API {
* @brief PDSCH mapping type
* @remark Described in TS 38.331 V15.10.0 Section PDSCH-TimeDomainResourceAllocationList
*/
typedef enum SRSLTE_API { srslte_pdsch_mapping_type_A = 0, srslte_pdsch_mapping_type_B } srslte_pdsch_mapping_type_t;
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_search_space_type_common = 0,
@ -155,6 +155,8 @@ typedef enum SRSLTE_API {
srslte_rnti_type_ra,
srslte_rnti_type_tc,
srslte_rnti_type_cs,
srslte_rnti_type_sp_csi,
srslte_rnti_type_mcs_crnti,
} srslte_rnti_type_t;
/**
@ -170,7 +172,9 @@ typedef enum SRSLTE_API {
srslte_dci_format_nr_2_1, ///< @brief Notifying a group of UEs of the PRB(s) and OFDM symbol(s) where UE may assume no
///< transmission is intended for the UE
srslte_dci_format_nr_2_2, ///< @brief Transmission of TPC commands for PUCCH and PUSCH
srslte_dci_format_nr_2_3 ///< @brief Transmission of a group of TPC commands for SRS transmissions by one or more UEs
srslte_dci_format_nr_2_3, ///< @brief Transmission of a group of TPC commands for SRS transmissions by one or more UEs
srslte_dci_format_nr_rar, ///< @brief Scheduling a transmission of PUSCH from RAR
srslte_dci_format_nr_cg ///< @brief Scheduling of PUSCH using a configured grant
} srslte_dci_format_nr_t;
/**
@ -287,7 +291,7 @@ SRSLTE_API uint32_t srslte_coreset_get_sz(const srslte_coreset_t* coreset);
* @param mapping_type Mapping type
* @return Constant string with PDSCH mapping type
*/
SRSLTE_API const char* srslte_pdsch_mapping_type_to_str(srslte_pdsch_mapping_type_t mapping_type);
SRSLTE_API const char* srslte_sch_mapping_type_to_str(srslte_sch_mapping_type_t mapping_type);
/**
* @brief Get the MCS table string

View File

@ -37,9 +37,9 @@ typedef struct SRSLTE_API {
srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
srslte_pdsch_nr_t pdsch;
srslte_dmrs_pdsch_t dmrs;
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
srslte_pdsch_nr_t pdsch;
srslte_dmrs_sch_t dmrs;
srslte_pdcch_nr_t pdcch;
} srslte_enb_dl_nr_t;
@ -64,17 +64,17 @@ SRSLTE_API int srslte_enb_dl_nr_pdcch_put(srslte_enb_dl_nr_t* q,
const srslte_dci_location_t* dci_location,
uint16_t rnti);
SRSLTE_API int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB]);
SRSLTE_API int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB]);
SRSLTE_API int srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
char* str,
uint32_t str_len);
SRSLTE_API int srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len);
#ifdef __cplusplus
}

View File

@ -15,7 +15,7 @@
#include "dci.h"
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/pdsch_cfg_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
typedef struct SRSLTE_API {
srslte_dci_location_t location;

View File

@ -18,12 +18,12 @@
* Reference: 3GPP TS 38.211 V15.8.0 Sec. 7.3.1
*****************************************************************************/
#ifndef srslte_pdsch_nr_H
#define srslte_pdsch_nr_H
#ifndef SRSLTE_PDSCH_NR_H
#define SRSLTE_PDSCH_NR_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/dmrs_pdsch.h"
#include "srslte/phy/phch/pdsch_cfg_nr.h"
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/sch_nr.h"
#include "srslte/phy/scrambling/scrambling.h"
@ -72,30 +72,30 @@ SRSLTE_API void srslte_pdsch_nr_free(srslte_pdsch_nr_t* q);
SRSLTE_API int srslte_pdsch_nr_set_carrier(srslte_pdsch_nr_t* q, const srslte_carrier_nr_t* carrier);
SRSLTE_API int srslte_pdsch_nr_encode(srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB],
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_nr_encode(srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB],
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_nr_decode(srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_pdsch_res_nr_t data[SRSLTE_MAX_TB]);
SRSLTE_API int srslte_pdsch_nr_decode(srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_pdsch_res_nr_t data[SRSLTE_MAX_TB]);
SRSLTE_API uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t* res,
char* str,
uint32_t str_len);
SRSLTE_API uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t* res,
char* str,
uint32_t str_len);
SRSLTE_API uint32_t srslte_pdsch_nr_tx_info(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
char* str,
uint32_t str_len);
SRSLTE_API uint32_t srslte_pdsch_nr_tx_info(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len);
#endif // srslte_pdsch_nr_H
#endif // SRSLTE_PDSCH_NR_H

View File

@ -18,8 +18,8 @@
* Reference:
*****************************************************************************/
#ifndef SRSLTE_PDSCH_CFG_NR_H
#define SRSLTE_PDSCH_CFG_NR_H
#ifndef SRSLTE_PHCH_CFG_NR_H
#define SRSLTE_PHCH_CFG_NR_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/sch_cfg_nr.h"
@ -32,35 +32,35 @@ extern "C" {
* @brief PDSCH DMRS type
*/
typedef enum {
srslte_dmrs_pdsch_type_1 = 0, // 1 pilot every 2 sub-carriers (default)
srslte_dmrs_pdsch_type_2 // 2 consecutive pilots every 6 sub-carriers
} srslte_dmrs_pdsch_type_t;
srslte_dmrs_sch_type_1 = 0, // 1 pilot every 2 sub-carriers (default)
srslte_dmrs_sch_type_2 // 2 consecutive pilots every 6 sub-carriers
} srslte_dmrs_sch_type_t;
/**
* @brief PDSCH DMRS length in symbols
*/
typedef enum {
srslte_dmrs_pdsch_len_1 = 0, // single, 1 symbol long (default)
srslte_dmrs_pdsch_len_2 // double, 2 symbol long
} srslte_dmrs_pdsch_len_t;
srslte_dmrs_sch_len_1 = 0, // single, 1 symbol long (default)
srslte_dmrs_sch_len_2 // double, 2 symbol long
} srslte_dmrs_sch_len_t;
/**
* @brief Determines whether the first pilot goes into symbol index 2 or 3
*/
typedef enum {
srslte_dmrs_pdsch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default)
srslte_dmrs_pdsch_typeA_pos_3 // Start in slot symbol index 3
} srslte_dmrs_pdsch_typeA_pos_t;
srslte_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default)
srslte_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3
} srslte_dmrs_sch_typeA_pos_t;
/**
* @brief Determines additional symbols if possible to be added
*/
typedef enum {
srslte_dmrs_pdsch_add_pos_2 = 0,
srslte_dmrs_pdsch_add_pos_0,
srslte_dmrs_pdsch_add_pos_1,
srslte_dmrs_pdsch_add_pos_3
} srslte_dmrs_pdsch_add_pos_t;
srslte_dmrs_sch_add_pos_2 = 0,
srslte_dmrs_sch_add_pos_0,
srslte_dmrs_sch_add_pos_1,
srslte_dmrs_sch_add_pos_3
} srslte_dmrs_sch_add_pos_t;
/**
* @brief Provides PDSCH DMRS configuration from higher layers
@ -68,22 +68,22 @@ typedef enum {
*/
typedef struct {
/// Parameters provided by IE DMRS-DownlinkConfig
srslte_dmrs_pdsch_type_t type;
srslte_dmrs_pdsch_add_pos_t additional_pos;
srslte_dmrs_pdsch_len_t length;
bool scrambling_id0_present;
uint32_t scrambling_id0;
bool scrambling_id1_present;
uint32_t scrambling_id1;
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;
/// Parameters provided by ServingCellConfigCommon
srslte_dmrs_pdsch_typeA_pos_t typeA_pos;
bool lte_CRS_to_match_around;
srslte_dmrs_sch_typeA_pos_t typeA_pos;
bool lte_CRS_to_match_around;
/// Parameters provided by FeatureSetDownlink-v1540
bool additional_DMRS_DL_Alt;
} srslte_pdsch_dmrs_cfg_t;
} srslte_dmrs_sch_cfg_t;
/**
* @brief flatten PDSCH time domain allocation parameters
@ -94,7 +94,7 @@ typedef struct SRSLTE_API {
uint32_t k0;
/// PDSCH mapping type
srslte_pdsch_mapping_type_t mapping_type;
srslte_sch_mapping_type_t mapping_type;
/// An index giving valid combinations of start symbol and length (jointly encoded) as start and length indicator
/// (SLIV). The network configures the field so that the allocation does not cross the slot boundary
@ -111,10 +111,11 @@ typedef struct SRSLTE_API {
srslte_rnti_type_t rnti_type;
/// Time domain resources
uint32_t k0;
uint32_t S;
uint32_t L;
srslte_pdsch_mapping_type_t mapping;
uint32_t k0; // PDSCH only
uint32_t k2; // PUSCH only
uint32_t S;
uint32_t L;
srslte_sch_mapping_type_t mapping;
/// Frequency domain resources
bool prb_idx[SRSLTE_MAX_PRB_NR];
@ -138,25 +139,29 @@ typedef struct SRSLTE_API {
/// ....
srslte_sch_tb_t tb[SRSLTE_MAX_TB];
} srslte_pdsch_grant_nr_t;
} srslte_sch_grant_nr_t;
/**
* @brief flatten PDSCH configuration parameters provided by higher layers
* @brief flatten SCH configuration parameters provided by higher layers
* @remark Described in TS 38.331 V15.10.0 Section PDSCH-Config
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config
*/
typedef struct SRSLTE_API {
bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
srslte_pdsch_dmrs_cfg_t dmrs_cfg_typeA;
srslte_pdsch_dmrs_cfg_t dmrs_cfg_typeB;
srslte_dmrs_sch_cfg_t dmrs_typeA;
srslte_dmrs_sch_cfg_t dmrs_typeB;
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters
} srslte_pdsch_cfg_nr_t;
/// Uplink params
bool enable_transform_precoder;
} srslte_sch_cfg_nr_t;
#ifdef __cplusplus
}
#endif
#endif // SRSLTE_PDSCH_CFG_NR_H
#endif // SRSLTE_PHCH_CFG_NR_H

View File

@ -0,0 +1,93 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_PUSCH_NR_H
#define SRSLTE_PUSCH_NR_H
#include "srslte/config.h"
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/sch_nr.h"
#include "srslte/phy/scrambling/scrambling.h"
/**
* @brief PUSCH encoder and decoder initialization arguments
*/
typedef struct SRSLTE_API {
srslte_sch_nr_args_t sch;
bool measure_evm;
bool measure_time;
} srslte_pusch_nr_args_t;
/**
* @brief PDSCH NR object
*/
typedef struct SRSLTE_API {
uint32_t max_prb; ///< Maximum number of allocated prb
uint32_t max_layers; ///< Maximum number of allocated layers
uint32_t max_cw; ///< Maximum number of allocated code words
srslte_carrier_nr_t carrier; ///< NR carrier configuration
srslte_sch_nr_t sch; ///< SCH Encoder/Decoder Object
uint8_t* b[SRSLTE_MAX_CODEWORDS]; ///< SCH Encoded and scrambled data
cf_t* d[SRSLTE_MAX_CODEWORDS]; ///< PDSCH modulated bits
cf_t* x[SRSLTE_MAX_LAYERS_NR]; ///< PDSCH modulated bits
srslte_modem_table_t modem_tables[SRSLTE_MOD_NITEMS]; ///< Modulator tables
srslte_evm_buffer_t* evm_buffer;
bool meas_time_en;
uint32_t meas_time_us;
} srslte_pusch_nr_t;
/**
*
*/
typedef struct {
uint8_t* payload;
bool crc;
float evm;
} srslte_pusch_res_nr_t;
SRSLTE_API int srslte_pusch_nr_init_enb(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args);
SRSLTE_API int srslte_pusch_nr_init_ue(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args);
SRSLTE_API void srslte_pusch_nr_free(srslte_pusch_nr_t* q);
SRSLTE_API int srslte_pusch_nr_set_carrier(srslte_pusch_nr_t* q, const srslte_carrier_nr_t* carrier);
SRSLTE_API int srslte_pusch_nr_encode(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB],
cf_t* sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pusch_nr_decode(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_pusch_res_nr_t data[SRSLTE_MAX_TB]);
SRSLTE_API uint32_t srslte_pusch_nr_rx_info(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
const srslte_pusch_res_nr_t* res,
char* str,
uint32_t str_len);
SRSLTE_API uint32_t srslte_pusch_nr_tx_info(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len);
#endif // SRSLTE_PUSCH_NR_H

View File

@ -26,7 +26,7 @@
#include "srslte/config.h"
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/pdsch_cfg_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#ifdef __cplusplus
extern "C" {
@ -68,8 +68,7 @@ SRSLTE_API srslte_mod_t srslte_ra_nr_mod_from_mcs(srslte_mcs_table_t mcs
* @param grant The given PDSCH transmission grant
* @return The number of resource elements if the provided configuration is valid, otherwise SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_dl_nr_slot_nof_re(const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant);
SRSLTE_API int srslte_ra_dl_nr_slot_nof_re(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates shared channel TBS
@ -82,10 +81,10 @@ SRSLTE_API int srslte_ra_dl_nr_slot_nof_re(const srslte_pdsch_cfg_nr_t* pdsch_
*/
SRSLTE_API uint32_t srslte_ra_nr_tbs(uint32_t N_re, double S, double R, uint32_t Qm, uint32_t nof_layers);
SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t mcs_idx,
srslte_sch_tb_t* tb);
SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t mcs_idx,
srslte_sch_tb_t* tb);
#ifdef __cplusplus
}

View File

@ -27,7 +27,7 @@
#include "srslte/phy/fec/ldpc/ldpc_decoder.h"
#include "srslte/phy/fec/ldpc/ldpc_encoder.h"
#include "srslte/phy/fec/ldpc/ldpc_rm.h"
#include "srslte/phy/phch/pdsch_cfg_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#define SRSLTE_SCH_NR_MAX_NOF_CB_LDPC \
((SRSLTE_SLOT_MAX_NOF_BITS_NR + (SRSLTE_LDPC_BG2_MAX_LEN_CB - 1)) / SRSLTE_LDPC_BG2_MAX_LEN_CB)
@ -110,17 +110,39 @@ SRSLTE_API srslte_basegraph_t srslte_sch_nr_select_basegraph(uint32_t tbs, doubl
* @param cfg SCH object
* @return
*/
SRSLTE_API int srslte_dlsch_nr_fill_cfg(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_common_cfg_t* cfg);
SRSLTE_API int srslte_sch_nr_fill_cfg(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_common_cfg_t* cfg);
SRSLTE_API int srslte_sch_nr_init_tx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* cfg);
/**
* @brief Initialises an SCH object as transmitter
* @param q Points ats the SCH object
* @param args Provides static configuration arguments
* @return SRSLTE_SUCCESS if the initialization is successful, SRSLTE_ERROR otherwise
*/
SRSLTE_API int srslte_sch_nr_init_tx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* args);
SRSLTE_API int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* cfg);
/**
* @brief Initialises an SCH object as receiver
* @param q Points ats the SCH object
* @param args Provides static configuration arguments
* @return SRSLTE_SUCCESS if the initialization is successful, SRSLTE_ERROR otherwise
*/
SRSLTE_API int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* args);
/**
* @brief Sets SCH object carrier attribute
* @param q Points ats the SCH object
* @param carrier Provides the NR carrier object
* @return SRSLTE_SUCCESS if the setting is successful, SRSLTE_ERROR otherwise
*/
SRSLTE_API int srslte_sch_nr_set_carrier(srslte_sch_nr_t* q, const srslte_carrier_nr_t* carrier);
/**
* @brief Free allocated resources used by an SCH intance
* @param q Points ats the SCH object
*/
SRSLTE_API void srslte_sch_nr_free(srslte_sch_nr_t* q);
SRSLTE_API int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
@ -129,8 +151,6 @@ SRSLTE_API int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
const uint8_t* data,
uint8_t* e_bits);
SRSLTE_API int srslte_sch_nr_decoder_set_carrier(srslte_sch_nr_t* q, const srslte_carrier_nr_t* carrier);
SRSLTE_API int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
@ -138,6 +158,19 @@ SRSLTE_API int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
uint8_t* data,
bool* crc_ok);
SRSLTE_API int srslte_ulsch_nr_encode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint8_t* e_bits);
SRSLTE_API int srslte_ulsch_nr_decode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
int8_t* e_bits,
uint8_t* data,
bool* crc_ok);
SRSLTE_API int srslte_sch_nr_tb_info(const srslte_sch_tb_t* tb, char* str, uint32_t str_len);
#endif // SRSLTE_SCH_NR_H

View File

@ -46,7 +46,7 @@ typedef struct SRSLTE_API {
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
srslte_chest_dl_res_t chest;
srslte_pdsch_nr_t pdsch;
srslte_dmrs_pdsch_t dmrs_pdsch;
srslte_dmrs_sch_t dmrs_pdsch;
srslte_dmrs_pdcch_estimator_t dmrs_pdcch;
srslte_pdcch_nr_t pdcch;
@ -71,18 +71,18 @@ SRSLTE_API int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q,
srslte_dci_dl_nr_t* dci_dl_list,
uint32_t nof_dci_msg);
SRSLTE_API int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
srslte_pdsch_res_nr_t* res);
SRSLTE_API int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
srslte_pdsch_res_nr_t* res);
SRSLTE_API int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len);
SRSLTE_API int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len);
#ifdef __cplusplus
}

View File

@ -24,7 +24,7 @@
#define SRSLTE_UE_DL_NR_DATA_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/pdsch_cfg_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#ifdef __cplusplus
extern "C" {
@ -41,7 +41,7 @@ extern "C" {
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_hl(const srslte_pdsch_allocation_t* pdsch_alloc,
srslte_pdsch_grant_nr_t* grant);
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the PDSCH time resource default A and stores it in the provided PDSCH NR grant. This can be used by
@ -55,9 +55,9 @@ SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_hl(const srslte_pdsch_allocat
* @param[out] grant PDSCH mapping type
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t m,
srslte_dmrs_pdsch_typeA_pos_t dmrs_typeA_pos,
srslte_pdsch_grant_nr_t* grant);
SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t m,
srslte_dmrs_sch_typeA_pos_t dmrs_typeA_pos,
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PDSCH-DMRS CDM groups without data for DCI format 1_0
*
@ -67,8 +67,8 @@ SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t
* @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_ue_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_pdsch_cfg_nr_t* pdsch_cfg,
srslte_pdsch_grant_nr_t* grant);
SRSLTE_API int srslte_ue_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);
#ifdef __cplusplus
}

View File

@ -0,0 +1,61 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/******************************************************************************
* @file ue_dl_nr.h
*
* Description: NR UE uplink physical layer procedures for data
*
* This module is a frontend to all the uplink data channel processing modules.
*
* Reference:
*****************************************************************************/
#ifndef SRSLTE_UE_UL_DATA_H
#define SRSLTE_UE_UL_DATA_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Calculates the PUSCH time resource default A and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 Table 6.1.2.1.1-2: Default PUSCH time domain resource allocation A for normal
* CP
*
* @param m Time domain resource assignment field value m of the DCI
* @param[out] grant PUSCH grant
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_ul_nr_pdsch_time_resource_default_A(uint32_t m, srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0
*
* @remark Defined by TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure
*
* @param cfg PUSCH 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_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant);
#ifdef __cplusplus
}
#endif
#endif // SRSLTE_UE_UL_DATA_H

View File

@ -10,22 +10,22 @@
*
*/
#include "srslte/phy/ch_estimation/dmrs_pdsch.h"
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include <srslte/phy/utils/debug.h>
#define SRSLTE_DMRS_PDSCH_TYPEA_SINGLE_DURATION_MIN 3
#define SRSLTE_DMRS_PDSCH_TYPEA_DOUBLE_DURATION_MIN 4
#define SRSLTE_DMRS_SCH_TYPEA_SINGLE_DURATION_MIN 3
#define SRSLTE_DMRS_SCH_TYPEA_DOUBLE_DURATION_MIN 4
int srslte_dmrs_pdsch_cfg_to_str(const srslte_pdsch_dmrs_cfg_t* cfg, char* msg, uint32_t max_len)
int srslte_dmrs_sch_cfg_to_str(const srslte_dmrs_sch_cfg_t* cfg, char* msg, uint32_t max_len)
{
int type = (int)cfg->type + 1;
int typeA_pos = (int)cfg->typeA_pos + 2;
int additional_pos = cfg->additional_pos == srslte_dmrs_pdsch_add_pos_0
int additional_pos = cfg->additional_pos == srslte_dmrs_sch_add_pos_0
? 0
: cfg->additional_pos == srslte_dmrs_pdsch_add_pos_1
: cfg->additional_pos == srslte_dmrs_sch_add_pos_1
? 1
: cfg->additional_pos == srslte_dmrs_pdsch_add_pos_2 ? 2 : 3;
const char* len = cfg->length == srslte_dmrs_pdsch_len_1 ? "single" : "double";
: cfg->additional_pos == srslte_dmrs_sch_add_pos_2 ? 2 : 3;
const char* len = cfg->length == srslte_dmrs_sch_len_1 ? "single" : "double";
return srslte_print_check(
msg, max_len, 0, "type=%d, typeA_pos=%d, add_pos=%d, len=%s", type, typeA_pos, additional_pos, len);
@ -63,9 +63,9 @@ srslte_dmrs_get_pilots_type2(uint32_t start_prb, uint32_t nof_prb, uint32_t delt
return count;
}
static uint32_t srslte_dmrs_get_lse(srslte_dmrs_pdsch_t* q,
static uint32_t srslte_dmrs_get_lse(srslte_dmrs_sch_t* q,
srslte_sequence_state_t* sequence_state,
srslte_dmrs_pdsch_type_t dmrs_type,
srslte_dmrs_sch_type_t dmrs_type,
uint32_t start_prb,
uint32_t nof_prb,
uint32_t delta,
@ -76,10 +76,10 @@ static uint32_t srslte_dmrs_get_lse(srslte_dmrs_pdsch_t* q,
switch (dmrs_type) {
case srslte_dmrs_pdsch_type_1:
case srslte_dmrs_sch_type_1:
count = srslte_dmrs_get_pilots_type1(start_prb, nof_prb, delta, symbols, least_square_estimates);
break;
case srslte_dmrs_pdsch_type_2:
case srslte_dmrs_sch_type_2:
count = srslte_dmrs_get_pilots_type2(start_prb, nof_prb, delta, symbols, least_square_estimates);
break;
default:
@ -127,25 +127,25 @@ srslte_dmrs_put_pilots_type2(uint32_t start_prb, uint32_t nof_prb, uint32_t delt
return count;
}
static uint32_t srslte_dmrs_put_pilots(srslte_dmrs_pdsch_t* q,
static uint32_t srslte_dmrs_put_pilots(srslte_dmrs_sch_t* q,
srslte_sequence_state_t* sequence_state,
srslte_dmrs_pdsch_type_t dmrs_type,
srslte_dmrs_sch_type_t dmrs_type,
uint32_t start_prb,
uint32_t nof_prb,
uint32_t delta,
cf_t* symbols)
{
uint32_t count = (dmrs_type == srslte_dmrs_pdsch_type_1) ? nof_prb * 6 : nof_prb * 4;
uint32_t count = (dmrs_type == srslte_dmrs_sch_type_1) ? nof_prb * 6 : nof_prb * 4;
// Generate sequence for the given pilots
srslte_sequence_state_gen_f(sequence_state, M_SQRT1_2, (float*)q->temp, count * 2);
switch (dmrs_type) {
case srslte_dmrs_pdsch_type_1:
case srslte_dmrs_sch_type_1:
count = srslte_dmrs_put_pilots_type1(start_prb, nof_prb, delta, symbols, q->temp);
break;
case srslte_dmrs_pdsch_type_2:
case srslte_dmrs_sch_type_2:
count = srslte_dmrs_put_pilots_type2(start_prb, nof_prb, delta, symbols, q->temp);
break;
default:
@ -155,19 +155,19 @@ static uint32_t srslte_dmrs_put_pilots(srslte_dmrs_pdsch_t* q,
return count;
}
static int srslte_dmrs_pdsch_put_symbol(srslte_dmrs_pdsch_t* q,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t cinit,
uint32_t delta,
cf_t* symbols)
static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t cinit,
uint32_t delta,
cf_t* symbols)
{
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &pdsch_cfg->dmrs_cfg_typeA : &pdsch_cfg->dmrs_cfg_typeB;
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_pdsch_type_1 ? 6 : 4;
uint32_t nof_pilots_x_prb = dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4;
uint32_t pilot_count = 0;
// Initialise sequence
@ -216,19 +216,19 @@ static int srslte_dmrs_pdsch_put_symbol(srslte_dmrs_pdsch_t* q,
}
// Implements 3GPP 38.211 R.15 Table 7.4.1.1.2-3 PDSCH mapping type A Single
static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(const srslte_pdsch_dmrs_cfg_t* dmrs_cfg,
uint32_t ld,
uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS])
static int srslte_dmrs_sch_get_symbols_idx_mapping_type_A_single(const srslte_dmrs_sch_cfg_t* dmrs_cfg,
uint32_t ld,
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS])
{
int count = 0;
if (ld < SRSLTE_DMRS_PDSCH_TYPEA_SINGLE_DURATION_MIN) {
if (ld < SRSLTE_DMRS_SCH_TYPEA_SINGLE_DURATION_MIN) {
ERROR("Duration is below the minimum\n");
return SRSLTE_ERROR;
}
// l0 = 3 if the higher-layer parameter dmrs-TypeA-Position is equal to 'pos3' and l0 = 2 otherwise
int l0 = (dmrs_cfg->typeA_pos == srslte_dmrs_pdsch_typeA_pos_3) ? 3 : 2;
int l0 = (dmrs_cfg->typeA_pos == srslte_dmrs_sch_typeA_pos_3) ? 3 : 2;
// For PDSCH mapping Type A single-symbol DM-RS, l1 = 11 except if all of the following conditions are fulfilled in
// which case l1 = 12:
@ -236,15 +236,15 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(const srslte_
// - the higher-layer parameters dmrs-AdditionalPosition is equal to 'pos1' and l0 = 3; and
// - the UE has indicated it is capable of additionalDMRS-DL-Alt
int l1 = 11;
if (dmrs_cfg->lte_CRS_to_match_around && dmrs_cfg->additional_pos == srslte_dmrs_pdsch_add_pos_1 &&
dmrs_cfg->typeA_pos == srslte_dmrs_pdsch_typeA_pos_3 && dmrs_cfg->additional_DMRS_DL_Alt) {
if (dmrs_cfg->lte_CRS_to_match_around && dmrs_cfg->additional_pos == srslte_dmrs_sch_add_pos_1 &&
dmrs_cfg->typeA_pos == srslte_dmrs_sch_typeA_pos_3 && dmrs_cfg->additional_DMRS_DL_Alt) {
l1 = 12;
}
symbols[count] = l0;
count++;
if (ld < 8 || dmrs_cfg->additional_pos == srslte_dmrs_pdsch_add_pos_0) {
if (ld < 8 || dmrs_cfg->additional_pos == srslte_dmrs_sch_add_pos_0) {
return count;
}
@ -252,7 +252,7 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(const srslte_
symbols[count] = 7;
count++;
} else if (ld < 12) {
if (dmrs_cfg->additional_pos > srslte_dmrs_pdsch_add_pos_2) {
if (dmrs_cfg->additional_pos > srslte_dmrs_sch_add_pos_2) {
symbols[count] = 6;
count++;
}
@ -262,11 +262,11 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(const srslte_
} else if (ld == 12) {
switch (dmrs_cfg->additional_pos) {
case srslte_dmrs_pdsch_add_pos_1:
case srslte_dmrs_sch_add_pos_1:
symbols[count] = 9;
count++;
break;
case srslte_dmrs_pdsch_add_pos_2:
case srslte_dmrs_sch_add_pos_2:
symbols[count] = 6;
count++;
symbols[count] = 9;
@ -282,11 +282,11 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(const srslte_
}
} else {
switch (dmrs_cfg->additional_pos) {
case srslte_dmrs_pdsch_add_pos_1:
case srslte_dmrs_sch_add_pos_1:
symbols[count] = l1;
count++;
break;
case srslte_dmrs_pdsch_add_pos_2:
case srslte_dmrs_sch_add_pos_2:
symbols[count] = 7;
count++;
symbols[count] = 11;
@ -306,31 +306,31 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(const srslte_
}
// Implements 3GPP 38.211 R.15 Table 7.4.1.1.2-4 PDSCH mapping type A Double
static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_double(const srslte_pdsch_dmrs_cfg_t* dmrs_cfg,
uint32_t ld,
uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS])
static int srslte_dmrs_sch_get_symbols_idx_mapping_type_A_double(const srslte_dmrs_sch_cfg_t* dmrs_cfg,
uint32_t ld,
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS])
{
int count = 0;
if (ld < SRSLTE_DMRS_PDSCH_TYPEA_DOUBLE_DURATION_MIN) {
if (ld < SRSLTE_DMRS_SCH_TYPEA_DOUBLE_DURATION_MIN) {
return SRSLTE_ERROR;
}
// According to Table 7.4.1.1.2-4, the additional position 3 is invalid.
if (dmrs_cfg->additional_pos == srslte_dmrs_pdsch_add_pos_3) {
if (dmrs_cfg->additional_pos == srslte_dmrs_sch_add_pos_3) {
ERROR("Invalid additional DMRS (%d)\n", dmrs_cfg->additional_pos);
return SRSLTE_ERROR;
}
// l0 = 3 if the higher-layer parameter dmrs-TypeA-Position is equal to 'pos3' and l0 = 2 otherwise
int l0 = (dmrs_cfg->typeA_pos == srslte_dmrs_pdsch_typeA_pos_3) ? 3 : 2;
int l0 = (dmrs_cfg->typeA_pos == srslte_dmrs_sch_typeA_pos_3) ? 3 : 2;
symbols[count] = l0;
count++;
symbols[count] = symbols[count - 1] + 1;
count++;
if (ld < 10 || dmrs_cfg->additional_pos == srslte_dmrs_pdsch_add_pos_0) {
if (ld < 10 || dmrs_cfg->additional_pos == srslte_dmrs_sch_add_pos_0) {
return count;
}
@ -349,27 +349,26 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_double(const srslte_
return count;
}
int srslte_dmrs_pdsch_get_symbols_idx(const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS])
int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS])
{
// The position(s) of the DM-RS symbols is given by l and duration ld where
// - for PDSCH mapping type A, ld is the duration between the first OFDM symbol of the slot and the last OFDM symbol
// of the scheduled PDSCH resources in the slot
// - for PDSCH mapping type B, ld is the duration of the scheduled PDSCH resources
uint32_t ld = grant->L;
if (grant->mapping == srslte_pdsch_mapping_type_A) {
if (grant->mapping == srslte_sch_mapping_type_A) {
ld = grant->S + grant->L;
}
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &cfg->dmrs_cfg_typeA : &cfg->dmrs_cfg_typeB;
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_pdsch_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'
if (dmrs_cfg->typeA_pos != srslte_dmrs_pdsch_typeA_pos_2 &&
dmrs_cfg->additional_pos == srslte_dmrs_pdsch_add_pos_3) {
if (dmrs_cfg->typeA_pos != srslte_dmrs_sch_typeA_pos_2 && dmrs_cfg->additional_pos == srslte_dmrs_sch_add_pos_3) {
ERROR("The case dmrs-AdditionalPosition equals to 'pos3' is only supported when dmrs-TypeA-Position is equal "
"to 'pos2'\n");
return SRSLTE_ERROR;
@ -377,17 +376,17 @@ int srslte_dmrs_pdsch_get_symbols_idx(const srslte_pdsch_cfg_nr_t* cfg,
// For PDSCH mapping type A, ld = 3 and ld = 4 symbols in Tables 7.4.1.1.2-3 and 7.4.1.1.2-4 respectively is only
// applicable when dmrs-TypeA-Position is equal to 'pos2
if ((ld == 3 || ld == 4) && dmrs_cfg->typeA_pos != srslte_dmrs_pdsch_typeA_pos_2) {
if ((ld == 3 || ld == 4) && dmrs_cfg->typeA_pos != srslte_dmrs_sch_typeA_pos_2) {
ERROR("For PDSCH mapping type A, ld = 3 and ld = 4 symbols in Tables 7.4.1.1.2-3 and 7.4.1.1.2-4 respectively "
"is only applicable when dmrs-TypeA-Position is equal to 'pos2\n");
return SRSLTE_ERROR;
}
if (dmrs_cfg->length == srslte_dmrs_pdsch_len_1) {
return srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_single(dmrs_cfg, ld, symbols);
if (dmrs_cfg->length == srslte_dmrs_sch_len_1) {
return srslte_dmrs_sch_get_symbols_idx_mapping_type_A_single(dmrs_cfg, ld, symbols);
}
return srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_double(dmrs_cfg, ld, symbols);
case srslte_pdsch_mapping_type_B:
return srslte_dmrs_sch_get_symbols_idx_mapping_type_A_double(dmrs_cfg, ld, symbols);
case srslte_sch_mapping_type_B:
ERROR("Error PDSCH mapping type B not supported\n");
return SRSLTE_ERROR;
}
@ -395,12 +394,12 @@ int srslte_dmrs_pdsch_get_symbols_idx(const srslte_pdsch_cfg_nr_t* cfg,
return SRSLTE_ERROR;
}
int srslte_dmrs_pdsch_get_sc_idx(const srslte_pdsch_dmrs_cfg_t* cfg, uint32_t max_count, uint32_t* sc_idx)
int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint32_t max_count, uint32_t* sc_idx)
{
int count = 0;
uint32_t delta = 0;
if (cfg->type == srslte_dmrs_pdsch_type_1) {
if (cfg->type == srslte_dmrs_sch_type_1) {
for (uint32_t n = 0; count < max_count; n += 4) {
for (uint32_t k_prime = 0; k_prime < 2 && count < max_count; k_prime++) {
sc_idx[count++] = n + 2 * k_prime + delta;
@ -417,10 +416,10 @@ int srslte_dmrs_pdsch_get_sc_idx(const srslte_pdsch_dmrs_cfg_t* cfg, uint32_t ma
return count;
}
int srslte_dmrs_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, const srslte_pdsch_grant_nr_t* grant)
int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant)
{
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &cfg->dmrs_cfg_typeA : &cfg->dmrs_cfg_typeB;
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",
@ -429,12 +428,12 @@ int srslte_dmrs_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, const srslte_p
}
// Get number of frequency domain resource elements used for DMRS
int nof_sc = SRSLTE_MIN(
SRSLTE_NRE, grant->nof_dmrs_cdm_groups_without_data * (dmrs_cfg->type == srslte_dmrs_pdsch_type_1 ? 6 : 4));
int nof_sc = SRSLTE_MIN(SRSLTE_NRE,
grant->nof_dmrs_cdm_groups_without_data * (dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4));
// Get number of symbols used for DMRS
uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS] = {};
int ret = srslte_dmrs_pdsch_get_symbols_idx(cfg, grant, symbols);
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int ret = srslte_dmrs_sch_get_symbols_idx(cfg, grant, symbols);
if (ret < SRSLTE_SUCCESS) {
ERROR("Error getting PDSCH DMRS symbol indexes\n");
return SRSLTE_ERROR;
@ -443,14 +442,14 @@ int srslte_dmrs_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, const srslte_p
return nof_sc * ret;
}
static uint32_t srslte_dmrs_pdsch_seed(const srslte_carrier_nr_t* carrier,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t slot_idx,
uint32_t symbol_idx)
static uint32_t srslte_dmrs_sch_seed(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t slot_idx,
uint32_t symbol_idx)
{
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &cfg->dmrs_cfg_typeA : &cfg->dmrs_cfg_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
slot_idx = slot_idx % SRSLTE_NSLOTS_PER_FRAME_NR(carrier->numerology);
@ -470,7 +469,7 @@ static uint32_t srslte_dmrs_pdsch_seed(const srslte_carrier_nr_t* carrier,
(uint64_t)INT32_MAX);
}
int srslte_dmrs_pdsch_init(srslte_dmrs_pdsch_t* q, bool is_ue)
int srslte_dmrs_sch_init(srslte_dmrs_sch_t* q, bool is_ue)
{
if (q == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
@ -483,7 +482,7 @@ int srslte_dmrs_pdsch_init(srslte_dmrs_pdsch_t* q, bool is_ue)
return SRSLTE_SUCCESS;
}
void srslte_dmrs_pdsch_free(srslte_dmrs_pdsch_t* q)
void srslte_dmrs_sch_free(srslte_dmrs_sch_t* q)
{
if (q == NULL) {
return;
@ -498,10 +497,10 @@ void srslte_dmrs_pdsch_free(srslte_dmrs_pdsch_t* q)
free(q->temp);
}
SRSLTE_MEM_ZERO(q, srslte_dmrs_pdsch_t, 1);
SRSLTE_MEM_ZERO(q, srslte_dmrs_sch_t, 1);
}
int srslte_dmrs_pdsch_set_carrier(srslte_dmrs_pdsch_t* q, const srslte_carrier_nr_t* carrier)
int srslte_dmrs_sch_set_carrier(srslte_dmrs_sch_t* q, const srslte_carrier_nr_t* carrier)
{
bool max_nof_prb_changed = q->max_nof_prb < carrier->nof_prb;
@ -544,7 +543,7 @@ int srslte_dmrs_pdsch_set_carrier(srslte_dmrs_pdsch_t* q, const srslte_carrier_n
}
// The maximum number of pilots is for Type 1
q->pilot_estimates = srslte_vec_cf_malloc(SRSLTE_DMRS_PDSCH_MAX_SYMBOLS * q->max_nof_prb * SRSLTE_NRE / 2);
q->pilot_estimates = srslte_vec_cf_malloc(SRSLTE_DMRS_SCH_MAX_SYMBOLS * q->max_nof_prb * SRSLTE_NRE / 2);
if (!q->pilot_estimates) {
ERROR("malloc\n");
return SRSLTE_ERROR;
@ -554,11 +553,11 @@ int srslte_dmrs_pdsch_set_carrier(srslte_dmrs_pdsch_t* q, const srslte_carrier_n
return SRSLTE_SUCCESS;
}
int srslte_dmrs_pdsch_put_sf(srslte_dmrs_pdsch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* sf_symbols)
int srslte_dmrs_sch_put_sf(srslte_dmrs_sch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* sf_symbols)
{
uint32_t delta = 0;
@ -569,8 +568,8 @@ int srslte_dmrs_pdsch_put_sf(srslte_dmrs_pdsch_t* q,
uint32_t symbol_sz = q->carrier.nof_prb * SRSLTE_NRE; // Symbol size in resource elements
// Get symbols indexes
uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_pdsch_get_symbols_idx(pdsch_cfg, grant, symbols);
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols);
if (nof_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -579,29 +578,29 @@ int srslte_dmrs_pdsch_put_sf(srslte_dmrs_pdsch_t* q,
for (uint32_t i = 0; i < nof_symbols; i++) {
uint32_t l = symbols[i]; // Symbol index inside the slot
uint32_t slot_idx = slot_cfg->idx; // Slot index in the frame
uint32_t cinit = srslte_dmrs_pdsch_seed(&q->carrier, pdsch_cfg, grant, slot_idx, l);
uint32_t cinit = srslte_dmrs_sch_seed(&q->carrier, pdsch_cfg, grant, slot_idx, l);
srslte_dmrs_pdsch_put_symbol(q, pdsch_cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l]);
srslte_dmrs_sch_put_symbol(q, pdsch_cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l]);
}
return SRSLTE_SUCCESS;
}
static int srslte_dmrs_pdsch_get_symbol(srslte_dmrs_pdsch_t* q,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t cinit,
uint32_t delta,
const cf_t* symbols,
cf_t* least_square_estimates)
static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t cinit,
uint32_t delta,
const cf_t* symbols,
cf_t* least_square_estimates)
{
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &pdsch_cfg->dmrs_cfg_typeA : &pdsch_cfg->dmrs_cfg_typeB;
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_pdsch_type_1 ? 6 : 4;
uint32_t nof_pilots_x_prb = dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4;
uint32_t pilot_count = 0;
// Initialise sequence
@ -662,12 +661,12 @@ static int srslte_dmrs_pdsch_get_symbol(srslte_dmrs_pdsch_t* q,
return pilot_count;
}
int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
const cf_t* sf_symbols,
srslte_chest_dl_res_t* chest_res)
int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
const cf_t* sf_symbols,
srslte_chest_dl_res_t* chest_res)
{
const uint32_t delta = 0;
@ -675,15 +674,15 @@ int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
return SRSLTE_ERROR_INVALID_INPUTS;
}
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &pdsch_cfg->dmrs_cfg_typeA : &pdsch_cfg->dmrs_cfg_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB;
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_PDSCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_pdsch_get_symbols_idx(pdsch_cfg, grant, symbols);
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols);
if (nof_symbols <= SRSLTE_SUCCESS) {
ERROR("Error getting symbol indexes\n");
return SRSLTE_ERROR;
@ -695,9 +694,9 @@ int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
for (uint32_t i = 0; i < nof_symbols; i++) {
uint32_t l = symbols[i]; // Symbol index inside the slot
uint32_t cinit = srslte_dmrs_pdsch_seed(&q->carrier, pdsch_cfg, grant, slot_cfg->idx, l);
uint32_t cinit = srslte_dmrs_sch_seed(&q->carrier, pdsch_cfg, grant, slot_cfg->idx, l);
nof_pilots_x_symbol = srslte_dmrs_pdsch_get_symbol(
nof_pilots_x_symbol = srslte_dmrs_sch_get_symbol(
q, pdsch_cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l], &q->pilot_estimates[nof_pilots_x_symbol * i]);
if (nof_pilots_x_symbol == 0) {
@ -720,8 +719,8 @@ int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
// Frequency domain interpolate
uint32_t nof_re_x_symbol =
(dmrs_cfg->type == srslte_dmrs_pdsch_type_1) ? nof_pilots_x_symbol * 2 : nof_pilots_x_symbol * 3;
if (dmrs_cfg->type == srslte_dmrs_pdsch_type_1) {
(dmrs_cfg->type == srslte_dmrs_sch_type_1) ? nof_pilots_x_symbol * 2 : nof_pilots_x_symbol * 3;
if (dmrs_cfg->type == srslte_dmrs_sch_type_1) {
// Prepare interpolator
if (srslte_interp_linear_resize(&q->interpolator_type1, nof_pilots_x_symbol, 2) < SRSLTE_SUCCESS) {
ERROR("Resizing interpolator nof_pilots_x_symbol=%d; M=%d;\n", nof_pilots_x_symbol, 2);
@ -753,7 +752,7 @@ int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
if (symbols[symbol_idx] == l) {
switch (dmrs_cfg->type) {
case srslte_dmrs_pdsch_type_1:
case srslte_dmrs_sch_type_1:
// Skip if there is no data to read
if (grant->nof_dmrs_cdm_groups_without_data != 1) {
continue;
@ -763,7 +762,7 @@ int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q,
count++;
}
break;
case srslte_dmrs_pdsch_type_2:
case srslte_dmrs_sch_type_2:
// Skip if there is no data to read
if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) {
continue;

View File

@ -11,7 +11,7 @@
*/
#include "srslte/common/test_common.h"
#include "srslte/phy/ch_estimation/dmrs_pdsch.h"
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/ue/ue_dl_nr_data.h"
#include "srslte/srslte.h"
#include <complex.h>
@ -29,95 +29,95 @@ static srslte_carrier_nr_t carrier = {
};
typedef struct {
srslte_pdsch_mapping_type_t mapping_type;
srslte_dmrs_pdsch_typeA_pos_t typeA_pos;
srslte_dmrs_pdsch_len_t max_length;
srslte_dmrs_pdsch_add_pos_t additional_pos;
srslte_dmrs_pdsch_type_t type;
uint32_t symbol_idx[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS];
uint32_t nof_symbols;
uint32_t sc_idx[SRSLTE_NRE];
uint32_t nof_sc;
srslte_sch_mapping_type_t mapping_type;
srslte_dmrs_sch_typeA_pos_t typeA_pos;
srslte_dmrs_sch_len_t max_length;
srslte_dmrs_sch_add_pos_t additional_pos;
srslte_dmrs_sch_type_t type;
uint32_t symbol_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS];
uint32_t nof_symbols;
uint32_t sc_idx[SRSLTE_NRE];
uint32_t nof_sc;
} golden_t;
// Golden values extracted from https://www.sharetechnote.com/html/5G/5G_PDSCH_DMRS.html
static const golden_t gold[] = {{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_0,
.type = srslte_dmrs_pdsch_type_2,
static const golden_t gold[] = {{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_0,
.type = srslte_dmrs_sch_type_2,
.nof_symbols = 1,
.symbol_idx = {2},
.nof_sc = 4,
.sc_idx = {0, 1, 6, 7}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_3,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_0,
.type = srslte_dmrs_pdsch_type_2,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_3,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_0,
.type = srslte_dmrs_sch_type_2,
.nof_symbols = 1,
.symbol_idx = {3},
.nof_sc = 4,
.sc_idx = {0, 1, 6, 7}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_2,
.additional_pos = srslte_dmrs_pdsch_add_pos_0,
.type = srslte_dmrs_pdsch_type_2,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_2,
.additional_pos = srslte_dmrs_sch_add_pos_0,
.type = srslte_dmrs_sch_type_2,
.nof_symbols = 2,
.symbol_idx = {2, 3},
.nof_sc = 4,
.sc_idx = {0, 1, 6, 7}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_1,
.type = srslte_dmrs_pdsch_type_2,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_1,
.type = srslte_dmrs_sch_type_2,
.nof_symbols = 2,
.symbol_idx = {2, 11},
.nof_sc = 4,
.sc_idx = {0, 1, 6, 7}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_2,
.type = srslte_dmrs_pdsch_type_2,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_2,
.type = srslte_dmrs_sch_type_2,
.nof_symbols = 3,
.symbol_idx = {2, 7, 11},
.nof_sc = 4,
.sc_idx = {0, 1, 6, 7}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_3,
.type = srslte_dmrs_pdsch_type_2,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_3,
.type = srslte_dmrs_sch_type_2,
.nof_symbols = 4,
.symbol_idx = {2, 5, 8, 11},
.nof_sc = 4,
.sc_idx = {0, 1, 6, 7}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_0,
.type = srslte_dmrs_pdsch_type_1,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_0,
.type = srslte_dmrs_sch_type_1,
.nof_symbols = 1,
.symbol_idx = {2},
.nof_sc = 6,
.sc_idx = {0, 2, 4, 6, 8, 10}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_2,
.additional_pos = srslte_dmrs_pdsch_add_pos_0,
.type = srslte_dmrs_pdsch_type_1,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_2,
.additional_pos = srslte_dmrs_sch_add_pos_0,
.type = srslte_dmrs_sch_type_1,
.nof_symbols = 2,
.symbol_idx = {2, 3},
.nof_sc = 6,
.sc_idx = {0, 2, 4, 6, 8, 10}},
{.mapping_type = srslte_pdsch_mapping_type_A,
.typeA_pos = srslte_dmrs_pdsch_typeA_pos_2,
.max_length = srslte_dmrs_pdsch_len_1,
.additional_pos = srslte_dmrs_pdsch_add_pos_3,
.type = srslte_dmrs_pdsch_type_1,
{.mapping_type = srslte_sch_mapping_type_A,
.typeA_pos = srslte_dmrs_sch_typeA_pos_2,
.max_length = srslte_dmrs_sch_len_1,
.additional_pos = srslte_dmrs_sch_add_pos_3,
.type = srslte_dmrs_sch_type_1,
.nof_symbols = 4,
.symbol_idx = {2, 5, 8, 11},
.nof_sc = 6,
@ -156,7 +156,7 @@ static void parse_args(int argc, char** argv)
}
}
static int assert_cfg(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch_grant_nr_t* grant)
static int assert_cfg(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_grant_nr_t* grant)
{
for (uint32_t i = 0; gold[i].nof_sc != 0; i++) {
// Gold examples are done for more than 12 symbols
@ -168,24 +168,24 @@ static int assert_cfg(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch
continue;
}
if (pdsch_cfg->dmrs_cfg_typeA.typeA_pos != gold[i].typeA_pos) {
if (pdsch_cfg->dmrs_typeA.typeA_pos != gold[i].typeA_pos) {
continue;
}
if (pdsch_cfg->dmrs_cfg_typeA.additional_pos != gold[i].additional_pos) {
if (pdsch_cfg->dmrs_typeA.additional_pos != gold[i].additional_pos) {
continue;
}
if (pdsch_cfg->dmrs_cfg_typeA.length != gold[i].max_length) {
if (pdsch_cfg->dmrs_typeA.length != gold[i].max_length) {
continue;
}
if (pdsch_cfg->dmrs_cfg_typeA.type != gold[i].type) {
if (pdsch_cfg->dmrs_typeA.type != gold[i].type) {
continue;
}
uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_pdsch_get_symbols_idx(pdsch_cfg, grant, symbols);
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols);
TESTASSERT(nof_symbols == gold[i].nof_symbols);
@ -194,7 +194,7 @@ static int assert_cfg(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch
}
uint32_t sc[SRSLTE_NRE] = {};
srslte_dmrs_pdsch_get_sc_idx(&pdsch_cfg->dmrs_cfg_typeA, SRSLTE_NRE, sc);
srslte_dmrs_sch_get_sc_idx(&pdsch_cfg->dmrs_typeA, SRSLTE_NRE, sc);
for (uint32_t j = 0; j < gold[i].nof_sc; j++) {
TESTASSERT(sc[j] == gold[i].sc_idx[j]);
@ -206,19 +206,19 @@ static int assert_cfg(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch
return SRSLTE_SUCCESS;
}
static int run_test(srslte_dmrs_pdsch_t* dmrs_pdsch,
const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* sf_symbols,
srslte_chest_dl_res_t* chest_res)
static int run_test(srslte_dmrs_sch_t* dmrs_pdsch,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* sf_symbols,
srslte_chest_dl_res_t* chest_res)
{
TESTASSERT(assert_cfg(pdsch_cfg, grant) == SRSLTE_SUCCESS);
srslte_dl_slot_cfg_t slot_cfg = {};
for (slot_cfg.idx = 0; slot_cfg.idx < SRSLTE_NSLOTS_PER_FRAME_NR(dmrs_pdsch->carrier.numerology); slot_cfg.idx++) {
TESTASSERT(srslte_dmrs_pdsch_put_sf(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols) == SRSLTE_SUCCESS);
TESTASSERT(srslte_dmrs_sch_put_sf(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols) == SRSLTE_SUCCESS);
TESTASSERT(srslte_dmrs_pdsch_estimate(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols, chest_res) ==
TESTASSERT(srslte_dmrs_sch_estimate(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols, chest_res) ==
SRSLTE_SUCCESS);
float mse = 0.0f;
@ -241,10 +241,10 @@ int main(int argc, char** argv)
parse_args(argc, argv);
srslte_dmrs_pdsch_t dmrs_pdsch = {};
srslte_pdsch_cfg_nr_t pdsch_cfg = {};
srslte_pdsch_grant_nr_t grant = {};
srslte_chest_dl_res_t chest_dl_res = {};
srslte_dmrs_sch_t dmrs_pdsch = {};
srslte_sch_cfg_nr_t pdsch_cfg = {};
srslte_sch_grant_nr_t grant = {};
srslte_chest_dl_res_t chest_dl_res = {};
uint32_t nof_re = carrier.nof_prb * SRSLTE_NRE * SRSLTE_NOF_SLOTS_PER_SF * SRSLTE_MAX_NSYMB;
cf_t* sf_symbols = srslte_vec_cf_malloc(nof_re);
@ -253,13 +253,13 @@ int main(int argc, char** argv)
uint32_t test_passed = 0;
// Initialise object DMRS for PDSCH
if (srslte_dmrs_pdsch_init(&dmrs_pdsch, true) != SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_init(&dmrs_pdsch, true) != SRSLTE_SUCCESS) {
ERROR("Init\n");
goto clean_exit;
}
// Set carrier configuration
if (srslte_dmrs_pdsch_set_carrier(&dmrs_pdsch, &carrier) != SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_set_carrier(&dmrs_pdsch, &carrier) != SRSLTE_SUCCESS) {
ERROR("Setting carrier\n");
goto clean_exit;
}
@ -271,38 +271,36 @@ int main(int argc, char** argv)
// For each DCI m param
for (uint32_t m = 0; m < 16; m++) {
srslte_dmrs_pdsch_type_t type_begin = srslte_dmrs_pdsch_type_1;
srslte_dmrs_pdsch_type_t type_end = srslte_dmrs_pdsch_type_2;
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_cfg_typeA.type = type_begin; pdsch_cfg.dmrs_cfg_typeA.type <= type_end;
pdsch_cfg.dmrs_cfg_typeA.type++) {
srslte_dmrs_pdsch_typeA_pos_t typeA_pos_begin = srslte_dmrs_pdsch_typeA_pos_2;
srslte_dmrs_pdsch_typeA_pos_t typeA_pos_end = srslte_dmrs_pdsch_typeA_pos_3;
for (pdsch_cfg.dmrs_typeA.type = type_begin; pdsch_cfg.dmrs_typeA.type <= type_end; pdsch_cfg.dmrs_typeA.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_cfg_typeA.typeA_pos = typeA_pos_begin; pdsch_cfg.dmrs_cfg_typeA.typeA_pos <= typeA_pos_end;
pdsch_cfg.dmrs_cfg_typeA.typeA_pos++) {
srslte_dmrs_pdsch_add_pos_t add_pos_begin = srslte_dmrs_pdsch_add_pos_2;
srslte_dmrs_pdsch_add_pos_t add_pos_end = srslte_dmrs_pdsch_add_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++) {
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_cfg_typeA.typeA_pos == srslte_dmrs_pdsch_typeA_pos_3) {
add_pos_end = srslte_dmrs_pdsch_add_pos_1;
if (pdsch_cfg.dmrs_typeA.typeA_pos == srslte_dmrs_sch_typeA_pos_3) {
add_pos_end = srslte_dmrs_sch_add_pos_1;
}
for (pdsch_cfg.dmrs_cfg_typeA.additional_pos = add_pos_begin;
pdsch_cfg.dmrs_cfg_typeA.additional_pos <= add_pos_end;
pdsch_cfg.dmrs_cfg_typeA.additional_pos++) {
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++) {
srslte_dmrs_pdsch_len_t max_len_begin = srslte_dmrs_pdsch_len_1;
srslte_dmrs_pdsch_len_t max_len_end = srslte_dmrs_pdsch_len_2;
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_cfg_typeA.additional_pos == srslte_dmrs_pdsch_add_pos_2 ||
pdsch_cfg.dmrs_cfg_typeA.additional_pos == srslte_dmrs_pdsch_add_pos_3) {
max_len_end = srslte_dmrs_pdsch_len_1;
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) {
max_len_end = srslte_dmrs_sch_len_1;
}
for (pdsch_cfg.dmrs_cfg_typeA.length = max_len_begin; pdsch_cfg.dmrs_cfg_typeA.length <= max_len_end;
pdsch_cfg.dmrs_cfg_typeA.length++) {
for (pdsch_cfg.dmrs_typeA.length = max_len_begin; pdsch_cfg.dmrs_typeA.length <= max_len_end;
pdsch_cfg.dmrs_typeA.length++) {
for (uint32_t bw = 1; bw <= carrier.nof_prb; bw++) {
@ -314,22 +312,21 @@ int main(int argc, char** argv)
grant.nof_dmrs_cdm_groups_without_data++) {
// Load default type A grant
srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &grant);
srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &grant);
// Copy configuration
pdsch_cfg.dmrs_cfg_typeB = pdsch_cfg.dmrs_cfg_typeA;
pdsch_cfg.dmrs_typeB = pdsch_cfg.dmrs_typeA;
int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res);
if (n == SRSLTE_SUCCESS) {
test_passed++;
} else {
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg = grant.mapping == srslte_pdsch_mapping_type_A
? &pdsch_cfg.dmrs_cfg_typeA
: &pdsch_cfg.dmrs_cfg_typeB;
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_pdsch_cfg_to_str(dmrs_cfg, str, 64);
srslte_dmrs_sch_cfg_to_str(dmrs_cfg, str, 64);
ERROR("Test %d failed. %s.\n", test_counter, str);
}
@ -349,7 +346,7 @@ clean_exit:
free(sf_symbols);
}
srslte_chest_dl_res_free(&chest_dl_res);
srslte_dmrs_pdsch_free(&dmrs_pdsch);
srslte_dmrs_sch_free(&dmrs_pdsch);
ret = test_passed == test_counter ? SRSLTE_SUCCESS : SRSLTE_ERROR;
printf("%s, %d of %d test passed successfully.\n", ret ? "Failed" : "Passed", test_passed, test_counter);

View File

@ -35,12 +35,12 @@ uint32_t srslte_coreset_get_sz(const srslte_coreset_t* coreset)
return srslte_coreset_get_bw(coreset) * SRSLTE_NRE * coreset->duration;
}
const char* srslte_pdsch_mapping_type_to_str(srslte_pdsch_mapping_type_t mapping_type)
const char* srslte_sch_mapping_type_to_str(srslte_sch_mapping_type_t mapping_type)
{
switch (mapping_type) {
case srslte_pdsch_mapping_type_A:
case srslte_sch_mapping_type_A:
return "A";
case srslte_pdsch_mapping_type_B:
case srslte_sch_mapping_type_B:
return "B";
default:
return "undefined";

View File

@ -66,7 +66,7 @@ int srslte_enb_dl_nr_init(srslte_enb_dl_nr_t* q, cf_t* output[SRSLTE_MAX_PORTS],
srslte_ofdm_tx_init_cfg(&q->fft[i], &fft_cfg);
}
if (srslte_dmrs_pdsch_init(&q->dmrs, false) < SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_init(&q->dmrs, false) < SRSLTE_SUCCESS) {
ERROR("Error DMRS\n");
return SRSLTE_ERROR;
}
@ -94,7 +94,7 @@ void srslte_enb_dl_nr_free(srslte_enb_dl_nr_t* q)
}
srslte_pdsch_nr_free(&q->pdsch);
srslte_dmrs_pdsch_free(&q->dmrs);
srslte_dmrs_sch_free(&q->dmrs);
srslte_pdcch_nr_free(&q->pdcch);
@ -107,7 +107,7 @@ int srslte_enb_dl_nr_set_carrier(srslte_enb_dl_nr_t* q, const srslte_carrier_nr_
return SRSLTE_ERROR;
}
if (srslte_dmrs_pdsch_set_carrier(&q->dmrs, carrier) < SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_set_carrier(&q->dmrs, carrier) < SRSLTE_SUCCESS) {
ERROR("Error DMRS\n");
return SRSLTE_ERROR;
}
@ -213,14 +213,14 @@ int srslte_enb_dl_nr_pdcch_put(srslte_enb_dl_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB])
int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB])
{
if (srslte_dmrs_pdsch_put_sf(&q->dmrs, slot, cfg, grant, q->sf_symbols[0]) < SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_put_sf(&q->dmrs, slot, cfg, grant, q->sf_symbols[0]) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -231,11 +231,11 @@ int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
char* str,
uint32_t str_len)
int srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len)
{
int len = 0;

View File

@ -198,11 +198,11 @@ static void srslte_pdsch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count,
* - 1, data is mapped in RE marked as 2
* - Otherwise, no data is mapped in this symbol
*/
static uint32_t srslte_pdsch_nr_cp_dmrs_type1(const srslte_pdsch_nr_t* q,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
static uint32_t srslte_pdsch_nr_cp_dmrs_type1(const srslte_pdsch_nr_t* q,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
uint32_t delta = 0;
@ -239,11 +239,11 @@ static uint32_t srslte_pdsch_nr_cp_dmrs_type1(const srslte_pdsch_nr_t* q,
* - 2, data is mapped in RE marked as 3
* - otherwise, no data is mapped in this symbol
*/
static uint32_t srslte_pdsch_nr_cp_dmrs_type2(const srslte_pdsch_nr_t* q,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
static uint32_t srslte_pdsch_nr_cp_dmrs_type2(const srslte_pdsch_nr_t* q,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
@ -269,23 +269,23 @@ static uint32_t srslte_pdsch_nr_cp_dmrs_type2(const srslte_pdsch_nr_t* q,
return count;
}
static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &cfg->dmrs_cfg_typeA : &cfg->dmrs_cfg_typeB;
const srslte_dmrs_sch_cfg_t* dmrs_cfg =
grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB;
switch (dmrs_cfg->type) {
case srslte_dmrs_pdsch_type_1:
case srslte_dmrs_sch_type_1:
count = srslte_pdsch_nr_cp_dmrs_type1(q, grant, symbols, sf_symbols, put);
break;
case srslte_dmrs_pdsch_type_2:
case srslte_dmrs_sch_type_2:
count = srslte_pdsch_nr_cp_dmrs_type2(q, grant, symbols, sf_symbols, put);
break;
}
@ -293,11 +293,11 @@ static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q,
return count;
}
static uint32_t srslte_pdsch_nr_cp_clean(const srslte_pdsch_nr_t* q,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
static uint32_t srslte_pdsch_nr_cp_clean(const srslte_pdsch_nr_t* q,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
uint32_t start = 0; // Index of the start of continuous data
@ -339,19 +339,19 @@ static uint32_t srslte_pdsch_nr_cp_clean(const srslte_pdsch_nr_t* q,
return count;
}
static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
uint32_t dmrs_l_idx[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS] = {};
uint32_t dmrs_l_count = 0;
uint32_t count = 0;
uint32_t dmrs_l_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
uint32_t dmrs_l_count = 0;
// Get symbol indexes carrying DMRS
int32_t nof_dmrs_symbols = srslte_dmrs_pdsch_get_symbols_idx(cfg, grant, dmrs_l_idx);
int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(cfg, grant, dmrs_l_idx);
if (nof_dmrs_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -381,26 +381,26 @@ static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q,
return count;
}
static int srslte_pdsch_nr_put(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
static int srslte_pdsch_nr_put(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
{
return srslte_pdsch_nr_cp(q, cfg, grant, symbols, sf_symbols, true);
}
static int srslte_pdsch_nr_get(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
static int srslte_pdsch_nr_get(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
{
return srslte_pdsch_nr_cp(q, cfg, grant, symbols, sf_symbols, false);
}
static uint32_t
pdsch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_pdsch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx)
pdsch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx)
{
uint32_t n_id = carrier->id;
if (cfg->scrambling_id_present && SRSLTE_RNTI_ISUSER(rnti)) {
@ -413,11 +413,11 @@ pdsch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_pdsch_cfg_nr_t*
return cinit;
}
static inline int pdsch_nr_encode_codeword(srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint16_t rnti)
static inline int pdsch_nr_encode_codeword(srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint16_t rnti)
{
// Early return if TB is not enabled
if (!tb->enabled) {
@ -462,11 +462,11 @@ static inline int pdsch_nr_encode_codeword(srslte_pdsch_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_pdsch_nr_encode(srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB],
cf_t* sf_symbols[SRSLTE_MAX_PORTS])
int srslte_pdsch_nr_encode(srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB],
cf_t* sf_symbols[SRSLTE_MAX_PORTS])
{
// Check input pointers
@ -530,11 +530,11 @@ int srslte_pdsch_nr_encode(srslte_pdsch_nr_t* q,
return SRSLTE_SUCCESS;
}
static inline int pdsch_nr_decode_codeword(srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_sch_tb_t* tb,
srslte_pdsch_res_nr_t* res,
uint16_t rnti)
static inline int pdsch_nr_decode_codeword(srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_tb_t* tb,
srslte_pdsch_res_nr_t* res,
uint16_t rnti)
{
// Early return if TB is not enabled
if (!tb->enabled) {
@ -591,12 +591,12 @@ static inline int pdsch_nr_decode_codeword(srslte_pdsch_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_pdsch_nr_decode(srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_pdsch_res_nr_t data[SRSLTE_MAX_TB])
int srslte_pdsch_nr_decode(srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_pdsch_res_nr_t data[SRSLTE_MAX_TB])
{
// Check input pointers
if (!q || !cfg || !grant || !data || !sf_symbols) {
@ -666,10 +666,10 @@ int srslte_pdsch_nr_decode(srslte_pdsch_nr_t* q,
return SRSLTE_SUCCESS;
}
static uint32_t srslte_pdsch_nr_grant_info(const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
char* str,
uint32_t str_len)
static uint32_t srslte_pdsch_nr_grant_info(const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len)
{
uint32_t len = 0;
len = srslte_print_check(str, str_len, len, "rnti=0x%x", grant->rnti);
@ -682,7 +682,7 @@ static uint32_t srslte_pdsch_nr_grant_info(const srslte_pdsch_cfg_nr_t* cfg,
grant->k0,
grant->S,
grant->L,
srslte_pdsch_mapping_type_to_str(grant->mapping));
srslte_sch_mapping_type_to_str(grant->mapping));
// Skip frequency domain resources...
// ...
@ -701,12 +701,12 @@ static uint32_t srslte_pdsch_nr_grant_info(const srslte_pdsch_cfg_nr_t* cfg,
return len;
}
uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len)
uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len)
{
uint32_t len = 0;
@ -750,11 +750,11 @@ uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q,
return len;
}
uint32_t srslte_pdsch_nr_tx_info(const srslte_pdsch_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
char* str,
uint32_t str_len)
uint32_t srslte_pdsch_nr_tx_info(const srslte_pdsch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len)
{
uint32_t len = 0;

769
lib/src/phy/phch/pusch_nr.c Normal file
View File

@ -0,0 +1,769 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/phch/pusch_nr.h"
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/ra_nr.h"
int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args)
{
for (srslte_mod_t mod = SRSLTE_MOD_BPSK; mod < SRSLTE_MOD_NITEMS; mod++) {
if (srslte_modem_table_lte(&q->modem_tables[mod], mod) < SRSLTE_SUCCESS) {
ERROR("Error initialising modem table for %s\n", srslte_mod_string(mod));
return SRSLTE_ERROR;
}
if (args->measure_evm) {
srslte_modem_table_bytes(&q->modem_tables[mod]);
}
}
return SRSLTE_SUCCESS;
}
int srslte_pusch_nr_init_enb(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args)
{
if (q == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (pusch_nr_init_common(q, args) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
if (srslte_sch_nr_init_tx(&q->sch, &args->sch)) {
ERROR("Initialising SCH\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_pusch_nr_init_ue(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args)
{
if (q == NULL || args == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (pusch_nr_init_common(q, args) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
if (srslte_sch_nr_init_rx(&q->sch, &args->sch)) {
ERROR("Initialising SCH\n");
return SRSLTE_ERROR;
}
if (args->measure_evm) {
q->evm_buffer = srslte_evm_buffer_alloc(8);
if (q->evm_buffer == NULL) {
ERROR("Initialising EVM\n");
return SRSLTE_ERROR;
}
}
q->meas_time_en = args->measure_time;
return SRSLTE_SUCCESS;
}
int srslte_pusch_nr_set_carrier(srslte_pusch_nr_t* q, const srslte_carrier_nr_t* carrier)
{
// Set carrier
q->carrier = *carrier;
// Reallocate symbols if necessary
if (q->max_layers < carrier->max_mimo_layers || q->max_prb < carrier->nof_prb) {
q->max_layers = carrier->max_mimo_layers;
q->max_prb = carrier->nof_prb;
// Free current allocations
for (uint32_t i = 0; i < SRSLTE_MAX_LAYERS_NR; i++) {
if (q->x[i] != NULL) {
free(q->x[i]);
}
}
// Allocate for new sizes
for (uint32_t i = 0; i < q->max_layers; i++) {
q->x[i] = srslte_vec_cf_malloc(SRSLTE_SLOT_LEN_RE_NR(q->max_prb));
if (q->x[i] == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
}
}
// Allocate code words according to table 7.3.1.3-1
uint32_t max_cw = (q->max_layers > 5) ? 2 : 1;
if (q->max_cw < max_cw) {
q->max_cw = max_cw;
for (uint32_t i = 0; i < max_cw; i++) {
if (q->b[i] == NULL) {
q->b[i] = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
if (q->b[i] == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
}
if (q->d[i] == NULL) {
q->d[i] = srslte_vec_cf_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
if (q->d[i] == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
}
}
}
// Set carrier in SCH
if (srslte_sch_nr_set_carrier(&q->sch, carrier) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
if (q->evm_buffer != NULL) {
srslte_evm_buffer_resize(q->evm_buffer, SRSLTE_SLOT_LEN_RE_NR(q->max_prb) * SRSLTE_MAX_QM);
}
return SRSLTE_SUCCESS;
}
void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
{
if (q == NULL) {
return;
}
for (uint32_t cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
if (q->b[cw]) {
free(q->b[cw]);
}
if (q->d[cw]) {
free(q->d[cw]);
}
}
srslte_sch_nr_free(&q->sch);
for (uint32_t i = 0; i < SRSLTE_MAX_LAYERS_NR; i++) {
if (q->x[i]) {
free(q->x[i]);
}
}
for (srslte_mod_t mod = SRSLTE_MOD_BPSK; mod < SRSLTE_MOD_NITEMS; mod++) {
srslte_modem_table_free(&q->modem_tables[mod]);
}
if (q->evm_buffer != NULL) {
srslte_evm_free(q->evm_buffer);
}
}
/**
* @brief copies a number of countiguous Resource Elements
* @param sf_symbols slot symbols in frequency domain
* @param symbols resource elements
* @param count number of resource elements to copy
* @param put Direction, symbols are copied into sf_symbols if put is true, otherwise sf_symbols are copied into symbols
*/
static void srslte_pusch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count, bool put)
{
if (put) {
srslte_vec_cf_copy(sf_symbols, symbols, count);
} else {
srslte_vec_cf_copy(symbols, sf_symbols, count);
}
}
/*
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2:
*
* +---+---+---+---+---+---+---+---+---+---+---+---+
* | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* -- k -->
*
* If the number of DMRS CDM groups without data is set to:
* - 1, data is mapped in RE marked as 2
* - Otherwise, no data is mapped in this symbol
*/
static uint32_t srslte_pusch_nr_cp_dmrs_type1(const srslte_pusch_nr_t* q,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
uint32_t delta = 0;
if (grant->nof_dmrs_cdm_groups_without_data != 1) {
return count;
}
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
if (grant->prb_idx[i]) {
for (uint32_t j = 0; j < SRSLTE_NRE; j += 2) {
if (put) {
sf_symbols[i * SRSLTE_NRE + delta + j + 1] = symbols[count++];
} else {
symbols[count++] = sf_symbols[i * SRSLTE_NRE + delta + j + 1];
}
}
}
}
return count;
}
/*
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with groups 2 and 3:
*
* +---+---+---+---+---+---+---+---+---+---+---+---+
* | 1 | 1 | 2 | 2 | 3 | 3 | 1 | 1 | 2 | 2 | 3 | 3 |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* -- k -->
*
* If the number of DMRS CDM groups without data is set to:
* - 1, data is mapped in RE marked as 2 and 3
* - 2, data is mapped in RE marked as 3
* - otherwise, no data is mapped in this symbol
*/
static uint32_t srslte_pusch_nr_cp_dmrs_type2(const srslte_pusch_nr_t* q,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) {
return count;
}
uint32_t re_offset = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 2 : 4;
uint32_t re_count = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 4 : 2;
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
if (grant->prb_idx[i]) {
// Copy RE between pilot pairs
srslte_pusch_re_cp(&sf_symbols[i * SRSLTE_NRE + re_offset], &symbols[count], re_count, put);
count += re_count;
// Copy RE after second pilot
srslte_pusch_re_cp(&sf_symbols[(i + 1) * SRSLTE_NRE - re_count], &symbols[count], re_count, put);
count += re_count;
}
}
return count;
}
static uint32_t srslte_pusch_nr_cp_dmrs(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
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;
switch (dmrs_cfg->type) {
case srslte_dmrs_sch_type_1:
count = srslte_pusch_nr_cp_dmrs_type1(q, grant, symbols, sf_symbols, put);
break;
case srslte_dmrs_sch_type_2:
count = srslte_pusch_nr_cp_dmrs_type2(q, grant, symbols, sf_symbols, put);
break;
}
return count;
}
static uint32_t srslte_pusch_nr_cp_clean(const srslte_pusch_nr_t* q,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
uint32_t start = 0; // Index of the start of continuous data
uint32_t length = 0; // End of continuous RE
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
if (grant->prb_idx[i]) {
// If fist continuous block, save start
if (length == 0) {
start = i * SRSLTE_NRE;
}
length += SRSLTE_NRE;
} else {
// Consecutive block is finished
if (put) {
srslte_vec_cf_copy(&sf_symbols[start], &symbols[count], length);
} else {
srslte_vec_cf_copy(&symbols[count], &sf_symbols[start], length);
}
// Increase RE count
count += length;
// Reset consecutive block
length = 0;
}
}
// Copy last contiguous block
if (length > 0) {
if (put) {
srslte_vec_cf_copy(&sf_symbols[start], &symbols[count], length);
} else {
srslte_vec_cf_copy(&symbols[count], &sf_symbols[start], length);
}
count += length;
}
return count;
}
static int srslte_pusch_nr_cp(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols,
bool put)
{
uint32_t count = 0;
uint32_t dmrs_l_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
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);
if (nof_dmrs_symbols < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("dmrs_l_idx=");
srslte_vec_fprint_i(stdout, (int32_t*)dmrs_l_idx, nof_dmrs_symbols);
}
for (uint32_t l = grant->S; l < grant->S + grant->L; l++) {
// Advance DMRS symbol counter until:
// - the current DMRS symbol index is greater or equal than current symbol l
// - no more DMRS symbols
while (dmrs_l_idx[dmrs_l_count] < l && dmrs_l_count < nof_dmrs_symbols) {
dmrs_l_count++;
}
if (l == dmrs_l_idx[dmrs_l_count]) {
count += srslte_pusch_nr_cp_dmrs(
q, cfg, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSLTE_NRE], put);
} else {
count +=
srslte_pusch_nr_cp_clean(q, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSLTE_NRE], put);
}
}
return count;
}
static int srslte_pusch_nr_put(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
{
return srslte_pusch_nr_cp(q, cfg, grant, symbols, sf_symbols, true);
}
static int srslte_pusch_nr_get(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* symbols,
cf_t* sf_symbols)
{
return srslte_pusch_nr_cp(q, cfg, grant, symbols, sf_symbols, false);
}
static uint32_t
pusch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx)
{
uint32_t n_id = carrier->id;
if (cfg->scrambling_id_present && SRSLTE_RNTI_ISUSER(rnti)) {
n_id = cfg->scambling_id;
}
uint32_t cinit = (((uint32_t)rnti) << 15U) + (cw_idx << 14U) + n_id;
INFO("PUSCH: RNTI=%d (0x%x); nid=%d; cinit=%d (0x%x);\n", rnti, rnti, n_id, cinit, cinit);
return cinit;
}
static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint16_t rnti)
{
// Early return if TB is not enabled
if (!tb->enabled) {
return SRSLTE_SUCCESS;
}
// Check codeword index
if (tb->cw_idx >= q->max_cw) {
ERROR("Unsupported codeword index %d\n", tb->cw_idx);
return SRSLTE_ERROR;
}
// Check modulation
if (tb->mod >= SRSLTE_MOD_NITEMS) {
ERROR("Invalid modulation %s\n", srslte_mod_string(tb->mod));
return SRSLTE_ERROR_OUT_OF_BOUNDS;
}
// Encode SCH
if (srslte_ulsch_nr_encode(&q->sch, &cfg->sch_cfg, tb, data, q->b[tb->cw_idx]) < SRSLTE_SUCCESS) {
ERROR("Error in DL-SCH encoding\n");
return SRSLTE_ERROR;
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
}
// 7.3.1.1 Scrambling
uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx);
srslte_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit);
// 7.3.1.2 Modulation
srslte_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits);
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("d=");
srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
}
return SRSLTE_SUCCESS;
}
int srslte_pusch_nr_encode(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
uint8_t* data[SRSLTE_MAX_TB],
cf_t* sf_symbols[SRSLTE_MAX_PORTS])
{
// Check input pointers
if (!q || !cfg || !grant || !data || !sf_symbols) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
struct timeval t[3];
if (q->meas_time_en) {
gettimeofday(&t[1], NULL);
}
// Check number of layers
if (q->max_layers < grant->nof_layers) {
ERROR("Error number of layers (%d) exceeds configured maximum (%d)\n", grant->nof_layers, q->max_layers);
return SRSLTE_ERROR;
}
// 7.3.1.1 and 7.3.1.2
uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0;
if (pusch_nr_encode_codeword(q, cfg, &grant->tb[tb], data[tb], grant->rnti) < SRSLTE_SUCCESS) {
ERROR("Error encoding TB %d\n", tb);
return SRSLTE_ERROR;
}
}
// 7.3.1.3 Layer mapping
cf_t** x = q->d;
if (grant->nof_layers > 1) {
x = q->x;
srslte_layermap_nr(q->d, nof_cw, x, grant->nof_layers, grant->nof_layers);
}
// 7.3.1.4 Antenna port mapping
// ... Not implemented
// 7.3.1.5 Mapping to virtual resource blocks
// ... Not implemented
// 7.3.1.6 Mapping from virtual to physical resource blocks
int n = srslte_pusch_nr_put(q, cfg, grant, x[0], sf_symbols[0]);
if (n < SRSLTE_SUCCESS) {
ERROR("Putting NR PUSCH resources\n");
return SRSLTE_ERROR;
}
if (n != grant->tb[0].nof_re) {
ERROR("Unmatched number of RE (%d != %d)\n", n, grant->tb[0].nof_re);
return SRSLTE_ERROR;
}
if (q->meas_time_en) {
gettimeofday(&t[2], NULL);
get_time_interval(t);
q->meas_time_us = (uint32_t)t[0].tv_usec;
}
return SRSLTE_SUCCESS;
}
static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_tb_t* tb,
srslte_pusch_res_nr_t* res,
uint16_t rnti)
{
// Early return if TB is not enabled
if (!tb->enabled) {
return SRSLTE_SUCCESS;
}
// Check codeword index
if (tb->cw_idx >= q->max_cw) {
ERROR("Unsupported codeword index %d\n", tb->cw_idx);
return SRSLTE_ERROR;
}
// Check modulation
if (tb->mod >= SRSLTE_MOD_NITEMS) {
ERROR("Invalid modulation %s\n", srslte_mod_string(tb->mod));
return SRSLTE_ERROR_OUT_OF_BOUNDS;
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("d=");
srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
}
// Demodulation
int8_t* llr = (int8_t*)q->b[tb->cw_idx];
if (srslte_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) {
return SRSLTE_ERROR;
}
// EVM
if (q->evm_buffer != NULL) {
res->evm = srslte_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
}
// Change LLR sign
for (uint32_t i = 0; i < tb->nof_bits; i++) {
llr[i] = -llr[i];
}
// Descrambling
srslte_sequence_apply_c(llr, llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
}
// Decode SCH
if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSLTE_SUCCESS) {
ERROR("Error in DL-SCH encoding\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
int srslte_pusch_nr_decode(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
srslte_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSLTE_MAX_PORTS],
srslte_pusch_res_nr_t data[SRSLTE_MAX_TB])
{
// Check input pointers
if (!q || !cfg || !grant || !data || !sf_symbols) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
struct timeval t[3];
if (q->meas_time_en) {
gettimeofday(&t[1], NULL);
}
uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0;
}
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(cfg, grant);
if (channel->nof_re != nof_re) {
ERROR("Inconsistent number of RE (%d!=%d)\n", channel->nof_re, nof_re);
return SRSLTE_ERROR;
}
// Demapping from virtual to physical resource blocks
uint32_t nof_re_get = srslte_pusch_nr_get(q, cfg, grant, q->x[0], sf_symbols[0]);
if (nof_re_get != nof_re) {
ERROR("Inconsistent number of RE (%d!=%d)\n", nof_re_get, nof_re);
return SRSLTE_ERROR;
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("ce=");
srslte_vec_fprint_c(stdout, channel->ce[0][0], nof_re);
DEBUG("x=");
srslte_vec_fprint_c(stdout, q->x[0], nof_re);
}
// Demapping to virtual resource blocks
// ... Not implemented
// Antenna port demapping
// ... Not implemented
srslte_predecoding_type(
q->x, channel->ce, q->d, NULL, 1, 1, 1, 0, nof_re, SRSLTE_TXSCHEME_PORT0, 1.0f, channel->noise_estimate);
// Layer demapping
if (grant->nof_layers > 1) {
srslte_layerdemap_nr(q->d, nof_cw, q->x, grant->nof_layers, nof_re);
}
// SCH decode
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0;
if (pusch_nr_decode_codeword(q, cfg, &grant->tb[tb], &data[tb], grant->rnti) < SRSLTE_SUCCESS) {
ERROR("Error encoding TB %d\n", tb);
return SRSLTE_ERROR;
}
}
if (q->meas_time_en) {
gettimeofday(&t[2], NULL);
get_time_interval(t);
q->meas_time_us = (uint32_t)t[0].tv_usec;
}
return SRSLTE_SUCCESS;
}
static uint32_t srslte_pusch_nr_grant_info(const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len)
{
uint32_t len = 0;
len = srslte_print_check(str, str_len, len, "rnti=0x%x", grant->rnti);
// Append time-domain resource mapping
len = srslte_print_check(str,
str_len,
len,
",k0=%d,S=%d,L=%d,mapping=%s",
grant->k0,
grant->S,
grant->L,
srslte_sch_mapping_type_to_str(grant->mapping));
// Skip frequency domain resources...
// ...
// Append spatial resources
len = srslte_print_check(str, str_len, len, ",Nl=%d", grant->nof_layers);
// Append scrambling ID
len = srslte_print_check(str, str_len, len, ",n_scid=%d,", grant->n_scid);
// Append TB info
for (uint32_t i = 0; i < SRSLTE_MAX_TB; i++) {
len += srslte_sch_nr_tb_info(&grant->tb[i], &str[len], str_len - len);
}
return len;
}
uint32_t srslte_pusch_nr_rx_info(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
const srslte_pusch_res_nr_t res[SRSLTE_MAX_CODEWORDS],
char* str,
uint32_t str_len)
{
uint32_t len = 0;
len += srslte_pusch_nr_grant_info(cfg, grant, &str[len], str_len - len);
if (q->evm_buffer != NULL) {
len = srslte_print_check(str, str_len, len, ",evm={", 0);
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled && !isnan(res[i].evm)) {
len = srslte_print_check(str, str_len, len, "%.2f", res[i].evm);
if (i < SRSLTE_MAX_CODEWORDS - 1) {
if (grant->tb[i + 1].enabled) {
len = srslte_print_check(str, str_len, len, ",", 0);
}
}
}
}
len = srslte_print_check(str, str_len, len, "}", 0);
}
if (res != NULL) {
len = srslte_print_check(str, str_len, len, ",crc={", 0);
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled) {
len = srslte_print_check(str, str_len, len, "%s", res[i].crc ? "OK" : "KO");
if (i < SRSLTE_MAX_CODEWORDS - 1) {
if (grant->tb[i + 1].enabled) {
len = srslte_print_check(str, str_len, len, ",", 0);
}
}
}
}
len = srslte_print_check(str, str_len, len, "}", 0);
}
if (q->meas_time_en) {
len = srslte_print_check(str, str_len, len, ", t=%d us\n", q->meas_time_us);
}
return len;
}
uint32_t srslte_pusch_nr_tx_info(const srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
char* str,
uint32_t str_len)
{
uint32_t len = 0;
len += srslte_pusch_nr_grant_info(cfg, grant, &str[len], str_len - len);
if (q->meas_time_en) {
len = srslte_print_check(str, str_len, len, ", t=%d us\n", q->meas_time_us);
}
return len;
}

View File

@ -108,10 +108,63 @@ static const uint32_t ra_nr_tbs_table[RA_NR_TBS_SIZE_TABLE] = {
typedef enum { ra_nr_table_1 = 0, ra_nr_table_2, ra_nr_table_3 } ra_nr_table_t;
static ra_nr_table_t ra_nr_select_table(srslte_mcs_table_t mcs_table,
srslte_dci_format_nr_t dci_format,
srslte_search_space_type_t search_space_type,
srslte_rnti_type_t rnti_type)
static ra_nr_table_t ra_nr_select_table_pusch_noprecoding(srslte_mcs_table_t mcs_table,
srslte_dci_format_nr_t dci_format,
srslte_search_space_type_t search_space_type,
srslte_rnti_type_t rnti_type)
{
// Non-implemented parameters
bool mcs_c_rnti = false;
srslte_mcs_table_t configured_grant_table = srslte_mcs_table_64qam;
// - if mcs-Table in pusch-Config is set to 'qam256', and
// - PUSCH is scheduled by a PDCCH with DCI format 0_1 with
// - CRC scrambled by C-RNTI or SP-CSI-RNTI,
if (mcs_table == srslte_mcs_table_256qam && dci_format == srslte_dci_format_nr_0_1 &&
(rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_sp_csi)) {
return ra_nr_table_2;
}
// - the UE is not configured with MCS-C-RNTI,
// - mcs-Table in pusch-Config is set to 'qam64LowSE', and the
// - PUSCH is scheduled by a PDCCH in a UE-specific search space with
// - CRC scrambled by C-RNTI or SP-CSI-RNTI,
if (!mcs_c_rnti && mcs_table == srslte_mcs_table_qam64LowSE && dci_format != srslte_dci_format_nr_rar &&
search_space_type == srslte_search_space_type_ue &&
(rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_sp_csi)) {
return ra_nr_table_3;
}
// - 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) {
return ra_nr_table_3;
}
// - mcs-Table in configuredGrantConfig is set to 'qam256',
// - if PUSCH is scheduled by a PDCCH with CRC scrambled by CS-RNTI or
// - if PUSCH is transmitted with configured grant
if (configured_grant_table == srslte_mcs_table_256qam &&
(rnti_type == srslte_rnti_type_cs || dci_format == srslte_dci_format_nr_cg)) {
return ra_nr_table_2;
}
// - mcs-Table in configuredGrantConfig is set to 'qam64LowSE'
// - if PUSCH is scheduled by a PDCCH with CRC scrambled by CS-RNTI or
// - if PUSCH is transmitted with configured grant,
if (configured_grant_table == srslte_mcs_table_qam64LowSE &&
(rnti_type == srslte_rnti_type_cs || dci_format == srslte_dci_format_nr_cg)) {
return ra_nr_table_3;
}
return ra_nr_table_1;
}
static ra_nr_table_t ra_nr_select_table_pdsch(srslte_mcs_table_t mcs_table,
srslte_dci_format_nr_t dci_format,
srslte_search_space_type_t search_space_type,
srslte_rnti_type_t rnti_type)
{
// Non-implemented parameters
bool sps_config_mcs_table_present = false;
@ -156,6 +209,21 @@ static ra_nr_table_t ra_nr_select_table(srslte_mcs_table_t mcs_table,
return ra_nr_table_1;
}
static ra_nr_table_t ra_nr_select_table(srslte_mcs_table_t mcs_table,
srslte_dci_format_nr_t dci_format,
srslte_search_space_type_t search_space_type,
srslte_rnti_type_t rnti_type)
{
// Check if it is a PUSCH transmission
if (dci_format == srslte_dci_format_nr_0_0 || dci_format == srslte_dci_format_nr_0_1 ||
dci_format == srslte_dci_format_nr_rar || dci_format == srslte_dci_format_nr_cg) {
return ra_nr_select_table_pusch_noprecoding(mcs_table, dci_format, search_space_type, rnti_type);
}
return ra_nr_select_table_pdsch(mcs_table, dci_format, search_space_type, rnti_type);
}
double srslte_ra_nr_R_from_mcs(srslte_mcs_table_t mcs_table,
srslte_dci_format_nr_t dci_format,
srslte_search_space_type_t search_space_type,
@ -200,13 +268,13 @@ srslte_mod_t srslte_ra_nr_mod_from_mcs(srslte_mcs_table_t mcs_table,
return SRSLTE_MOD_NITEMS;
}
int srslte_ra_dl_nr_slot_nof_re(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch_grant_nr_t* grant)
int srslte_ra_dl_nr_slot_nof_re(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_grant_nr_t* grant)
{
// the number of symbols of the PDSCH allocation within the slot
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_pdsch_get_N_prb(pdsch_cfg, grant);
int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(pdsch_cfg, grant);
if (n_prb_dmrs < SRSLTE_SUCCESS) {
ERROR("Invalid number of DMRS RE\n");
return SRSLTE_ERROR;
@ -319,10 +387,10 @@ uint32_t srslte_ra_nr_tbs(uint32_t N_re, double S, double R, uint32_t Qm, uint32
return ra_nr_tbs_from_n_info4(n_info, R);
}
int srslte_ra_nr_fill_tb(const srslte_pdsch_cfg_nr_t* pdsch_cfg,
const srslte_pdsch_grant_nr_t* grant,
uint32_t mcs_idx,
srslte_sch_tb_t* tb)
int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t mcs_idx,
srslte_sch_tb_t* tb)
{
uint32_t cw_idx = 0;

View File

@ -65,10 +65,10 @@ uint32_t sch_nr_n_prb_lbrm(uint32_t nof_prb)
return 273;
}
int srslte_dlsch_nr_fill_cfg(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_common_cfg_t* cfg)
int srslte_sch_nr_fill_cfg(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_common_cfg_t* cfg)
{
if (!sch_cfg || !tb || !cfg) {
@ -357,14 +357,14 @@ void srslte_sch_nr_free(srslte_sch_nr_t* q)
srslte_ldpc_rm_rx_free_c(&q->rx_rm);
}
int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* pdsch_cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint8_t* e_bits)
static inline int sch_nr_encode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint8_t* e_bits)
{
// Pointer protection
if (!q || !pdsch_cfg || !tb || !data || !e_bits) {
if (!q || !sch_cfg || !tb || !data || !e_bits) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
@ -377,7 +377,7 @@ int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
uint8_t* output_ptr = e_bits;
srslte_sch_nr_common_cfg_t cfg = {};
if (srslte_dlsch_nr_fill_cfg(q, pdsch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
if (srslte_sch_nr_fill_cfg(q, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -500,12 +500,12 @@ int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
int8_t* e_bits,
uint8_t* data,
bool* crc_ok)
int sch_nr_decode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
int8_t* e_bits,
uint8_t* data,
bool* crc_ok)
{
// Pointer protection
if (!q || !sch_cfg || !tb || !data || !e_bits || !crc_ok) {
@ -515,7 +515,7 @@ int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
int8_t* input_ptr = e_bits;
srslte_sch_nr_common_cfg_t cfg = {};
if (srslte_dlsch_nr_fill_cfg(q, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
if (srslte_sch_nr_fill_cfg(q, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -655,6 +655,44 @@ int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* pdsch_cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint8_t* e_bits)
{
return sch_nr_encode(q, pdsch_cfg, tb, data, e_bits);
}
int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
int8_t* e_bits,
uint8_t* data,
bool* crc_ok)
{
return sch_nr_decode(q, sch_cfg, tb, e_bits, data, crc_ok);
}
int srslte_ulsch_nr_encode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* pdsch_cfg,
const srslte_sch_tb_t* tb,
const uint8_t* data,
uint8_t* e_bits)
{
return sch_nr_encode(q, pdsch_cfg, tb, data, e_bits);
}
int srslte_ulsch_nr_decode(srslte_sch_nr_t* q,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
int8_t* e_bits,
uint8_t* data,
bool* crc_ok)
{
return sch_nr_decode(q, sch_cfg, tb, e_bits, data, crc_ok);
}
int srslte_sch_nr_tb_info(const srslte_sch_tb_t* tb, char* str, uint32_t str_len)
{
int len = 0;

View File

@ -614,14 +614,17 @@ endif(RF_FOUND)
# NR
########################################################################
add_executable(dlsch_nr_test dlsch_nr_test.c)
target_link_libraries(dlsch_nr_test srslte_phy)
add_test(dlsch_nr_test dlsch_nr_test -m 0 -p 1)
add_executable(sch_nr_test sch_nr_test.c)
target_link_libraries(sch_nr_test srslte_phy)
add_test(sch_nr_test sch_nr_test -m 0 -p 1)
add_executable(pdsch_nr_test pdsch_nr_test.c)
target_link_libraries(pdsch_nr_test srslte_phy)
add_test(pdsch_nr_test pdsch_nr_test -p 6 -m 20)
add_executable(pusch_nr_test pusch_nr_test.c)
target_link_libraries(pusch_nr_test srslte_phy)
add_test(pusch_nr_test pusch_nr_test -p 6 -m 20)
add_executable(pdcch_nr_test pdcch_nr_test.c)
target_link_libraries(pdcch_nr_test srslte_phy)

View File

@ -26,11 +26,11 @@ static srslte_carrier_nr_t carrier = {
1 // max_mimo_layers
};
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_pdsch_cfg_nr_t pdsch_cfg = {};
static srslte_pdsch_grant_nr_t pdsch_grant = {};
static uint16_t rnti = 0x1234;
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pdsch_cfg = {};
static srslte_sch_grant_nr_t pdsch_grant = {};
static uint16_t rnti = 0x1234;
void usage(char* prog)
{
@ -151,8 +151,7 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) <
SRSLTE_SUCCESS) {
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}

View File

@ -0,0 +1,301 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/phch/pusch_nr.h"
#include "srslte/phy/phch/ra_nr.h"
#include "srslte/phy/ue/ue_ul_nr_data.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/random.h"
#include "srslte/phy/utils/vector.h"
#include <getopt.h>
static srslte_carrier_nr_t carrier = {
1, // cell_id
0, // numerology
SRSLTE_MAX_PRB_NR, // nof_prb
0, // start
1 // max_mimo_layers
};
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pusch_cfg = {};
static srslte_sch_grant_nr_t pusch_grant = {};
static uint16_t rnti = 0x1234;
void usage(char* prog)
{
printf("Usage: %s [pTL] \n", prog);
printf("\t-p Number of grant PRB, set to 0 for steering [Default %d]\n", n_prb);
printf("\t-m MCS PRB, set to >28 for steering [Default %d]\n", mcs);
printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n",
srslte_mcs_table_to_str(pusch_cfg.sch_cfg.mcs_table));
printf("\t-L Provide number of layers [Default %d]\n", carrier.max_mimo_layers);
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
int parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "pmTLv")) != -1) {
switch (opt) {
case 'p':
n_prb = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'm':
mcs = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'T':
pusch_cfg.sch_cfg.mcs_table = srslte_mcs_table_from_str(argv[optind]);
break;
case 'L':
carrier.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'v':
srslte_verbose++;
break;
default:
usage(argv[0]);
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
}
int main(int argc, char** argv)
{
int ret = SRSLTE_ERROR;
srslte_pusch_nr_t pusch_tx = {};
srslte_pusch_nr_t pusch_rx = {};
srslte_chest_dl_res_t chest = {};
srslte_pusch_res_nr_t pusch_res[SRSLTE_MAX_TB] = {};
srslte_random_t rand_gen = srslte_random_init(1234);
uint8_t* data_tx[SRSLTE_MAX_TB] = {};
uint8_t* data_rx[SRSLTE_MAX_CODEWORDS] = {};
cf_t* sf_symbols[SRSLTE_MAX_LAYERS_NR] = {};
// Set default PUSCH configuration
pusch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam;
if (parse_args(argc, argv) < SRSLTE_SUCCESS) {
goto clean_exit;
}
srslte_pusch_nr_args_t pusch_args = {};
pusch_args.sch.disable_simd = false;
pusch_args.measure_evm = true;
if (srslte_pusch_nr_init_enb(&pusch_tx, &pusch_args) < SRSLTE_SUCCESS) {
ERROR("Error initiating PUSCH for Tx\n");
goto clean_exit;
}
if (srslte_pusch_nr_init_ue(&pusch_rx, &pusch_args) < SRSLTE_SUCCESS) {
ERROR("Error initiating SCH NR for Rx\n");
goto clean_exit;
}
if (srslte_pusch_nr_set_carrier(&pusch_tx, &carrier)) {
ERROR("Error setting SCH NR carrier\n");
goto clean_exit;
}
if (srslte_pusch_nr_set_carrier(&pusch_rx, &carrier)) {
ERROR("Error setting SCH NR carrier\n");
goto clean_exit;
}
for (uint32_t i = 0; i < carrier.max_mimo_layers; i++) {
sf_symbols[i] = srslte_vec_cf_malloc(SRSLTE_SLOT_LEN_RE_NR(carrier.nof_prb));
if (sf_symbols[i] == NULL) {
ERROR("Error malloc\n");
goto clean_exit;
}
}
for (uint32_t i = 0; i < pusch_tx.max_cw; i++) {
data_tx[i] = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
data_rx[i] = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR);
if (data_tx[i] == NULL || data_rx[i] == NULL) {
ERROR("Error malloc\n");
goto clean_exit;
}
pusch_res[i].payload = data_rx[i];
}
srslte_softbuffer_tx_t softbuffer_tx = {};
srslte_softbuffer_rx_t softbuffer_rx = {};
if (srslte_softbuffer_tx_init_guru(&softbuffer_tx, SRSLTE_SCH_NR_MAX_NOF_CB_LDPC, SRSLTE_LDPC_MAX_LEN_ENCODED_CB) <
SRSLTE_SUCCESS) {
ERROR("Error init soft-buffer\n");
goto clean_exit;
}
if (srslte_softbuffer_rx_init_guru(&softbuffer_rx, SRSLTE_SCH_NR_MAX_NOF_CB_LDPC, SRSLTE_LDPC_MAX_LEN_ENCODED_CB) <
SRSLTE_SUCCESS) {
ERROR("Error init soft-buffer\n");
goto clean_exit;
}
// Use grant default A time resources with m=0
if (srslte_ue_ul_nr_pdsch_time_resource_default_A(0, &pusch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}
// Load number of DMRS CDM groups without data
if (srslte_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups without data\n");
goto clean_exit;
}
pusch_grant.nof_layers = carrier.max_mimo_layers;
pusch_grant.dci_format = srslte_dci_format_nr_1_0;
pusch_grant.rnti = rnti;
uint32_t n_prb_start = 1;
uint32_t n_prb_end = carrier.nof_prb + 1;
if (n_prb > 0) {
n_prb_start = SRSLTE_MIN(n_prb, n_prb_end - 1);
n_prb_end = SRSLTE_MIN(n_prb + 1, n_prb_end);
}
uint32_t mcs_start = 0;
uint32_t mcs_end = pusch_cfg.sch_cfg.mcs_table == srslte_mcs_table_256qam ? 28 : 29;
if (mcs < mcs_end) {
mcs_start = SRSLTE_MIN(mcs, mcs_end - 1);
mcs_end = SRSLTE_MIN(mcs + 1, mcs_end);
}
if (srslte_chest_dl_res_init(&chest, carrier.nof_prb) < SRSLTE_SUCCESS) {
ERROR("Initiating chest\n");
goto clean_exit;
}
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
for (mcs = mcs_start; mcs < mcs_end; mcs++) {
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
pusch_grant.prb_idx[n] = (n < n_prb);
}
pusch_grant.dci_format = srslte_dci_format_nr_0_0;
if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_grant, mcs, &pusch_grant.tb[0]) < SRSLTE_SUCCESS) {
ERROR("Error filing tb\n");
goto clean_exit;
}
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
// Skip TB if no allocated
if (data_tx[tb] == NULL) {
continue;
}
for (uint32_t i = 0; i < pusch_grant.tb[tb].tbs; i++) {
data_tx[tb][i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
}
pusch_grant.tb[tb].softbuffer.tx = &softbuffer_tx;
}
if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_grant, data_tx, sf_symbols) < SRSLTE_SUCCESS) {
ERROR("Error encoding\n");
goto clean_exit;
}
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
pusch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(pusch_grant.tb[tb].softbuffer.rx);
}
for (uint32_t i = 0; i < pusch_grant.tb->nof_re; i++) {
chest.ce[0][0][i] = 1.0f;
}
chest.nof_re = pusch_grant.tb->nof_re;
if (srslte_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_grant, &chest, sf_symbols, pusch_res) < SRSLTE_SUCCESS) {
ERROR("Error encoding\n");
goto clean_exit;
}
if (pusch_res->evm > 0.001f) {
ERROR("Error PUSCH EVM is too high %f\n", pusch_res->evm);
goto clean_exit;
}
float mse = 0.0f;
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_grant);
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) {
for (uint32_t j = 0; j < nof_re; j++) {
mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]);
}
}
if (nof_re * pusch_grant.nof_layers > 0) {
mse = mse / (nof_re * pusch_grant.nof_layers);
}
if (mse > 0.001) {
ERROR("MSE error (%f) is too high\n", mse);
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) {
printf("d_tx[%d]=", i);
srslte_vec_fprint_c(stdout, pusch_tx.d[i], nof_re);
printf("d_rx[%d]=", i);
srslte_vec_fprint_c(stdout, pusch_rx.d[i], nof_re);
}
goto clean_exit;
}
if (!pusch_res[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;\n", n_prb, mcs, pusch_grant.tb[0].tbs);
goto clean_exit;
}
if (memcmp(data_tx[0], data_rx[0], pusch_grant.tb[0].tbs / 8) != 0) {
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;\n", n_prb, mcs, pusch_grant.tb[0].tbs);
printf("Tx data: ");
srslte_vec_fprint_byte(stdout, data_tx[0], pusch_grant.tb[0].tbs / 8);
printf("Rx data: ");
srslte_vec_fprint_byte(stdout, data_rx[0], pusch_grant.tb[0].tbs / 8);
goto clean_exit;
}
printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_grant.tb[0].tbs, pusch_res[0].evm);
}
}
ret = SRSLTE_SUCCESS;
clean_exit:
srslte_chest_dl_res_free(&chest);
srslte_random_free(rand_gen);
srslte_pusch_nr_free(&pusch_tx);
srslte_pusch_nr_free(&pusch_rx);
for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data_tx[i]) {
free(data_tx[i]);
}
if (data_rx[i]) {
free(data_rx[i]);
}
}
for (uint32_t i = 0; i < SRSLTE_MAX_LAYERS_NR; i++) {
if (sf_symbols[i]) {
free(sf_symbols[i]);
}
}
srslte_softbuffer_tx_free(&softbuffer_tx);
srslte_softbuffer_rx_free(&softbuffer_rx);
return ret;
}

View File

@ -26,10 +26,10 @@ static srslte_carrier_nr_t carrier = {
1 // max_mimo_layers
};
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_pdsch_cfg_nr_t pdsch_cfg = {};
static srslte_pdsch_grant_nr_t pdsch_grant = {};
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pdsch_cfg = {};
static srslte_sch_grant_nr_t pdsch_grant = {};
void usage(char* prog)
{
@ -84,7 +84,7 @@ int main(int argc, char** argv)
uint8_t* data_rx = srslte_vec_u8_malloc(1024 * 1024);
// Set default PDSCH configuration
pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam;
pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam;
if (parse_args(argc, argv) < SRSLTE_SUCCESS) {
goto clean_exit;
@ -132,8 +132,7 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) <
SRSLTE_SUCCESS) {
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}

View File

@ -79,7 +79,7 @@ int srslte_ue_dl_nr_init(srslte_ue_dl_nr_t* q, cf_t* input[SRSLTE_MAX_PORTS], co
srslte_ofdm_rx_init_cfg(&q->fft[i], &fft_cfg);
}
if (srslte_dmrs_pdsch_init(&q->dmrs_pdsch, true) < SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_init(&q->dmrs_pdsch, true) < SRSLTE_SUCCESS) {
ERROR("Error DMRS\n");
return SRSLTE_ERROR;
}
@ -109,7 +109,7 @@ void srslte_ue_dl_nr_free(srslte_ue_dl_nr_t* q)
srslte_chest_dl_res_free(&q->chest);
srslte_pdsch_nr_free(&q->pdsch);
srslte_dmrs_pdsch_free(&q->dmrs_pdsch);
srslte_dmrs_sch_free(&q->dmrs_pdsch);
srslte_dmrs_pdcch_estimator_free(&q->dmrs_pdcch);
srslte_pdcch_nr_free(&q->pdcch);
@ -126,7 +126,7 @@ int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t*
return SRSLTE_ERROR;
}
if (srslte_dmrs_pdsch_set_carrier(&q->dmrs_pdsch, carrier) < SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_set_carrier(&q->dmrs_pdsch, carrier) < SRSLTE_SUCCESS) {
ERROR("Error DMRS\n");
return SRSLTE_ERROR;
}
@ -305,14 +305,14 @@ int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q,
return (int)count;
}
int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
srslte_pdsch_res_nr_t* res)
int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
srslte_pdsch_res_nr_t* res)
{
if (srslte_dmrs_pdsch_estimate(&q->dmrs_pdsch, slot, cfg, grant, q->sf_symbols[0], &q->chest) < SRSLTE_SUCCESS) {
if (srslte_dmrs_sch_estimate(&q->dmrs_pdsch, slot, cfg, grant, q->sf_symbols[0], &q->chest) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -329,12 +329,12 @@ int srslte_ue_dl_nr_pdsch_get(srslte_ue_dl_nr_t* q,
return SRSLTE_SUCCESS;
}
int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
const srslte_pdsch_cfg_nr_t* cfg,
const srslte_pdsch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t* res,
char* str,
uint32_t str_len)
int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_grant_nr_t* grant,
const srslte_pdsch_res_nr_t* res,
char* str,
uint32_t str_len)
{
int len = 0;

View File

@ -55,7 +55,7 @@ static int srslte_ue_dl_nr_pdsch_time_resource_hl_B(uint32_t sliv, uint32_t* S,
return SRSLTE_ERROR;
}
int srslte_ue_dl_nr_pdsch_time_resource_hl(const srslte_pdsch_allocation_t* pdsch_alloc, srslte_pdsch_grant_nr_t* grant)
int srslte_ue_dl_nr_pdsch_time_resource_hl(const srslte_pdsch_allocation_t* pdsch_alloc, srslte_sch_grant_nr_t* grant)
{
if (pdsch_alloc == NULL || grant == NULL) {
@ -65,16 +65,16 @@ int srslte_ue_dl_nr_pdsch_time_resource_hl(const srslte_pdsch_allocation_t* pdsc
grant->k0 = pdsch_alloc->k0;
grant->mapping = pdsch_alloc->mapping_type;
if (pdsch_alloc->mapping_type == srslte_pdsch_mapping_type_A) {
if (pdsch_alloc->mapping_type == srslte_sch_mapping_type_A) {
return srslte_ue_dl_nr_pdsch_time_resource_hl_A(pdsch_alloc->sliv, &grant->S, &grant->L);
}
return srslte_ue_dl_nr_pdsch_time_resource_hl_B(pdsch_alloc->sliv, &grant->S, &grant->L);
}
int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t m,
srslte_dmrs_pdsch_typeA_pos_t dmrs_typeA_pos,
srslte_pdsch_grant_nr_t* grant)
int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t m,
srslte_dmrs_sch_typeA_pos_t dmrs_typeA_pos,
srslte_sch_grant_nr_t* grant)
{
if (grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
@ -89,23 +89,23 @@ int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t
grant->k0 = 0;
// Select PDSCH mapping
static srslte_pdsch_mapping_type_t pdsch_mapping_lut[16] = {srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_A,
srslte_pdsch_mapping_type_B,
srslte_pdsch_mapping_type_B};
grant->mapping = pdsch_mapping_lut[m];
static srslte_sch_mapping_type_t pdsch_mapping_lut[16] = {srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_A,
srslte_sch_mapping_type_B,
srslte_sch_mapping_type_B};
grant->mapping = pdsch_mapping_lut[m];
static uint32_t S_pos2[16] = {2, 2, 2, 2, 2, 9, 4, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos2[16] = {12, 10, 9, 7, 5, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
@ -115,11 +115,11 @@ int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t
// Select start symbol (S) and length (L)
switch (dmrs_typeA_pos) {
case srslte_dmrs_pdsch_typeA_pos_2:
case srslte_dmrs_sch_typeA_pos_2:
grant->S = S_pos2[m];
grant->L = L_pos2[m];
break;
case srslte_dmrs_pdsch_typeA_pos_3:
case srslte_dmrs_sch_typeA_pos_3:
grant->S = S_pos3[m];
grant->L = L_pos3[m];
break;
@ -131,15 +131,15 @@ int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t
return SRSLTE_SUCCESS;
}
int srslte_ue_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_pdsch_cfg_nr_t* pdsch_cfg,
srslte_pdsch_grant_nr_t* grant)
int srslte_ue_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)
{
if (pdsch_cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
const srslte_pdsch_dmrs_cfg_t* dmrs_cfg =
grant->mapping == srslte_pdsch_mapping_type_A ? &pdsch_cfg->dmrs_cfg_typeA : &pdsch_cfg->dmrs_cfg_typeB;
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
@ -147,7 +147,7 @@ int srslte_ue_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_pds
* 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_pdsch_len_2) {
if (dmrs_cfg->length == srslte_dmrs_sch_len_2) {
grant->nof_dmrs_cdm_groups_without_data = 1;
} else {
grant->nof_dmrs_cdm_groups_without_data = 2;

View File

@ -0,0 +1,84 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/ue/ue_ul_nr_data.h"
#include "srslte/phy/utils/debug.h"
typedef struct {
srslte_sch_mapping_type_t mapping;
uint32_t K2;
uint32_t S;
uint32_t L;
} ue_ul_time_resource_t;
static const ue_ul_time_resource_t ue_ul_default_A_lut[16] = {{srslte_sch_mapping_type_A, 0, 0, 14},
{srslte_sch_mapping_type_A, 0, 0, 12},
{srslte_sch_mapping_type_A, 0, 0, 10},
{srslte_sch_mapping_type_B, 0, 2, 10},
{srslte_sch_mapping_type_B, 0, 4, 10},
{srslte_sch_mapping_type_B, 0, 4, 8},
{srslte_sch_mapping_type_B, 0, 4, 6},
{srslte_sch_mapping_type_A, 1, 0, 14},
{srslte_sch_mapping_type_A, 1, 0, 12},
{srslte_sch_mapping_type_A, 1, 0, 10},
{srslte_sch_mapping_type_A, 2, 0, 14},
{srslte_sch_mapping_type_A, 2, 0, 12},
{srslte_sch_mapping_type_A, 2, 0, 10},
{srslte_sch_mapping_type_B, 0, 8, 6},
{srslte_sch_mapping_type_A, 3, 0, 14},
{srslte_sch_mapping_type_A, 3, 0, 10}};
int srslte_ue_ul_nr_pdsch_time_resource_default_A(uint32_t m, srslte_sch_grant_nr_t* grant)
{
if (grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (m >= 16) {
ERROR("m (%d) is out-of-range\n", m);
return SRSLTE_ERROR_INVALID_INPUTS;
}
// Select mapping
grant->mapping = ue_ul_default_A_lut[m].mapping;
grant->k2 = ue_ul_default_A_lut[m].K2;
grant->S = ue_ul_default_A_lut[m].S;
grant->L = ue_ul_default_A_lut[m].L;
return SRSLTE_SUCCESS;
}
int srslte_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant)
{
if (cfg == NULL || grant == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
/* According to TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure:
* For PUSCH scheduled by DCI format 0_0 or by activation DCI format 0_0 with CRC scrambled by CS-RNTI, 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
* PUSCH with allocation duration of 2 or less OFDM symbols with transform precoding disabled, the UE shall assume
* that the number of DM-RS CDM groups without data is 3 which corresponds to CDM group {0,1,2} for the case of PUSCH
* scheduled by activation DCI format 0_0 and the dmrs-Type in cg-DMRS-Configuration equal to 'type2' and the PUSCH
* allocation duration being more than 2 OFDM 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 (grant->L <= 2 && !cfg->enable_transform_precoder) {
grant->nof_dmrs_cdm_groups_without_data = 1;
// } else if (grant->L > 2 && cfg->dmrs_cg.type == srslte_dmrs_sch_type_2){
// grant->nof_dmrs_cdm_groups_without_data = 3;
} else {
grant->nof_dmrs_cdm_groups_without_data = 2;
}
return SRSLTE_SUCCESS;
}

View File

@ -28,12 +28,12 @@ static srslte_carrier_nr_t carrier = {
};
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_pdsch_cfg_nr_t pdsch_cfg = {};
static srslte_pdsch_grant_nr_t pdsch_grant = {};
static uint16_t rnti = 0x1234;
static uint32_t nof_slots = 10;
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pdsch_cfg = {};
static srslte_sch_grant_nr_t pdsch_grant = {};
static uint16_t rnti = 0x1234;
static uint32_t nof_slots = 10;
void usage(char* prog)
{
@ -254,8 +254,7 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) <
SRSLTE_SUCCESS) {
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}

View File

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

View File

@ -110,11 +110,10 @@ uint32_t cc_worker::get_buffer_len()
bool cc_worker::work_dl()
{
srslte_pdsch_grant_nr_t pdsch_grant = {};
srslte_pdsch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch;
srslte_sch_grant_nr_t pdsch_grant = {};
srslte_sch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch;
// Use grant default A time resources with m=0
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) <
SRSLTE_SUCCESS) {
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
return false;
}

View File

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

View File

@ -107,13 +107,12 @@ uint32_t cc_worker::get_buffer_len()
bool cc_worker::work_dl()
{
srslte_pdsch_grant_nr_t pdsch_grant = {};
srslte_pdsch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch;
srslte_sch_grant_nr_t pdsch_grant = {};
srslte_sch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch;
std::array<srslte_pdsch_res_nr_t, SRSLTE_MAX_CODEWORDS> pdsch_res = {};
// Use grant default A time resources with m=0
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) <
SRSLTE_SUCCESS) {
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
return false;
}