diff --git a/lib/include/srslte/phy/enb/enb_ul.h b/lib/include/srslte/phy/enb/enb_ul.h index 1b865b7f7..0957ccbc0 100644 --- a/lib/include/srslte/phy/enb/enb_ul.h +++ b/lib/include/srslte/phy/enb/enb_ul.h @@ -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); diff --git a/lib/include/srslte/phy/phch/pusch.h b/lib/include/srslte/phy/phch/pusch.h index 01db068a5..2328c8ff3 100644 --- a/lib/include/srslte/phy/phch/pusch.h +++ b/lib/include/srslte/phy/phch/pusch.h @@ -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); diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index 8e72b5793..91592501f 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -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, - bool is_ri); + srslte_uci_bit_t *ri_bits); -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); +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, + uint8_t *data); #endif diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index 8ea5dd3e4..f94eb0277 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -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); } diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 8589ee51a..2c0940af5 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -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) { diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index 7876a4f86..a8c6064fc 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -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) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 1e972594d..930364725 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -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; } diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index 651803617..cf0be75c3 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -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) { diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 8a1a36544..cb09ca08b 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -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;wcqi_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;jcqi_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;wcqi_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;wcqi_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;igrant.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); + + 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++) { + 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); + } + } + + 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(data, data_len, q_encoded_bits, cfg->grant.Qm); - - 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_put(&q_encoded_bits[(i * cfg->grant.Qm) % nof_encoded_bits], - cfg->grant.Qm, - &bits[cfg->grant.Qm * i]); + uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm); + + for (uint32_t i=0;igrant.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;igrant.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;igrant.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; } + diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 4183016e0..db7118b0c 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -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); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 990633aa7..5298e6e7a 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -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= 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;irnti; + 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<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; } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 29cbdef8e..e176e8ac5 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -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; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 2beff5900..0068724b4 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -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); }