diff --git a/lib/include/srslte/phy/common/phy_common_nr.h b/lib/include/srslte/phy/common/phy_common_nr.h index 84064953c..a8c77226a 100644 --- a/lib/include/srslte/phy/common/phy_common_nr.h +++ b/lib/include/srslte/phy/common/phy_common_nr.h @@ -155,6 +155,18 @@ typedef enum SRSLTE_API { 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_t; +/** + * @brief Overhead configuration provided by higher layers + * @remark Described in TS 38.331 V15.10.0 PDSCH-ServingCellConfig + * @remark Described in TS 38.331 V15.10.0 PUSCH-ServingCellConfig + */ +typedef enum SRSLTE_API { + srslte_xoverhead_0 = 0, + srslte_xoverhead_6, + srslte_xoverhead_12, + srslte_xoverhead_18 +} srslte_xoverhead_t; + /** * @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP) */ @@ -236,6 +248,15 @@ typedef struct SRSLTE_API { uint32_t n_cce; } srslte_pdcch_cfg_nr_t; +typedef struct SRSLTE_API { + uint32_t max_mimo_layers; ///< @brief DL: Indicates the maximum number of MIMO layers to be used for PDSCH in all BWPs + ///< of this serving cell. (see TS 38.212 [17], clause 5.4.2.1). UL: Indicates the maximum + ///< MIMO layer to be used for PUSCH in all BWPs of the normal UL of this serving cell (see + ///< TS 38.212 [17], clause 5.4.2.1) + srslte_xoverhead_t xoverhead; ///< Accounts for overhead from CSI-RS, CORESET, etc. If the field is absent, the UE + ///< applies value xOh0 (see TS 38.214 [19], clause 5.1.3.2). +} srslte_serving_cell_cfg_t; + /** * @brief Calculates the bandwidth of a given CORESET in physical resource blocks (PRB) . This function uses the * frequency domain resources bit-map for counting the number of PRB. diff --git a/lib/include/srslte/phy/phch/pdsch_cfg_nr.h b/lib/include/srslte/phy/phch/pdsch_cfg_nr.h index 2692f9e2d..05982ad31 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg_nr.h @@ -32,7 +32,6 @@ #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/fec/softbuffer.h" -#include "srslte/phy/phch/ra.h" /** * @brief PDSCH DMRS type @@ -151,6 +150,10 @@ typedef struct SRSLTE_API { srslte_pdsch_dmrs_cfg_t dmrs_cfg_typeA; srslte_pdsch_dmrs_cfg_t dmrs_cfg_typeB; srslte_mcs_table_t mcs_table; + + /// Parameters provided by PDSCH-ServingCellConfig + srslte_serving_cell_cfg_t serving_cell_cfg; + } srslte_pdsch_cfg_nr_t; #endif // SRSLTE_PDSCH_CFG_NR_H diff --git a/lib/include/srslte/phy/phch/ra_nr.h b/lib/include/srslte/phy/phch/ra_nr.h index 00c663c14..4df787fe8 100644 --- a/lib/include/srslte/phy/phch/ra_nr.h +++ b/lib/include/srslte/phy/phch/ra_nr.h @@ -43,7 +43,9 @@ typedef struct SRSLTE_API { srslte_mod_t mod; - int tbs; + uint32_t N_L; ///< the number of transmission layers that the transport block is mapped onto + int tbs; ///< Payload size, TS 38.212 refers to it as A + double R; ///< Target LDPC rate int rv; uint32_t nof_bits; uint32_t cw_idx; @@ -51,9 +53,27 @@ typedef struct SRSLTE_API { // this is for debugging and metrics purposes uint32_t mcs_idx; + + /// Soft-buffers pointers + union { + srslte_softbuffer_tx_t* tx; + srslte_softbuffer_rx_t* rx; + } softbuffer; } srslte_ra_tb_nr_t; -SRSLTE_API int -srslte_ra_nr_tbs(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch_grant_nr_t* grant, uint32_t mcs_idx); +/** + * @brief Calculates shared channel TBS + * @param N_re Number of resource elements + * @param S TB scaling, used in rare occasions. Set to 1, 0, NAN or INF if unused. + * @param R Target Rate + * @param Qm Modulation level + * @param nof_layers Number of layers + * @return The transport block size + */ +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_ra_tb_nr_t* tb); #endif // SRSLTE_RA_NR_H diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 8edfde1d9..d4445e7c0 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -106,7 +106,7 @@ RA_NR_READ_TABLE(2) RA_NR_READ_TABLE(3) /** - * TS 38.214 V15.10.0 Table 5.1.3.2-1: TBS for N inf o ≤ 3824 + * TS 38.214 V15.10.0 Table 5.1.3.2-1: TBS for N info ≤ 3824 */ static const uint32_t ra_nr_tbs_table[RA_NR_TBS_SIZE_TABLE] = { 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, @@ -222,6 +222,20 @@ static int ra_nr_determine_N_re(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const sr // the overhead configured by higher layer parameter xOverhead in PDSCH-ServingCellConfig uint32_t n_prb_oh = 0; + switch (pdsch_cfg->serving_cell_cfg.xoverhead) { + case srslte_xoverhead_0: + n_prb_oh = 0; + break; + case srslte_xoverhead_6: + n_prb_oh = 6; + break; + case srslte_xoverhead_12: + n_prb_oh = 12; + break; + case srslte_xoverhead_18: + n_prb_oh = 18; + break; + } // Compute total number of n_re used for PDSCH uint32_t n_re_prime = SRSLTE_NRE * n_sh_symb - n_prb_dmrs - n_prb_oh; @@ -291,7 +305,27 @@ static double ra_nr_get_scaling(uint32_t tb_scaling_field) return NAN; } -int srslte_ra_nr_tbs(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch_grant_nr_t* grant, uint32_t mcs_idx) +uint32_t srslte_ra_nr_tbs(uint32_t N_re, double S, double R, uint32_t Qm, uint32_t nof_layers) +{ + if (!isnormal(S)) { + S = 1.0; + } + + // 2) Intermediate number of information bits (N info ) is obtained by N inf o = N RE · R · Q m · υ . + uint32_t n_info = (uint32_t)(N_re * S * R * Qm * nof_layers); + + // 3) When n_info ≤ 3824 + if (n_info <= 3824) { + return ra_nr_tbs_from_n_info3(n_info); + } + // 4) When n_info > 3824 + 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_ra_tb_nr_t* tb) { // Get target Rate double R = @@ -330,19 +364,16 @@ int srslte_ra_nr_tbs(const srslte_pdsch_cfg_nr_t* pdsch_cfg, const srslte_pdsch_ } // 1) The UE shall first determine the number of REs (N RE ) within the slot. - int n_re = ra_nr_determine_N_re(pdsch_cfg, grant); - if (n_re < SRSLTE_SUCCESS) { + int N_re = ra_nr_determine_N_re(pdsch_cfg, grant); + if (N_re < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } - // 2) Intermediate number of information bits (N info ) is obtained by N inf o = N RE · R · Q m · υ . - uint32_t n_info = (uint32_t)(n_re * S * R * Qm * grant->nof_layers); + // Steps 2,3,4 + tb->tbs = (int)srslte_ra_nr_tbs(N_re, S, R, Qm, grant->nof_layers); + tb->R = R; + tb->mod = m; + tb->nof_bits = N_re * Qm * grant->nof_layers; - // 3) When n_info ≤ 3824 - if (n_info <= 3824) { - return (int)ra_nr_tbs_from_n_info3(n_info); - } - - // 4) When n_info > 3824 - return (int)ra_nr_tbs_from_n_info4(n_info, R); + return SRSLTE_SUCCESS; } \ No newline at end of file