Refactored PMI/CQI/RI reporting

master
Xavier Arteaga 7 years ago
parent de654cd344
commit 9ffdb1e62d

@ -90,8 +90,19 @@ typedef struct SRSLTE_API {
transmission mode 8 configured without PMI/RI reporting). transmission mode 8 configured without PMI/RI reporting).
This is for PUCCH Format 2 reports This is for PUCCH Format 2 reports
*/ */
/* Table 5.2.3.3.1-2: UCI fields for channel quality and precoding information (CQI/PMI) feedback for
wideband reports (transmission mode 4, transmission mode 5 and transmission mode 6)
This is for PUCCH Format 2 reports
*/
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width uint8_t wideband_cqi; // 4-bit width
uint8_t spatial_diff_cqi; // If Rank==1 then it is 0-bit width otherwise it is 3-bit width
uint8_t pmi;
bool pmi_present;
bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false
bool rank_is_not_one; // If rank > 1 then true otherwise false
} srslte_cqi_format2_wideband_t; } srslte_cqi_format2_wideband_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
@ -165,4 +176,6 @@ SRSLTE_API int srslte_cqi_hl_get_subband_size(int num_prbs);
SRSLTE_API int srslte_cqi_hl_get_no_subbands(int num_prbs); SRSLTE_API int srslte_cqi_hl_get_no_subbands(int num_prbs);
SRSLTE_API void srslte_cqi_to_str(const uint8_t *cqi_value, int cqi_len, char *str, int str_len);
#endif // CQI_ #endif // CQI_

@ -64,10 +64,6 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS]; uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
uint32_t uci_cqi_len; 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 uint8_t uci_ri; // Only 1-bit supported for RI
uint32_t uci_ri_len; uint32_t uci_ri_len;
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack; // 1st codeword bit for HARQ-ACK

@ -292,9 +292,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS];
if (q->users[rnti]) { if (q->users[rnti]) {
uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + 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, nof_uci_bits);
// If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // If we are looking for SR and ACK at the same time and ret=0, means there is no SR.
@ -323,15 +321,6 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); 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) { if (uci_data->uci_ri_len) {
uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */ uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */
} }

@ -88,11 +88,30 @@ int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE
return 4+2+msg->L; return 4+2+msg->L;
} }
/* Pack CQI following 3GPP TS 36.212 Tables 5.2.3.3.1-1 and 5.2.3.3.1-2 */
int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4); srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4);
return 4;
if (msg->pmi_present) {
if (msg->four_antenna_ports) {
if (msg->rank_is_not_one) {
srslte_bit_unpack(msg->spatial_diff_cqi, &body_ptr, 3);
}
srslte_bit_unpack(msg->pmi, &body_ptr, 4);
} else {
if (msg->rank_is_not_one) {
srslte_bit_unpack(msg->spatial_diff_cqi, &body_ptr, 3);
srslte_bit_unpack(msg->pmi, &body_ptr, 1);
} else {
srslte_bit_unpack(msg->pmi, &body_ptr, 2);
}
}
}
return (int)(body_ptr - buff);
} }
int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
@ -168,10 +187,27 @@ int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_u
return 4+2+msg->L; return 4+2+msg->L;
} }
/* Unpack CQI following 3GPP TS 36.212 Tables 5.2.3.3.1-1 and 5.2.3.3.1-2 */
int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_format2_wideband_t *msg) int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_format2_wideband_t *msg)
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); msg->wideband_cqi = (uint8_t) srslte_bit_pack(&body_ptr, 4);
if (msg->pmi_present) {
if (msg->four_antenna_ports) {
if (msg->rank_is_not_one) {
msg->spatial_diff_cqi = (uint8_t) srslte_bit_pack(&body_ptr, 3);
}
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 4);
} else {
if (msg->rank_is_not_one) {
msg->spatial_diff_cqi = (uint8_t) srslte_bit_pack(&body_ptr, 3);
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 1);
} else {
msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 2);
}
}
}
return 4; return 4;
} }
@ -203,7 +239,26 @@ int srslte_cqi_size(srslte_cqi_value_t *value) {
switch(value->type) { switch(value->type) {
case SRSLTE_CQI_TYPE_WIDEBAND: case SRSLTE_CQI_TYPE_WIDEBAND:
/* Compute size according to 3GPP TS 36.212 Tables 5.2.3.3.1-1 and 5.2.3.3.1-2 */
size = 4; size = 4;
if (value->wideband.pmi_present) {
if (value->wideband.four_antenna_ports) {
if (value->wideband.rank_is_not_one) {
size += 3; // Differential
} else {
size += 0; // Differential
}
size += 4; // PMI
} else {
if (value->wideband.rank_is_not_one) {
size += 3; // Differential
size += 1; // PMI
} else {
size += 0; // Differential
size += 2; // PMI
}
}
}
break; break;
case SRSLTE_CQI_TYPE_SUBBAND: case SRSLTE_CQI_TYPE_SUBBAND:
size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1; size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1;
@ -398,3 +453,11 @@ int srslte_cqi_hl_get_no_subbands(int nof_prb)
return 0; return 0;
} }
} }
void srslte_cqi_to_str(const uint8_t *cqi_value, int cqi_len, char *str, int str_len) {
int i = 0;
for (i = 0; i < cqi_len && i < (str_len - 1); i++) {
str[i] = (cqi_value[i] == 0)?(char)'0':(char)'1';
}
str[i] = '\0';
}

@ -612,8 +612,6 @@ int srslte_pusch_decode(srslte_pusch_t *q,
if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL && cqi_value->subband_hl.ri_present) { if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL && cqi_value->subband_hl.ri_present) {
cqi_value->subband_hl.rank_is_not_one = false; cqi_value->subband_hl.rank_is_not_one = false;
uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1; uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1;
} else {
uci_data->uci_ri_len = 0;
} }
uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value);
} }

@ -274,9 +274,6 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS],
uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS])
{ {
uint8_t uci_buffer[SRSLTE_CQI_MAX_BITS];
uint8_t uci_buffer_len = 0;
if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) {
pucch_bits[0] = uci_data->uci_ack; pucch_bits[0] = uci_data->uci_ack;
pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a
@ -284,22 +281,12 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format
if (format >= SRSLTE_PUCCH_FORMAT_2) { if (format >= SRSLTE_PUCCH_FORMAT_2) {
/* Put RI (goes alone) */ /* Put RI (goes alone) */
if (uci_data->ri_periodic_report) { if (uci_data->ri_periodic_report) {
uci_buffer[0] = uci_data->uci_ri; // It assumes only 1 bit of RI uint8_t temp[2] = {uci_data->uci_ri, 0};
uci_buffer_len += uci_data->uci_ri_len; srslte_uci_encode_cqi_pucch(temp, uci_data->uci_ri_len, pucch_bits);
} else { } else {
/* Append CQI */ /* Put CQI Report*/
memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits);
uci_buffer_len += uci_data->uci_cqi_len;
/* Append Differential CQI */
memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len);
uci_buffer_len += uci_data->uci_dif_cqi_len;
/* Append PMI */
memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len);
uci_buffer_len += uci_data->uci_pmi_len;
} }
srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits);
if (format > SRSLTE_PUCCH_FORMAT_2) { if (format > SRSLTE_PUCCH_FORMAT_2) {
pucch2_bits[0] = uci_data->uci_ack; pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a

@ -444,10 +444,9 @@ unlock:
int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
{ {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data = {0};
bzero(&uci_data, sizeof(srslte_uci_data_t)); uint32_t wideband_cqi_value = 0, wideband_pmi = 0;
bool wideband_pmi_present = false;
uint32_t wideband_cqi_value = 0;
uint32_t n_rb_ho = 0; uint32_t n_rb_ho = 0;
for (uint32_t i=0;i<nof_pusch;i++) { for (uint32_t i=0;i<nof_pusch;i++) {
@ -481,8 +480,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
cqi_enabled = true; cqi_enabled = true;
if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3; cqi_value.wideband.pmi_present = true;
uci_data.uci_pmi_len = 2;
} }
} else if (grants[i].grant.cqi_request) { } else if (grants[i].grant.cqi_request) {
cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
@ -552,9 +550,15 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
if (cqi_enabled) { if (cqi_enabled) {
if (ue_db[rnti].cqi_en) { if (ue_db[rnti].cqi_en) {
wideband_cqi_value = cqi_value.wideband.wideband_cqi; wideband_cqi_value = cqi_value.wideband.wideband_cqi;
if (cqi_value.wideband.pmi_present) {
wideband_pmi_present = true;
wideband_pmi = cqi_value.wideband.pmi;
}
} else if (grants[i].grant.cqi_request) { } else if (grants[i].grant.cqi_request) {
wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0;
if (cqi_value.subband_hl.pmi_present) { if (cqi_value.subband_hl.pmi_present) {
wideband_pmi_present = true;
wideband_pmi = cqi_value.subband_hl.pmi;
if (cqi_value.subband_hl.rank_is_not_one) { if (cqi_value.subband_hl.rank_is_not_one) {
Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n", 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.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1,
@ -569,7 +573,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N); cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N);
} }
} }
snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, 64);
//snprintf(cqi_str, 64, ", cqi=%s", wideband_cqi_value);
} }
float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest)); float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest));
@ -587,7 +592,7 @@ 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, 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%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%s%s%s\n",
rnti, phy_grant.n_prb[0], phy_grant.n_prb[0] + phy_grant.L_prb, 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, phy_grant.mcs.tbs / 8, phy_grant.mcs.idx, grants[i].grant.rv_idx,
snr_db, snr_db,
@ -596,6 +601,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
(acks_pending[0] || acks_pending[1]) ? ", ack=" : "", (acks_pending[0] || acks_pending[1]) ? ", ack=" : "",
(acks_pending[0]) ? (uci_data.uci_ack ? "1" : "0") : "", (acks_pending[0]) ? (uci_data.uci_ack ? "1" : "0") : "",
(acks_pending[1]) ? (uci_data.uci_ack_2 ? "1" : "0") : "", (acks_pending[1]) ? (uci_data.uci_ack_2 ? "1" : "0") : "",
uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
uci_data.uci_cqi_len > 0 ? cqi_str : "", uci_data.uci_cqi_len > 0 ? cqi_str : "",
uci_data.uci_ri_len > 0 ? ((uci_data.uci_ri == 0) ? ", ri=0" : ", ri=1") : "", uci_data.uci_ri_len > 0 ? ((uci_data.uci_ri == 0) ? ", ri=0" : ", ri=1") : "",
timestr); timestr);
@ -631,10 +637,10 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
if (uci_data.uci_ri_len > 0 && crc_res) { if (uci_data.uci_ri_len > 0 && crc_res) {
phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri);
} }
if (cqi_value.subband_hl.pmi_present && crc_res) { if (wideband_pmi_present && crc_res) {
phy->mac->pmi_info(tti_rx, rnti, cqi_value.subband_hl.pmi); phy->mac->pmi_info(tti_rx, rnti, wideband_pmi);
} }
ue_db[rnti].
// Save metrics stats // Save metrics stats
ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch)); ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch));
} }
@ -652,8 +658,7 @@ int phch_worker::decode_pucch()
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { 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 // Check if user needs to receive PUCCH
bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false, bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false;
needs_ri = false;
uint32_t last_n_pdcch = 0; uint32_t last_n_pdcch = 0;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
@ -672,25 +677,23 @@ int phch_worker::decode_pucch()
uci_data.uci_ack_len++; uci_data.uci_ack_len++;
} }
} }
srslte_cqi_value_t cqi_value; srslte_cqi_value_t cqi_value = {0};
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; 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; 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].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)) { 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_pucch = true;
needs_ri = true;
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
uci_data.ri_periodic_report = true; uci_data.ri_periodic_report = true;
} else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { } else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
needs_pucch = true; needs_pucch = true;
needs_cqi = true; needs_cqi = true;
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; 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) { if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3; cqi_value.wideband.pmi_present = true;
uci_data.uci_pmi_len = 2;
} }
uci_data.uci_cqi_len = (uint32_t) srslte_cqi_size(&cqi_value);
} }
} }
@ -714,7 +717,7 @@ int phch_worker::decode_pucch()
char cqi_ri_str[64] = {0}; char cqi_ri_str[64] = {0};
if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) { if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) {
if (uci_data.uci_ri_len && needs_ri) { if (uci_data.ri_periodic_report) {
phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri);
sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri);
} else if (uci_data.uci_cqi_len && needs_cqi) { } else if (uci_data.uci_cqi_len && needs_cqi) {
@ -722,15 +725,10 @@ int phch_worker::decode_pucch()
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
if (uci_data.uci_pmi_len) { if (cqi_value.type == SRSLTE_CQI_TYPE_WIDEBAND && cqi_value.wideband.pmi_present) {
uint32_t packed_pmi = uci_data.uci_pmi[0]; phy->mac->pmi_info(tti_rx, rnti, cqi_value.wideband.pmi);
if (uci_data.uci_pmi_len > 1) { sprintf(cqi_ri_str, "%s, pmi=%d", cqi_ri_str, cqi_value.wideband.pmi);
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);
} }
} }
} }
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%s\n",
@ -740,7 +738,7 @@ int phch_worker::decode_pucch()
(uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"", (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"):"", (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"",
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
(needs_cqi || needs_ri)?cqi_ri_str:""); (needs_cqi || uci_data.ri_periodic_report)?cqi_ri_str:"");
// Notify MAC of RL status // Notify MAC of RL status

@ -76,7 +76,7 @@ private:
/* Internal methods */ /* Internal methods */
bool extract_fft_and_pdcch_llr(); bool extract_fft_and_pdcch_llr();
void compute_ri(); void compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr);
/* ... for DL */ /* ... for DL */
bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant);

@ -382,39 +382,21 @@ void phch_worker::work_imp()
#endif #endif
} }
void phch_worker::compute_ri() { void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) {
if (uci_data.uci_ri_len > 0) { if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) {
/* Do nothing */
} else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) {
if (ue_dl.nof_rx_antennas > 1) { if (ue_dl.nof_rx_antennas > 1) {
/* If 2 ort more receiving antennas, select RI */ /* If 2 ort more receiving antennas, select RI */
float cn = 0.0f; float cn = 0.0f;
srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); srslte_ue_dl_ri_select(&ue_dl, ri, &cn);
Info("RI select %d layers, κ=%fdB\n", uci_data.uci_ri + 1, cn); Debug("TM3 RI select %d layers, κ=%fdB\n", (*ri) + 1, cn);
} else { } else {
/* If only one receiving antenna, force RI for 1 layer */ /* If only one receiving antenna, force RI for 1 layer */
uci_data.uci_ri = 0; uci_data.uci_ri = 0;
Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n");
} }
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
float sinr = 0.0f; srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr);
uint8 packed_pmi = 0; Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]]));
srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr);
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;
}
srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len);
Info("ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]]));
/* If only one antenna in TM4 print limitation warning */
if (ue_dl.nof_rx_antennas < 2) {
Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi);
}
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} }
} }
@ -868,22 +850,27 @@ void phch_worker::set_uci_periodic_cqi()
int cqi_fixed = phy->args->cqi_fixed; int cqi_fixed = phy->args->cqi_fixed;
int cqi_max = phy->args->cqi_max; int cqi_max = phy->args->cqi_max;
uint8_t ri = (uint8_t) ue_dl.ri;
uint8_t pmi = (uint8_t) ue_dl.pmi[ri];
float sinr = ue_dl.sinr[ri][pmi];
if (period_cqi.configured && rnti_is_set) { 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))) { 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, PMI and SINR */
compute_ri(); compute_ri(&ri, &pmi, &sinr);
uci_data.uci_ri = ri;
uci_data.uci_ri_len = 1;
uci_data.ri_periodic_report = true; uci_data.ri_periodic_report = true;
Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); Debug("PUCCH: Periodic ri=%d\n", ri);
} else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) {
srslte_cqi_value_t cqi_report; srslte_cqi_value_t cqi_report = {0};
if (period_cqi.format_is_subband) { if (period_cqi.format_is_subband) {
// TODO: Implement subband periodic reports // TODO: Implement subband periodic reports
cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND;
cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); cqi_report.subband.subband_cqi = srslte_cqi_from_snr(phy->avg_snr_db);
cqi_report.subband.subband_label = 0; cqi_report.subband.subband_label = 0;
log_h->console("Warning: Subband CQI periodic reports not implemented\n"); log_h->console("Warning: Subband CQI periodic reports not implemented\n");
Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db); Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.subband.subband_cqi, phy->avg_snr_db);
} else { } else {
cqi_report.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_report.type = SRSLTE_CQI_TYPE_WIDEBAND;
if (cqi_fixed >= 0) { if (cqi_fixed >= 0) {
@ -894,19 +881,14 @@ void phch_worker::set_uci_periodic_cqi()
if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) { if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) {
cqi_report.wideband.wideband_cqi = cqi_max; cqi_report.wideband.wideband_cqi = cqi_max;
} }
Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
} cqi_report.wideband.pmi_present = true;
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { cqi_report.wideband.pmi = pmi;
if (ue_dl.ri == 0) { cqi_report.wideband.rank_is_not_one = (ri != 0);
uci_data.uci_pmi_len = 2;
} else {
uci_data.uci_pmi_len = 1;
uci_data.uci_dif_cqi_len = 3;
} }
uint8_t *ptr = uci_data.uci_pmi; Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db);
srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len);
} }
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); uci_data.uci_cqi_len = (uint32_t) srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
rar_cqi_request = false; rar_cqi_request = false;
} }
} }
@ -914,9 +896,13 @@ void phch_worker::set_uci_periodic_cqi()
void phch_worker::set_uci_aperiodic_cqi() void phch_worker::set_uci_aperiodic_cqi()
{ {
uint8_t ri = (uint8_t) ue_dl.ri;
uint8_t pmi = (uint8_t) ue_dl.pmi[ri];
float sinr = ue_dl.sinr[ri][pmi];
if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) {
/* Compute RI, PMI and SINR */ /* Compute RI, PMI and SINR */
compute_ri(); compute_ri(&ri, &pmi, &sinr);
switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) {
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30:
@ -1054,15 +1040,20 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec); snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec);
#endif #endif
char cqi_str[32] = "";
srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, 32);
uint8_t dummy[2] = {0,0}; uint8_t dummy[2] = {0,0};
log_h->info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d%s%s%s, cfo=%.1f KHz%s\n", log_h->info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d%s%s%s, cfo=%.1f KHz%s%s%s\n",
(tti + HARQ_DELAY_MS) % 10240, (tti + HARQ_DELAY_MS) % 10240,
grant->n_prb[0], grant->n_prb[0] + grant->L_prb, grant->n_prb[0], grant->n_prb[0] + grant->L_prb,
grant->mcs.tbs / 8, grant->mcs.idx, rv, grant->mcs.tbs / 8, grant->mcs.idx, rv,
uci_data.uci_ack_len > 0 ? (uci_data.uci_ack ? ", ack=1" : "0") : "", uci_data.uci_ack_len > 0 ? (uci_data.uci_ack ? ", ack=1" : "0") : "",
uci_data.uci_ack_len > 1 ? (uci_data.uci_ack_2 ? "1" : "0") : "", uci_data.uci_ack_len > 1 ? (uci_data.uci_ack_2 ? "1" : "0") : "",
uci_data.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "", uci_data.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "",
cfo * 15, timestr); cfo * 15, timestr,
uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
uci_data.uci_cqi_len > 0 ? cqi_str : "");
// Store metrics // Store metrics
ul_metrics.mcs = grant->mcs.idx; ul_metrics.mcs = grant->mcs.idx;
@ -1103,16 +1094,19 @@ 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 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); float gain = set_power(tx_power);
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f KHz%s\n", char str_cqi[32] = "";
(tti+4)%10240, srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, str_cqi, 32);
Info("PUCCH: tti_tx=%d, n_pucch=%d, n_prb=%d, ack=%s%s%s%s%s, sr=%s, cfo=%.1f KHz%s\n",
(tti + 4) % 10240,
ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, 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 > 0 ? (uci_data.uci_ack ? "1" : "0") : "no",
uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", 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.uci_ri_len > 0 ? (uci_data.uci_ri ? ", ri=1" : ", ri=0") : "",
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[1]?"1":"0"):"no", uci_data.uci_cqi_len > 0 ? ", cqi=" : "",
uci_data.uci_pmi_len>0?(uci_data.uci_pmi[0]?"1":"0"):"", uci_data.uci_cqi_len > 0 ? str_cqi : "",
uci_data.scheduling_request?"yes":"no", uci_data.scheduling_request ? "yes" : "no",
cfo*15, timestr); cfo * 15, timestr);
} }
if (uci_data.scheduling_request) { if (uci_data.scheduling_request) {

Loading…
Cancel
Save