master
Ismael Gomez 6 years ago
parent 243a7708d4
commit 197d855d3f

@ -81,6 +81,7 @@ typedef struct SRSLTE_API {
typedef struct { typedef struct {
srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME];
uint32_t cell_id;
bool sequence_generated; bool sequence_generated;
} srslte_pucch_user_t; } srslte_pucch_user_t;
@ -112,10 +113,15 @@ typedef struct SRSLTE_API {
uint32_t last_n_prb; uint32_t last_n_prb;
uint32_t last_n_pucch; uint32_t last_n_pucch;
srslte_sequence_t tmp_seq;
uint16_t ue_rnti;
bool is_ue;
}srslte_pucch_t; }srslte_pucch_t;
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q); SRSLTE_API int srslte_pucch_init_ue(srslte_pucch_t *q);
SRSLTE_API int srslte_pucch_init_enb(srslte_pucch_t *q);
SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q); SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q);

@ -76,7 +76,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q,
srslte_ofdm_set_normalize(&q->fft, false); srslte_ofdm_set_normalize(&q->fft, false);
srslte_ofdm_set_freq_shift(&q->fft, -0.5); srslte_ofdm_set_freq_shift(&q->fft, -0.5);
if (srslte_pucch_init(&q->pucch)) { if (srslte_pucch_init_enb(&q->pucch)) {
fprintf(stderr, "Error creating PUCCH object\n"); fprintf(stderr, "Error creating PUCCH object\n");
goto clean_exit; goto clean_exit;
} }

@ -615,10 +615,10 @@ static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti,
uint32_t rnti_idx = q->is_ue?0:rnti; uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE // The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated && if (q->users[rnti_idx] &&
q->users[rnti_idx]->cell_id == q->cell.id && q->users[rnti_idx]->sequence_generated &&
q->ue_rnti == rnti && q->users[rnti_idx]->cell_id == q->cell.id &&
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue)) (!q->is_ue || q->ue_rnti == rnti))
{ {
return &q->users[rnti_idx]->seq[codeword_idx][sf_idx]; return &q->users[rnti_idx]->seq[codeword_idx][sf_idx];
} else { } else {

@ -416,7 +416,7 @@ void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1_threshold) {
} }
/** Initializes the PDCCH transmitter and receiver */ /** Initializes the PDCCH transmitter and receiver */
int srslte_pucch_init(srslte_pucch_t *q) { int srslte_pucch_init_(srslte_pucch_t *q, bool is_ue) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) { if (q != NULL) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
@ -426,17 +426,26 @@ int srslte_pucch_init(srslte_pucch_t *q) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->users = calloc(sizeof(srslte_pucch_user_t*), 1+SRSLTE_SIRNTI); q->is_ue = is_ue;
q->users = calloc(sizeof(srslte_pucch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI));
if (!q->users) { if (!q->users) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
if (srslte_sequence_init(&q->tmp_seq, 20)) {
goto clean_exit;
}
srslte_uci_cqi_pucch_init(&q->cqi); 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);
if (!q->is_ue) {
q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
}
q->threshold_format1 = 0.8; q->threshold_format1 = 0.8;
@ -449,13 +458,28 @@ clean_exit:
return ret; return ret;
} }
int srslte_pucch_init_ue(srslte_pucch_t *q) {
return srslte_pucch_init_(q, true);
}
int srslte_pucch_init_enb(srslte_pucch_t *q) {
return srslte_pucch_init_(q, false);
}
void srslte_pucch_free(srslte_pucch_t *q) { void srslte_pucch_free(srslte_pucch_t *q) {
if (q->users) { if (q->users) {
for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) { if (q->is_ue) {
srslte_pucch_clear_rnti(q, rnti); srslte_pucch_clear_rnti(q, 0);
} else {
for (int rnti = 0; rnti <= SRSLTE_SIRNTI; rnti++) {
srslte_pucch_clear_rnti(q, rnti);
}
} }
free(q->users); free(q->users);
} }
srslte_sequence_free(&q->tmp_seq);
srslte_uci_cqi_pucch_free(&q->cqi); srslte_uci_cqi_pucch_free(&q->cqi);
if (q->z) { if (q->z) {
free(q->z); free(q->z);
@ -497,29 +521,43 @@ int srslte_pucch_set_cell(srslte_pucch_t *q, srslte_cell_t cell) {
void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) { void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) {
if (q->users[rnti]) { uint32_t rnti_idx = q->is_ue?0:rnti;
if (q->users[rnti_idx]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
srslte_sequence_free(&q->users[rnti]->seq_f2[i]); srslte_sequence_free(&q->users[rnti_idx]->seq_f2[i]);
} }
free(q->users[rnti]); free(q->users[rnti_idx]);
q->users[rnti] = NULL; q->users[rnti_idx] = NULL;
q->ue_rnti = 0;
} }
} }
int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) { int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) {
if (!q->users[rnti]) {
q->users[rnti] = calloc(1, sizeof(srslte_pucch_user_t)); uint32_t rnti_idx = q->is_ue?0:rnti;
if (q->users[rnti]) { if (!q->users[rnti_idx] || q->is_ue) {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) { if (!q->users[rnti_idx]) {
// Precompute scrambling sequence for pucch format 2 q->users[rnti_idx] = calloc(1, sizeof(srslte_pucch_user_t));
if (srslte_sequence_pucch(&q->users[rnti]->seq_f2[sf_idx], rnti, 2*sf_idx, q->cell.id)) { if (!q->users[rnti_idx]) {
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n"); perror("calloc");
srslte_pucch_clear_rnti(q, rnti); return -1;
return SRSLTE_ERROR; }
} }
q->users[rnti_idx]->sequence_generated = false;
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_idx]->seq_f2[sf_idx], rnti, 2*sf_idx, q->cell.id)) {
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
srslte_pucch_clear_rnti(q, rnti);
return SRSLTE_ERROR;
} }
q->users[rnti]->sequence_generated = true;
} }
q->ue_rnti = rnti;
q->users[rnti_idx]->cell_id = q->cell.id;
q->users[rnti_idx]->sequence_generated = true;
} else {
fprintf(stderr, "Error generating PUSCH sequence: rnti=0x%x already generated\n", rnti);
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -592,11 +630,36 @@ int srslte_pucch_format2ab_mod_bits(srslte_pucch_format_t format, uint8_t bits[2
} }
} }
static srslte_sequence_t *get_user_sequence(srslte_pucch_t *q, uint16_t rnti, uint32_t sf_idx)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
if (rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) {
if (q->users[rnti_idx] &&
q->users[rnti_idx]->sequence_generated &&
q->users[rnti_idx]->cell_id == q->cell.id &&
(!q->is_ue || q->ue_rnti == rnti))
{
return &q->users[rnti_idx]->seq_f2[sf_idx];
} else {
if (srslte_sequence_pucch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id)) {
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
return NULL;
}
return &q->tmp_seq;
}
} else {
fprintf(stderr, "Invalid RNTI=0x%x\n", rnti);
return NULL;
}
}
/* 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, uint16_t rnti) 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];
srslte_sequence_t *seq;
switch(format) { switch(format) {
case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1:
q->d[0] = uci_encode_format1(); q->d[0] = uci_encode_format1();
@ -612,12 +675,13 @@ 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:
if (q->users[rnti] && q->users[rnti]->sequence_generated) { seq = get_user_sequence(q, rnti, sf_idx);
if (seq) {
memcpy(q->bits_scram, bits, SRSLTE_PUCCH2_NOF_BITS*sizeof(uint8_t)); memcpy(q->bits_scram, bits, SRSLTE_PUCCH2_NOF_BITS*sizeof(uint8_t));
srslte_scrambling_b(&q->users[rnti]->seq_f2[sf_idx], q->bits_scram); srslte_scrambling_b(seq, q->bits_scram);
srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH2_NOF_BITS); srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH2_NOF_BITS);
} else { } else {
fprintf(stderr, "Error modulating PUCCH2 bits: rnti not set\n"); fprintf(stderr, "Error modulating PUCCH2 bits: could not generate sequence\n");
return -1; return -1;
} }
break; break;
@ -745,6 +809,8 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits) uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
srslte_sequence_t *seq;
if (q != NULL && if (q != NULL &&
ce != NULL && ce != NULL &&
sf_symbols != NULL) sf_symbols != NULL)
@ -843,7 +909,8 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
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:
if (q->users[rnti] && q->users[rnti]->sequence_generated) { seq = get_user_sequence(q, rnti, sf_idx);
if (seq) {
pucch_encode_(q, format, n_pucch, sf_idx, rnti, NULL, ref, true); pucch_encode_(q, format, n_pucch, sf_idx, rnti, NULL, ref, true);
srslte_vec_prod_conj_ccc(q->z, ref, q->z_tmp, SRSLTE_PUCCH_MAX_SYMBOLS); srslte_vec_prod_conj_ccc(q->z, ref, q->z_tmp, SRSLTE_PUCCH_MAX_SYMBOLS);
for (int i=0;i<SRSLTE_PUCCH2_NOF_BITS/2;i++) { for (int i=0;i<SRSLTE_PUCCH2_NOF_BITS/2;i++) {
@ -857,7 +924,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
q->last_corr = (float) srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, bits, nof_bits)/2000; q->last_corr = (float) srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, bits, nof_bits)/2000;
ret = 1; ret = 1;
} else { } else {
fprintf(stderr, "Decoding PUCCH2: rnti not set\n"); fprintf(stderr, "Decoding PUCCH2: could not generate sequence\n");
return -1; return -1;
} }
break; break;

@ -481,16 +481,24 @@ static srslte_sequence_t *get_user_sequence(srslte_pusch_t *q, uint16_t rnti, ui
{ {
uint32_t rnti_idx = q->is_ue?0:rnti; uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE if (rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) {
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated && // The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
q->users[rnti_idx]->cell_id == q->cell.id && if (q->users[rnti_idx] &&
q->ue_rnti == rnti && q->users[rnti_idx]->sequence_generated &&
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue)) q->users[rnti_idx]->cell_id == q->cell.id &&
{ (!q->is_ue || q->ue_rnti == rnti))
return &q->users[rnti_idx]->seq[sf_idx]; {
return &q->users[rnti_idx]->seq[sf_idx];
} else {
if (srslte_sequence_pusch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id, len)) {
fprintf(stderr, "Error generating temporal scrambling sequence\n");
return NULL;
}
return &q->tmp_seq;
}
} else { } else {
srslte_sequence_pusch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id, len); fprintf(stderr, "Invalid RNTI=0x%x\n", rnti);
return &q->tmp_seq; return NULL;
} }
} }

@ -65,7 +65,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
srslte_pucch_t pucch; srslte_pucch_t pucch;
if (srslte_pucch_init(&pucch, cell)) { if (srslte_pucch_init_ue(&pucch, cell)) {
mexErrMsgTxt("Error initiating PUSCH\n"); mexErrMsgTxt("Error initiating PUSCH\n");
return; return;
} }

@ -149,7 +149,7 @@ int main(int argc, char **argv) {
return test_uci_cqi_pucch(); return test_uci_cqi_pucch();
} }
if (srslte_pucch_init(&pucch)) { if (srslte_pucch_init_ue(&pucch)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
exit(-1); exit(-1);
} }

@ -67,7 +67,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
srslte_pucch_t pucch; srslte_pucch_t pucch;
if (srslte_pucch_init(&pucch, cell)) { if (srslte_pucch_init_ue(&pucch, cell)) {
mexErrMsgTxt("Error initiating PUSCH\n"); mexErrMsgTxt("Error initiating PUSCH\n");
return; return;
} }

@ -78,7 +78,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error creating PUSCH object\n"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pucch_init(&q->pucch)) { if (srslte_pucch_init_ue(&q->pucch)) {
fprintf(stderr, "Error creating PUSCH object\n"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; goto clean_exit;
} }

Loading…
Cancel
Save