|
|
|
@ -38,6 +38,7 @@
|
|
|
|
|
#include "srslte/phch/pucch.h"
|
|
|
|
|
#include "srslte/common/sequence.h"
|
|
|
|
|
#include "srslte/common/phy_common.h"
|
|
|
|
|
#include "srslte/scrambling/scrambling.h"
|
|
|
|
|
#include "srslte/utils/debug.h"
|
|
|
|
|
#include "srslte/utils/vector.h"
|
|
|
|
|
|
|
|
|
@ -65,6 +66,15 @@ bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verifies n_2_pucch as defined in 5.4
|
|
|
|
|
bool srslte_pucch_n2_isvalid(srslte_pucch_cfg_t *cfg, uint32_t n_pucch_2) {
|
|
|
|
|
if (n_pucch_2 < cfg->n_rb_2*SRSLTE_NRE+(uint32_t) ceilf((float) cfg->N_cs/8)*(SRSLTE_NRE-cfg->N_cs-2)) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void srslte_pucch_cfg_default(srslte_pucch_cfg_t *cfg) {
|
|
|
|
|
cfg->beta_pucch = 1.0;
|
|
|
|
|
cfg->delta_pucch_shift = 1;
|
|
|
|
@ -84,6 +94,25 @@ uint32_t get_N_sf(srslte_pucch_format_t format) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Number of bits per subframe (M_bit) Table 5.4-1 36.211
|
|
|
|
|
uint32_t srslte_pucch_nbits_format(srslte_pucch_format_t format) {
|
|
|
|
|
switch(format) {
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1:
|
|
|
|
|
return 0;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1A:
|
|
|
|
|
return 1;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1B:
|
|
|
|
|
return 2;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_2:
|
|
|
|
|
return 20;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_2A:
|
|
|
|
|
return 21;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_2B:
|
|
|
|
|
return 22;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) {
|
|
|
|
|
switch (format) {
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1:
|
|
|
|
@ -157,8 +186,8 @@ int srslte_pucch_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLOTS_
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Calculates alpha according to 5.5.2.2.2 (is_dmrs=true) or 5.4.1 (is_dmrs=false) of 36.211 */
|
|
|
|
|
float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
|
|
|
|
|
/* Calculates alpha for format 1/a/b according to 5.5.2.2.2 (is_dmrs=true) or 5.4.1 (is_dmrs=false) of 36.211 */
|
|
|
|
|
float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
|
|
|
|
|
srslte_pucch_cfg_t *cfg,
|
|
|
|
|
uint32_t n_pucch,
|
|
|
|
|
srslte_cp_t cp, bool is_dmrs,
|
|
|
|
@ -197,13 +226,40 @@ float srslte_pucch_alpha(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NOR
|
|
|
|
|
}
|
|
|
|
|
uint32_t n_cs = 0;
|
|
|
|
|
if (SRSLTE_CP_ISNORM(cp)) {
|
|
|
|
|
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+(n_oc%cfg->delta_pucch_shift))%N_prime)%12;
|
|
|
|
|
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+(n_oc%cfg->delta_pucch_shift))%N_prime)%SRSLTE_NRE;
|
|
|
|
|
} else {
|
|
|
|
|
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+n_oc/n_oc_div)%N_prime)%12;
|
|
|
|
|
n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+n_oc/n_oc_div)%N_prime)%SRSLTE_NRE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 2 * M_PI * (n_cs) / 12;
|
|
|
|
|
return 2 * M_PI * (n_cs) / SRSLTE_NRE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Calculates alpha for format 2/a/b according to 5.4.2 of 36.211 */
|
|
|
|
|
float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB],
|
|
|
|
|
srslte_pucch_cfg_t *cfg,
|
|
|
|
|
uint32_t n_pucch,
|
|
|
|
|
uint32_t ns, uint32_t l)
|
|
|
|
|
{
|
|
|
|
|
uint32_t n_prime = n_pucch%SRSLTE_NRE;
|
|
|
|
|
if (n_pucch >= SRSLTE_NRE*cfg->n_rb_2) {
|
|
|
|
|
n_prime = (n_pucch + cfg->N_cs + 1)%SRSLTE_NRE;
|
|
|
|
|
}
|
|
|
|
|
if (ns%2) {
|
|
|
|
|
n_prime = (SRSLTE_NRE*(n_prime+1))%(SRSLTE_NRE+1)-1;
|
|
|
|
|
if (n_pucch >= SRSLTE_NRE*cfg->n_rb_2) {
|
|
|
|
|
int x = (SRSLTE_NRE-2-(int) n_pucch)%SRSLTE_NRE;
|
|
|
|
|
if (x >= 0) {
|
|
|
|
|
n_prime = (uint32_t) x;
|
|
|
|
|
} else {
|
|
|
|
|
n_prime = SRSLTE_NRE+x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
uint32_t n_cs = (n_cs_cell[ns][l]+n_prime)%SRSLTE_NRE;
|
|
|
|
|
DEBUG("n_pucch: %d, ns: %d, l: %d, n_prime: %d, n_cs: %d\n", n_pucch, ns, l, n_prime, n_cs);
|
|
|
|
|
return 2 * M_PI * (n_cs) / SRSLTE_NRE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */
|
|
|
|
|
static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *output) {
|
|
|
|
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
|
|
|
@ -248,8 +304,14 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
|
|
|
|
|
bzero(q, sizeof(srslte_pucch_t));
|
|
|
|
|
|
|
|
|
|
q->cell = cell;
|
|
|
|
|
q->rnti_is_set = false;
|
|
|
|
|
|
|
|
|
|
srslte_pucch_cfg_default(&q->pucch_cfg);
|
|
|
|
|
|
|
|
|
|
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, false)) {
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Precompute group hopping values u.
|
|
|
|
|
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
@ -265,9 +327,27 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void srslte_pucch_free(srslte_pucch_t *q) {
|
|
|
|
|
if (q->rnti_is_set) {
|
|
|
|
|
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
|
|
|
|
|
srslte_sequence_free(&q->seq_f2[sf_idx]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
srslte_modem_table_free(&q->mod);
|
|
|
|
|
bzero(q, sizeof(srslte_pucch_t));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) {
|
|
|
|
|
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
|
|
|
|
|
// Precompute scrambling sequence for pucch format 2
|
|
|
|
|
if (srslte_sequence_pucch(&q->seq_f2[sf_idx], c_rnti, 2*sf_idx, q->cell.id)) {
|
|
|
|
|
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
q->rnti_is_set = true;
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool srslte_pucch_set_cfg(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg)
|
|
|
|
|
{
|
|
|
|
|
if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) {
|
|
|
|
@ -302,28 +382,63 @@ static cf_t uci_encode_format1b(uint8_t bits[2]) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Modulates bit 20 and 21 for Formats 2a and 2b as in Table 5.4.2-1 in 36.211 */
|
|
|
|
|
int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format, uint8_t bits[2], cf_t *d_10) {
|
|
|
|
|
if (d_10) {
|
|
|
|
|
if (format == SRSLTE_PUCCH_FORMAT_2A) {
|
|
|
|
|
*d_10 = bits[0]?-1.0:1.0;
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
} else if (format == SRSLTE_PUCCH_FORMAT_2B) {
|
|
|
|
|
if (bits[0] == 0) {
|
|
|
|
|
if (bits[1] == 0) {
|
|
|
|
|
*d_10 = 1.0;
|
|
|
|
|
} else {
|
|
|
|
|
*d_10 = -I;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (bits[1] == 0) {
|
|
|
|
|
*d_10 = I;
|
|
|
|
|
} else {
|
|
|
|
|
*d_10 = -1.0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
} else {
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Encode PUCCH bits according to Table 5.4.1-1 in Section 5.4.1 of 36.211 */
|
|
|
|
|
static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *d_0)
|
|
|
|
|
static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t sf_idx)
|
|
|
|
|
{
|
|
|
|
|
if (d_0) {
|
|
|
|
|
uint8_t tmp[2];
|
|
|
|
|
|
|
|
|
|
switch(format) {
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1:
|
|
|
|
|
*d_0 = uci_encode_format1();
|
|
|
|
|
q->d[0] = uci_encode_format1();
|
|
|
|
|
break;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1A:
|
|
|
|
|
*d_0 = uci_encode_format1a(bits[0]);
|
|
|
|
|
q->d[0] = uci_encode_format1a(bits[0]);
|
|
|
|
|
break;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_1B:
|
|
|
|
|
tmp[0] = bits[0];
|
|
|
|
|
tmp[1] = bits[1];
|
|
|
|
|
*d_0 = uci_encode_format1b(tmp);
|
|
|
|
|
q->d[0] = uci_encode_format1b(tmp);
|
|
|
|
|
break;
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_2:
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_2A:
|
|
|
|
|
case SRSLTE_PUCCH_FORMAT_2B:
|
|
|
|
|
memcpy(q->bits_scram, bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
|
|
|
|
|
srslte_scrambling_b(&q->seq_f2[sf_idx], q->bits_scram);
|
|
|
|
|
srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH_MAX_BITS);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf(stderr, "PUCCH format 2 not supported\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -331,18 +446,24 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t
|
|
|
|
|
void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u);
|
|
|
|
|
|
|
|
|
|
/* Encode, modulate and resource mapping of PUCCH bits according to Section 5.4.1 of 36.211 */
|
|
|
|
|
int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols)
|
|
|
|
|
int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
|
|
|
|
|
uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols)
|
|
|
|
|
{
|
|
|
|
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
|
|
|
|
if (q != NULL &&
|
|
|
|
|
sf_symbols != NULL)
|
|
|
|
|
{
|
|
|
|
|
ret = SRSLTE_ERROR;
|
|
|
|
|
cf_t d_0 = 0;
|
|
|
|
|
if (uci_mod_bits(q, format, bits, &d_0)) {
|
|
|
|
|
|
|
|
|
|
if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) {
|
|
|
|
|
fprintf(stderr, "Error encoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
if (uci_mod_bits(q, format, bits, sf_idx)) {
|
|
|
|
|
fprintf(stderr, "Error encoding PUCCH bits\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t N_sf=get_N_sf(format);
|
|
|
|
|
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
|
|
|
|
|
// Get group hopping number u
|
|
|
|
@ -358,15 +479,25 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, uint32_
|
|
|
|
|
uint32_t l = get_pucch_symbol(m, format, q->cell.cp);
|
|
|
|
|
uint32_t n_prime_ns;
|
|
|
|
|
uint32_t n_oc;
|
|
|
|
|
float alpha = srslte_pucch_alpha(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
|
|
|
|
|
float alpha=0;
|
|
|
|
|
if (format >= SRSLTE_PUCCH_FORMAT_2) {
|
|
|
|
|
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
|
|
|
|
|
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
|
|
|
|
|
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch
|
|
|
|
|
*q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
|
|
|
|
|
float S_ns = 0;
|
|
|
|
|
|
|
|
|
|
if (n_prime_ns%2) {
|
|
|
|
|
S_ns = M_PI/2;
|
|
|
|
|
}
|
|
|
|
|
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d\n", __real__ d_0, __imag__ d_0, alpha, n_oc, n_prime_ns);
|
|
|
|
|
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d\n",
|
|
|
|
|
__real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns);
|
|
|
|
|
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
|
|
|
|
|
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch*d_0*w_n_oc[n_oc%3][m]*cexpf(I*(q->tmp_arg[n]+alpha*n+S_ns));
|
|
|
|
|
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch
|
|
|
|
|
*q->d[0]*w_n_oc[n_oc%3][m]*cexpf(I*(q->tmp_arg[n]+alpha*n+S_ns));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|