mirror of https://github.com/PentHertz/srsLTE.git
Added Aperiodic mode 3-1 in enb and some more optimizations
This commit is contained in:
parent
0bd683b3c4
commit
8ab196901f
|
@ -141,6 +141,7 @@ SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q,
|
|||
uint32_t rv_idx,
|
||||
uint32_t current_tx_nb,
|
||||
uint8_t *data,
|
||||
srslte_cqi_value_t *cqi_value,
|
||||
srslte_uci_data_t *uci_data,
|
||||
uint32_t tti);
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q,
|
|||
float noise_estimate,
|
||||
uint16_t rnti,
|
||||
uint8_t *data,
|
||||
srslte_cqi_value_t *cqi_value,
|
||||
srslte_uci_data_t *uci_data);
|
||||
|
||||
SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q);
|
||||
|
|
|
@ -131,31 +131,25 @@ 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_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,
|
||||
SRSLTE_API 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 *ri_bits);
|
||||
|
||||
SRSLTE_API int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg,
|
||||
int16_t *q_bits,
|
||||
uint8_t *c_seq,
|
||||
float beta,
|
||||
uint32_t H_prime_total,
|
||||
uint32_t O_cqi,
|
||||
srslte_uci_bit_t *ri_bits,
|
||||
uint8_t *data);
|
||||
bool is_ri);
|
||||
|
||||
SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg,
|
||||
int16_t *q_bits,
|
||||
uint8_t *c_seq,
|
||||
float beta,
|
||||
uint32_t H_prime_total,
|
||||
uint32_t O_cqi,
|
||||
srslte_uci_bit_t *ack_ri_bits,
|
||||
uint8_t data[2],
|
||||
uint32_t nof_bits,
|
||||
bool is_ri);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -253,18 +253,22 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
|
|||
}
|
||||
}
|
||||
|
||||
void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer)
|
||||
void srslte_enb_ul_fft(srslte_enb_ul_t *q)
|
||||
{
|
||||
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])
|
||||
srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_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);
|
||||
|
||||
|
@ -273,7 +277,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);
|
||||
int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits, nof_bits);
|
||||
if (ret_val < 0) {
|
||||
fprintf(stderr,"Error decoding PUCCH\n");
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -286,16 +290,18 @@ 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]) {
|
||||
|
||||
int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_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);
|
||||
|
||||
// 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);
|
||||
ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits);
|
||||
}
|
||||
|
||||
// update schedulign request
|
||||
|
@ -305,12 +311,32 @@ 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];
|
||||
uci_data->uci_ack = pucch_bits[0];
|
||||
}
|
||||
|
||||
if (uci_data->uci_ack_len > 1) {
|
||||
uci_data->uci_ack_2 = pucch_bits[1];
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
@ -328,7 +354,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_uci_data_t *uci_data, uint32_t tti)
|
||||
uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti)
|
||||
{
|
||||
if (q->users[rnti]) {
|
||||
if (srslte_pusch_cfg(&q->pusch,
|
||||
|
@ -364,6 +390,7 @@ int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srs
|
|||
softbuffer, q->sf_symbols,
|
||||
q->ce, noise_power,
|
||||
rnti, data,
|
||||
cqi_value,
|
||||
uci_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -199,17 +199,44 @@ 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:
|
||||
return 4;
|
||||
size = 4;
|
||||
break;
|
||||
case SRSLTE_CQI_TYPE_SUBBAND:
|
||||
return 4+(value->subband.subband_label_2_bits)?2:1;
|
||||
size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1;
|
||||
break;
|
||||
case SRSLTE_CQI_TYPE_SUBBAND_UE:
|
||||
return 4+2+value->subband_ue.L;
|
||||
size = 4 + 2 + value->subband_ue.L;
|
||||
break;
|
||||
case SRSLTE_CQI_TYPE_SUBBAND_HL:
|
||||
return 4+2*value->subband_hl.N;
|
||||
/* 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 -1;
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool srslte_cqi_get_N(uint32_t I_cqi_pmi, uint32_t *N_p, uint32_t *N_offset) {
|
||||
|
|
|
@ -566,9 +566,9 @@ int srslte_pusch_decode(srslte_pusch_t *q,
|
|||
srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
||||
cf_t *sf_symbols,
|
||||
cf_t *ce, float noise_estimate, uint16_t rnti,
|
||||
uint8_t *data, srslte_uci_data_t *uci_data)
|
||||
uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data)
|
||||
{
|
||||
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
uint32_t n;
|
||||
|
||||
if (q != NULL &&
|
||||
|
@ -607,19 +607,42 @@ 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);
|
||||
|
||||
return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
// 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 ret;
|
||||
}
|
||||
|
||||
uint32_t srslte_pusch_last_noi(srslte_pusch_t *q) {
|
||||
|
|
|
@ -658,7 +658,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs
|
|||
if (cfg->cb_segm.tbs == 0) {
|
||||
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
|
||||
}
|
||||
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len);
|
||||
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);
|
||||
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_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri);
|
||||
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);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -756,13 +756,18 @@ 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 (uci_data.uci_ri_len > 0) {
|
||||
// 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;
|
||||
}
|
||||
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];
|
||||
}
|
||||
ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits);
|
||||
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);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -809,8 +814,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(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len,
|
||||
beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]);
|
||||
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);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
gettimeofday(&t[1], NULL);
|
||||
int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx);
|
||||
int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, NULL, &uci_data_rx);
|
||||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
if (r) {
|
||||
|
|
|
@ -103,26 +103,29 @@ 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 = 16;
|
||||
for (uint32_t w=0;w<nwords;w++) {
|
||||
q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int8_t));
|
||||
q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int16_t));
|
||||
uint8_t 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 *ptr = word;
|
||||
srslte_bit_unpack(w, &ptr, 4);
|
||||
srslte_uci_encode_cqi_pucch(word, 4, q->cqi_table[w]);
|
||||
for (int j=0;j<SRSLTE_UCI_CQI_CODED_PUCCH_B;j++) {
|
||||
q->cqi_table_s[w][j] = 2*q->cqi_table[w][j]-1;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) {
|
||||
uint32_t nwords = 16;
|
||||
uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH;
|
||||
for (uint32_t w=0;w<nwords;w++) {
|
||||
if (q->cqi_table[w]) {
|
||||
free(q->cqi_table[w]);
|
||||
|
@ -131,6 +134,8 @@ 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
|
||||
|
@ -151,17 +156,32 @@ 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 == 4 &&
|
||||
if (cqi_len < SRSLTE_UCI_MAX_CQI_LEN_PUCCH &&
|
||||
b_bits != NULL &&
|
||||
cqi_data != NULL)
|
||||
{
|
||||
uint32_t max_w = 0;
|
||||
int32_t max_corr = INT32_MIN;
|
||||
for (uint32_t w=0;w<16;w++) {
|
||||
int32_t max_corr = INT32_MIN;
|
||||
uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH;
|
||||
for (uint32_t w=0;w<nwords;w += 1<<(SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len)) {
|
||||
|
||||
// Calculate correlation with pregenerated word and select maximum
|
||||
int32_t corr = srslte_vec_dot_prod_sss(q->cqi_table_s[w], b_bits, SRSLTE_UCI_CQI_CODED_PUCCH_B);
|
||||
|
@ -172,7 +192,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, cqi_len);
|
||||
srslte_bit_unpack(max_w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH);
|
||||
|
||||
INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr);
|
||||
return max_corr;
|
||||
|
@ -586,9 +606,7 @@ 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
|
||||
*/
|
||||
#ifndef MIMO_ENB
|
||||
|
||||
static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos)
|
||||
static int32_t decode_ri_ack_1bit(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;
|
||||
|
@ -598,33 +616,8 @@ static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *
|
|||
|
||||
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;
|
||||
|
||||
if (beta < 0) {
|
||||
fprintf(stderr, "Error beta is reserved\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
|
||||
|
||||
// Use the same interleaver function to get the HARQ bit position
|
||||
for (uint32_t i=0;i<Qprime;i++) {
|
||||
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
|
||||
rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, &ack_bits[cfg->grant.Qm*i]);
|
||||
}
|
||||
|
||||
if (acks) {
|
||||
acks[0] = rx_ack>0;
|
||||
}
|
||||
return (int) Qprime;
|
||||
}
|
||||
#else
|
||||
|
||||
static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3])
|
||||
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])
|
||||
{
|
||||
uint32_t p0 = pos[Qm * 0 + 0].position;
|
||||
uint32_t p1 = pos[Qm * 0 + 1].position;
|
||||
|
@ -645,118 +638,91 @@ static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos
|
|||
data[2] -= q2 + q5;
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
/* 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) {
|
||||
if (beta < 0) {
|
||||
fprintf(stderr, "Error beta is reserved\n");
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
uint32_t Qprime = Q_prime_ri_ack(cfg, data_len, O_cqi, beta);
|
||||
srslte_uci_bit_type_t q_encoded_bits[18];
|
||||
|
||||
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
|
||||
uint32_t nof_encoded_bits = encode_ri_ack(data, data_len, q_encoded_bits, cfg->grant.Qm);
|
||||
|
||||
// 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 (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]);
|
||||
}
|
||||
|
||||
if (acks) {
|
||||
acks[0] = (uint8_t)(acks_sum[0] > 0);
|
||||
acks[1] = (uint8_t)(acks_sum[1] > 0);
|
||||
// TODO: Do something with acks_sum[2]
|
||||
}
|
||||
return (int) Qprime;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
|
||||
* Currently only supporting 1-bit HARQ
|
||||
*/
|
||||
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks,
|
||||
uint32_t O_cqi, float beta, uint32_t H_prime_total,
|
||||
srslte_uci_bit_t *ack_bits)
|
||||
{
|
||||
if (beta < 0) {
|
||||
fprintf(stderr, "Error beta is reserved\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
|
||||
srslte_uci_bit_type_t q_encoded_bits[18];
|
||||
|
||||
uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm);
|
||||
|
||||
for (uint32_t i=0;i<Qprime;i++) {
|
||||
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
|
||||
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]);
|
||||
}
|
||||
|
||||
return (int) Qprime;
|
||||
}
|
||||
|
||||
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
|
||||
/* Decode UCI ACK/RI bits as described in 5.2.2.6 of 36.212
|
||||
* Currently only supporting 1-bit 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)
|
||||
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)
|
||||
{
|
||||
int32_t ri_sum[3] = {0, 0, 0};
|
||||
|
||||
int32_t 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, 1, O_cqi, beta);
|
||||
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_bits, 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_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
|
||||
if ((i % 3 == 0) && i > 0) {
|
||||
//decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
*data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0);
|
||||
data[0] = (uint8_t) (sum[0] > 0);
|
||||
if (nof_bits == 2) {
|
||||
data[1] = (uint8_t) (sum[1] > 0);
|
||||
}
|
||||
|
||||
return (int) Qprime;
|
||||
}
|
||||
|
||||
|
||||
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
|
||||
* Currently only supporting 1-bit RI
|
||||
*/
|
||||
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
|
||||
uint8_t ri,
|
||||
uint32_t O_cqi, float beta, uint32_t H_prime_total,
|
||||
srslte_uci_bit_t *ri_bits)
|
||||
{
|
||||
// FIXME: It supports RI of 1 bit only
|
||||
uint8_t data[2] = {ri, 0};
|
||||
if (beta < 0) {
|
||||
fprintf(stderr, "Error beta is reserved\n");
|
||||
return -1;
|
||||
}
|
||||
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
|
||||
srslte_uci_bit_type_t q_encoded_bits[18];
|
||||
|
||||
uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm);
|
||||
|
||||
for (uint32_t i=0;i<Qprime;i++) {
|
||||
uci_ulsch_interleave_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
|
||||
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]);
|
||||
}
|
||||
|
||||
return (int) Qprime;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -725,7 +725,8 @@ 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;
|
||||
if (_sinr > best_sinr + 0.1) {
|
||||
/* 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) {
|
||||
best_sinr = _sinr;
|
||||
best_pmi = (uint8_t) q->pmi[nof_layers - 1];
|
||||
best_ri = (uint8_t) (nof_layers - 1);
|
||||
|
|
|
@ -88,16 +88,19 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
|
|||
pthread_mutex_init(&mutex, NULL);
|
||||
|
||||
// Init cell here
|
||||
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;
|
||||
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));
|
||||
}
|
||||
if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating ENB DL\n");
|
||||
|
@ -107,7 +110,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, phy->cell.nof_prb)) {
|
||||
if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], phy->cell.nof_prb)) {
|
||||
fprintf(stderr, "Error initiating ENB UL\n");
|
||||
return;
|
||||
}
|
||||
|
@ -154,12 +157,12 @@ void phch_worker::stop()
|
|||
|
||||
srslte_enb_dl_free(&enb_dl);
|
||||
srslte_enb_ul_free(&enb_ul);
|
||||
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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
@ -171,9 +174,9 @@ void phch_worker::reset()
|
|||
ue_db.clear();
|
||||
}
|
||||
|
||||
cf_t* phch_worker::get_buffer_rx()
|
||||
cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx)
|
||||
{
|
||||
return signal_buffer_rx;
|
||||
return signal_buffer_rx[antenna_idx];
|
||||
}
|
||||
|
||||
void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_)
|
||||
|
@ -214,12 +217,29 @@ 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,
|
||||
uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack)
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated)
|
||||
{
|
||||
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;
|
||||
|
@ -237,6 +257,16 @@ 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");
|
||||
}
|
||||
|
@ -278,7 +308,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;
|
||||
|
@ -293,7 +323,7 @@ void phch_worker::work_imp()
|
|||
}
|
||||
|
||||
// Process UL signal
|
||||
srslte_enb_ul_fft(&enb_ul, signal_buffer_rx);
|
||||
srslte_enb_ul_fft(&enb_ul);
|
||||
|
||||
// Decode pending UL grants for the tti they were scheduled
|
||||
decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants);
|
||||
|
@ -335,15 +365,22 @@ void phch_worker::work_imp()
|
|||
phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl)));
|
||||
for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) {
|
||||
// SI-RNTI and RAR-RNTI do not have ACK
|
||||
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);
|
||||
uint16_t rnti = dl_grants[t_tx_dl].sched_grants[i].rnti;
|
||||
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) {
|
||||
/* For each TB */
|
||||
for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) {
|
||||
/* If TB enabled, set pending ACK */
|
||||
if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) {
|
||||
phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), rnti, tb_idx, dl_grants[t_tx_dl].sched_grants[i].location.ncce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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[0], SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
|
||||
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, 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);
|
||||
|
@ -387,24 +424,39 @@ 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
|
||||
if (phy->ack_is_pending(t_rx, rnti)) {
|
||||
uci_data.uci_ack_len = 1;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure PUSCH CQI channel
|
||||
srslte_cqi_value_t cqi_value;
|
||||
srslte_cqi_value_t cqi_value = {0};
|
||||
bool cqi_enabled = false;
|
||||
if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
|
||||
#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)) {
|
||||
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
|
||||
cqi_enabled = true;
|
||||
} else if (grants[i].grant.cqi_request) {
|
||||
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) {
|
||||
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;
|
||||
|
@ -412,22 +464,6 @@ 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;
|
||||
}
|
||||
|
@ -436,6 +472,7 @@ 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 {
|
||||
|
@ -457,11 +494,24 @@ 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);
|
||||
}
|
||||
|
@ -481,14 +531,16 @@ 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\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\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>0?(uci_data.uci_ack?", ack=1":", ack=0"):"",
|
||||
(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_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
|
||||
|
@ -503,17 +555,28 @@ 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);
|
||||
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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify MAC of UL SNR and DL CQI
|
||||
// Notify MAC of UL SNR, DL CQI and DL RI
|
||||
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));
|
||||
|
@ -532,7 +595,8 @@ 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=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;
|
||||
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
||||
|
||||
|
@ -544,18 +608,32 @@ int phch_worker::decode_pucch()
|
|||
}
|
||||
}
|
||||
|
||||
if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) {
|
||||
needs_pucch = true;
|
||||
needs_ack = true;
|
||||
uci_data.uci_ack_len = 1;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
srslte_cqi_value_t cqi_value;
|
||||
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)) {
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,26 +642,48 @@ int phch_worker::decode_pucch()
|
|||
fprintf(stderr, "Error getting PUCCH\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
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 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.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);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n",
|
||||
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%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,
|
||||
needs_ack?(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"):"",
|
||||
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
|
||||
needs_cqi?cqi_str:"");
|
||||
(needs_cqi || needs_ri)?cqi_ri_str:"");
|
||||
|
||||
|
||||
// Notify MAC of RL status
|
||||
|
@ -642,25 +742,16 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra
|
|||
int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
|
||||
{
|
||||
for (uint32_t i=0;i<nof_grants;i++) {
|
||||
uint16_t rnti = grants[i].rnti;
|
||||
srslte_enb_dl_pdsch_t *grant = &grants[i];
|
||||
uint16_t rnti = grant->rnti;
|
||||
if (rnti) {
|
||||
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)) {
|
||||
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_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(format),
|
||||
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),
|
||||
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx_dl);
|
||||
}
|
||||
}
|
||||
|
@ -668,9 +759,8 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
|
|||
return 0;
|
||||
}
|
||||
|
||||
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
|
||||
{
|
||||
for (uint32_t i=0;i<nof_grants;i++) {
|
||||
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) {
|
||||
for (uint32_t i = 0; i < nof_grants; i++) {
|
||||
uint16_t rnti = grants[i].rnti;
|
||||
if (rnti) {
|
||||
|
||||
|
@ -678,53 +768,103 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
|
|||
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) {
|
||||
rnti_is_user = false;
|
||||
}
|
||||
|
||||
/* Mimo type (tx scheme) shall be single or tx diversity by default */
|
||||
srslte_mimo_type_t mimo_type = (enb_dl.cell.nof_ports == 1) ? SRSLTE_MIMO_TYPE_SINGLE_ANTENNA
|
||||
: SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
srslte_ra_dl_grant_t phy_grant;
|
||||
srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant);
|
||||
|
||||
char grant_str[64];
|
||||
switch(grants[i].grant.alloc_type) {
|
||||
switch (grants[i].grant.alloc_type) {
|
||||
case SRSLTE_RA_ALLOC_TYPE0:
|
||||
sprintf(grant_str, "mask=0x%x",grants[i].grant.type0_alloc.rbg_bitmask);
|
||||
break;
|
||||
sprintf(grant_str, "mask=0x%x", grants[i].grant.type0_alloc.rbg_bitmask);
|
||||
break;
|
||||
case SRSLTE_RA_ALLOC_TYPE1:
|
||||
sprintf(grant_str, "mask=0x%x",grants[i].grant.type1_alloc.vrb_bitmask);
|
||||
break;
|
||||
sprintf(grant_str, "mask=0x%x", grants[i].grant.type1_alloc.vrb_bitmask);
|
||||
break;
|
||||
default:
|
||||
sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start);
|
||||
break;
|
||||
sprintf(grant_str, "rb_start=%d", grants[i].grant.type2_alloc.RB_start);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
srslte_dci_format_t dci_format = grants[i].dci_format;
|
||||
switch (dci_format) {
|
||||
case SRSLTE_DCI_FORMAT1:
|
||||
case SRSLTE_DCI_FORMAT1A:
|
||||
/* Do nothing, it keeps default */
|
||||
break;
|
||||
case SRSLTE_DCI_FORMAT2A:
|
||||
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
||||
}
|
||||
break;
|
||||
case SRSLTE_DCI_FORMAT2:
|
||||
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
|
||||
if (phy_grant.pinfo == 0) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
} else {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
}
|
||||
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) {
|
||||
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
}
|
||||
break;
|
||||
case SRSLTE_DCI_FORMAT0:
|
||||
case SRSLTE_DCI_FORMAT1C:
|
||||
case SRSLTE_DCI_FORMAT1B:
|
||||
case SRSLTE_DCI_FORMAT1D:
|
||||
case SRSLTE_DCI_FORMAT2B:
|
||||
default:
|
||||
Error("Not implemented/Undefined DCI format (%d)\n", dci_format);
|
||||
}
|
||||
|
||||
if (LOG_THIS(rnti)) {
|
||||
uint8_t x = 0;
|
||||
uint8_t *ptr = grants[i].data;
|
||||
uint8_t *ptr = grants[i].data[0];
|
||||
uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8;
|
||||
if (!ptr) {
|
||||
ptr = &x;
|
||||
len = 1;
|
||||
}
|
||||
char pinfo_str[16] = {0};
|
||||
if (dci_format == SRSLTE_DCI_FORMAT2) {
|
||||
snprintf(pinfo_str, 15, ", pinfo=%x", phy_grant.pinfo);
|
||||
}
|
||||
char tbstr[SRSLTE_MAX_TB][128];
|
||||
for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||
if (phy_grant.tb_en[tb]) {
|
||||
snprintf(tbstr[tb], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d%s%s",
|
||||
tb,
|
||||
phy_grant.mcs[tb].tbs / 8,
|
||||
phy_grant.mcs[tb].idx,
|
||||
(tb == 0) ? grants[i].grant.rv_idx : grants[i].grant.rv_idx_1,
|
||||
grants[i].softbuffers[tb]==NULL?", \e[31msoftbuffer=NULL\e[0m":"",
|
||||
grants[i].data[tb]==NULL?", \e[31mdata=NULL\e[0m":"");
|
||||
} else {
|
||||
tbstr[tb][0] = '\0';
|
||||
}
|
||||
}
|
||||
log_h->info_hex(ptr, len,
|
||||
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, 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);
|
||||
"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]);
|
||||
}
|
||||
|
||||
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};
|
||||
int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1};
|
||||
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// Save metrics stats
|
||||
// Save metrics stats
|
||||
ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx);
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1142,7 +1142,11 @@ 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;
|
||||
phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
phy_cfg->cqi_report_cnfg.report_periodic_present = true;
|
||||
phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true;
|
||||
|
|
|
@ -859,7 +859,9 @@ 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))) {
|
||||
|
@ -902,6 +904,9 @@ 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
|
||||
|
@ -939,9 +944,6 @@ 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
|
||||
|
@ -972,9 +974,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=%d/%d, SINR=%2.1f dB, for %d subbands\n",
|
||||
cqi_report.wideband.wideband_cqi,
|
||||
phy->avg_snr_db, cqi_report.subband_hl.N);
|
||||
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);
|
||||
}
|
||||
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue