isolated common tx/rx pucch functions

master
Ismael Gomez 8 years ago
parent 4cdbed47f2
commit 17d5ebca7e

@ -125,11 +125,10 @@ SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q,
cf_t *signal_buffer); cf_t *signal_buffer);
SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q,
srslte_pucch_format_t format,
uint32_t pdcch_n_cce,
uint32_t rnti_idx, uint32_t rnti_idx,
srslte_uci_data_t *uci_data, uint32_t pdcch_n_cce,
uint32_t sf_rx); uint32_t sf_rx,
srslte_uci_data_t *uci_data);
SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q,
srslte_ra_ul_grant_t *grant, srslte_ra_ul_grant_t *grant,

@ -40,6 +40,7 @@
#include "srslte/common/sequence.h" #include "srslte/common/sequence.h"
#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"
#define SRSLTE_PUCCH_N_SEQ 12 #define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS #define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS
@ -51,7 +52,8 @@ typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1B, SRSLTE_PUCCH_FORMAT_1B,
SRSLTE_PUCCH_FORMAT_2, SRSLTE_PUCCH_FORMAT_2,
SRSLTE_PUCCH_FORMAT_2A, SRSLTE_PUCCH_FORMAT_2A,
SRSLTE_PUCCH_FORMAT_2B SRSLTE_PUCCH_FORMAT_2B,
SRSLTE_PUCCH_FORMAT_ERROR,
} srslte_pucch_format_t; } srslte_pucch_format_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
@ -160,6 +162,14 @@ SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg,
uint32_t n_pucch, uint32_t n_pucch,
srslte_cp_t cp); srslte_cp_t cp);
SRSLTE_API srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data,
srslte_cp_t cp);
SRSLTE_API uint32_t srslte_pucch_get_npucch(uint32_t n_cce,
srslte_pucch_format_t format,
bool has_scheduling_request,
srslte_pucch_sched_t *pucch_sched);
SRSLTE_API uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg, SRSLTE_API uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg,
srslte_pucch_format_t format, srslte_pucch_format_t format,
uint32_t n_pucch, uint32_t n_pucch,

@ -216,24 +216,16 @@ void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer)
srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols); srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols);
} }
int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, srslte_pucch_format_t format, uint32_t pdcch_n_cce, int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint32_t rnti_idx,
uint32_t rnti_idx, srslte_uci_data_t *uci_data, uint32_t sf_rx) uint32_t pdcch_n_cce, uint32_t sf_rx,
srslte_uci_data_t *uci_data)
{ {
if (rnti_idx < q->nof_rnti) { if (rnti_idx < q->nof_rnti) {
uint32_t n_pucch = 0;
switch(format) { srslte_pucch_format_t format = srslte_pucch_get_format(uci_data, q->cell.cp);
case SRSLTE_PUCCH_FORMAT_1:
n_pucch = q->pucch_sched[rnti_idx].n_pucch_sr; uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data->scheduling_request, &q->pucch_sched[rnti_idx]);
break;
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
n_pucch = pdcch_n_cce + q->pucch_sched[rnti_idx].N_pucch_1;
break;
default:
fprintf(stderr, "Error getting PUCCH format %d not supported\n", format);
return SRSLTE_ERROR;
}
if (srslte_chest_ul_estimate_pucch(&q->chest, q->sf_symbols, q->ce, format, n_pucch, sf_rx)) { if (srslte_chest_ul_estimate_pucch(&q->chest, q->sf_symbols, q->ce, format, n_pucch, sf_rx)) {
fprintf(stderr,"Error estimating PUCCH DMRS\n"); fprintf(stderr,"Error estimating PUCCH DMRS\n");
@ -243,33 +235,21 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, srslte_pucch_format_t format, ui
float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest);
uint8_t bits[SRSLTE_PUCCH_MAX_BITS]; uint8_t bits[SRSLTE_PUCCH_MAX_BITS];
if (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, q->sf_symbols, q->ce, noise_power, bits);
if (ret_val < 0) {
fprintf(stderr,"Error decoding PUCCH\n"); fprintf(stderr,"Error decoding PUCCH\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
switch(format) { // update schedulign request
case SRSLTE_PUCCH_FORMAT_1: if (uci_data->scheduling_request) {
if (bits[0]) { uci_data->scheduling_request = ret_val;
uci_data->scheduling_request = true; }
} else {
uci_data->scheduling_request = false; // Save ACK bits
} if (uci_data->uci_ack_len > 0) {
break; uci_data->uci_ack = bits[0];
case SRSLTE_PUCCH_FORMAT_1A:
case SRSLTE_PUCCH_FORMAT_1B:
uci_data->uci_ack = bits[0];
uci_data->uci_ack_len = 1;
if (format == SRSLTE_PUCCH_FORMAT_1B) {
uci_data->uci_ack_2 = bits[0];
uci_data->uci_ack_len = 2;
}
break;
default:
fprintf(stderr, "Error getting PUCCH format %d not supported\n", format);
return SRSLTE_ERROR;
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Invalid rnti_idx=%d\n", rnti_idx); fprintf(stderr, "Invalid rnti_idx=%d\n", rnti_idx);

@ -160,6 +160,64 @@ uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t
return 0; return 0;
} }
/* Choose PUCCH format based on pending transmission as described in 10.1 of 36.213 */
srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, srslte_cp_t cp)
{
srslte_pucch_format_t format = SRSLTE_PUCCH_FORMAT_ERROR;
// No CQI data
if (uci_data->uci_cqi_len == 0) {
// 1-bit ACK + optional SR
if (uci_data->uci_ack_len == 1) {
format = SRSLTE_PUCCH_FORMAT_1A;
}
// 2-bit ACK + optional SR
else if (uci_data->uci_ack_len == 2) {
format = SRSLTE_PUCCH_FORMAT_1B;
}
// SR only
else if (uci_data->scheduling_request) {
format = SRSLTE_PUCCH_FORMAT_1;
}
}
// CQI data
else {
// CQI and no ack
if (uci_data->uci_ack_len == 0) {
format = SRSLTE_PUCCH_FORMAT_2;
}
// CQI + 1-bit ACK
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1) {
format = SRSLTE_PUCCH_FORMAT_2A;
}
// CQI + 2-bit ACK
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 2) {
format = SRSLTE_PUCCH_FORMAT_2B;
}
// CQI + 2-bit ACK + cyclic prefix
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) {
format = SRSLTE_PUCCH_FORMAT_2B;
}
}
return format;
}
/** Choose PUCCH resource as desribed in 10.1 of 36.213 */
uint32_t srslte_pucch_get_npucch(uint32_t n_cce, srslte_pucch_format_t format, bool has_scheduling_request, srslte_pucch_sched_t *pucch_sched)
{
uint32_t n_pucch = 0;
if (has_scheduling_request) {
n_pucch = pucch_sched->n_pucch_sr;
} else if (format != SRSLTE_PUCCH_FORMAT_2) {
if (pucch_sched->sps_enabled) {
n_pucch = pucch_sched->n_pucch_1[pucch_sched->tpc_for_pucch%4];
} else {
n_pucch = n_cce + pucch_sched->N_pucch_1;
}
} else {
n_pucch = pucch_sched->n_pucch_2;
}
}
uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch,
uint32_t nof_prb, srslte_cp_t cp, uint32_t ns) uint32_t nof_prb, srslte_cp_t cp, uint32_t ns)
{ {
@ -655,15 +713,15 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp); pucch_encode(q, format, n_pucch, sf_idx, 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) {
bits[0] = 1; ret = 1;
} else { } else {
bits[0] = 0; ret = 0;
} }
DEBUG("format1 corr=%f, nof_re=%d, th=%f\n", corr, nof_re, q->threshold_format1); DEBUG("format1 corr=%f, nof_re=%d, th=%f\n", corr, nof_re, q->threshold_format1);
break; break;
case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_1A:
bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
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, bits, q->z_tmp);
@ -671,6 +729,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
if (corr > corr_max && corr >= q->threshold_format1a) { if (corr > corr_max && corr >= q->threshold_format1a) {
corr_max = corr; corr_max = corr;
b_max = b; b_max = b;
ret = 1;
} }
DEBUG("format1a b=%d, corr=%f, nof_re=%d, th=%f\n", b, corr, nof_re, q->threshold_format1a); DEBUG("format1a b=%d, corr=%f, nof_re=%d, th=%f\n", b, corr, nof_re, q->threshold_format1a);
} }
@ -678,6 +737,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format,
break; break;
default: default:
fprintf(stderr, "Error decoding PUCCH: Format %d not supported\n", format); fprintf(stderr, "Error decoding PUCCH: Format %d not supported\n", format);
ret = SRSLTE_ERROR;
break; break;
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;

@ -220,64 +220,19 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, &q->uci_cfg, &q->hopping_cfg, &q->srs_cfg, tti, rvidx, current_tx_nb); return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, &q->uci_cfg, &q->hopping_cfg, &q->srs_cfg, tti, rvidx, current_tx_nb);
} }
int pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t *format, // Encode bits from uci_data
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[2], void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format,
srslte_cp_t cp) uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS],
uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS])
{ {
int ret = SRSLTE_SUCCESS; if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) {
pucch_bits[0] = uci_data->uci_ack;
// No CQI data pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a
if (uci_data->uci_cqi_len == 0) {
// 1-bit ACK + optional SR
if (uci_data->uci_ack_len == 1) {
*format = SRSLTE_PUCCH_FORMAT_1A;
pucch_bits[0] = uci_data->uci_ack;
}
// 2-bit ACK + optional SR
else if (uci_data->uci_ack_len == 2) {
*format = SRSLTE_PUCCH_FORMAT_1B;
pucch_bits[0] = uci_data->uci_ack;
pucch_bits[1] = uci_data->uci_ack_2;
}
// SR only
else if (uci_data->scheduling_request) {
*format = SRSLTE_PUCCH_FORMAT_1;
} else {
ret = SRSLTE_ERROR;
}
}
// CQI data
else {
srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits);
// CQI and no ack
if (uci_data->uci_ack_len == 0) {
*format = SRSLTE_PUCCH_FORMAT_2;
}
// CQI + 1-bit ACK
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1) {
*format = SRSLTE_PUCCH_FORMAT_2A;
pucch2_bits[0] = uci_data->uci_ack;
}
// CQI + 2-bit ACK
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 2) {
*format = SRSLTE_PUCCH_FORMAT_2B;
pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2;
}
// CQI + 2-bit ACK + cyclic prefix
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) {
*format = SRSLTE_PUCCH_FORMAT_2B;
pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2;
} else {
ret = SRSLTE_ERROR;
}
} }
if (ret) { if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) {
fprintf(stderr, "Unsupported combination of UCI parameters: ack_len=%d, cqi_len=%d\n", pucch2_bits[0] = uci_data->uci_ack;
uci_data->uci_ack, uci_data->uci_cqi_len); pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a
} }
return ret;
} }
/* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal /* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal
@ -303,35 +258,24 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
bzero(pucch2_bits, 2*sizeof(uint8_t)); bzero(pucch2_bits, 2*sizeof(uint8_t));
srslte_pucch_format_t format = srslte_pucch_get_format(&uci_data, q->cell.cp);
// Encode UCI information // Encode UCI information
if (pucch_encode_bits(&uci_data, &q->last_pucch_format, pucch_bits, pucch2_bits, q->cell.cp)) { pucch_encode_bits(&uci_data, format, pucch_bits, pucch2_bits);
return SRSLTE_ERROR;
}
// Choose n_pucch // Choose n_pucch
uint32_t n_pucch = 0; uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data.scheduling_request, &q->pucch_sched);
if (uci_data.scheduling_request) { if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) {
n_pucch = q->pucch_sched.n_pucch_sr;
} else if (q->last_pucch_format < SRSLTE_PUCCH_FORMAT_2) {
if (q->pucch_sched.sps_enabled) {
n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4];
} else {
n_pucch = pdcch_n_cce + q->pucch_sched.N_pucch_1;
}
} else {
n_pucch = q->pucch_sched.n_pucch_2;
}
if (srslte_pucch_encode(&q->pucch, q->last_pucch_format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
return ret; return ret;
} }
if (srslte_refsignal_dmrs_pucch_gen(&q->signals, q->last_pucch_format, n_pucch, sf_idx, pucch2_bits, q->refsignal)) if (srslte_refsignal_dmrs_pucch_gen(&q->signals, format, n_pucch, sf_idx, pucch2_bits, q->refsignal))
{ {
fprintf(stderr, "Error generating PUSCH DRMS signals\n"); fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret; return ret;
} }
srslte_refsignal_dmrs_pucch_put(&q->signals, q->last_pucch_format, n_pucch, q->refsignal, q->sf_symbols); srslte_refsignal_dmrs_pucch_put(&q->signals, format, n_pucch, q->refsignal, q->sf_symbols);
if (srslte_ue_ul_srs_tx_enabled(&q->signals.srs_cfg, tti) && q->pucch.shortened) { if (srslte_ue_ul_srs_tx_enabled(&q->signals.srs_cfg, tti) && q->pucch.shortened) {
if (q->signals_pregenerated) { if (q->signals_pregenerated) {
@ -341,6 +285,8 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
srslte_refsignal_srs_put(&q->signals, tti, q->srs_signal, q->sf_symbols); srslte_refsignal_srs_put(&q->signals, tti, q->srs_signal, q->sf_symbols);
} }
} }
q->last_pucch_format = format;
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);

Loading…
Cancel
Save