diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index aa3e13257..71555234a 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -518,7 +518,7 @@ int main(int argc, char **argv) { // Variables for measurements uint32_t nframes=0; - uint32_t ri = 0, pmi = 0; + uint8_t ri = 0, pmi = 0; float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0, sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0; bool decode_pdsch = false; diff --git a/lib/include/srslte/phy/phch/cqi.h b/lib/include/srslte/phy/phch/cqi.h index 593592f1c..cfc9e92e7 100644 --- a/lib/include/srslte/phy/phch/cqi.h +++ b/lib/include/srslte/phy/phch/cqi.h @@ -41,11 +41,14 @@ #include "srslte/phy/common/phy_common.h" #define SRSLTE_CQI_MAX_BITS 64 +#define SRSLTE_DIF_CQI_MAX_BITS 3 +#define SRSLTE_PMI_MAX_BITS 4 typedef struct { bool configured; uint32_t pmi_idx; uint32_t ri_idx; + bool ri_idx_present; bool simul_cqi_ack; bool format_is_subband; uint32_t subband_size; diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index a674e43ea..0c53589e6 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -64,6 +64,10 @@ typedef struct SRSLTE_API { typedef struct SRSLTE_API { uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS]; uint32_t uci_cqi_len; + uint8_t uci_dif_cqi[SRSLTE_DIF_CQI_MAX_BITS]; + uint32_t uci_dif_cqi_len; + uint8_t uci_pmi[SRSLTE_PMI_MAX_BITS]; + uint8_t uci_pmi_len; uint8_t uci_ri; // Only 1-bit supported for RI uint32_t uci_ri_len; uint8_t uci_ack; // 1st codeword bit for HARQ-ACK diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 0f8b25ece..95523be84 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -182,8 +182,8 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, bool acks[SRSLTE_MAX_CODEWORDS]); SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, - uint32_t *ri, - uint32_t *pmi, + uint8_t *ri, + uint8_t *pmi, float *current_sinr); SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index dc88685b6..6d620be9d 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -454,10 +454,10 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], /* Compute the Rank Indicator (RI) and Precoder Matrix Indicator (PMI) by computing the Signal to Interference plus * Noise Ratio (SINR), valid for TM4 */ -int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, float *current_sinr) { +int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, float *current_sinr) { float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); float best_sinr = -INFINITY; - uint32_t best_pmi = 0, best_ri = 0; + uint8_t best_pmi = 0, best_ri = 0; if (q->cell.nof_ports < 2 || q->nof_rx_antennas < 2) { /* Do nothing */ @@ -471,11 +471,11 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, f /* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */ for (uint32_t nof_layers = 1; nof_layers <= 2; nof_layers++) { - float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers; + float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers; if (_sinr > best_sinr + 0.1) { best_sinr = _sinr; - best_pmi = q->pmi[nof_layers - 1]; - best_ri = nof_layers; + best_pmi = (uint8_t) q->pmi[nof_layers - 1]; + best_ri = (uint8_t) (nof_layers - 1); } } diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 08edcafe0..6c074ea45 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -230,6 +230,14 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { + /* Append Differential CQI */ + memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len; + + /* Append PMI */ + memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_data->uci_cqi_len += uci_data->uci_pmi_len; + srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index e2c181c98..9ef204cd4 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -230,11 +230,23 @@ void phch_worker::work_imp() } /* Select Rank Indicator by computing Condition Number */ - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || - phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { float cn = 0.0f; srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); uci_data.uci_ri_len = 1; + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4){ + float sinr = 0.0f; + uint8 packed_pmi = 0; + srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); + uci_data.uci_ri_len = 1; + if (uci_data.uci_ri == 0) { + uci_data.uci_pmi_len = 2; + uci_data.uci_dif_cqi_len = 0; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } } } } @@ -714,7 +726,16 @@ void phch_worker::set_uci_periodic_cqi() int cqi_max = phy->args->cqi_max; if (period_cqi.configured && rnti_is_set) { - if (srslte_cqi_send(period_cqi.pmi_idx, (tti+4)%10240)) { + if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, (tti+4)%10240)) { + if (uci_data.uci_ri_len) { + uci_data.uci_cqi[0] = uci_data.uci_ri; + uci_data.uci_cqi_len = uci_data.uci_ri_len; + uci_data.uci_ri_len = 0; + uci_data.uci_dif_cqi_len = 0; + uci_data.uci_pmi_len = 0; + Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); + } + } else if (srslte_cqi_send(period_cqi.pmi_idx, (tti+4)%10240)) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { // TODO: Implement subband periodic reports @@ -876,11 +897,12 @@ void phch_worker::encode_pucch() float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len); float gain = set_power(tx_power); - Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, sr=%s, cfo=%.1f Hz%s\n", + Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, sr=%s, cfo=%.1f Hz%s\n", tx_power, (tti+4)%10240, last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", + uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", uci_data.scheduling_request?"yes":"no", cfo*15000, timestr); } @@ -1011,12 +1033,19 @@ void phch_worker::set_ul_params(bool pregen_disabled) /* CQI configuration */ bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t)); period_cqi.configured = dedicated->cqi_report_cnfg.report_periodic_setup_present; - period_cqi.pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; + period_cqi.pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; period_cqi.simul_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; period_cqi.format_is_subband = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic == LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI; period_cqi.subband_size = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic_subband_k; - + + if (dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present) { + period_cqi.ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; + period_cqi.ri_idx_present = true; + } else { + period_cqi.ri_idx_present = false; + } + /* SR configuration */ I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;