Revert "Added Aperiodic mode 3-1 in enb and some more optimizations"

This reverts commit 8ab196901f.
master
Ismael Gomez 7 years ago
parent 8ab196901f
commit eefbdbc913

@ -141,7 +141,6 @@ SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q,
uint32_t rv_idx,
uint32_t current_tx_nb,
uint8_t *data,
srslte_cqi_value_t *cqi_value,
srslte_uci_data_t *uci_data,
uint32_t tti);

@ -142,7 +142,6 @@ SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q,
float noise_estimate,
uint16_t rnti,
uint8_t *data,
srslte_cqi_value_t *cqi_value,
srslte_uci_data_t *uci_data);
SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q);

@ -131,25 +131,31 @@ SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits);
SRSLTE_API int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg,
uint8_t *data,
uint32_t data_len,
SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg,
int16_t *q_bits,
uint8_t *c_seq,
float beta,
uint32_t H_prime_total,
uint32_t O_cqi,
srslte_uci_bit_t *ack_bits,
uint8_t acks[2],
uint32_t nof_acks);
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi,
float beta,
uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits);
SRSLTE_API int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg,
int16_t *q_bits,
uint8_t *c_seq,
float beta,
uint32_t H_prime_total,
uint32_t O_cqi,
srslte_uci_bit_t *ri_bits,
bool is_ri);
SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg,
int16_t *q_bits,
uint8_t *c_seq,
float beta,
uint32_t H_prime_total,
uint32_t O_cqi,
srslte_uci_bit_t *ack_ri_bits,
uint8_t data[2],
uint32_t nof_bits,
bool is_ri);
uint8_t *data);
#endif

@ -253,22 +253,18 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
}
}
void srslte_enb_ul_fft(srslte_enb_ul_t *q)
void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer)
{
srslte_ofdm_rx_sf(&q->fft);
}
int get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
uint32_t pdcch_n_cce, uint32_t sf_rx,
srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits)
srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS])
{
float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest);
srslte_pucch_format_t format = srslte_pucch_get_format(uci_data, q->cell.cp);
if (format == SRSLTE_PUCCH_FORMAT_ERROR) {
fprintf(stderr,"Error getting format\n");
return SRSLTE_ERROR;
}
uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data->scheduling_request, &q->users[rnti]->pucch_sched);
@ -277,7 +273,7 @@ int get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
return SRSLTE_ERROR;
}
int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits, nof_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) {
fprintf(stderr,"Error decoding PUCCH\n");
return SRSLTE_ERROR;
@ -290,18 +286,16 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
srslte_uci_data_t *uci_data)
{
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS];
if (q->users[rnti]) {
uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len +
uci_data->uci_dif_cqi_len +
uci_data->uci_pmi_len);
int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_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.
// try again to decode ACK only
if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) {
uci_data->scheduling_request = false;
ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits);
ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits);
}
// update schedulign request
@ -311,32 +305,12 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
// Save ACK bits
if (uci_data->uci_ack_len > 0) {
uci_data->uci_ack = pucch_bits[0];
}
if (uci_data->uci_ack_len > 1) {
uci_data->uci_ack_2 = pucch_bits[1];
uci_data->uci_ack = pucch_bits[0];
}
// PUCCH2 CQI bits are decoded inside srslte_pucch_decode()
if (uci_data->uci_cqi_len) {
memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t));
}
if (uci_data->uci_dif_cqi_len) {
memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t));
}
if (uci_data->uci_pmi_len) {
memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len,
uci_data->uci_pmi_len*sizeof(uint8_t));
}
if (uci_data->uci_ri_len) {
uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */
}
if (uci_data->uci_cqi_len || uci_data->uci_ri_len) {
if (uci_data->uci_ack_len >= 1) {
uci_data->uci_ack = pucch_bits[20];
}
@ -354,7 +328,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer,
uint16_t rnti, uint32_t rv_idx, uint32_t current_tx_nb,
uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti)
uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti)
{
if (q->users[rnti]) {
if (srslte_pusch_cfg(&q->pusch,
@ -390,7 +364,6 @@ int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srs
softbuffer, q->sf_symbols,
q->ce, noise_power,
rnti, data,
cqi_value,
uci_data);
}

@ -199,44 +199,17 @@ int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_value_
}
int srslte_cqi_size(srslte_cqi_value_t *value) {
int size = 0;
switch(value->type) {
case SRSLTE_CQI_TYPE_WIDEBAND:
size = 4;
break;
return 4;
case SRSLTE_CQI_TYPE_SUBBAND:
size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1;
break;
return 4+(value->subband.subband_label_2_bits)?2:1;
case SRSLTE_CQI_TYPE_SUBBAND_UE:
size = 4 + 2 + value->subband_ue.L;
break;
return 4+2+value->subband_ue.L;
case SRSLTE_CQI_TYPE_SUBBAND_HL:
/* First codeword */
size += 4 + 2 * value->subband_hl.N;
/* Add Second codeword if required */
if (value->subband_hl.rank_is_not_one && value->subband_hl.pmi_present) {
size += 4 + 2 * value->subband_hl.N;
}
/* Add PMI if required*/
if (value->subband_hl.pmi_present) {
if (value->subband_hl.four_antenna_ports) {
size += 4;
} else {
if (value->subband_hl.rank_is_not_one) {
size += 1;
} else {
size += 2;
}
}
}
break;
default:
size = SRSLTE_ERROR;
return 4+2*value->subband_hl.N;
}
return size;
return -1;
}
static bool srslte_cqi_get_N(uint32_t I_cqi_pmi, uint32_t *N_p, uint32_t *N_offset) {

@ -566,9 +566,9 @@ int srslte_pusch_decode(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce, float noise_estimate, uint16_t rnti,
uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data)
uint8_t *data, srslte_uci_data_t *uci_data)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t n;
if (q != NULL &&
@ -607,42 +607,19 @@ int srslte_pusch_decode(srslte_pusch_t *q,
// Generate scrambling sequence if not pre-generated
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
// Set CQI len assuming RI = 1 (3GPP 36.212 Clause 5.2.4.1. Uplink control information on PUSCH without UL-SCH data)
if (cqi_value) {
if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) {
cqi_value->subband_hl.rank_is_not_one = false;
}
uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value);
uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1;
}
// Decode RI/HARQ bits before descrambling
if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) {
fprintf(stderr, "Error decoding RI/HARQ bits\n");
return SRSLTE_ERROR;
}
// Set CQI len with corresponding RI
if (cqi_value) {
if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) {
cqi_value->subband_hl.rank_is_not_one = (uci_data->uci_ri != 0);
}
uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value);
}
// Descrambling
srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits);
// Decode
ret = srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
// Unpack CQI value if available
if (cqi_value) {
srslte_cqi_value_unpack(uci_data->uci_cqi, cqi_value);
}
return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
return ret;
}
uint32_t srslte_pusch_last_noi(srslte_pusch_t *q) {

@ -658,7 +658,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
}
ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len, false);
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len);
if (ret < 0) {
return ret;
}
@ -678,7 +678,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
}
ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri, uci_data->uci_ri_len, true);
ret = srslte_uci_decode_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri);
if (ret < 0) {
return ret;
}
@ -756,18 +756,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
uint32_t nb_q = cfg->nbits.nof_bits;
uint32_t Qm = cfg->grant.Qm;
// Encode RI if CQI enabled
if (uci_data.uci_ri_len > 0 || uci_data.uci_cqi_len > 0) {
/* If no RI is reported set it to zero as specified in 3GPP 36.213 clause 7.2.1 */
if (uci_data.uci_ri_len == 0) {
uci_data.uci_ri = 0;
}
// Encode RI
if (uci_data.uci_ri_len > 0) {
float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri];
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
}
uint8_t ri[2] = {uci_data.uci_ri, 0};
ret = srslte_uci_encode_ack_ri(cfg, ri, uci_data.uci_ri_len, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits, true);
ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits);
if (ret < 0) {
return ret;
}
@ -814,8 +809,8 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
}
ret = srslte_uci_encode_ack_ri(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len,
beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm], false);
ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len,
beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]);
if (ret < 0) {
return ret;
}

@ -252,7 +252,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[1], NULL);
int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, NULL, &uci_data_rx);
int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx);
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (r) {

@ -103,29 +103,26 @@ static uint8_t M_basis_seq_pucch[20][13]={
{1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1},
{1, 1, 0, 1, 1, 1, 1, 1, 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 = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH;
q->cqi_table = srslte_vec_malloc(nwords * sizeof(int8_t *));
q->cqi_table_s = srslte_vec_malloc(nwords * sizeof(int16_t *));
for (uint32_t w = 0; w < nwords; w++) {
q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int8_t));
q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int16_t));
uint8_t word[16];
uint32_t nwords = 16;
for (uint32_t w=0;w<nwords;w++) {
q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int8_t));
q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int16_t));
uint8_t *ptr = word;
srslte_bit_unpack(w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH);
srslte_uci_encode_cqi_pucch(word, SRSLTE_UCI_MAX_CQI_LEN_PUCCH, q->cqi_table[w]);
for (int j = 0; j < SRSLTE_UCI_CQI_CODED_PUCCH_B; j++) {
q->cqi_table_s[w][j] = (int16_t)(2 * q->cqi_table[w][j] - 1);
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;
}
}
}
void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) {
uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH;
uint32_t nwords = 16;
for (uint32_t w=0;w<nwords;w++) {
if (q->cqi_table[w]) {
free(q->cqi_table[w]);
@ -134,8 +131,6 @@ void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) {
free(q->cqi_table_s[w]);
}
}
free(q->cqi_table);
free(q->cqi_table_s);
}
/* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212
@ -156,32 +151,17 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b
}
}
int srslte_uci_encode_cqi_pucch_from_table(srslte_uci_cqi_pucch_t *q, 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) {
bzero(&cqi_data[cqi_len], SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len);
uint8_t *ptr = cqi_data;
uint32_t packed = srslte_bit_pack(&ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH);
memcpy(b_bits, q->cqi_table[packed], SRSLTE_UCI_CQI_CODED_PUCCH_B);
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 < SRSLTE_UCI_MAX_CQI_LEN_PUCCH &&
if (cqi_len == 4 &&
b_bits != NULL &&
cqi_data != NULL)
{
uint32_t max_w = 0;
int32_t max_corr = INT32_MIN;
uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH;
for (uint32_t w=0;w<nwords;w += 1<<(SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len)) {
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);
@ -192,7 +172,7 @@ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32
}
// Convert word to bits again
uint8_t *ptr = cqi_data;
srslte_bit_unpack(max_w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH);
srslte_bit_unpack(max_w, &ptr, cqi_len);
INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr);
return max_corr;
@ -606,7 +586,9 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit
/* Decode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ
*/
static int32_t decode_ri_ack_1bit(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos)
#ifndef MIMO_ENB
static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos)
{
uint32_t p0 = pos[0].position;
uint32_t p1 = pos[1].position;
@ -616,8 +598,33 @@ static int32_t decode_ri_ack_1bit(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bi
return -(q0+q1);
}
int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq,
float beta, uint32_t H_prime_total,
uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks)
{
int32_t rx_ack = 0;
static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3])
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
// Use the same interleaver function to get the HARQ bit position
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, &ack_bits[cfg->grant.Qm*i]);
}
if (acks) {
acks[0] = rx_ack>0;
}
return (int) Qprime;
}
#else
static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3])
{
uint32_t p0 = pos[Qm * 0 + 0].position;
uint32_t p1 = pos[Qm * 0 + 1].position;
@ -638,91 +645,118 @@ static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_
data[2] -= q2 + q5;
}
/* Encode UCI ACK/RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI
*/
int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg,
uint8_t *data, uint32_t data_len,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *bits, bool ack_ri) {
int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq,
float beta, uint32_t H_prime_total,
uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks)
{
int32_t acks_sum[3] = {0, 0, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, data_len, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[18];
uint32_t nof_encoded_bits = encode_ri_ack(data, data_len, q_encoded_bits, cfg->grant.Qm);
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
// Use the same interleaver function to get the HARQ bit position
for (uint32_t i = 0; i < Qprime; i++) {
if (ack_ri) {
uci_ulsch_interleave_ri_gen(i,
cfg->grant.Qm,
H_prime_total,
cfg->nbits.nof_symb,
cfg->cp,
&bits[cfg->grant.Qm * i]);
} else {
uci_ulsch_interleave_ack_gen(i,
cfg->grant.Qm,
H_prime_total,
cfg->nbits.nof_symb,
cfg->cp,
&bits[cfg->grant.Qm * i]);
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
if ((i % 3 == 0) && i > 0) {
decode_ri_ack(q_bits, &c_seq[0], &ack_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, acks_sum);
}
uci_ulsch_interleave_put(&q_encoded_bits[(i * cfg->grant.Qm) % nof_encoded_bits],
cfg->grant.Qm,
&bits[cfg->grant.Qm * i]);
}
if (acks) {
acks[0] = (uint8_t)(acks_sum[0] > 0);
acks[1] = (uint8_t)(acks_sum[1] > 0);
// TODO: Do something with acks_sum[2]
}
return (int) Qprime;
}
#endif
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ
*/
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *ack_bits)
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[18];
uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]);
}
return (int) Qprime;
}
/* Decode UCI ACK/RI bits as described in 5.2.2.6 of 36.212
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI
*/
int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq,
float beta, uint32_t H_prime_total,
uint32_t O_cqi, srslte_uci_bit_t *ack_ri_bits, uint8_t data[2], uint32_t nof_bits, bool is_ri)
int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq,
float beta, uint32_t H_prime_total,
uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data)
{
int32_t sum[3] = {0, 0, 0};
int32_t ri_sum[3] = {0, 0, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_bits, O_cqi, beta);
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
for (uint32_t i = 0; i < Qprime; i++) {
if (is_ri) {
uci_ulsch_interleave_ri_gen(i,
cfg->grant.Qm,
H_prime_total,
cfg->nbits.nof_symb,
cfg->cp,
&ack_ri_bits[cfg->grant.Qm * i]);
} else {
uci_ulsch_interleave_ack_gen(i,
cfg->grant.Qm,
H_prime_total,
cfg->nbits.nof_symb,
cfg->cp,
&ack_ri_bits[cfg->grant.Qm * i]);
}
if (nof_bits == 2 && (i % 3 == 0) && i > 0) {
decode_ri_ack_2bits(q_bits, &c_seq[0], &ack_ri_bits[cfg->grant.Qm * (i - 3)], cfg->grant.Qm, sum);
} else if (nof_bits == 1) {
sum[0] += (int32_t) decode_ri_ack_1bit(q_bits, c_seq, &ack_ri_bits[cfg->grant.Qm * i]);
// Use the same interleaver function to get the HARQ bit position
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
if ((i % 3 == 0) && i > 0) {
//decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum);
}
}
data[0] = (uint8_t) (sum[0] > 0);
if (nof_bits == 2) {
data[1] = (uint8_t) (sum[1] > 0);
if (data) {
*data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0);
}
return (int) Qprime;
}
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI
*/
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t ri,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits)
{
// FIXME: It supports RI of 1 bit only
uint8_t data[2] = {ri, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[18];
uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]);
}
return (int) Qprime;
}

@ -725,8 +725,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo
/* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */
for (uint32_t nof_layers = 1; nof_layers <= SRSLTE_MAX_LAYERS; nof_layers++) {
float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers;
/* Find best SINR, force maximum number of layers if SNR is higher than 30 dB */
if (_sinr > best_sinr + 0.1 || _sinr > 1.0e+3) {
if (_sinr > best_sinr + 0.1) {
best_sinr = _sinr;
best_pmi = (uint8_t) q->pmi[nof_layers - 1];
best_ri = (uint8_t) (nof_layers - 1);

@ -88,19 +88,16 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
pthread_mutex_init(&mutex, NULL);
// Init cell here
for(int p = 0; p < SRSLTE_MAX_PORTS; p++) {
signal_buffer_rx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
if (!signal_buffer_rx[p]) {
fprintf(stderr, "Error allocating memory\n");
return;
}
bzero(signal_buffer_rx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
if (!signal_buffer_tx[p]) {
fprintf(stderr, "Error allocating memory\n");
return;
}
bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
signal_buffer_rx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t));
if (!signal_buffer_rx) {
fprintf(stderr, "Error allocating memory\n");
return;
}
bzero(&signal_buffer_tx, sizeof(cf_t *) * SRSLTE_MAX_PORTS);
signal_buffer_tx[0] = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t));
if (!signal_buffer_tx[0]) {
fprintf(stderr, "Error allocating memory\n");
return;
}
if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB DL\n");
@ -110,7 +107,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error initiating ENB DL\n");
return;
}
if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], phy->cell.nof_prb)) {
if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB UL\n");
return;
}
@ -157,12 +154,12 @@ void phch_worker::stop()
srslte_enb_dl_free(&enb_dl);
srslte_enb_ul_free(&enb_ul);
for (int p = 0; p < SRSLTE_MAX_PORTS; p++) {
if (signal_buffer_rx[p]) {
free(signal_buffer_rx[p]);
}
if (signal_buffer_tx[p]) {
free(signal_buffer_tx[p]);
if (signal_buffer_rx) {
free(signal_buffer_rx);
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (signal_buffer_tx[i]) {
free(signal_buffer_tx[i]);
}
}
pthread_mutex_unlock(&mutex);
@ -174,9 +171,9 @@ void phch_worker::reset()
ue_db.clear();
}
cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx)
cf_t* phch_worker::get_buffer_rx()
{
return signal_buffer_rx[antenna_idx];
return signal_buffer_rx;
}
void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_)
@ -217,29 +214,12 @@ uint32_t phch_worker::get_nof_rnti() {
return ue_db.size();
}
void phch_worker::set_conf_dedicated_ack(uint16_t rnti, bool ack){
pthread_mutex_lock(&mutex);
if (ue_db.count(rnti)) {
ue_db[rnti].dedicated_ack = ack;
} else {
Error("Setting dedicated ack: rnti=0x%x does not exist\n");
}
pthread_mutex_unlock(&mutex);
}
void phch_worker::set_config_dedicated(uint16_t rnti,
srslte_uci_cfg_t *uci_cfg,
srslte_pucch_sched_t *pucch_sched,
srslte_refsignal_srs_cfg_t *srs_cfg,
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated)
srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack)
{
uint32_t I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
bool pucch_cqi = dedicated->cqi_report_cnfg.report_periodic_setup_present;
uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx;
bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi;
bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present;
uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx;
pthread_mutex_lock(&mutex);
if (ue_db.count(rnti)) {
pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an;
@ -257,16 +237,6 @@ void phch_worker::set_config_dedicated(uint16_t rnti,
ue_db[rnti].cqi_en = false;
}
if (pucch_ri) {
ue_db[rnti].ri_idx = ri_idx;
ue_db[rnti].ri_en = true;
} else {
ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false;
}
/* Copy all dedicated RRC configuration to UE */
memcpy(&ue_db[rnti].dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT));
} else {
Error("Setting config dedicated: rnti=0x%x does not exist\n");
}
@ -308,7 +278,7 @@ void phch_worker::work_imp()
}
pthread_mutex_lock(&mutex);
mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants;
mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants;
mac_interface_phy *mac = phy->mac;
@ -323,7 +293,7 @@ void phch_worker::work_imp()
}
// Process UL signal
srslte_enb_ul_fft(&enb_ul);
srslte_enb_ul_fft(&enb_ul, signal_buffer_rx);
// Decode pending UL grants for the tti they were scheduled
decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants);
@ -365,22 +335,15 @@ void phch_worker::work_imp()
phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl)));
for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) {
// SI-RNTI and RAR-RNTI do not have ACK
uint16_t rnti = dl_grants[t_tx_dl].sched_grants[i].rnti;
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) {
/* For each TB */
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
/* If TB enabled, set pending ACK */
if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) {
phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), rnti, tb_idx, dl_grants[t_tx_dl].sched_grants[i].location.ncce);
}
}
if (dl_grants[t_tx_dl].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) {
phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce);
}
}
// Generate signal and transmit
srslte_enb_dl_gen_signal(&enb_dl);
Debug("Sending to radio\n");
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
phy->worker_end(tx_mutex_cnt, signal_buffer_tx[0], SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
#ifdef DEBUG_WRITE_FILE
fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t), 1, f);
@ -424,39 +387,24 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
gettimeofday(&t[1], NULL);
#endif
bool acks_pending[SRSLTE_MAX_TB] = {false};
// Get pending ACKs with an associated PUSCH transmission
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
acks_pending[tb] = phy->ack_is_pending(t_rx, rnti, tb);
if (acks_pending[tb]) {
uci_data.uci_ack_len++;
}
if (phy->ack_is_pending(t_rx, rnti)) {
uci_data.uci_ack_len = 1;
}
// Configure PUSCH CQI channel
srslte_cqi_value_t cqi_value = {0};
srslte_cqi_value_t cqi_value;
bool cqi_enabled = false;
#if 0
if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) {
uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */
ri_enabled = true;
} else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
cqi_enabled = true;
if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3;
uci_data.uci_pmi_len = 2;
}
} else
#endif
if (grants[i].grant.cqi_request) {
} else if (grants[i].grant.cqi_request) {
cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0;
cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4);
cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31);
cqi_enabled = true;
}
if (cqi_enabled) {
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
}
// mark this tti as having an ul grant to avoid pucch
ue_db[rnti].has_grant_tti = tti_rx;
@ -464,6 +412,22 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
srslte_ra_ul_grant_t phy_grant;
int res = -1;
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant)) {
// Handle Format0 adaptive retx
// Use last TBS for this TB in case of mcs>28
if (phy_grant.mcs.idx > 28) {
phy_grant.mcs.tbs = ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)];
Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS));
}
ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.tbs;
if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) {
phy_grant.mcs.mod = ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)];
phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod);
}
ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.mod;
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
phy_grant.mcs.mod = SRSLTE_MOD_16QAM;
}
@ -472,7 +436,6 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
rnti, grants[i].rv_idx,
grants[i].current_tx_nb,
grants[i].data,
(cqi_enabled) ? &cqi_value : NULL,
&uci_data,
sf_rx);
} else {
@ -494,24 +457,11 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
char cqi_str[64];
if (cqi_enabled) {
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
if (ue_db[rnti].cqi_en) {
wideband_cqi_value = cqi_value.wideband.wideband_cqi;
} else if (grants[i].grant.cqi_request) {
wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0;
if (cqi_value.subband_hl.pmi_present) {
if (cqi_value.subband_hl.rank_is_not_one) {
Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n",
cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1,
cqi_value.subband_hl.pmi, cqi_value.subband_hl.N);
} else {
Info("PUSCH: Aperiodic ri=1, CQI=%02d, pmi=%d for %d subbands\n",
cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.pmi, cqi_value.subband_hl.N);
}
} else {
Info("PUSCH: Aperiodic ri%s, CQI=%02d for %d subbands\n",
cqi_value.subband_hl.rank_is_not_one?"~1":"=1",
cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N);
}
}
snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value);
}
@ -531,16 +481,14 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
}
*/
log_h->info_hex(grants[i].data, phy_grant.mcs.tbs/8,
"PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s%s\n",
"PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n",
rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb,
phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx,
snr_db,
srslte_pusch_last_noi(&enb_ul.pusch),
crc_res?"OK":"KO",
(uci_data.uci_ack_len)?(uci_data.uci_ack?"1":"0"):"",
(uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"",
uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"",
uci_data.uci_cqi_len>0?cqi_str:"",
uci_data.uci_ri_len>0?(uci_data.uci_ri?", ri=0":", ri=1"):"",
timestr);
// Notify MAC of RL status
@ -555,28 +503,17 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
// Notify MAC new received data and HARQ Indication value
phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res);
uint32_t ack_idx = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (acks_pending[tb]) {
bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2);
bool valid = (crc_res || snr_db > PUSCH_RL_SNR_DB_TH);
phy->mac->ack_info(tti_rx, rnti, tb, ack && valid);
}
if (uci_data.uci_ack_len) {
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH));
}
// Notify MAC of UL SNR, DL CQI and DL RI
// Notify MAC of UL SNR and DL CQI
if (snr_db >= PUSCH_RL_SNR_DB_TH) {
phy->mac->snr_info(tti_rx, rnti, snr_db);
}
if (uci_data.uci_cqi_len>0 && crc_res) {
phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value);
}
if (uci_data.uci_ri_len > 0 && crc_res) {
phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri);
}
if (cqi_value.subband_hl.pmi_present && crc_res) {
phy->mac->pmi_info(tti_rx, rnti, cqi_value.subband_hl.pmi);
}
// Save metrics stats
ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch));
@ -595,8 +532,7 @@ int phch_worker::decode_pucch()
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) {
// Check if user needs to receive PUCCH
bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false,
needs_ri = false;
bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false;
uint32_t last_n_pdcch = 0;
bzero(&uci_data, sizeof(srslte_uci_data_t));
@ -608,32 +544,18 @@ int phch_worker::decode_pucch()
}
}
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
needs_ack[tb] = phy->ack_is_pending(t_rx, rnti, tb, &last_n_pdcch);
if (needs_ack[tb]) {
needs_pucch = true;
uci_data.uci_ack_len++;
}
if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) {
needs_pucch = true;
needs_ack = true;
uci_data.uci_ack_len = 1;
}
srslte_cqi_value_t cqi_value;
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated;
LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode;
if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) {
if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) {
needs_pucch = true;
needs_ri = true;
uci_data.uci_ri_len = 1;
uci_data.ri_periodic_report = true;
} else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) {
if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
needs_pucch = true;
needs_cqi = true;
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3;
uci_data.uci_pmi_len = 2;
}
}
}
@ -642,48 +564,26 @@ int phch_worker::decode_pucch()
fprintf(stderr, "Error getting PUCCH\n");
return SRSLTE_ERROR;
}
/* If only one ACK is required, it can be for TB0 or TB1 */
uint32_t ack_idx = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (needs_ack[tb]) {
bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2);
bool valid = srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH;
phy->mac->ack_info(tti_rx, rnti, tb, ack && valid);
}
if (uci_data.uci_ack_len > 0) {
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH));
}
if (uci_data.scheduling_request) {
phy->mac->sr_detected(tti_rx, rnti);
}
char cqi_ri_str[64];
if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) {
if (uci_data.uci_ri_len && needs_ri) {
phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri);
sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri);
} else if (uci_data.uci_cqi_len && needs_cqi) {
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
if (uci_data.uci_pmi_len) {
uint32_t packed_pmi = uci_data.uci_pmi[0];
if (uci_data.uci_pmi_len > 1) {
packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1];
}
phy->mac->pmi_info(tti_rx, rnti, packed_pmi);
sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30);
}
}
char cqi_str[64];
if (uci_data.uci_cqi_len) {
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
}
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n",
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n",
rnti,
srslte_pucch_get_last_corr(&enb_ul.pucch),
enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb,
(uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"",
(uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"",
needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"",
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
(needs_cqi || needs_ri)?cqi_ri_str:"");
needs_cqi?cqi_str:"");
// Notify MAC of RL status
@ -742,16 +642,25 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra
int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
{
for (uint32_t i=0;i<nof_grants;i++) {
srslte_enb_dl_pdsch_t *grant = &grants[i];
uint16_t rnti = grant->rnti;
uint16_t rnti = grants[i].rnti;
if (rnti) {
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_tx)) {
srslte_dci_format_t format = SRSLTE_DCI_FORMAT1;
switch(grants[i].grant.alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
case SRSLTE_RA_ALLOC_TYPE1:
format = SRSLTE_DCI_FORMAT1;
break;
case SRSLTE_RA_ALLOC_TYPE2:
format = SRSLTE_DCI_FORMAT1A;
break;
}
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_tx)) {
fprintf(stderr, "Error putting PDCCH %d\n",i);
return SRSLTE_ERROR;
}
if (LOG_THIS(rnti)) {
Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(grant->dci_format),
Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(format),
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx_dl);
}
}
@ -759,8 +668,9 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
return 0;
}
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) {
for (uint32_t i = 0; i < nof_grants; i++) {
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
{
for (uint32_t i=0;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti;
if (rnti) {
@ -768,103 +678,53 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) {
rnti_is_user = false;
}
/* Mimo type (tx scheme) shall be single or tx diversity by default */
srslte_mimo_type_t mimo_type = (enb_dl.cell.nof_ports == 1) ? SRSLTE_MIMO_TYPE_SINGLE_ANTENNA
: SRSLTE_MIMO_TYPE_TX_DIVERSITY;
srslte_ra_dl_grant_t phy_grant;
srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant);
char grant_str[64];
switch (grants[i].grant.alloc_type) {
switch(grants[i].grant.alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
sprintf(grant_str, "mask=0x%x", grants[i].grant.type0_alloc.rbg_bitmask);
break;
sprintf(grant_str, "mask=0x%x",grants[i].grant.type0_alloc.rbg_bitmask);
break;
case SRSLTE_RA_ALLOC_TYPE1:
sprintf(grant_str, "mask=0x%x", grants[i].grant.type1_alloc.vrb_bitmask);
break;
default:
sprintf(grant_str, "rb_start=%d", grants[i].grant.type2_alloc.RB_start);
break;
}
srslte_dci_format_t dci_format = grants[i].dci_format;
switch (dci_format) {
case SRSLTE_DCI_FORMAT1:
case SRSLTE_DCI_FORMAT1A:
/* Do nothing, it keeps default */
break;
case SRSLTE_DCI_FORMAT2A:
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) {
mimo_type = SRSLTE_MIMO_TYPE_CDD;
}
break;
case SRSLTE_DCI_FORMAT2:
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
if (phy_grant.pinfo == 0) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
}
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
}
break;
case SRSLTE_DCI_FORMAT0:
case SRSLTE_DCI_FORMAT1C:
case SRSLTE_DCI_FORMAT1B:
case SRSLTE_DCI_FORMAT1D:
case SRSLTE_DCI_FORMAT2B:
sprintf(grant_str, "mask=0x%x",grants[i].grant.type1_alloc.vrb_bitmask);
break;
default:
Error("Not implemented/Undefined DCI format (%d)\n", dci_format);
sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start);
break;
}
if (LOG_THIS(rnti)) {
uint8_t x = 0;
uint8_t *ptr = grants[i].data[0];
uint8_t *ptr = grants[i].data;
uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8;
if (!ptr) {
ptr = &x;
len = 1;
}
char pinfo_str[16] = {0};
if (dci_format == SRSLTE_DCI_FORMAT2) {
snprintf(pinfo_str, 15, ", pinfo=%x", phy_grant.pinfo);
}
char tbstr[SRSLTE_MAX_TB][128];
for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (phy_grant.tb_en[tb]) {
snprintf(tbstr[tb], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d%s%s",
tb,
phy_grant.mcs[tb].tbs / 8,
phy_grant.mcs[tb].idx,
(tb == 0) ? grants[i].grant.rv_idx : grants[i].grant.rv_idx_1,
grants[i].softbuffers[tb]==NULL?", \e[31msoftbuffer=NULL\e[0m":"",
grants[i].data[tb]==NULL?", \e[31mdata=NULL\e[0m":"");
} else {
tbstr[tb][0] = '\0';
}
}
log_h->info_hex(ptr, len,
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tti_tx_dl=%d, tx_scheme=%s%s%s%s\n",
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, tti_tx_dl,
srslte_mimotype2str(mimo_type), pinfo_str, tbstr[0], tbstr[1]);
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d\n",
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process,
phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl);
}
int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1};
srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL};
uint8_t *d[SRSLTE_MAX_CODEWORDS] = {grants[i].data, NULL};
int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, 0};
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_tx, grants[i].data, mimo_type)) {
fprintf(stderr, "Error putting PDSCH %d\n", i);
return SRSLTE_ERROR;
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, sb, rnti, rv, sf_tx, d, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0))
{
fprintf(stderr, "Error putting PDSCH %d\n",i);
return SRSLTE_ERROR;
}
// Save metrics stats
// Save metrics stats
ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx);
}
}
return SRSLTE_SUCCESS;
return SRSLTE_SUCCESS;
}

@ -1142,11 +1142,7 @@ void rrc::ue::send_connection_setup(bool is_setup)
phy_cfg->cqi_report_cnfg_present = true;
if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true;
if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31;
} else {
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
}
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
} else {
phy_cfg->cqi_report_cnfg.report_periodic_present = true;
phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true;

@ -859,9 +859,7 @@ void phch_worker::set_uci_periodic_cqi()
if (period_cqi.configured && rnti_is_set) {
if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) {
/* Compute RI, PMI and SINR */
compute_ri();
uci_data.ri_periodic_report = true;
Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri);
} else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) {
@ -904,9 +902,6 @@ void phch_worker::set_uci_periodic_cqi()
void phch_worker::set_uci_aperiodic_cqi()
{
if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) {
/* Compute RI, PMI and SINR */
compute_ri();
switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) {
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30:
/* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1
@ -944,6 +939,9 @@ void phch_worker::set_uci_aperiodic_cqi()
other transmission modes they are reported conditioned on rank 1.
*/
if (rnti_is_set) {
/* Compute RI, PMI and SINR */
compute_ri();
/* Select RI, PMI and SINR */
uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented)
uint32_t pmi = ue_dl.pmi[ri]; // Select PMI
@ -974,9 +972,9 @@ void phch_worker::set_uci_aperiodic_cqi()
cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1,
sinr_db, sinr_db, pmi, cqi_report.subband_hl.N);
} else {
Info("PUSCH: Aperiodic ri=1, CQI=%02d, SINR=%2.1f, pmi=%d for %d subbands\n",
cqi_report.subband_hl.wideband_cqi_cw0,
sinr_db, pmi, cqi_report.subband_hl.N);
Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n",
cqi_report.wideband.wideband_cqi,
phy->avg_snr_db, cqi_report.subband_hl.N);
}
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
}

Loading…
Cancel
Save