Added more docs to PUCCH 1b CS resource selection

This commit is contained in:
Xavier Arteaga 2020-02-06 12:16:33 +01:00 committed by Xavier Arteaga
parent 73c63b10f2
commit d66fdefbb3
5 changed files with 90 additions and 59 deletions

View File

@ -471,4 +471,12 @@ SRSLTE_API char* srslte_nbiot_mode_string(srslte_nbiot_mode_t mode);
bool srslte_psbch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t i);
/**
* Returns a constant string pointer with the ACK/NACK feedback mode
*
* @param ack_nack_feedback_mode Mode
* @return Returns constant pointer with the text of the mode if succesful, `error` otherwise
*/
SRSLTE_API const char* srslte_ack_nack_feedback_mode_string(srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode);
#endif // SRSLTE_PHY_COMMON_H

View File

@ -49,6 +49,8 @@
// PUCCH Format 1B Channel selection
#define SRSLTE_PUCCH_CS_MAX_ACK 4
#define SRSLTE_PUCCH_CS_MAX_CARRIERS 2
#define SRSLTE_PUCCH_FORMAT3_MAX_CARRIERS 5
#define SRSLTE_PUCCH_CS_MAX_NOF_ALLOC 4
typedef struct {
@ -173,16 +175,17 @@ SRSLTE_API srslte_pucch_format_t srslte_pucch_select_format(srslte_pucch_cfg_t*
srslte_cp_t cp);
/**
* Implements 3GPP 36.213 R10 10.1.2.2.1 PUCCH format 1b with channel selection HARQ-ACK procedure
* resource list
* 3GPP 36.213 R10 10.1.2.2.1 PUCCH format 1b with channel selection HARQ-ACK procedure. Determines the A
* PUCCH resources, n_pucch_i associated with HARQ-ACK(j) where 0 j A 1 in Table 10.1.2.2.1-1
*
* @param cfg PUCCH configuration struct
* @param uci_cfg uplink control information configuration
* @param n_pucch_i table with the PUCCH format 1b possible resources
* @return Returns the number of entries in the table or negative value indicating error
*/
SRSLTE_API int srslte_pucch_cs_resources(srslte_pucch_cfg_t* cfg,
srslte_uci_cfg_t* uci_cfg,
uint32_t n_pucch_i[SRSLTE_PUCCH_CS_MAX_NOF_ALLOC]);
SRSLTE_API int srslte_pucch_cs_resources(const srslte_pucch_cfg_t* cfg,
const srslte_uci_cfg_t* uci_cfg,
uint32_t n_pucch_i[SRSLTE_PUCCH_CS_MAX_NOF_ALLOC]);
/**
* Decodes the HARQ ACK bits from a selected resource (j) and received bits (b)

View File

@ -854,3 +854,18 @@ bool srslte_psbch_is_symbol(srslte_sl_symbol_t type, srslte_sl_tm_t tm, uint32_t
return srslte_psbch_symbol_map_tm34[i] == type;
}
}
const char* srslte_ack_nack_feedback_mode_string(srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode)
{
switch (ack_nack_feedback_mode) {
case SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL:
return "normal";
case SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS:
return "cs";
case SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3:
return "pucch3";
case SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_ERROR:
default:
return "error";
}
}

View File

@ -1299,41 +1299,48 @@ srslte_pucch_format_t srslte_pucch_select_format(srslte_pucch_cfg_t* cfg, srslte
return format;
}
int srslte_pucch_cs_resources(srslte_pucch_cfg_t* cfg, srslte_uci_cfg_t* uci_cfg, uint32_t n_pucch_i[4])
int srslte_pucch_cs_resources(const srslte_pucch_cfg_t* cfg, const srslte_uci_cfg_t* uci_cfg, uint32_t n_pucch_i[4])
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (cfg && uci_cfg && n_pucch_i) {
// Determine the 4 PUCCH resources n_pucch_j associated with HARQ-ACK(j)
uint32_t k = 0;
for (int i = 0; i < SRSLTE_MAX_CARRIERS && k < SRSLTE_PUCCH_CS_MAX_ACK; i++) {
// If grant has been scheduled in PCell
if (uci_cfg->ack[i].grant_cc_idx == 0) {
for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks && k < SRSLTE_PUCCH_CS_MAX_ACK; j++) {
if (k % 2 == 1) {
n_pucch_i[k] = cfg->n1_pucch_an_cs[uci_cfg->ack[i].tpc_for_pucch][k / 2];
} else {
n_pucch_i[k] = uci_cfg->ack[i].ncce[0] + cfg->N_pucch_1 + j;
}
k++;
}
} else {
for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks; j++) {
if (k < 4) {
n_pucch_i[k++] = cfg->n1_pucch_an_cs[uci_cfg->ack[i].tpc_for_pucch % SRSLTE_PUCCH_SIZE_AN_CS]
[j % SRSLTE_PUCCH_NOF_AN_CS];
} else {
fprintf(stderr, "get_npucch_cs(): Too many ack bits\n");
return SRSLTE_ERROR;
}
}
}
}
ret = (int)k;
// Check inputs
if (!cfg || !uci_cfg || !n_pucch_i) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
return ret;
// Determine up to 4 PUCCH resources n_pucch_j associated with HARQ-ACK(j)
int k = 0;
for (int i = 0; i < SRSLTE_PUCCH_CS_MAX_CARRIERS && k < SRSLTE_PUCCH_CS_MAX_ACK; i++) {
if (uci_cfg->ack[i].grant_cc_idx == 0) {
// - for a PDSCH transmission indicated by the detection of a corresponding PDCCH in subframe n 4 on the primary
// cell, or for a PDCCH indicating downlink SPS release (defined in subclause 9.2) in subframe n 4 on the
// primary cell, the PUCCH resource is n_pucch_i = n_cce + N_pucch_1, and for transmission mode that supports up
// to two transport blocks, the PUCCH resource n_pucch_i+1 = n_cce + N_pucch_1 + 1
for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks && k < SRSLTE_PUCCH_CS_MAX_ACK; j++) {
n_pucch_i[k++] = uci_cfg->ack[i].ncce[0] + cfg->N_pucch_1 + j;
}
} else if (i == 0) {
// - for a PDSCH transmission on the primary cell where there is not a corresponding PDCCH detected in subframe
// n 4 , the value of n_pucch_i is determined according to higher layer configuration and Table 9.2-2. For
// transmission mode that supports up to two transport blocks, the PUCCH resource n_pucch_i+1 = n_pucch_i + 1
for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks && k < SRSLTE_PUCCH_CS_MAX_ACK; j++) {
n_pucch_i[k++] = cfg->n1_pucch_an_cs[uci_cfg->ack[i].tpc_for_pucch % SRSLTE_PUCCH_SIZE_AN_CS][0] + j;
}
} else {
// - for a PDSCH transmission indicated by the detection of a corresponding PDCCH in subframe n 4 on the
// secondary cell, the value of n_pucch_i, and the value of n_pucch_i+1 for the transmission mode that supports
// up to two transport blocks is determined according to higher layer configuration and Table 10.1.2.2.1-2. The
// TPC field in the DCI format of the corresponding PDCCH shall be used to determine the PUCCH resource values
// from one of the four resource values configured by higher layers, with the mapping defined in Table
// 10.1.2.2.1-2. For a UE configured for a transmission mode that supports up to two transport blocks a PUCCH
// resource value in Table 10.1.2.2.1-2 maps to two PUCCH resources (n_pucch_i, n_pucch_i + 1), otherwise the
// PUCCH resource value maps to a single PUCCH resource n_pucch_i.
for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks && k < SRSLTE_PUCCH_CS_MAX_ACK; j++) {
n_pucch_i[k++] =
cfg->n1_pucch_an_cs[uci_cfg->ack[i].tpc_for_pucch % SRSLTE_PUCCH_SIZE_AN_CS][j % SRSLTE_PUCCH_NOF_AN_CS];
}
}
}
return k;
}
#define PUCCH_CS_SET_ACK(J, B0, B1, ...) \

View File

@ -30,9 +30,9 @@
#include "srslte/srslte.h"
static int test_pucch_cs(srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode,
static int test_pucch_ca(srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode,
uint32_t nof_prb,
const uint32_t nof_tb[SRSLTE_MAX_CARRIERS],
const uint32_t* nof_tb,
uint16_t nof_carriers)
{
srslte_pucch_cfg_t pucch_cfg = {};
@ -145,28 +145,26 @@ int main(int argc, char** argv)
// Set PHY lib verbose to INFO
srslte_verbose = SRSLTE_VERBOSE_INFO;
uint32_t nof_tb_1[SRSLTE_MAX_CARRIERS] = {1, 1, 1, 1, 0};
uint32_t nof_tb_2[SRSLTE_MAX_CARRIERS] = {2, 1, 1, 0, 0};
uint32_t nof_tb_1[SRSLTE_MAX_CARRIERS] = {1, 1, 1, 1, 1};
uint32_t nof_tb_2[SRSLTE_MAX_CARRIERS] = {2, 1, 1, 1, 1};
uint32_t nof_tb_3[SRSLTE_MAX_CARRIERS] = {2, 2, 2, 2, 2};
for (srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS;
ack_nack_feedback_mode < SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_ERROR;
ack_nack_feedback_mode++) {
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_1, 2));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_1, 3));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_1, 4));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_2, 3));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_2, 3));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_3, 2));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 100, nof_tb_1, 2));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 100, nof_tb_1, 3));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 100, nof_tb_1, 4));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 100, nof_tb_2, 3));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 100, nof_tb_2, 3));
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 100, nof_tb_3, 2));
if (ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3) {
TESTASSERT(!test_pucch_cs(ack_nack_feedback_mode, 6, nof_tb_3, 5));
}
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS, 6, nof_tb_1, 2));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS, 6, nof_tb_2, 2));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS, 6, nof_tb_3, 2));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS, 100, nof_tb_1, 2));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS, 100, nof_tb_2, 2));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS, 100, nof_tb_3, 2));
for (uint32_t i = 2; i < SRSLTE_PUCCH_FORMAT3_MAX_CARRIERS; i++) {
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3, 6, nof_tb_1, i));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3, 6, nof_tb_2, i));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3, 6, nof_tb_3, i));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3, 100, nof_tb_1, i));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3, 100, nof_tb_2, i));
TESTASSERT(!test_pucch_ca(SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3, 100, nof_tb_3, i));
}
printf("Ok\n");