Initial HARQ-ACK multiplex in PUSCH

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 7b588eafec
commit f4e9d00ea8

@ -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

@ -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,

@ -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,

@ -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

@ -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

@ -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 <stdbool.h>
#include <stdint.h>
@ -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

@ -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,

@ -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;
}

@ -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;
}

@ -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);

@ -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;

@ -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++) {

@ -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 <inttypes.h>
#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);
}

@ -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;
}

@ -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;
}

Loading…
Cancel
Save