pucch2 rx tested over the air2

master
Ismael Gomez 8 years ago
parent 6be81d9bd5
commit d8ff0f7560

@ -41,9 +41,9 @@
#include "srslte/modem/mod.h" #include "srslte/modem/mod.h"
#include "srslte/phch/cqi.h" #include "srslte/phch/cqi.h"
#include "srslte/phch/uci.h" #include "srslte/phch/uci.h"
#include "srslte/modem/demod_hard.h"
#define SRSLTE_PUCCH_N_SEQ 12 #define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS #define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS
#define SRSLTE_PUCCH_MAX_SYMBOLS 120 #define SRSLTE_PUCCH_MAX_SYMBOLS 120
@ -79,13 +79,19 @@ typedef struct SRSLTE_API {
bool srs_simul_ack; bool srs_simul_ack;
} srslte_pucch_cfg_t; } srslte_pucch_cfg_t;
typedef struct {
srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME];
} srslte_pucch_user_t;
/* PUCCH object */ /* PUCCH object */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;
srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_modem_table_t mod; srslte_modem_table_t mod;
srslte_demod_hard_t demod;
srslte_uci_cqi_pucch_t cqi;
srslte_pucch_user_t **users;
uint8_t bits_scram[SRSLTE_PUCCH_MAX_BITS]; uint8_t bits_scram[SRSLTE_PUCCH_MAX_BITS];
cf_t d[SRSLTE_PUCCH_MAX_BITS/2]; cf_t d[SRSLTE_PUCCH_MAX_BITS/2];
@ -97,7 +103,6 @@ typedef struct SRSLTE_API {
cf_t *z_tmp; cf_t *z_tmp;
cf_t *ce; cf_t *ce;
bool rnti_is_set;
bool shortened; bool shortened;
bool group_hopping_en; bool group_hopping_en;
@ -126,6 +131,9 @@ SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q,
SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q, SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q,
uint16_t c_rnti); uint16_t c_rnti);
SRSLTE_API void srslte_pucch_clear_rnti(srslte_pucch_t *q,
uint16_t rnti);
SRSLTE_API uint32_t srslte_pucch_nof_symbols(srslte_pucch_cfg_t *cfg, SRSLTE_API uint32_t srslte_pucch_nof_symbols(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format, srslte_pucch_format_t format,
bool shortened); bool shortened);
@ -136,6 +144,7 @@ SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q,
srslte_pucch_format_t format, srslte_pucch_format_t format,
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
cf_t *sf_symbols); cf_t *sf_symbols);
@ -143,6 +152,7 @@ SRSLTE_API int srslte_pucch_decode(srslte_pucch_t *q,
srslte_pucch_format_t format, srslte_pucch_format_t format,
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti,
cf_t *sf_symbols, cf_t *sf_symbols,
cf_t *ce, cf_t *ce,
float noise_estimate, float noise_estimate,

@ -56,6 +56,11 @@ typedef struct SRSLTE_API {
int16_t *cqi_table_s[11]; int16_t *cqi_table_s[11];
} srslte_uci_cqi_pusch_t; } srslte_uci_cqi_pusch_t;
typedef struct SRSLTE_API {
uint8_t cqi_table[16][32];
int16_t cqi_table_s[16][32]; // aligned for simd
} srslte_uci_cqi_pucch_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS]; uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
uint32_t uci_cqi_len; uint32_t uci_cqi_len;
@ -78,6 +83,18 @@ typedef struct {
srslte_uci_bit_type_t type; srslte_uci_bit_type_t type;
} srslte_uci_bit_t; } srslte_uci_bit_t;
SRSLTE_API void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q);
SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data,
uint32_t cqi_len,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q,
int16_t b_bits[32], // aligned for simd
uint8_t *cqi_data,
uint32_t cqi_len);
SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q); SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q);
SRSLTE_API void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q); SRSLTE_API void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q);
@ -99,10 +116,6 @@ SRSLTE_API int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q,
uint8_t *cqi_data, uint8_t *cqi_data,
bool *cqi_ack); bool *cqi_ack);
SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data,
uint32_t cqi_len,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
uint8_t data, uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,

@ -162,7 +162,16 @@ int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti)
{ {
if (!q->users[rnti]) { if (!q->users[rnti]) {
q->users[rnti] = malloc(sizeof(srslte_enb_ul_user_t)); q->users[rnti] = malloc(sizeof(srslte_enb_ul_user_t));
return srslte_pusch_set_rnti(&q->pusch, rnti);
if (srslte_pucch_set_crnti(&q->pucch, rnti)) {
fprintf(stderr, "Error setting PUCCH rnti\n");
return -1;
}
if (srslte_pusch_set_rnti(&q->pusch, rnti)) {
fprintf(stderr, "Error setting PUSCH rnti\n");
return -1;
}
return 0;
} else { } else {
fprintf(stderr, "Error adding rnti=0x%x, already exists\n", rnti); fprintf(stderr, "Error adding rnti=0x%x, already exists\n", rnti);
return -1; return -1;
@ -227,7 +236,7 @@ int get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
} }
int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, q->sf_symbols, q->ce, noise_power, bits); int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits);
if (ret_val < 0) { if (ret_val < 0) {
fprintf(stderr,"Error decoding PUCCH\n"); fprintf(stderr,"Error decoding PUCCH\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -239,17 +248,17 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
uint32_t pdcch_n_cce, uint32_t sf_rx, uint32_t pdcch_n_cce, uint32_t sf_rx,
srslte_uci_data_t *uci_data) srslte_uci_data_t *uci_data)
{ {
uint8_t bits[SRSLTE_PUCCH_MAX_BITS]; uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS];
if (q->users[rnti]) { if (q->users[rnti]) {
int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, bits); int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits);
// If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // If we are looking for SR and ACK at the same time and ret=0, means there is no SR.
// try again to decode ACK only // try again to decode ACK only
if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) { if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) {
uci_data->scheduling_request = false; uci_data->scheduling_request = false;
ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, bits); ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits);
} }
// update schedulign request // update schedulign request
@ -259,8 +268,14 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
// Save ACK bits // Save ACK bits
if (uci_data->uci_ack_len > 0) { if (uci_data->uci_ack_len > 0) {
uci_data->uci_ack = bits[0]; uci_data->uci_ack = pucch_bits[0];
} }
// Decode CQI bits
if (uci_data->uci_cqi_len) {
memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t));
}
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Error getting PUCCH: rnti=0x%x not found\n", rnti); fprintf(stderr, "Error getting PUCCH: rnti=0x%x not found\n", rnti);

@ -42,6 +42,7 @@
#include "srslte/scrambling/scrambling.h" #include "srslte/scrambling/scrambling.h"
#include "srslte/utils/debug.h" #include "srslte/utils/debug.h"
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
#include "srslte/modem/demod_soft.h"
#define MAX_PUSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12) #define MAX_PUSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
@ -422,7 +423,6 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
bzero(q, sizeof(srslte_pucch_t)); bzero(q, sizeof(srslte_pucch_t));
q->cell = cell; q->cell = cell;
q->rnti_is_set = false;
srslte_pucch_cfg_default(&q->pucch_cfg); srslte_pucch_cfg_default(&q->pucch_cfg);
@ -430,9 +430,6 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_demod_hard_init(&q->demod);
srslte_demod_hard_table_set(&q->demod, SRSLTE_MOD_QPSK);
// Precompute group hopping values u. // Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -442,6 +439,14 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->users = calloc(sizeof(srslte_pucch_user_t*), 1+SRSLTE_SIRNTI);
if (!q->users) {
perror("malloc");
return SRSLTE_ERROR;
}
srslte_uci_cqi_pucch_init(&q->cqi);
q->z = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); q->z = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
@ -452,10 +457,11 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
} }
void srslte_pucch_free(srslte_pucch_t *q) { void srslte_pucch_free(srslte_pucch_t *q) {
if (q->rnti_is_set) { if (q->users) {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) { for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) {
srslte_sequence_free(&q->seq_f2[sf_idx]); srslte_pucch_clear_rnti(q, rnti);
} }
free(q->users);
} }
if (q->z) { if (q->z) {
free(q->z); free(q->z);
@ -471,15 +477,29 @@ void srslte_pucch_free(srslte_pucch_t *q) {
bzero(q, sizeof(srslte_pucch_t)); bzero(q, sizeof(srslte_pucch_t));
} }
int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) { void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) { if (q->users[rnti]) {
// Precompute scrambling sequence for pucch format 2 for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pucch(&q->seq_f2[sf_idx], c_rnti, 2*sf_idx, q->cell.id)) { srslte_sequence_free(&q->users[rnti]->seq_f2[i]);
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n"); }
return SRSLTE_ERROR; free(q->users[rnti]);
q->users[rnti] = NULL;
}
}
int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) {
if (!q->users[rnti]) {
q->users[rnti] = malloc(sizeof(srslte_pucch_user_t));
if (q->users[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->users[rnti]->seq_f2[sf_idx], 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; return SRSLTE_SUCCESS;
} }
@ -552,7 +572,7 @@ int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format, uint8_t bits[2
} }
/* Encode PUCCH bits according to Table 5.4.1-1 in Section 5.4.1 of 36.211 */ /* 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], uint32_t sf_idx) 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, uint16_t rnti)
{ {
uint8_t tmp[2]; uint8_t tmp[2];
@ -571,9 +591,14 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t
case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2:
case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2A:
case SRSLTE_PUCCH_FORMAT_2B: case SRSLTE_PUCCH_FORMAT_2B:
memcpy(q->bits_scram, bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); if (q->users[rnti]) {
srslte_scrambling_b(&q->seq_f2[sf_idx], q->bits_scram); memcpy(q->bits_scram, bits, SRSLTE_PUCCH2_NOF_BITS*sizeof(uint8_t));
srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH_MAX_BITS); srslte_scrambling_b(&q->users[rnti]->seq_f2[sf_idx], q->bits_scram);
srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH2_NOF_BITS);
} else {
fprintf(stderr, "Error modulating PUCCH2 bits: rnti not set\n");
return -1;
}
break; break;
default: default:
fprintf(stderr, "PUCCH format 2 not supported\n"); fprintf(stderr, "PUCCH format 2 not supported\n");
@ -586,11 +611,11 @@ 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); void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u);
static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format, static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format,
uint32_t n_pucch, uint32_t sf_idx, uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS], bool signal_only) uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS], bool signal_only)
{ {
if (!signal_only) { if (!signal_only) {
if (uci_mod_bits(q, format, bits, sf_idx)) { if (uci_mod_bits(q, format, bits, sf_idx, rnti)) {
fprintf(stderr, "Error encoding PUCCH bits\n"); fprintf(stderr, "Error encoding PUCCH bits\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -641,16 +666,16 @@ static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format,
} }
static int pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, static int pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
uint32_t n_pucch, uint32_t sf_idx, uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS]) uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS])
{ {
return pucch_encode_(q, format, n_pucch, sf_idx, bits, z, false); return pucch_encode_(q, format, n_pucch, sf_idx, rnti, bits, z, false);
} }
/* Encode, modulate and resource mapping of PUCCH bits according to Section 5.4.1 of 36.211 */ /* 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, 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], uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti, uint8_t bits[SRSLTE_PUCCH_MAX_BITS],
cf_t *sf_symbols) cf_t *sf_symbols)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -673,11 +698,7 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
q->last_n_pucch = n_pucch; q->last_n_pucch = n_pucch;
if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) { if (pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z)) {
fprintf(stderr, "Error encoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n");
return SRSLTE_ERROR;
}
if (pucch_encode(q, format, n_pucch, sf_idx, bits, q->z)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (pucch_put(q, format, n_pucch, q->z, sf_symbols) < 0) { if (pucch_put(q, format, n_pucch, q->z, sf_symbols) < 0) {
@ -697,7 +718,7 @@ float srslte_pucch_get_last_corr(srslte_pucch_t* q)
/* Equalize, demodulate and decode PUCCH bits according to Section 5.4.1 of 36.211 */ /* Equalize, demodulate and decode PUCCH bits according to Section 5.4.1 of 36.211 */
int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
uint32_t n_pucch, uint32_t sf_idx, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti, cf_t *sf_symbols, cf_t *ce, float noise_estimate,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) uint8_t bits[SRSLTE_PUCCH_MAX_BITS])
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -707,6 +728,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
cf_t ref[SRSLTE_PUCCH_MAX_SYMBOLS]; cf_t ref[SRSLTE_PUCCH_MAX_SYMBOLS];
int16_t llr_pucch2[32];
// Shortened PUCCH happen in every cell-specific SRS subframes for Format 1/1a/1b // Shortened PUCCH happen in every cell-specific SRS subframes for Format 1/1a/1b
if (q->pucch_cfg.srs_configured && format < SRSLTE_PUCCH_FORMAT_2) { if (q->pucch_cfg.srs_configured && format < SRSLTE_PUCCH_FORMAT_2) {
@ -722,10 +744,6 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
q->last_n_pucch = n_pucch; q->last_n_pucch = n_pucch;
if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) {
fprintf(stderr, "Error decoding PUCCH: C-RNTI must be set before decoding PUCCH Format 2/2a/2b\n");
return SRSLTE_ERROR;
}
int nof_re = pucch_get(q, format, n_pucch, sf_symbols, q->z_tmp); int nof_re = pucch_get(q, format, n_pucch, sf_symbols, q->z_tmp);
if (nof_re < 0) { if (nof_re < 0) {
fprintf(stderr, "Error getting PUCCH symbols\n"); fprintf(stderr, "Error getting PUCCH symbols\n");
@ -746,7 +764,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
switch(format) { switch(format) {
case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1:
bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp); pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp);
corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re;
if (corr >= q->threshold_format1) { if (corr >= q->threshold_format1) {
ret = 1; ret = 1;
@ -761,7 +779,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
ret = 0; ret = 0;
for (int b=0;b<2;b++) { for (int b=0;b<2;b++) {
bits[0] = b; bits[0] = b;
pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp); pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp);
corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re;
if (corr > corr_max) { if (corr > corr_max) {
corr_max = corr; corr_max = corr;
@ -776,17 +794,23 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
bits[0] = b_max; bits[0] = b_max;
break; break;
case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2:
pucch_encode_(q, format, n_pucch, sf_idx, NULL, ref, true); if (q->users[rnti]) {
srslte_vec_prod_conj_ccc(q->z, ref, q->z_tmp, SRSLTE_PUCCH_MAX_SYMBOLS); pucch_encode_(q, format, n_pucch, sf_idx, rnti, NULL, ref, true);
for (int i=0;i<SRSLTE_PUCCH_MAX_BITS/2;i++) { srslte_vec_prod_conj_ccc(q->z, ref, q->z_tmp, SRSLTE_PUCCH_MAX_SYMBOLS);
q->z[i] = 0; for (int i=0;i<SRSLTE_PUCCH2_NOF_BITS/2;i++) {
for (int j=0;j<SRSLTE_NRE;j++) { q->z[i] = 0;
q->z[i] += q->z_tmp[i*SRSLTE_NRE+j]/SRSLTE_NRE; for (int j=0;j<SRSLTE_NRE;j++) {
q->z[i] += q->z_tmp[i*SRSLTE_NRE+j]/SRSLTE_NRE;
}
} }
srslte_demod_soft_demodulate_s(SRSLTE_MOD_QPSK, q->z, llr_pucch2, SRSLTE_PUCCH2_NOF_BITS/2);
srslte_scrambling_s(&q->users[rnti]->seq_f2[sf_idx], llr_pucch2);
q->last_corr = (float) srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, bits, 4)/2000;
ret = 1;
} else {
fprintf(stderr, "Decoding PUCCH2: rnti not set\n");
return -1;
} }
srslte_demod_hard_demodulate(&q->demod, q->z, bits, SRSLTE_PUCCH_MAX_BITS/2);
srslte_scrambling_b(&q->seq_f2[sf_idx], bits);
ret = 1;
break; break;
default: default:
fprintf(stderr, "PUCCH format %d not implemented\n", format); fprintf(stderr, "PUCCH format %d not implemented\n", format);

@ -135,7 +135,7 @@ int main(int argc, char **argv) {
goto quit; goto quit;
} }
if (srslte_pucch_encode(&pucch, format, n_pucch, subframe, bits, sf_symbols)) { if (srslte_pucch_encode(&pucch, format, n_pucch, subframe, 1, bits, sf_symbols)) {
fprintf(stderr, "Error encoding PUCCH\n"); fprintf(stderr, "Error encoding PUCCH\n");
goto quit; goto quit;
} }

@ -104,6 +104,74 @@ static uint8_t M_basis_seq_pucch[20][13]={
{1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
}; };
void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q) {
uint8_t word[16];
uint32_t nwords = 16;
for (uint32_t w=0;w<nwords;w++) {
uint8_t *ptr = word;
srslte_bit_unpack(w, &ptr, 4);
srslte_uci_encode_cqi_pucch(word, 4, q->cqi_table[w]);
for (int j=0;j<SRSLTE_UCI_CQI_CODED_PUCCH_B;j++) {
q->cqi_table_s[w][j] = 2*q->cqi_table[w][j]-1;
}
}
}
/* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212
*/
int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B])
{
if (cqi_len <= SRSLTE_UCI_MAX_CQI_LEN_PUCCH) {
for (uint32_t i=0;i<SRSLTE_UCI_CQI_CODED_PUCCH_B;i++) {
uint64_t x=0;
for (uint32_t n=0;n<cqi_len;n++) {
x += cqi_data[n]*M_basis_seq_pucch[i][n];
}
b_bits[i] = (uint8_t) (x%2);
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
/* Decode UCI CQI/PMI over PUCCH
*/
int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32], uint8_t *cqi_data, uint32_t cqi_len)
{
if (cqi_len == 4 &&
b_bits != NULL &&
cqi_data != NULL)
{
uint32_t max_w = 0;
int32_t max_corr = INT32_MIN;
for (uint32_t w=0;w<16;w++) {
// Calculate correlation with pregenerated word and select maximum
int32_t corr = srslte_vec_dot_prod_sss(q->cqi_table_s[w], b_bits, SRSLTE_UCI_CQI_CODED_PUCCH_B);
if (corr > max_corr) {
max_corr = corr;
max_w = w;
}
}
// Convert word to bits again
uint8_t *ptr = cqi_data;
srslte_bit_unpack(max_w, &ptr, cqi_len);
INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr);
return max_corr;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
void encode_cqi_pusch_block(srslte_uci_cqi_pusch_t *q, uint8_t *data, uint32_t nof_bits, uint8_t output[32]) { void encode_cqi_pusch_block(srslte_uci_cqi_pusch_t *q, uint8_t *data, uint32_t nof_bits, uint8_t output[32]) {
for (int i=0;i<32;i++) { for (int i=0;i<32;i++) {
@ -320,24 +388,6 @@ int decode_cqi_long(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q,
return ret; return ret;
} }
/* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212
*/
int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B])
{
if (cqi_len <= SRSLTE_UCI_MAX_CQI_LEN_PUCCH) {
for (uint32_t i=0;i<SRSLTE_UCI_CQI_CODED_PUCCH_B;i++) {
uint64_t x=0;
for (uint32_t n=0;n<cqi_len;n++) {
x += cqi_data[n]*M_basis_seq_pucch[i][n];
}
b_bits[i] = (uint8_t) (x%2);
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
/* Encode UCI CQI/PMI /* Encode UCI CQI/PMI
*/ */
int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *cfg, int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *cfg,

@ -269,7 +269,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
// Choose n_pucch // Choose n_pucch
uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data.scheduling_request, &q->pucch_sched); uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data.scheduling_request, &q->pucch_sched);
if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) { if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, q->current_rnti, pucch_bits, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
return ret; return ret;
} }

Loading…
Cancel
Save