diff --git a/lib/include/srslte/phy/phch/phch_cfg_nr.h b/lib/include/srslte/phy/phch/phch_cfg_nr.h index 27011170b..79a74069f 100644 --- a/lib/include/srslte/phy/phch/phch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/phch_cfg_nr.h @@ -23,6 +23,7 @@ #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/phch/sch_cfg_nr.h" +#include "srslte/phy/phch/uci_cfg_nr.h" /** * @brief PDSCH DMRS type @@ -201,8 +202,12 @@ typedef struct SRSLTE_API { srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters - /// Uplink params - bool enable_transform_precoder; + /// PUSCH only parameters + srslte_uci_cfg_nr_t uci; ///< Uplink Control Information configuration + bool enable_transform_precoder; + float beta_harq_ack_offset; + float beta_csi_part1_offset; + float scaling; } srslte_sch_cfg_nr_t; #endif // SRSLTE_PHCH_CFG_NR_H diff --git a/lib/include/srslte/phy/phch/pucch_nr.h b/lib/include/srslte/phy/phch/pucch_nr.h index 2c8584386..cdaf5ed57 100644 --- a/lib/include/srslte/phy/phch/pucch_nr.h +++ b/lib/include/srslte/phy/phch/pucch_nr.h @@ -42,6 +42,7 @@ typedef struct SRSLTE_API { */ typedef struct SRSLTE_API { uint32_t max_prb; + srslte_carrier_nr_t carrier; srslte_zc_sequence_lut_t r_uv_1prb; cf_t format1_w_i_m[SRSLTE_PUCCH_NR_FORMAT1_N_MAX][SRSLTE_PUCCH_NR_FORMAT1_N_MAX][SRSLTE_PUCCH_NR_FORMAT1_N_MAX]; srslte_modem_table_t bpsk; @@ -55,10 +56,19 @@ typedef struct SRSLTE_API { /** * @brief Initialises an NR-PUCCH encoder/decoder object * @param q Object + * @param args PUCCH configuration arguments * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_init(srslte_pucch_nr_t* q, const srslte_pucch_nr_args_t* args); +/** + * @brief Initialises an NR-PUCCH encoder/decoder object + * @param q Object + * @param carrier + * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_pucch_nr_set_carrier(srslte_pucch_nr_t* q, const srslte_carrier_nr_t* carrier); + /** * @brief Deallocates an NR-PUCCH encoder/decoder object * @param q Object @@ -104,7 +114,6 @@ SRSLTE_API int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* car * @brief Encode and writes NR-PUCCH format 0 in the resource grid * @remark Described in TS 38.211 clause 6.3.2.3 PUCCH format 0 * @param[in,out] q NR-PUCCH encoder/decoder object - * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 0 resource @@ -113,7 +122,6 @@ SRSLTE_API int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* car * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, srslte_pucch_nr_resource_t* resource, @@ -123,7 +131,6 @@ SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* /** * @brief Measures PUCCH format 0 in the resource grid * @param[in,out] q NR-PUCCH encoder/decoder object - * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 0 resource @@ -133,7 +140,6 @@ SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, srslte_pucch_nr_resource_t* resource, @@ -156,7 +162,6 @@ SRSLTE_API cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n * @brief Encodes and puts NR-PUCCH format 1 in the resource grid * @remark Described in TS 38.211 clause 6.3.2.4 PUCCH format 1 * @param[in,out] q NR-PUCCH encoder/decoder object - * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 1 resource @@ -166,7 +171,6 @@ SRSLTE_API cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -177,7 +181,6 @@ SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* /** * @brief Decodes NR-PUCCH format 1 * @param[in,out] q NR-PUCCH encoder/decoder object - * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 2-4 resource @@ -188,7 +191,6 @@ SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -200,7 +202,6 @@ SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* /** * @brief Encoder NR-PUCCH formats 2, 3 and 4. The NR-PUCCH format is selected by resource->format. * @param[in,out] q NR-PUCCH encoder/decoder object - * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 1 resource @@ -210,7 +211,6 @@ SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -221,7 +221,6 @@ SRSLTE_API int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* /** * @brief Decode NR-PUCCH format 2, 3, and 4. The NR-PUCCH format is selected by resource->format. * @param q[in,out] q NR-PUCCH encoder/decoder - * @param[in] carrier Serving cell and Uplink BWP configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 2-4 resource @@ -232,7 +231,6 @@ SRSLTE_API int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise */ SRSLTE_API int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, diff --git a/lib/include/srslte/phy/phch/pusch_nr.h b/lib/include/srslte/phy/phch/pusch_nr.h index 00ed9299e..74d32b586 100644 --- a/lib/include/srslte/phy/phch/pusch_nr.h +++ b/lib/include/srslte/phy/phch/pusch_nr.h @@ -20,6 +20,7 @@ #include "srslte/phy/phch/phch_cfg_nr.h" #include "srslte/phy/phch/regs.h" #include "srslte/phy/phch/sch_nr.h" +#include "srslte/phy/phch/uci_nr.h" #include "srslte/phy/scrambling/scrambling.h" /** @@ -27,6 +28,7 @@ */ typedef struct SRSLTE_API { srslte_sch_nr_args_t sch; + srslte_uci_nr_args_t uci; bool measure_evm; bool measure_time; } srslte_pusch_nr_args_t; @@ -40,6 +42,7 @@ typedef struct SRSLTE_API { 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 + srslte_uci_nr_t uci; ///< UCI 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 @@ -47,15 +50,26 @@ typedef struct SRSLTE_API { srslte_evm_buffer_t* evm_buffer; bool meas_time_en; uint32_t meas_time_us; + uint8_t* uci_ack; + uint8_t* uci_csi; } srslte_pusch_nr_t; /** - * + * @brief Groups NR-PUSCH data for transmission */ typedef struct { - uint8_t* payload; - bool crc; - float evm; + uint8_t* payload; ///< SCH payload + srslte_uci_value_nr_t uci; ///< UCI payload +} srslte_pusch_data_nr_t; + +/** + * @brief Groups NR-PUSCH data for reception + */ +typedef struct { + uint8_t* payload; ///< SCH payload + srslte_uci_value_nr_t uci; ///< UCI payload + bool crc; ///< CRC match + float evm; ///< EVM measurement if configured through arguments } srslte_pusch_res_nr_t; SRSLTE_API int srslte_pusch_nr_init_gnb(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args); @@ -66,11 +80,11 @@ 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_encode(srslte_pusch_nr_t* q, + const srslte_sch_cfg_nr_t* cfg, + const srslte_sch_grant_nr_t* grant, + const srslte_pusch_data_nr_t* data, + 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, diff --git a/lib/include/srslte/phy/phch/sch_nr.h b/lib/include/srslte/phy/phch/sch_nr.h index ce3cebbf3..1772ea9ad 100644 --- a/lib/include/srslte/phy/phch/sch_nr.h +++ b/lib/include/srslte/phy/phch/sch_nr.h @@ -69,27 +69,24 @@ typedef struct SRSLTE_API { * @brief Common SCH configuration */ typedef struct { - srslte_basegraph_t bg; ///< @brief Base graph - uint32_t Qm; ///< @brief Modulation order - uint32_t G; ///< Number of available bits - uint32_t A; ///< @brief Payload size, TBS - uint32_t L_tb; ///< @brief the number of the transport block parity bits (16 or 24 bits) - uint32_t L_cb; ///< @brief the number of the code block parity bits (0 or 24 bits) - uint32_t B; ///< @brief the number of bits in the transport block including TB CRC - uint32_t Bp; ///< @brief the number of bits in the transport block including CB and TB CRCs - uint32_t Kp; ///< @brief Number of payload bits of the code block including CB CRC - uint32_t Kr; ///< @brief Number of payload bits of the code block including CB CRC and filler bits - uint32_t F; ///< @brief Number of filler bits - uint32_t Nref; ///< @brief N_ref parameter described in TS 38.212 V15.9.0 5.4.2.1 - uint32_t Z; ///< @brief LDPC lifting size - uint32_t Nl; ///< @brief Number of transmission layers that the transport block is mapped onto - bool mask[SRSLTE_SCH_NR_MAX_NOF_CB_LDPC]; ///< Indicates what codeblocks shall be encoded/decoded - uint32_t C; ///< Number of codeblocks - uint32_t Cp; ///< Number of codeblocks that are actually transmitted - srslte_crc_t* crc_tb; ///< Selected CRC for transport block - srslte_ldpc_encoder_t* encoder; ///< @brief Points to the selected encoder (if valid) - srslte_ldpc_decoder_t* decoder; ///< @brief Points to the selected decoder (if valid) -} srslte_sch_nr_common_cfg_t; + srslte_basegraph_t bg; ///< @brief Base graph + uint32_t Qm; ///< @brief Modulation order + uint32_t G; ///< Number of available bits + uint32_t A; ///< @brief Payload size, TBS + uint32_t L_tb; ///< @brief the number of the transport block parity bits (16 or 24 bits) + uint32_t L_cb; ///< @brief the number of the code block parity bits (0 or 24 bits) + uint32_t B; ///< @brief the number of bits in the transport block including TB CRC + uint32_t Bp; ///< @brief the number of bits in the transport block including CB and TB CRCs + uint32_t Kp; ///< @brief Number of payload bits of the code block including CB CRC + uint32_t Kr; ///< @brief Number of payload bits of the code block including CB CRC and filler bits + uint32_t F; ///< @brief Number of filler bits + uint32_t Nref; ///< @brief N_ref parameter described in TS 38.212 V15.9.0 5.4.2.1 + uint32_t Z; ///< @brief LDPC lifting size + uint32_t Nl; ///< @brief Number of transmission layers that the transport block is mapped onto + bool mask[SRSLTE_SCH_NR_MAX_NOF_CB_LDPC]; ///< Indicates what codeblocks shall be encoded/decoded + uint32_t C; ///< Number of codeblocks + uint32_t Cp; ///< Number of codeblocks that are actually transmitted +} srslte_sch_nr_tb_info_t; /** * @brief Base graph selection from a provided transport block size and target rate @@ -110,10 +107,10 @@ SRSLTE_API srslte_basegraph_t srslte_sch_nr_select_basegraph(uint32_t tbs, doubl * @param cfg SCH object * @return */ -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_fill_cfg(const srslte_carrier_nr_t* carrier, + const srslte_sch_cfg_t* sch_cfg, + const srslte_sch_tb_t* tb, + srslte_sch_nr_tb_info_t* cfg); /** * @brief Initialises an SCH object as transmitter diff --git a/lib/include/srslte/phy/phch/uci_cfg_nr.h b/lib/include/srslte/phy/phch/uci_cfg_nr.h index 34c1729a2..1408e0897 100644 --- a/lib/include/srslte/phy/phch/uci_cfg_nr.h +++ b/lib/include/srslte/phy/phch/uci_cfg_nr.h @@ -29,23 +29,12 @@ */ #define SRSLTE_UCI_NR_MAX_ACK_BITS 360 -/** - * @brief Maximum number of Scheduling Request (SR) bits that can be carried in Uplink Control Information (UCI) message - */ -#define SRSLTE_UCI_NR_MAX_SR_BITS 10 - /** * @brief Maximum number of Channel State Information part 1 (CSI1) bits that can be carried in Uplink Control * Information (UCI) message */ #define SRSLTE_UCI_NR_MAX_CSI1_BITS 10 -/** - * @brief Maximum number of Channel State Information part 2 (CSI2) bits that can be carried in Uplink Control - * Information (UCI) message - */ -#define SRSLTE_UCI_NR_MAX_CSI2_BITS 10 - /** * @brief Uplink Control Information (UCI) message configuration */ @@ -57,7 +46,8 @@ typedef struct SRSLTE_API { uint32_t nof_csi; ///< Number of CSI reports /// PUSCH only parameters - srslte_mod_t modulation; ///< Modulation + bool without_ul_sch; ///< Set to true if no UL-SCH data is scheduled + bool has_csi_part2; ///< Set to true if the CSI reports have part 2 /// PUCCH only parameters uint16_t rnti; ///< RNTI diff --git a/lib/include/srslte/phy/phch/uci_nr.h b/lib/include/srslte/phy/phch/uci_nr.h index 114c95aeb..c98b7a82b 100644 --- a/lib/include/srslte/phy/phch/uci_nr.h +++ b/lib/include/srslte/phy/phch/uci_nr.h @@ -13,13 +13,14 @@ #ifndef SRSLTE_UCI_NR_H #define SRSLTE_UCI_NR_H +#include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/fec/crc.h" #include "srslte/phy/fec/polar/polar_code.h" #include "srslte/phy/fec/polar/polar_decoder.h" #include "srslte/phy/fec/polar/polar_encoder.h" #include "srslte/phy/fec/polar/polar_rm.h" +#include "srslte/phy/phch/phch_cfg_nr.h" #include "srslte/phy/phch/pucch_cfg_nr.h" -#include "uci_cfg.h" #include "uci_cfg_nr.h" #include #include @@ -33,6 +34,7 @@ typedef struct { } srslte_uci_nr_args_t; typedef struct { + srslte_carrier_nr_t carrier; srslte_polar_rm_t rm_tx; srslte_polar_rm_t rm_rx; srslte_polar_encoder_t encoder; @@ -70,6 +72,14 @@ SRSLTE_API uint32_t srslte_uci_nr_crc_len(uint32_t A); */ SRSLTE_API int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args); +/** + * @brief Sets NR carrier + * @param[in,out] q NR-UCI object + * @param carrier Provides carrier configuration + * @return SRSLTE_SUCCESS if successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_uci_nr_set_carrier(srslte_uci_nr_t* q, const srslte_carrier_nr_t* carrier); + /** * @brief Deallocates NR-UCI encoder/decoder object * @param[in,out] q NR-UCI object @@ -114,6 +124,27 @@ SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q, int8_t* llr, srslte_uci_value_nr_t* value); +/** + * @brief Calculates the total number of encoded bits for HARQ-ACK + * @param[in,out] q NR-UCI object + * @param[in] cfg PUSCH transmission configuration + * @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_uci_nr_pusch_E_uci_ack(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* cfg); + +/** + * @brief Encodes HARQ-ACK bits for PUSCH transmission + * @param[in,out] q NR-UCI object + * @param[in] cfg PUSCH transmission configuration + * @param[in] value UCI value + * @param[out] o_ack Encoded ack bits + * @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise + */ +SRSLTE_API int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q, + const srslte_sch_cfg_nr_t* cfg, + const srslte_uci_value_nr_t* value, + uint8_t* o_ack); + /** * @brief Calculates the total number of UCI bits * @param uci_cfg UCI configuration diff --git a/lib/include/srslte/phy/ue/ue_ul_nr.h b/lib/include/srslte/phy/ue/ue_ul_nr.h index 25c57d987..d87f35556 100644 --- a/lib/include/srslte/phy/ue/ue_ul_nr.h +++ b/lib/include/srslte/phy/ue/ue_ul_nr.h @@ -54,10 +54,10 @@ SRSLTE_API int srslte_ue_ul_nr_init(srslte_ue_ul_nr_t* q, cf_t* output, const sr SRSLTE_API int srslte_ue_ul_nr_set_carrier(srslte_ue_ul_nr_t* q, const srslte_carrier_nr_t* carrier); -SRSLTE_API int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q, - const srslte_slot_cfg_t* slot_cfg, - const srslte_sch_cfg_nr_t* pusch_cfg, - uint8_t* data_); +SRSLTE_API int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q, + const srslte_slot_cfg_t* slot_cfg, + const srslte_sch_cfg_nr_t* pusch_cfg, + const srslte_pusch_data_nr_t* data); SRSLTE_API int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* q, const srslte_slot_cfg_t* slot_cfg, diff --git a/lib/src/phy/phch/pucch_nr.c b/lib/src/phy/phch/pucch_nr.c index 6b2a2e57b..92e4b9d51 100644 --- a/lib/src/phy/phch/pucch_nr.c +++ b/lib/src/phy/phch/pucch_nr.c @@ -174,6 +174,17 @@ int srslte_pucch_nr_init(srslte_pucch_nr_t* q, const srslte_pucch_nr_args_t* arg return SRSLTE_SUCCESS; } +int srslte_pucch_nr_set_carrier(srslte_pucch_nr_t* q, const srslte_carrier_nr_t* carrier) +{ + if (q == NULL || carrier == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + q->carrier = *carrier; + + return SRSLTE_SUCCESS; +} + void srslte_pucch_nr_free(srslte_pucch_nr_t* q) { if (q == NULL) { @@ -201,14 +212,13 @@ void srslte_pucch_nr_free(srslte_pucch_nr_t* q) } int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, srslte_pucch_nr_resource_t* resource, uint32_t m_cs, cf_t* slot_symbols) { - if (carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL) { + if (cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -219,7 +229,7 @@ int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q, uint32_t u = 0; uint32_t v = 0; - if (srslte_pucch_nr_group_sequence(carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { + if (srslte_pucch_nr_group_sequence(&q->carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { ERROR("Error getting group sequence"); return SRSLTE_ERROR; } @@ -228,8 +238,8 @@ int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q, for (uint32_t l = 0; l < resource->nof_symbols; l++) { // Get Alpha index uint32_t alpha_idx = 0; - if (srslte_pucch_nr_alpha_idx(carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, m_cs, &alpha_idx) < - SRSLTE_SUCCESS) { + if (srslte_pucch_nr_alpha_idx( + &q->carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, m_cs, &alpha_idx) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -241,7 +251,7 @@ int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q, } // Get start of the sequence in resource grid - cf_t* slot_symbols_ptr = &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; + cf_t* slot_symbols_ptr = &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; // Copy sequence in grid srslte_vec_cf_copy(slot_symbols_ptr, r_uv, SRSLTE_NRE); @@ -251,7 +261,6 @@ int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q, } int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, srslte_pucch_nr_resource_t* resource, @@ -259,7 +268,7 @@ int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q, const cf_t* slot_symbols, srslte_pucch_nr_measure_t* measure) { - if (carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || measure == NULL) { + if (cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || measure == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -270,7 +279,7 @@ int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q, uint32_t u = 0; uint32_t v = 0; - if (srslte_pucch_nr_group_sequence(carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { + if (srslte_pucch_nr_group_sequence(&q->carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { ERROR("Error getting group sequence"); return SRSLTE_ERROR; } @@ -281,8 +290,8 @@ int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q, for (uint32_t l = 0; l < resource->nof_symbols; l++) { // Get Alpha index uint32_t alpha_idx = 0; - if (srslte_pucch_nr_alpha_idx(carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, m_cs, &alpha_idx) < - SRSLTE_SUCCESS) { + if (srslte_pucch_nr_alpha_idx( + &q->carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, m_cs, &alpha_idx) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -295,7 +304,7 @@ int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q, // Get start of the sequence in resource grid const cf_t* slot_symbols_ptr = - &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; + &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; // Measure EPRE and average epre += srslte_vec_avg_power_cf(slot_symbols_ptr, SRSLTE_NRE) / resource->nof_symbols; @@ -360,7 +369,6 @@ cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n_pucch, uin } int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -368,7 +376,7 @@ int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q, uint32_t nof_bits, cf_t* slot_symbols) { - if (carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || b == NULL || slot_symbols == NULL) { + if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || b == NULL || slot_symbols == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -393,7 +401,7 @@ int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q, // Get group sequence uint32_t u = 0; uint32_t v = 0; - if (srslte_pucch_nr_group_sequence(carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { + if (srslte_pucch_nr_group_sequence(&q->carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { ERROR("Error getting group sequence"); return SRSLTE_ERROR; } @@ -404,11 +412,11 @@ int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q, uint32_t l_prime = resource->start_symbol_idx; for (uint32_t l = 1, m = 0; l < resource->nof_symbols; l += 2, m++) { // Get start of the sequence in resource grid - cf_t* slot_symbols_ptr = &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; + cf_t* slot_symbols_ptr = &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; // Get Alpha index uint32_t alpha_idx = 0; - if (srslte_pucch_nr_alpha_idx(carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, 0, &alpha_idx) < + if (srslte_pucch_nr_alpha_idx(&q->carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, 0, &alpha_idx) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -439,7 +447,6 @@ int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q, } int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -450,6 +457,11 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, { uint32_t m_cs = 0; + if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || chest_res == NULL || b == NULL || + slot_symbols == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + if (srslte_pucch_nr_cfg_resource_valid(resource) < SRSLTE_SUCCESS) { ERROR("Invalid PUCCH format 1 resource"); return SRSLTE_SUCCESS; @@ -466,7 +478,7 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, // Get group sequence uint32_t u = 0; uint32_t v = 0; - if (srslte_pucch_nr_group_sequence(carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { + if (srslte_pucch_nr_group_sequence(&q->carrier, cfg, &u, &v) < SRSLTE_SUCCESS) { ERROR("Error getting group sequence"); return SRSLTE_ERROR; } @@ -477,8 +489,8 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, uint32_t l_prime = resource->start_symbol_idx; for (uint32_t l = 1, m = 0; l < resource->nof_symbols; l += 2, m++) { // Get start of the sequence in resource grid - cf_t* slot_symbols_ptr = &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; - cf_t* ce_ptr = &chest_res->ce[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; + cf_t* slot_symbols_ptr = &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; + cf_t* ce_ptr = &chest_res->ce[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSLTE_NRE]; // Equalise x = w(i) * d' * r_uv(n) cf_t x[SRSLTE_NRE]; @@ -486,8 +498,8 @@ int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q, // Get Alpha index uint32_t alpha_idx = 0; - if (srslte_pucch_nr_alpha_idx(carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, m_cs, &alpha_idx) < - SRSLTE_SUCCESS) { + if (srslte_pucch_nr_alpha_idx( + &q->carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, m_cs, &alpha_idx) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -630,7 +642,6 @@ static int pucch_nr_format2_decode(srslte_pucch_nr_t* q, } int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -639,8 +650,8 @@ int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, cf_t* slot_symbols) { // Validate input pointers - if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL || - uci_value == NULL || slot_symbols == NULL) { + if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL || uci_value == NULL || + slot_symbols == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -653,7 +664,7 @@ int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, // Modulate PUCCH switch (resource->format) { case SRSLTE_PUCCH_NR_FORMAT_2: - return pucch_nr_format2_encode(q, carrier, cfg, resource, uci_cfg, slot_symbols); + return pucch_nr_format2_encode(q, &q->carrier, cfg, resource, uci_cfg, slot_symbols); case SRSLTE_PUCCH_NR_FORMAT_3: case SRSLTE_PUCCH_NR_FORMAT_4: ERROR("Not implemented"); @@ -667,7 +678,6 @@ int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q, } int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q, - const srslte_carrier_nr_t* carrier, const srslte_pucch_nr_common_cfg_t* cfg, const srslte_slot_cfg_t* slot, const srslte_pucch_nr_resource_t* resource, @@ -677,8 +687,8 @@ int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q, srslte_uci_value_nr_t* uci_value) { // Validate input pointers - if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL || - chest_res == NULL || uci_value == NULL || slot_symbols == NULL) { + if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || uci_cfg == NULL || chest_res == NULL || + uci_value == NULL || slot_symbols == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -686,7 +696,8 @@ int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q, int8_t* llr = (int8_t*)q->b; switch (resource->format) { case SRSLTE_PUCCH_NR_FORMAT_2: - if (pucch_nr_format2_decode(q, carrier, cfg, resource, uci_cfg, chest_res, slot_symbols, llr) < SRSLTE_SUCCESS) { + if (pucch_nr_format2_decode(q, &q->carrier, cfg, resource, uci_cfg, chest_res, slot_symbols, llr) < + SRSLTE_SUCCESS) { ERROR("Demodulating PUCCH format 2"); return SRSLTE_ERROR; } diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index a88056b26..858f3124c 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -28,6 +28,11 @@ int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* arg } } + if (srslte_uci_nr_init(&q->uci, &args->uci) < SRSLTE_SUCCESS) { + ERROR("Initialising UCI"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; } @@ -59,7 +64,7 @@ int srslte_pusch_nr_init_gnb(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* return SRSLTE_ERROR; } - if (srslte_sch_nr_init_rx(&q->sch, &args->sch)) { + if (srslte_sch_nr_init_rx(&q->sch, &args->sch) < SRSLTE_SUCCESS) { ERROR("Initialising SCH"); return SRSLTE_ERROR; } @@ -415,11 +420,20 @@ pusch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cf 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) +// int pusch_nr_mux_uci(srslte_pusch_nr_t* q) { +// uint8_t *g_ul_sch; // coded bits for UL-SCH +// uint8_t *g_ack; // coded bits for HARQ-ACK +// uint8_t *g_csi_p1; // coded bits for CSI part 1 +// uint8_t *g_csi_p2; // coded bits for CSI part 2 +// +//} + +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, + const srslte_uci_value_nr_t* uci, + uint16_t rnti) { // Early return if TB is not enabled if (!tb->enabled) { @@ -464,11 +478,11 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q, 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]) +int srslte_pusch_nr_encode(srslte_pusch_nr_t* q, + const srslte_sch_cfg_nr_t* cfg, + const srslte_sch_grant_nr_t* grant, + const srslte_pusch_data_nr_t* data, + cf_t* sf_symbols[SRSLTE_MAX_PORTS]) { // Check input pointers if (!q || !cfg || !grant || !data || !sf_symbols) { @@ -486,12 +500,20 @@ int srslte_pusch_nr_encode(srslte_pusch_nr_t* q, return SRSLTE_ERROR; } + // Encode HARQ-ACK bits + int E_uci_ack = srslte_uci_nr_encode_pusch_ack(&q->uci, cfg, &data[0].uci, q->uci_ack); + if (E_uci_ack < SRSLTE_SUCCESS) { + ERROR("Error encoding HARQ-ACK bits"); + 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) { + if (pusch_nr_encode_codeword(q, cfg, &grant->tb[tb], data[tb].payload, &data[0].uci, grant->rnti) < + SRSLTE_SUCCESS) { ERROR("Error encoding TB %d", tb); return SRSLTE_ERROR; } diff --git a/lib/src/phy/phch/sch_nr.c b/lib/src/phy/phch/sch_nr.c index cc3d8cb97..794cc855f 100644 --- a/lib/src/phy/phch/sch_nr.c +++ b/lib/src/phy/phch/sch_nr.c @@ -65,10 +65,10 @@ uint32_t sch_nr_n_prb_lbrm(uint32_t nof_prb) return 273; } -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) +int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier, + const srslte_sch_cfg_t* sch_cfg, + const srslte_sch_tb_t* tb, + srslte_sch_nr_tb_info_t* cfg) { if (!sch_cfg || !tb || !cfg) { return SRSLTE_ERROR_INVALID_INPUTS; @@ -111,10 +111,10 @@ int srslte_sch_nr_fill_cfg(srslte_sch_nr_t* q, cfg->Nl = tb->N_L; // Calculate Nref - uint32_t N_re_lbrm = 156 * sch_nr_n_prb_lbrm(q->carrier.nof_prb); + uint32_t N_re_lbrm = 156 * sch_nr_n_prb_lbrm(carrier->nof_prb); double TCR_lbrm = 948.0 / 1024.0; uint32_t Qm_lbrm = (sch_cfg->mcs_table == srslte_mcs_table_256qam) ? 8 : 6; - uint32_t TBS_LRBM = srslte_ra_nr_tbs(N_re_lbrm, 1.0, TCR_lbrm, Qm_lbrm, q->carrier.max_mimo_layers); + uint32_t TBS_LRBM = srslte_ra_nr_tbs(N_re_lbrm, 1.0, TCR_lbrm, Qm_lbrm, carrier->max_mimo_layers); double R = 2.0 / 3.0; cfg->Nref = ceil(TBS_LRBM / (cbsegm.C * R)); @@ -128,22 +128,13 @@ int srslte_sch_nr_fill_cfg(srslte_sch_nr_t* q, cfg->C = cbsegm.C; cfg->Cp = cbsegm.C; - // Select encoder - cfg->encoder = (bg == BG1) ? q->encoder_bg1[cfg->Z] : q->encoder_bg2[cfg->Z]; - - // Select decoder - cfg->decoder = (bg == BG1) ? q->decoder_bg1[cfg->Z] : q->decoder_bg2[cfg->Z]; - - // Select CRC for TB - cfg->crc_tb = (cbsegm.L_tb == 24) ? &q->crc_tb_24 : &q->crc_tb_16; - return SRSLTE_SUCCESS; } #define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN)) #define MOD(NUM, DEN) ((NUM) % (DEN)) -static inline uint32_t sch_nr_get_E(const srslte_sch_nr_common_cfg_t* cfg, uint32_t j) +static inline uint32_t sch_nr_get_E(const srslte_sch_nr_tb_info_t* cfg, uint32_t j) { if (cfg->Nl == 0 || cfg->Qm == 0 || cfg->Cp == 0) { ERROR("Invalid Nl (%d), Qm (%d) or Cp (%d)", cfg->Nl, cfg->Qm, cfg->Cp); @@ -380,19 +371,23 @@ static inline int sch_nr_encode(srslte_sch_nr_t* q, const uint8_t* input_ptr = data; uint8_t* output_ptr = e_bits; - srslte_sch_nr_common_cfg_t cfg = {}; - if (srslte_sch_nr_fill_cfg(q, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) { + srslte_sch_nr_tb_info_t cfg = {}; + if (srslte_sch_nr_fill_cfg(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } + // Select encoder and CRC + srslte_ldpc_encoder_t* encoder = (cfg.bg == BG1) ? q->encoder_bg1[cfg.Z] : q->encoder_bg2[cfg.Z]; + srslte_crc_t* crc_tb = (cfg.L_tb == 24) ? &q->crc_tb_24 : &q->crc_tb_16; + // Check encoder - if (cfg.encoder == NULL) { + if (encoder == NULL) { ERROR("Error: encoder for lifting size Z=%d not found (tbs=%d)", cfg.Z, tb->tbs); return SRSLTE_ERROR; } // Check CRC for TB - if (cfg.crc_tb == NULL) { + if (crc_tb == NULL) { ERROR("Error: CRC for TB not found"); return SRSLTE_ERROR; } @@ -406,16 +401,16 @@ static inline int sch_nr_encode(srslte_sch_nr_t* q, return SRSLTE_ERROR; } - if (tb->softbuffer.tx->max_cb_size < (cfg.encoder->liftN - 2 * cfg.Z)) { + if (tb->softbuffer.tx->max_cb_size < (encoder->liftN - 2 * cfg.Z)) { ERROR("Soft-buffer code-block maximum size insufficient (max_cb_size=%d) for a TBS=%d, requires %d.", tb->softbuffer.tx->max_cb_size, tb->tbs, - (cfg.encoder->liftN - 2 * cfg.Z)); + (encoder->liftN - 2 * cfg.Z)); return SRSLTE_ERROR; } // Calculate TB CRC - uint32_t checksum_tb = srslte_crc_checksum_byte(cfg.crc_tb, data, tb->tbs); + uint32_t checksum_tb = srslte_crc_checksum_byte(crc_tb, data, tb->tbs); if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { DEBUG("tb="); srslte_vec_fprint_byte(stdout, data, tb->tbs / 8); @@ -470,11 +465,11 @@ static inline int sch_nr_encode(srslte_sch_nr_t* q, } // Encode code block - srslte_ldpc_encoder_encode(cfg.encoder, q->temp_cb, rm_buffer, cfg.Kr); + srslte_ldpc_encoder_encode(encoder, q->temp_cb, rm_buffer, cfg.Kr); if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { DEBUG("encoded="); - srslte_vec_fprint_b(stdout, rm_buffer, cfg.encoder->liftN - 2 * cfg.encoder->ls); + srslte_vec_fprint_b(stdout, rm_buffer, encoder->liftN - 2 * encoder->ls); } } @@ -518,25 +513,29 @@ int sch_nr_decode(srslte_sch_nr_t* q, int8_t* input_ptr = e_bits; - srslte_sch_nr_common_cfg_t cfg = {}; - if (srslte_sch_nr_fill_cfg(q, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) { + srslte_sch_nr_tb_info_t cfg = {}; + if (srslte_sch_nr_fill_cfg(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } + // Select encoder and CRC + srslte_ldpc_decoder_t* decoder = (cfg.bg == BG1) ? q->decoder_bg1[cfg.Z] : q->decoder_bg2[cfg.Z]; + srslte_crc_t* crc_tb = (cfg.L_tb == 24) ? &q->crc_tb_24 : &q->crc_tb_16; + // Check decoder - if (cfg.decoder == NULL) { + if (decoder == NULL) { ERROR("Error: decoder for lifting size Z=%d not found", cfg.Z); return SRSLTE_ERROR; } // Check CRC for TB - if (cfg.crc_tb == NULL) { + if (crc_tb == NULL) { ERROR("Error: CRC for TB not found"); return SRSLTE_ERROR; } // Soft-buffer number of code-block protection - if (tb->softbuffer.rx->max_cb < cfg.Cp || tb->softbuffer.rx->max_cb_size < (cfg.decoder->liftN - 2 * cfg.Z)) { + if (tb->softbuffer.rx->max_cb < cfg.Cp || tb->softbuffer.rx->max_cb_size < (decoder->liftN - 2 * cfg.Z)) { return SRSLTE_ERROR; } @@ -586,7 +585,7 @@ int sch_nr_decode(srslte_sch_nr_t* q, srslte_ldpc_rm_rx_c(&q->rx_rm, input_ptr, rm_buffer, E, cfg.F, cfg.bg, cfg.Z, tb->rv, tb->mod, cfg.Nref); // Decode - srslte_ldpc_decoder_decode_c(cfg.decoder, rm_buffer, q->temp_cb); + srslte_ldpc_decoder_decode_c(decoder, rm_buffer, q->temp_cb); // Compute CB CRC uint32_t cb_len = cfg.Kp - cfg.L_cb; @@ -650,7 +649,7 @@ int sch_nr_decode(srslte_sch_nr_t* q, } // Calculate TB CRC from packed data - uint32_t checksum1 = srslte_crc_checksum_byte(cfg.crc_tb, data, tb->tbs); + uint32_t checksum1 = srslte_crc_checksum_byte(crc_tb, data, tb->tbs); *crc_ok = (checksum1 == checksum2 && !all_zeros); SCH_INFO_RX("TB: TBS=%d; CRC={%06x, %06x}", tb->tbs, checksum1, checksum2); diff --git a/lib/src/phy/phch/test/pucch_nr_test.c b/lib/src/phy/phch/test/pucch_nr_test.c index c3d026f10..bbabd4712 100644 --- a/lib/src/phy/phch/test/pucch_nr_test.c +++ b/lib/src/phy/phch/test/pucch_nr_test.c @@ -53,15 +53,14 @@ static int test_pucch_format0(srslte_pucch_nr_t* pucch, const srslte_pucch_nr_co for (resource.initial_cyclic_shift = 0; resource.initial_cyclic_shift <= 11; resource.initial_cyclic_shift++) { for (uint32_t m_cs = 0; m_cs <= 6; m_cs += 2) { - TESTASSERT(srslte_pucch_nr_format0_encode(pucch, &carrier, cfg, &slot, &resource, m_cs, slot_symbols) == + TESTASSERT(srslte_pucch_nr_format0_encode(pucch, cfg, &slot, &resource, m_cs, slot_symbols) == SRSLTE_SUCCESS); // Measure PUCCH format 0 for all possible values of m_cs for (uint32_t m_cs_test = 0; m_cs_test <= 6; m_cs_test += 2) { srslte_pucch_nr_measure_t measure = {}; TESTASSERT(srslte_pucch_nr_format0_measure( - pucch, &carrier, cfg, &slot, &resource, m_cs_test, slot_symbols, &measure) == - SRSLTE_SUCCESS); + pucch, cfg, &slot, &resource, m_cs_test, slot_symbols, &measure) == SRSLTE_SUCCESS); if (m_cs == m_cs_test) { TESTASSERT(fabsf(measure.epre - 1) < 0.001); @@ -115,8 +114,8 @@ static int test_pucch_format1(srslte_pucch_nr_t* pucch, } // Encode PUCCH - TESTASSERT(srslte_pucch_nr_format1_encode( - pucch, &carrier, cfg, &slot, &resource, b, nof_bits, slot_symbols) == SRSLTE_SUCCESS); + TESTASSERT(srslte_pucch_nr_format1_encode(pucch, cfg, &slot, &resource, b, nof_bits, slot_symbols) == + SRSLTE_SUCCESS); // Put DMRS TESTASSERT(srslte_dmrs_pucch_format1_put(pucch, &carrier, cfg, &slot, &resource, slot_symbols) == @@ -137,7 +136,7 @@ static int test_pucch_format1(srslte_pucch_nr_t* pucch, // Decode PUCCH uint8_t b_rx[SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS]; TESTASSERT(srslte_pucch_nr_format1_decode( - pucch, &carrier, cfg, &slot, &resource, chest_res, slot_symbols, b_rx, nof_bits) == + pucch, cfg, &slot, &resource, chest_res, slot_symbols, b_rx, nof_bits) == SRSLTE_SUCCESS); // Check received bits @@ -202,8 +201,7 @@ static int test_pucch_format2(srslte_pucch_nr_t* pucch, // Encode PUCCH TESTASSERT(srslte_pucch_nr_format_2_3_4_encode( - pucch, &carrier, cfg, &slot, &resource, &uci_cfg, &uci_value, slot_symbols) == - SRSLTE_SUCCESS); + pucch, cfg, &slot, &resource, &uci_cfg, &uci_value, slot_symbols) == SRSLTE_SUCCESS); // Put DMRS TESTASSERT(srslte_dmrs_pucch_format2_put(pucch, &carrier, cfg, &slot, &resource, slot_symbols) == @@ -226,10 +224,9 @@ static int test_pucch_format2(srslte_pucch_nr_t* pucch, // Decode PUCCH srslte_uci_value_nr_t uci_value_rx = {}; - TESTASSERT( - srslte_pucch_nr_format_2_3_4_decode( - pucch, &carrier, cfg, &slot, &resource, &uci_cfg, chest_res, slot_symbols, &uci_value_rx) == - SRSLTE_SUCCESS); + TESTASSERT(srslte_pucch_nr_format_2_3_4_decode( + pucch, cfg, &slot, &resource, &uci_cfg, chest_res, slot_symbols, &uci_value_rx) == + SRSLTE_SUCCESS); TESTASSERT(uci_value_rx.valid == true); @@ -311,6 +308,11 @@ int main(int argc, char** argv) goto clean_exit; } + if (srslte_pucch_nr_set_carrier(&pucch, &carrier) < SRSLTE_SUCCESS) { + ERROR("PUCCH set carrier"); + goto clean_exit; + } + if (srslte_chest_ul_res_init(&chest_res, carrier.nof_prb)) { ERROR("Chest UL"); goto clean_exit; diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index 8edbed4dc..581b3752f 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -27,11 +27,13 @@ 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_sch_cfg_nr_t pusch_cfg = {}; -static srslte_sch_grant_nr_t pusch_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 pusch_cfg = {}; +static srslte_sch_grant_nr_t pusch_grant = {}; +static uint16_t rnti = 0x1234; +static uint32_t nof_ack_bits = 0; +static uint32_t nof_csi_bits = 0; void usage(char* prog) { @@ -41,13 +43,15 @@ void usage(char* prog) 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-A Provide a number of HARQ-ACK bits [Default %d]\n", nof_ack_bits); + printf("\t-C Provide a number of CSI bits [Default %d]\n", nof_csi_bits); 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) { + while ((opt = getopt(argc, argv, "pmTLACv")) != -1) { switch (opt) { case 'p': n_prb = (uint32_t)strtol(argv[optind], NULL, 10); @@ -61,6 +65,12 @@ int parse_args(int argc, char** argv) case 'L': carrier.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10); break; + case 'A': + nof_ack_bits = (uint32_t)strtol(argv[optind], NULL, 10); + break; + case 'C': + nof_csi_bits = (uint32_t)strtol(argv[optind], NULL, 10); + break; case 'v': srslte_verbose++; break; @@ -75,16 +85,15 @@ int parse_args(int argc, char** argv) 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); + int ret = SRSLTE_ERROR; + srslte_pusch_nr_t pusch_tx = {}; + srslte_pusch_nr_t pusch_rx = {}; + srslte_chest_dl_res_t chest = {}; + 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] = {}; + srslte_pusch_data_nr_t data_tx[SRSLTE_MAX_TB] = {}; + srslte_pusch_res_nr_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; @@ -126,14 +135,12 @@ int main(int argc, char** argv) } 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) { + data_tx[i].payload = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR); + data_rx[i].payload = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_NOF_BITS_NR); + if (data_tx[i].payload == NULL || data_rx[i].payload == NULL) { ERROR("Error malloc"); goto clean_exit; } - - pusch_res[i].payload = data_rx[i]; } srslte_softbuffer_tx_t softbuffer_tx = {}; @@ -198,18 +205,39 @@ int main(int argc, char** argv) goto clean_exit; } + // Generate SCH payload for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { // Skip TB if no allocated - if (data_tx[tb] == NULL) { + if (data_tx[tb].payload == 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); + data_tx[tb].payload[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, UINT8_MAX); } pusch_grant.tb[tb].softbuffer.tx = &softbuffer_tx; } + // Generate HARQ ACK bits + if (nof_ack_bits > 0) { + pusch_cfg.uci.o_ack = nof_ack_bits; + for (uint32_t i = 0; i < nof_ack_bits; i++) { + data_tx->uci.ack[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, 1); + } + } + + // Generate CSI report bits + uint8_t csi_report[SRSLTE_UCI_NR_MAX_CSI1_BITS]; + if (nof_csi_bits > 0) { + pusch_cfg.uci.csi[0].quantity = SRSLTE_CSI_REPORT_QUANTITY_NONE; + pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits; + pusch_cfg.uci.nof_csi = 1; + data_tx->uci.csi[0].none = csi_report; + for (uint32_t i = 0; i < nof_csi_bits; i++) { + csi_report[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, 1); + } + } + if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_grant, data_tx, sf_symbols) < SRSLTE_SUCCESS) { ERROR("Error encoding"); goto clean_exit; @@ -225,13 +253,13 @@ int main(int argc, char** argv) } 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) { + if (srslte_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_grant, &chest, sf_symbols, data_rx) < SRSLTE_SUCCESS) { ERROR("Error encoding"); goto clean_exit; } - if (pusch_res->evm > 0.001f) { - ERROR("Error PUSCH EVM is too high %f", pusch_res->evm); + if (data_rx[0].evm > 0.001f) { + ERROR("Error PUSCH EVM is too high %f", data_rx[0].evm); goto clean_exit; } @@ -256,21 +284,21 @@ int main(int argc, char** argv) goto clean_exit; } - if (!pusch_res[0].crc) { + if (!data_rx[0].crc) { ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", 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) { + if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_grant.tb[0].tbs / 8) != 0) { ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", 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); + srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_grant.tb[0].tbs / 8); printf("Rx data: "); - srslte_vec_fprint_byte(stdout, data_rx[0], pusch_grant.tb[0].tbs / 8); + srslte_vec_fprint_byte(stdout, data_tx[0].payload, 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); + printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_grant.tb[0].tbs, data_rx[0].evm); } } @@ -282,11 +310,11 @@ clean_exit: 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_tx[i].payload) { + free(data_tx[i].payload); } - if (data_rx[i]) { - free(data_rx[i]); + if (data_rx[i].payload) { + free(data_rx[i].payload); } } for (uint32_t i = 0; i < SRSLTE_MAX_LAYERS_NR; i++) { diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index 3aac61c30..1a5c778b7 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -11,13 +11,14 @@ */ #include "srslte/phy/phch/uci_nr.h" +#include "srslte/phy/ch_estimation/dmrs_sch.h" #include "srslte/phy/fec/block/block.h" #include "srslte/phy/fec/polar/polar_chanalloc.h" #include "srslte/phy/phch/csi.h" +#include "srslte/phy/phch/sch_nr.h" #include "srslte/phy/phch/uci_cfg.h" #include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/vector.h" -#include #define UCI_NR_INFO_TX(...) INFO("UCI-NR Tx: " __VA_ARGS__) #define UCI_NR_INFO_RX(...) INFO("UCI-NR Rx: " __VA_ARGS__) @@ -118,6 +119,17 @@ int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args) return SRSLTE_SUCCESS; } +int srslte_uci_nr_set_carrier(srslte_uci_nr_t* q, const srslte_carrier_nr_t* carrier) +{ + if (q == NULL || carrier == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + q->carrier = *carrier; + + return SRSLTE_SUCCESS; +} + void srslte_uci_nr_free(srslte_uci_nr_t* q) { if (q == NULL) { @@ -207,7 +219,7 @@ static int uci_nr_A(const srslte_uci_cfg_nr_t* cfg) return SRSLTE_ERROR; } -static int uci_nr_packing(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence) +static int uci_nr_pack_pucch(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence) { int o_csi = srslte_csi_nof_bits(cfg->csi, cfg->nof_csi); @@ -226,7 +238,7 @@ static int uci_nr_packing(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value return SRSLTE_ERROR; } -static int uci_nr_unpacking(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence, srslte_uci_value_nr_t* value) +static int uci_nr_unpack_pucch(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence, srslte_uci_value_nr_t* value) { int o_csi = srslte_csi_nof_bits(cfg->csi, cfg->nof_csi); @@ -246,12 +258,13 @@ static int uci_nr_unpacking(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence, s return SRSLTE_ERROR; } -static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E) +static int +uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mod_t modulation, uint8_t* o, uint32_t E) { uint32_t i = 0; srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1; - switch (cfg->modulation) { + switch (modulation) { case SRSLTE_MOD_BPSK: while (i < E) { o[i++] = c0; @@ -304,14 +317,15 @@ static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg return E; } -static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E) +static int +uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mod_t modulation, uint8_t* o, uint32_t E) { uint32_t i = 0; srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1; srslte_uci_bit_type_t c1 = (q->bit_sequence[1] == 0) ? UCI_BIT_0 : UCI_BIT_1; srslte_uci_bit_type_t c2 = ((q->bit_sequence[0] ^ q->bit_sequence[1]) == 0) ? UCI_BIT_0 : UCI_BIT_1; - switch (cfg->modulation) { + switch (modulation) { case SRSLTE_MOD_BPSK: case SRSLTE_MOD_QPSK: while (i < E) { @@ -629,31 +643,21 @@ static int uci_nr_decode_11_1706_bit(srslte_uci_nr_t* q, return SRSLTE_SUCCESS; } -static int uci_nr_encode(srslte_uci_nr_t* q, - const srslte_uci_cfg_nr_t* uci_cfg, - const srslte_uci_value_nr_t* uci_value, - uint8_t* o, - uint32_t E_uci) +static int uci_nr_encode(srslte_uci_nr_t* q, + const srslte_uci_cfg_nr_t* uci_cfg, + srslte_mod_t mod, + uint32_t A, + uint8_t* o, + uint32_t E_uci) { - if (q == NULL || uci_cfg == NULL || uci_value == NULL || o == NULL) { - return SRSLTE_ERROR_INVALID_INPUTS; - } - - // 6.3.1.1 UCI bit sequence generation - int A = uci_nr_packing(uci_cfg, uci_value, q->bit_sequence); - if (A < SRSLTE_SUCCESS) { - ERROR("Generating bit sequence"); - return SRSLTE_ERROR; - } - // 5.3.3.1 Encoding of 1-bit information if (A == 1) { - return uci_nr_encode_1bit(q, uci_cfg, o, E_uci); + return uci_nr_encode_1bit(q, uci_cfg, mod, o, E_uci); } // 5.3.3.2 Encoding of 2-bit information if (A == 2) { - return uci_nr_encode_2bit(q, uci_cfg, o, E_uci); + return uci_nr_encode_2bit(q, uci_cfg, mod, o, E_uci); } // 5.3.3.3 Encoding of other small block lengths @@ -704,7 +708,7 @@ static int uci_nr_decode(srslte_uci_nr_t* q, } // Unpack bits - if (uci_nr_unpacking(uci_cfg, q->bit_sequence, uci_value) < SRSLTE_SUCCESS) { + if (uci_nr_unpack_pucch(uci_cfg, q->bit_sequence, uci_value) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -770,7 +774,14 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q, return SRSLTE_ERROR; } - return uci_nr_encode(q, uci_cfg, value, o, E_uci); + // 6.3.1.1 UCI bit sequence generation + int A = uci_nr_pack_pucch(uci_cfg, value, q->bit_sequence); + if (A < SRSLTE_SUCCESS) { + ERROR("Generating bit sequence"); + return SRSLTE_ERROR; + } + + return uci_nr_encode(q, uci_cfg, SRSLTE_MOD_NITEMS, A, o, E_uci); } int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q, @@ -823,3 +834,115 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin return len; } + +static int uci_nr_Q_ack_prime(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* sch_cfg, uint32_t A) +{ + // Get UL-SCH TB information + srslte_sch_nr_tb_info_t tb_info = {}; + if (srslte_sch_nr_fill_cfg(&q->carrier, &sch_cfg->sch_cfg, &sch_cfg->grant.tb[0], &tb_info) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + + // Get DMRS symbol indexes + uint32_t nof_dmrs_l = 0; + uint32_t dmrs_l[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; + int n = srslte_dmrs_sch_get_symbols_idx(&sch_cfg->dmrs, &sch_cfg->grant, dmrs_l); + if (n < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + nof_dmrs_l = (uint32_t)n; + + uint32_t O_ack = A; // Number of HARQ-ACK bits + uint32_t L_ack = srslte_uci_nr_crc_len(A); // Number of CRC bits + float beta_pusch_offset = sch_cfg->beta_harq_ack_offset; // Beta offset given by higher layers + uint32_t C_ulsch = tb_info.C; // number of code blocks for UL-SCH of the PUSCH + float alpha = sch_cfg->scaling; // Higher layer parameter scaling + float R = (float)sch_cfg->grant.tb[0].R; // code rate of the PUSCH + float Qm = srslte_mod_bits_x_symbol(sch_cfg->grant.tb[0].mod); // modulation order of the PUSCH + + uint32_t K_sum = 0; + for (uint32_t i = 0; i < SRSLTE_MIN(C_ulsch, SRSLTE_SCH_NR_MAX_NOF_CB_LDPC); i++) { + K_sum += tb_info.mask[i] ? 0 : tb_info.Kr; + } + + uint32_t dmrs_l_idx = 0; + uint32_t M_uci_sum = 0; + uint32_t M_uci_l0_sum = 0; + for (uint32_t l = sch_cfg->grant.S; l < sch_cfg->grant.S + sch_cfg->grant.L; l++) { + uint32_t M_ptrs_sc = 0; // Not implemented yet + uint32_t M_pusch_sc = sch_cfg->grant.nof_prb * SRSLTE_NRE; + uint32_t M_uci_sc = M_pusch_sc - M_ptrs_sc; + + // If the OFDM symbol contains DMRS, no UCI is mapped + if (l == dmrs_l[dmrs_l_idx] && dmrs_l_idx < nof_dmrs_l) { + M_uci_sc = 0; + dmrs_l_idx++; + } + + // Add subcarriers that can contain UCI RE + M_uci_sum += M_uci_sc; + + // Start adding after the first DMRS symbol + if (dmrs_l_idx > 0) { + M_uci_l0_sum += M_uci_sc; + } + } + + if (sch_cfg->uci.without_ul_sch) { + return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * beta_pusch_offset) / (Qm * R)), alpha * M_uci_l0_sum); + } + return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * beta_pusch_offset * M_uci_sum) / (float)K_sum), alpha * M_uci_l0_sum); +} + +int srslte_uci_nr_pusch_E_uci_ack(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* cfg) +{ + int A = cfg->uci.o_ack; + + // Check inputs + if (q == NULL || cfg == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + if (cfg->uci.without_ul_sch && cfg->uci.nof_csi > 1 && !cfg->uci.has_csi_part2 && cfg->uci.o_ack < 2) { + A = 2; + } + + int Q_ack_prime = uci_nr_Q_ack_prime(q, cfg, A); + if (Q_ack_prime < SRSLTE_SUCCESS) { + return Q_ack_prime; + } + + return (int)(Q_ack_prime * cfg->grant.nof_layers * srslte_mod_bits_x_symbol(cfg->grant.tb[0].mod)); +} + +int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q, + const srslte_sch_cfg_nr_t* cfg, + const srslte_uci_value_nr_t* value, + uint8_t* o) +{ + int A = cfg->uci.o_ack; + + // Check inputs + if (q == NULL || cfg == NULL || value == NULL || o == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + // 6.3.2.1 UCI bit sequence generation + // 6.3.2.1.1 HARQ-ACK + if (cfg->uci.without_ul_sch && cfg->uci.nof_csi > 1 && !cfg->uci.has_csi_part2 && cfg->uci.o_ack < 2) { + A = 2; + q->bit_sequence[0] = (cfg->uci.o_ack == 0) ? 0 : value->ack[0]; + q->bit_sequence[1] = 0; + } else { + srslte_vec_u8_copy(q->bit_sequence, value->ack, cfg->uci.o_ack); + } + + // Compute total of encoded bits according to 6.3.2.4 Rate matching + int E_uci = srslte_uci_nr_pusch_E_uci_ack(q, cfg); + if (E_uci < SRSLTE_SUCCESS) { + ERROR("Error calculating number of encoded bits"); + return SRSLTE_ERROR; + } + + return uci_nr_encode(q, &cfg->uci, cfg->grant.tb[0].mod, A, o, E_uci); +} \ No newline at end of file diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index b44252551..43496a887 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -82,6 +82,11 @@ int srslte_ue_ul_nr_set_carrier(srslte_ue_ul_nr_t* q, const srslte_carrier_nr_t* return SRSLTE_ERROR; } + if (srslte_pucch_nr_set_carrier(&q->pucch, carrier) < SRSLTE_SUCCESS) { + ERROR("Setting PUSCH carrier"); + return SRSLTE_ERROR; + } + if (srslte_dmrs_sch_set_carrier(&q->dmrs, carrier)) { ERROR("Setting DMRS carrier"); return SRSLTE_ERROR; @@ -90,16 +95,13 @@ int srslte_ue_ul_nr_set_carrier(srslte_ue_ul_nr_t* q, const srslte_carrier_nr_t* return SRSLTE_SUCCESS; } -int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q, - const srslte_slot_cfg_t* slot_cfg, - const srslte_sch_cfg_nr_t* pusch_cfg, - uint8_t* data_) +int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q, + const srslte_slot_cfg_t* slot_cfg, + const srslte_sch_cfg_nr_t* pusch_cfg, + const srslte_pusch_data_nr_t* data) { - uint8_t* data[SRSLTE_MAX_TB] = {}; - data[0] = data_; - // Check inputs - if (q == NULL || pusch_cfg == NULL || data_ == NULL) { + if (q == NULL || pusch_cfg == NULL || data == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -158,7 +160,7 @@ static int ue_ul_nr_encode_pucch_format1(srslte_ue_ul_nr_t* q, return SRSLTE_ERROR; } - return srslte_pucch_nr_format1_encode(&q->pucch, &q->carrier, cfg, slot, resource, b, nof_bits, q->sf_symbols[0]); + return srslte_pucch_nr_format1_encode(&q->pucch, cfg, slot, resource, b, nof_bits, q->sf_symbols[0]); } int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* q, @@ -192,7 +194,7 @@ int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* q, return SRSLTE_ERROR; } if (srslte_pucch_nr_format_2_3_4_encode( - &q->pucch, &q->carrier, cfg, slot_cfg, resource, &uci_data->cfg, &uci_data->value, q->sf_symbols[0]) < + &q->pucch, cfg, slot_cfg, resource, &uci_data->cfg, &uci_data->value, q->sf_symbols[0]) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 4f5ba9236..3cd314902 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -288,8 +288,11 @@ bool cc_worker::work_ul() // Assignning MAC provided values to PUSCH config structs pusch_cfg.grant.tb[0].softbuffer.tx = ul_action.tb.softbuffer; + srslte_pusch_data_nr_t data = {}; + data.payload = ul_action.tb.payload->msg; + // Encode PUSCH transmission - if (srslte_ue_ul_nr_encode_pusch(&ue_ul, &ul_slot_cfg, &pusch_cfg, ul_action.tb.payload->msg) < SRSLTE_SUCCESS) { + if (srslte_ue_ul_nr_encode_pusch(&ue_ul, &ul_slot_cfg, &pusch_cfg, &data) < SRSLTE_SUCCESS) { ERROR("Encoding PUSCH"); return false; }