diff --git a/lib/include/srslte/phy/phch/pucch.h b/lib/include/srslte/phy/phch/pucch.h index 887766868..175b1f672 100644 --- a/lib/include/srslte/phy/phch/pucch.h +++ b/lib/include/srslte/phy/phch/pucch.h @@ -39,13 +39,14 @@ #include "srslte/phy/phch/pucch_cfg.h" #include "srslte/phy/phch/uci.h" -#define SRSLTE_PUCCH_N_SEQ 12 +#define SRSLTE_PUCCH_N_SEQ SRSLTE_NRE #define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B +#define SRSLTE_PUCCH2_N_SF (5) #define SRSLTE_PUCCH_1A_2A_NOF_ACK (1) #define SRSLTE_PUCCH_1B_2B_NOF_ACK (2) #define SRSLTE_PUCCH3_NOF_BITS (4 * SRSLTE_NRE) #define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS -#define SRSLTE_PUCCH_MAX_SYMBOLS 128 +#define SRSLTE_PUCCH_MAX_SYMBOLS (SRSLTE_PUCCH_N_SEQ * SRSLTE_PUCCH2_N_SF * SRSLTE_NOF_SLOTS_PER_SF) // PUCCH Format 1B Channel selection #define SRSLTE_PUCCH_CS_MAX_ACK 4 diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index bb96717da..b650d0bdf 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -356,7 +356,7 @@ static uint32_t get_N_sf(srslte_pucch_format_t format, uint32_t slot_idx, bool s case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - return 5; + return SRSLTE_PUCCH2_N_SF; case SRSLTE_PUCCH_FORMAT_3: if (!slot_idx) { return 5; @@ -474,8 +474,9 @@ static int encode_signal_format12(srslte_pucch_t* q, return SRSLTE_ERROR; } } else { - for (int i = 0; i < SRSLTE_PUCCH_MAX_BITS / 2; i++) { - q->d[i] = 1.0; + // Set all ones + for (uint32_t i = 0; i < SRSLTE_PUCCH_MAX_BITS / 2; i++) { + q->d[i] = 1.0f; } } uint32_t N_sf_0 = get_N_sf(cfg->format, 0, sf->shortened); @@ -774,19 +775,25 @@ static bool decode_signal(srslte_pucch_t* q, case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - seq = get_user_sequence(q, cfg->rnti, sf->tti % 10); + seq = get_user_sequence(q, cfg->rnti, sf->tti % SRSLTE_NOF_SF_X_FRAME); if (seq) { encode_signal_format12(q, sf, cfg, NULL, ref, true); srslte_vec_prod_conj_ccc(q->z, ref, q->z_tmp, SRSLTE_PUCCH_MAX_SYMBOLS); - for (int i = 0; i < SRSLTE_PUCCH2_NOF_BITS / 2; i++) { - q->z[i] = 0; - for (int j = 0; j < SRSLTE_NRE; j++) { - q->z[i] += q->z_tmp[i * SRSLTE_NRE + j] / SRSLTE_NRE; - } + for (int i = 0; i < (SRSLTE_PUCCH2_N_SF * SRSLTE_NOF_SLOTS_PER_SF); i++) { + q->z[i] = srslte_vec_acc_cc(&q->z_tmp[i * SRSLTE_NRE], SRSLTE_NRE) / SRSLTE_NRE; } srslte_demod_soft_demodulate_s(SRSLTE_MOD_QPSK, q->z, llr_pucch2, SRSLTE_PUCCH2_NOF_BITS / 2); srslte_scrambling_s_offset(seq, llr_pucch2, 0, SRSLTE_PUCCH2_NOF_BITS); - corr = (float)srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, pucch_bits, nof_uci_bits) / 2000; + + // Calculate the LLR RMS for normalising + float llr_pow = srslte_vec_avg_power_sf(llr_pucch2, SRSLTE_PUCCH2_NOF_BITS); + + if (isnormal(llr_pow)) { + float llr_rms = sqrtf(llr_pow) * SRSLTE_PUCCH2_NOF_BITS; + corr = ((float)srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, pucch_bits, nof_uci_bits)) / (llr_rms); + } else { + corr = 0; + } detected = true; } else { ERROR("Decoding PUCCH2: could not generate sequence\n"); @@ -905,6 +912,19 @@ int srslte_pucch_decode(srslte_pucch_t* q, // Equalization srslte_predecoding_single(q->z_tmp, q->ce, q->z, NULL, nof_re, 1.0f, channel->noise_estimate); + // DMRS Detection + cf_t _dmrs_corr = srslte_vec_acc_cc(q->ce, nof_re) / nof_re; + float _rms = __real__(conjf(_dmrs_corr) * _dmrs_corr); + float _pow = srslte_vec_avg_power_cf(q->ce, nof_re); + float _r = _rms / _pow; + + // Return not detected if the ratio is 0, NAN, +/- Infinity or below 0.1 + if (!isnormal(_r) || _r < 0.1f) { + data->detected = false; + data->correlation = NAN; + return SRSLTE_SUCCESS; + } + // Perform ML-decoding bool pucch_found = decode_signal(q, sf, cfg, pucch_bits, nof_re, nof_uci_bits, &data->correlation); @@ -922,8 +942,9 @@ int srslte_pucch_decode(srslte_pucch_t* q, case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - data->uci_data.ack.valid = data->correlation > cfg->threshold_data_valid_format2; - data->uci_data.cqi.data_crc = data->correlation > cfg->threshold_data_valid_format2; + data->detected = data->correlation > cfg->threshold_data_valid_format2; + data->uci_data.ack.valid = data->detected; + data->uci_data.cqi.data_crc = data->detected; break; case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_3: diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 1a62389a6..d44323bdd 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -620,7 +620,7 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t* cfg, uint32_t O, uint32_t O_c return Q_prime; } -static uint32_t encode_ri_ack(uint8_t data[2], uint32_t O_ack, uint8_t Qm, srslte_uci_bit_t* q_encoded_bits) +static uint32_t encode_ri_ack(const uint8_t data[2], uint32_t O_ack, uint8_t Qm, srslte_uci_bit_t* q_encoded_bits) { uint32_t i = 0; @@ -652,7 +652,7 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t O_ack, uint8_t Qm, srslt } static uint32_t -encode_ack_long(uint8_t* data, uint32_t O_ack, uint8_t Q_m, uint32_t Q_prime, srslte_uci_bit_t* q_encoded_bits) +encode_ack_long(const uint8_t* data, uint32_t O_ack, uint8_t Q_m, uint32_t Q_prime, srslte_uci_bit_t* q_encoded_bits) { uint32_t Q_ack = Q_m * Q_prime; @@ -674,15 +674,8 @@ encode_ack_long(uint8_t* data, uint32_t O_ack, uint8_t Q_m, uint32_t Q_prime, sr static void decode_ri_ack_1bit(const int16_t* q_bits, const uint8_t* c_seq, uint8_t data[1]) { - // Unscramble p1 - int16_t q1 = c_seq[1] ? -q_bits[1] : q_bits[1]; - - // Scramble with correct position - int16_t q0 = q_bits[0]; - q1 = c_seq[0] ? -q1 : q1; - if (data) { - data[0] = ((q0 + q1) > 0) ? 1 : 0; + data[0] = ((q_bits[0] + q_bits[1]) > 0) ? 1 : 0; } } @@ -829,9 +822,19 @@ int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t* cfg, for (uint32_t j = 0; j < Qm; j++, count_acc++) { // Calculate circular LLR index uint32_t acc_idx = count_acc % nof_acc; + uint32_t pos = ack_ri_bits[count_acc].position; + + int16_t q = q_bits[pos]; + + // Remove scrambling of repeated bits + if (nof_bits == 1) { + if (acc_idx == 1 && pos > 0) { + q = (c_seq[pos] == c_seq[pos - 1]) ? +q : -q; + } + } // Accumulate LLR - llr_acc[acc_idx] += q_bits[ack_ri_bits[count_acc].position]; + llr_acc[acc_idx] += q; /// Limit accumulator boundaries llr_acc[acc_idx] = SRSLTE_MIN(llr_acc[acc_idx], INT16_MAX / 2); diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index f8314a1e6..ed3419014 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -969,7 +969,7 @@ static void gen_ack_fdd(const srslte_pdsch_ack_t* ack_info, srslte_uci_data_t* u uci_data->value.ack.ack_value[cc_idx] = 2; } } - for (uint32_t i = 0; i < 2; i++) { + for (uint32_t i = 0; i < SRSLTE_PUCCH_CS_MAX_CARRIERS; i++) { uci_data->cfg.ack[i].nof_acks = 1; } } else { @@ -1017,36 +1017,9 @@ static void gen_ack_fdd(const srslte_pdsch_ack_t* ack_info, srslte_uci_data_t* u // subframe n − 4 , the UE shall use PUCCH format 3 and PUCCH resource n_pucch_3 where the value of n PUCCH // is determined according to higher layer configuration and Table 10.1.2.2.2-1. uci_data->cfg.ack[0].nof_acks = tb_count_cc0; // So, set only PCell - } else if (uci_data->cfg.cqi.data_enable && !ack_info->is_pusch_available) { - // 3GPP 36.213 R.15 Section 10.1.1: - // For FDD or for FDD-TDD and primary cell frame structure type 1 and for a UE that is configured with more than - // one serving cell, in case of collision between a periodic CSI report and an HARQ-ACK in a same subframe without - // PUSCH, - if (tb_count_cc0 == tb_count && ack_info->simul_cqi_ack) { - // - if the parameter simultaneousAckNackAndCQI provided by higher layers is set TRUE and if the HARQ-ACK - // corresponds to a PDSCH transmission or PDCCH/EPDCCH indicating downlink SPS release only on the - // primary cell, then the periodic CSI report is multiplexed with HARQ-ACK on PUCCH using PUCCH format 2/2a/2b - uci_data->cfg.ack[0].nof_acks = tb_count_cc0; - } else if (ack_info->simul_cqi_ack_pucch3 && total_uci_bits <= 22) { - // - else if the UE is configured with PUCCH format 3 and if the parameter simultaneousAckNackAndCQI-Format3- - // r11 provided by higher layers is set TRUE, and if PUCCH resource is determined according to subclause - // 10.1.2.2.2, and - // - if the total number of bits in the subframe corresponding to HARQ-ACKs, SR (if any), and the CSI is not - // larger than 22 or - // - if the total number of bits in the subframe corresponding to spatially bundled HARQ-ACKs, SR (if any), - // and the CSI is not larger than 22 then the periodic CSI report is multiplexed with HARQ-ACK on PUCCH - // using the determined PUCCH format 3 resource according to [4] - for (int i = 0; i < ack_info->nof_cc; i++) { - uci_data->cfg.ack[i].nof_acks = nof_tb; - } - } else { - // - otherwise, CSI is dropped - uci_data->cfg.cqi.data_enable = false; - // - for (int i = 0; i < ack_info->nof_cc; i++) { - uci_data->cfg.ack[i].nof_acks = nof_tb; - } + for (int i = 1; i < ack_info->nof_cc; i++) { + uci_data->cfg.ack[i].nof_acks = 0; } } else { // For 2 or more configured cells, report nof_tb per carrier except if there are no HARQ-ACK bits to report, in @@ -1055,6 +1028,44 @@ static void gen_ack_fdd(const srslte_pdsch_ack_t* ack_info, srslte_uci_data_t* u uci_data->cfg.ack[i].nof_acks = nof_tb; } } + + if (tb_count && uci_data->cfg.cqi.data_enable && !ack_info->is_pusch_available) { + bool drop_csi_report = true; ///< CSI report shall be dropped by default + + // 3GPP 36.213 R.15 Section 10.1.1: + // For FDD or for FDD-TDD and primary cell frame structure type 1 and for a UE that is configured with more than + // one serving cell, in case of collision between a periodic CSI report and an HARQ-ACK in a same subframe without + // PUSCH, + + // - if the parameter simultaneousAckNackAndCQI provided by higher layers is set TRUE and if the HARQ-ACK + // corresponds to a PDSCH transmission or PDCCH/EPDCCH indicating downlink SPS release only on the + // primary cell, then the periodic CSI report is multiplexed with HARQ-ACK on PUCCH using PUCCH format 2/2a/2b + if ((tb_count_cc0 == tb_count && ack_info->simul_cqi_ack)) { + // Do not drop CSI report + drop_csi_report = false; + + // Set number of active only ACKs + uci_data->cfg.ack[0].nof_acks = tb_count_cc0; + + // Set all SCell number of ACKs to 0 + for (int i = 1; i < ack_info->nof_cc; i++) { + uci_data->cfg.ack[i].nof_acks = 0; + } + } + + // - else if the UE is configured with PUCCH format 3 and if the parameter simultaneousAckNackAndCQI-Format3- + // r11 provided by higher layers is set TRUE, and if PUCCH resource is determined according to subclause + // 10.1.2.2.2, and + // - if the total number of bits in the subframe corresponding to HARQ-ACKs, SR (if any), and the CSI is not + // larger than 22 or + // - if the total number of bits in the subframe corresponding to spatially bundled HARQ-ACKs, SR (if any), + // and the CSI is not larger than 22 then the periodic CSI report is multiplexed with HARQ-ACK on PUCCH + // using the determined PUCCH format 3 resource according to [4] + drop_csi_report &= !(ack_info->simul_cqi_ack_pucch3 && total_uci_bits <= 22); + + // - otherwise, CSI is dropped + uci_data->cfg.cqi.data_enable = !drop_csi_report; + } } // n_cce values are just copied diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index e0644fc19..2a02dc041 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -141,7 +141,7 @@ int sf_worker::add_rnti(uint16_t rnti, uint32_t cc_idx, bool is_pcell, bool is_t int ret = SRSLTE_ERROR; if (cc_idx < cc_workers.size()) { - cc_workers[cc_idx]->add_rnti(rnti, true, is_temporal); + cc_workers[cc_idx]->add_rnti(rnti, is_pcell, is_temporal); ret = SRSLTE_SUCCESS; }