mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next_mimo' into next
This commit is contained in:
commit
3e712d6a57
|
@ -774,11 +774,13 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
|
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
|
||||||
for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
if (pdsch_cfg.grant.tb_en[tb]) {
|
||||||
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
|
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
|
||||||
data[tb][i] = (uint8_t) rand();
|
data[tb][i] = (uint8_t) rand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Uncomment this to transmit on sf 0 and 5 only */
|
/* Uncomment this to transmit on sf 0 and 5 only */
|
||||||
if (sf_idx != 0 && sf_idx != 5) {
|
if (sf_idx != 0 && sf_idx != 5) {
|
||||||
send_data = true;
|
send_data = true;
|
||||||
|
@ -832,13 +834,15 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
if (net_port > 0 && net_packet_ready) {
|
if (net_port > 0 && net_packet_ready) {
|
||||||
if (null_file_sink) {
|
if (null_file_sink) {
|
||||||
for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
if (pdsch_cfg.grant.tb_en[tb]) {
|
||||||
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
|
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
|
||||||
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
|
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
|
||||||
fprintf(stderr, "Error sending data through UDP socket\n");
|
fprintf(stderr, "Error sending data through UDP socket\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
net_packet_ready = false;
|
net_packet_ready = false;
|
||||||
sem_post(&net_sem);
|
sem_post(&net_sem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -518,7 +518,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
// Variables for measurements
|
// Variables for measurements
|
||||||
uint32_t nframes=0;
|
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,
|
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;
|
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
|
||||||
bool decode_pdsch = false;
|
bool decode_pdsch = false;
|
||||||
|
@ -641,9 +641,10 @@ int main(int argc, char **argv) {
|
||||||
/* Send data if socket active */
|
/* Send data if socket active */
|
||||||
if (prog_args.net_port > 0) {
|
if (prog_args.net_port > 0) {
|
||||||
// FIXME: UDP Data transmission does not work
|
// FIXME: UDP Data transmission does not work
|
||||||
for (uint32_t tb = 0; tb < ue_dl.pdsch_cfg.grant.nof_tb; tb++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
if (ue_dl.pdsch_cfg.grant.tb_en[tb]) {
|
||||||
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
|
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +705,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
/* Print basic Parameters */
|
/* Print basic Parameters */
|
||||||
PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers);
|
PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers);
|
||||||
PRINT_LINE("nof codewords: %d", ue_dl.pdsch_cfg.grant.nof_tb);
|
PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant));
|
||||||
PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000);
|
PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000);
|
||||||
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
|
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
|
||||||
PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate);
|
PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate);
|
||||||
|
|
|
@ -281,6 +281,8 @@ public:
|
||||||
bool last_ndi[SRSLTE_MAX_CODEWORDS];
|
bool last_ndi[SRSLTE_MAX_CODEWORDS];
|
||||||
uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
|
uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
|
||||||
int rv[SRSLTE_MAX_CODEWORDS];
|
int rv[SRSLTE_MAX_CODEWORDS];
|
||||||
|
bool tb_en[SRSLTE_MAX_CODEWORDS];
|
||||||
|
bool tb_cw_swap;
|
||||||
uint16_t rnti;
|
uint16_t rnti;
|
||||||
bool is_from_rar;
|
bool is_from_rar;
|
||||||
bool is_sps_release;
|
bool is_sps_release;
|
||||||
|
|
|
@ -41,11 +41,14 @@
|
||||||
#include "srslte/phy/common/phy_common.h"
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
|
||||||
#define SRSLTE_CQI_MAX_BITS 64
|
#define SRSLTE_CQI_MAX_BITS 64
|
||||||
|
#define SRSLTE_DIF_CQI_MAX_BITS 3
|
||||||
|
#define SRSLTE_PMI_MAX_BITS 4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool configured;
|
bool configured;
|
||||||
uint32_t pmi_idx;
|
uint32_t pmi_idx;
|
||||||
uint32_t ri_idx;
|
uint32_t ri_idx;
|
||||||
|
bool ri_idx_present;
|
||||||
bool simul_cqi_ack;
|
bool simul_cqi_ack;
|
||||||
bool format_is_subband;
|
bool format_is_subband;
|
||||||
uint32_t subband_size;
|
uint32_t subband_size;
|
||||||
|
|
|
@ -104,10 +104,12 @@ typedef struct SRSLTE_API {
|
||||||
uint32_t nof_prb;
|
uint32_t nof_prb;
|
||||||
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
|
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
|
||||||
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
|
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
|
||||||
uint32_t nof_tb;
|
bool tb_en[SRSLTE_MAX_CODEWORDS];
|
||||||
uint32_t pinfo;
|
uint32_t pinfo;
|
||||||
} srslte_ra_dl_grant_t;
|
} srslte_ra_dl_grant_t;
|
||||||
|
|
||||||
|
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
|
||||||
|
|
||||||
/** Unpacked DCI message for DL grant */
|
/** Unpacked DCI message for DL grant */
|
||||||
typedef struct SRSLTE_API {
|
typedef struct SRSLTE_API {
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,10 @@ 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
|
||||||
|
@ -119,7 +123,8 @@ SRSLTE_API int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q,
|
||||||
bool *cqi_ack);
|
bool *cqi_ack);
|
||||||
|
|
||||||
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
|
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
|
||||||
uint8_t data,
|
uint8_t acks[2],
|
||||||
|
uint32_t nof_acks,
|
||||||
uint32_t O_cqi,
|
uint32_t O_cqi,
|
||||||
float beta,
|
float beta,
|
||||||
uint32_t H_prime_total,
|
uint32_t H_prime_total,
|
||||||
|
@ -132,7 +137,8 @@ SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg,
|
||||||
uint32_t H_prime_total,
|
uint32_t H_prime_total,
|
||||||
uint32_t O_cqi,
|
uint32_t O_cqi,
|
||||||
srslte_uci_bit_t *ack_bits,
|
srslte_uci_bit_t *ack_bits,
|
||||||
uint8_t *data);
|
uint8_t acks[2],
|
||||||
|
uint32_t nof_acks);
|
||||||
|
|
||||||
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
|
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
|
||||||
uint8_t data,
|
uint8_t data,
|
||||||
|
|
|
@ -182,12 +182,12 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
|
||||||
bool acks[SRSLTE_MAX_CODEWORDS]);
|
bool acks[SRSLTE_MAX_CODEWORDS]);
|
||||||
|
|
||||||
SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q,
|
SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q,
|
||||||
uint32_t *ri,
|
uint8_t *ri,
|
||||||
uint32_t *pmi,
|
uint8_t *pmi,
|
||||||
float *current_sinr);
|
float *current_sinr);
|
||||||
|
|
||||||
SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q,
|
SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q,
|
||||||
uint32_t *ri,
|
uint8_t *ri,
|
||||||
float *cn);
|
float *cn);
|
||||||
|
|
||||||
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
|
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
|
||||||
|
|
|
@ -427,17 +427,19 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g
|
||||||
int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
|
int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
|
||||||
uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type,
|
uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type,
|
||||||
uint32_t pmi) {
|
uint32_t pmi) {
|
||||||
if (cfg) {
|
if (cfg && grant) {
|
||||||
if (grant) {
|
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
|
||||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < grant->nof_tb; i++) {
|
|
||||||
if (srslte_cbsegm(&cfg->cb_segm[i], (uint32_t) cfg->grant.mcs[i].tbs)) {
|
for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
|
||||||
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[i].tbs);
|
if (grant->tb_en[cw]) {
|
||||||
|
if (srslte_cbsegm(&cfg->cb_segm[cw], (uint32_t) cfg->grant.mcs[cw].tbs)) {
|
||||||
|
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[cw].tbs);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits);
|
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits);
|
||||||
|
|
||||||
cfg->sf_idx = sf_idx;
|
cfg->sf_idx = sf_idx;
|
||||||
|
@ -447,33 +449,36 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
|
||||||
/* Check and configure PDSCH transmission modes */
|
/* Check and configure PDSCH transmission modes */
|
||||||
switch(mimo_type) {
|
switch(mimo_type) {
|
||||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||||
if (grant->nof_tb != 1) {
|
if (nof_tb != 1) {
|
||||||
ERROR("Number of transport blocks is not supported for single transmission mode.");
|
ERROR("Wrong number of transport blocks (%d) for single antenna.", nof_tb);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
cfg->nof_layers = 1;
|
cfg->nof_layers = 1;
|
||||||
break;
|
break;
|
||||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||||
if (grant->nof_tb != 1) {
|
if (nof_tb != 1) {
|
||||||
ERROR("Number of transport blocks is not supported for transmit diversity mode.");
|
ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
cfg->nof_layers = 2;
|
cfg->nof_layers = 2;
|
||||||
break;
|
break;
|
||||||
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
|
||||||
if (grant->nof_tb == 1) {
|
if (nof_tb == 1) {
|
||||||
cfg->codebook_idx = pmi;
|
cfg->codebook_idx = pmi;
|
||||||
cfg->nof_layers = 1;
|
cfg->nof_layers = 1;
|
||||||
} else {
|
} else if (nof_tb == 2) {
|
||||||
cfg->codebook_idx = pmi + 1;
|
cfg->codebook_idx = pmi + 1;
|
||||||
cfg->nof_layers = 2;
|
cfg->nof_layers = 2;
|
||||||
|
} else {
|
||||||
|
ERROR("Wrong number of transport blocks (%d) for spatial multiplexing.", nof_tb);
|
||||||
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n",
|
INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n",
|
||||||
grant->nof_tb, cfg->nof_layers, cfg->codebook_idx);
|
nof_tb, cfg->nof_layers, cfg->codebook_idx);
|
||||||
break;
|
break;
|
||||||
case SRSLTE_MIMO_TYPE_CDD:
|
case SRSLTE_MIMO_TYPE_CDD:
|
||||||
if (grant->nof_tb != 2) {
|
if (nof_tb != 2) {
|
||||||
ERROR("Number of transport blocks (%d) is not supported for CDD transmission mode.", grant->nof_tb);
|
ERROR("Wrong number of transport blocks (%d) for CDD.", nof_tb);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
cfg->nof_layers = 2;
|
cfg->nof_layers = 2;
|
||||||
|
@ -532,12 +537,13 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
|
||||||
|
|
||||||
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
|
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
|
||||||
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
|
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
|
||||||
uint32_t codeword_idx) {
|
uint32_t codeword_idx, bool *ack) {
|
||||||
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
|
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
|
||||||
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
|
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
|
||||||
uint32_t rv = cfg->rv[codeword_idx];
|
uint32_t rv = cfg->rv[codeword_idx];
|
||||||
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
if (nbits->nof_bits) {
|
if (softbuffer && data && ack) {
|
||||||
INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||||
cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
|
cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
|
||||||
nbits->nof_re, nbits->nof_bits, rv);
|
nbits->nof_re, nbits->nof_bits, rv);
|
||||||
|
@ -561,10 +567,20 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
|
||||||
srslte_sequence_free(&seq);
|
srslte_sequence_free(&seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
return srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx);
|
/* Return */
|
||||||
|
ret = srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx);
|
||||||
|
|
||||||
|
if (ret == SRSLTE_SUCCESS) {
|
||||||
|
*ack = true;
|
||||||
|
} else if (ret == SRSLTE_ERROR) {
|
||||||
|
*ack = false;
|
||||||
|
ret = SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERROR("Detected NULL pointer");
|
||||||
}
|
}
|
||||||
|
|
||||||
return SRSLTE_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decodes the PDSCH from the received symbols
|
/** Decodes the PDSCH from the received symbols
|
||||||
|
@ -585,9 +601,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
||||||
data != NULL &&
|
data != NULL &&
|
||||||
cfg != NULL)
|
cfg != NULL)
|
||||||
{
|
{
|
||||||
|
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant);
|
||||||
|
|
||||||
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%d, nof_layers=%d, nof_tb=%d\n",
|
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%d, nof_layers=%d, nof_tb=%d\n",
|
||||||
cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, cfg->grant.nof_tb);
|
cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, nof_tb);
|
||||||
|
|
||||||
// Extract Symbols and Channel Estimates
|
// Extract Symbols and Channel Estimates
|
||||||
for (int j=0;j<q->nof_rx_antennas;j++) {
|
for (int j=0;j<q->nof_rx_antennas;j++) {
|
||||||
|
@ -608,10 +625,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
||||||
|
|
||||||
// Prepare layers
|
// Prepare layers
|
||||||
int nof_symbols [SRSLTE_MAX_CODEWORDS];
|
int nof_symbols [SRSLTE_MAX_CODEWORDS];
|
||||||
nof_symbols[0] = cfg->nbits[0].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
|
nof_symbols[0] = cfg->nbits[0].nof_re * nof_tb / cfg->nof_layers;
|
||||||
nof_symbols[1] = cfg->nbits[1].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
|
nof_symbols[1] = cfg->nbits[1].nof_re * nof_tb / cfg->nof_layers;
|
||||||
|
|
||||||
if (cfg->nof_layers == cfg->grant.nof_tb) {
|
if (cfg->nof_layers == nof_tb) {
|
||||||
/* Skip layer demap */
|
/* Skip layer demap */
|
||||||
for (i = 0; i < cfg->nof_layers; i++) {
|
for (i = 0; i < cfg->nof_layers; i++) {
|
||||||
x[i] = q->d[i];
|
x[i] = q->d[i];
|
||||||
|
@ -629,15 +646,21 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
|
||||||
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
|
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
|
||||||
|
|
||||||
// Layer demapping only if necessary
|
// Layer demapping only if necessary
|
||||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
if (cfg->nof_layers != nof_tb) {
|
||||||
srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb,
|
srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb,
|
||||||
nof_symbols[0], nof_symbols, cfg->mimo_type);
|
nof_symbols[0], nof_symbols, cfg->mimo_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Codeword decoding
|
// Codeword decoding
|
||||||
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
|
||||||
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
|
if (cfg->grant.tb_en[tb]) {
|
||||||
acks[tb] = (ret == SRSLTE_SUCCESS);
|
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]);
|
||||||
|
|
||||||
|
/* Check if there has been any execution error */
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pdsch_decode_debug(q, cfg, sf_symbols, ce);
|
pdsch_decode_debug(q, cfg, sf_symbols, ce);
|
||||||
|
@ -689,6 +712,8 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
||||||
|
|
||||||
if (q != NULL &&
|
if (q != NULL &&
|
||||||
cfg != NULL) {
|
cfg != NULL) {
|
||||||
|
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant);
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||||
if (sf_symbols[i] == NULL) {
|
if (sf_symbols[i] == NULL) {
|
||||||
|
@ -708,15 +733,17 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
||||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
|
||||||
|
if (cfg->grant.tb_en[tb]) {
|
||||||
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
|
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Layer mapping & precode if necessary
|
// Layer mapping & precode if necessary
|
||||||
if (q->cell.nof_ports > 1) {
|
if (q->cell.nof_ports > 1) {
|
||||||
int nof_symbols;
|
int nof_symbols;
|
||||||
/* If number of layers is equal to transport blocks (codewords) skip layer mapping */
|
/* If number of layers is equal to transport blocks (codewords) skip layer mapping */
|
||||||
if (cfg->nof_layers == cfg->grant.nof_tb) {
|
if (cfg->nof_layers == nof_tb) {
|
||||||
for (i = 0; i < cfg->nof_layers; i++) {
|
for (i = 0; i < cfg->nof_layers; i++) {
|
||||||
x[i] = q->d[i];
|
x[i] = q->d[i];
|
||||||
}
|
}
|
||||||
|
@ -728,7 +755,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
|
||||||
}
|
}
|
||||||
memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
|
memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
|
||||||
|
|
||||||
nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers,
|
nof_symbols = srslte_layermap_type(q->d, x, nof_tb, cfg->nof_layers,
|
||||||
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits[0].nof_re, cfg->nbits[1].nof_re},
|
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits[0].nof_re, cfg->nbits[1].nof_re},
|
||||||
cfg->mimo_type);
|
cfg->mimo_type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,11 +521,10 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
|
||||||
grant->mcs[1].tbs = 0;
|
grant->mcs[1].tbs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grant->nof_tb = 0;
|
|
||||||
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
grant->tb_en[tb] = dci->tb_en[tb];
|
||||||
if (dci->tb_en[tb]) {
|
if (dci->tb_en[tb]) {
|
||||||
grant->Qm[tb] = srslte_mod_bits_x_symbol(grant->mcs[tb].mod);
|
grant->Qm[tb] = srslte_mod_bits_x_symbol(grant->mcs[tb].mod);
|
||||||
grant->nof_tb++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grant->pinfo = dci->pinfo;
|
grant->pinfo = dci->pinfo;
|
||||||
|
@ -541,7 +540,8 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
|
||||||
srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS])
|
srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS])
|
||||||
{
|
{
|
||||||
// Compute number of RE
|
// Compute number of RE
|
||||||
for (int i = 0; i < grant->nof_tb; i++) {
|
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
|
if (grant->tb_en[i]) {
|
||||||
/* Compute number of RE for first transport block */
|
/* Compute number of RE for first transport block */
|
||||||
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
|
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
|
||||||
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
|
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
|
||||||
|
@ -549,6 +549,7 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
|
||||||
nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
|
nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Obtains a DL grant from a DCI grant for PDSCH */
|
/** Obtains a DL grant from a DCI grant for PDSCH */
|
||||||
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
|
int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
|
||||||
|
@ -820,13 +821,15 @@ void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb)
|
||||||
void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
||||||
srslte_ra_prb_fprint(f, grant);
|
srslte_ra_prb_fprint(f, grant);
|
||||||
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
|
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
|
||||||
fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb);
|
fprintf(f, " - Number of TBs:\t\t\t%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant));
|
||||||
for (int i = 0; i < grant->nof_tb; i++) {
|
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
|
if (grant->tb_en[i]) {
|
||||||
fprintf(f, " - Transport block:\t\t\t%d\n", i);
|
fprintf(f, " - Transport block:\t\t\t%d\n", i);
|
||||||
fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
|
fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
|
||||||
fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
|
fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
|
||||||
if (grant->nof_prb > 0) {
|
if (grant->nof_prb > 0) {
|
||||||
|
|
|
@ -524,7 +524,7 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
|
||||||
int16_t *e_bits, uint8_t *data, int codeword_idx) {
|
int16_t *e_bits, uint8_t *data, int codeword_idx) {
|
||||||
uint32_t Nl = 1;
|
uint32_t Nl = 1;
|
||||||
|
|
||||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
|
||||||
Nl = 2;
|
Nl = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,7 +553,7 @@ int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
|
||||||
uint8_t *data, uint8_t *e_bits, int codeword_idx) {
|
uint8_t *data, uint8_t *e_bits, int codeword_idx) {
|
||||||
uint32_t Nl = 1;
|
uint32_t Nl = 1;
|
||||||
|
|
||||||
if (cfg->nof_layers != cfg->grant.nof_tb) {
|
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
|
||||||
Nl = 2;
|
Nl = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,14 +657,17 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs
|
||||||
|
|
||||||
// Deinterleave and decode HARQ bits
|
// Deinterleave and decode HARQ bits
|
||||||
if (uci_data->uci_ack_len > 0) {
|
if (uci_data->uci_ack_len > 0) {
|
||||||
|
uint8_t acks[2] = {0, 0};
|
||||||
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
|
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
|
||||||
if (cfg->cb_segm.tbs == 0) {
|
if (cfg->cb_segm.tbs == 0) {
|
||||||
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
|
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, &uci_data->uci_ack);
|
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
uci_data->uci_ack = acks[0];
|
||||||
|
uci_data->uci_ack_2 = acks[1];
|
||||||
Q_prime_ack = (uint32_t) ret;
|
Q_prime_ack = (uint32_t) ret;
|
||||||
|
|
||||||
// Set zeros to HARQ bits
|
// Set zeros to HARQ bits
|
||||||
|
@ -805,11 +808,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
|
||||||
|
|
||||||
// Encode (and interleave) ACK
|
// Encode (and interleave) ACK
|
||||||
if (uci_data.uci_ack_len > 0) {
|
if (uci_data.uci_ack_len > 0) {
|
||||||
|
uint8_t acks [2] = {uci_data.uci_ack, uci_data.uci_ack_2};
|
||||||
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
|
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
|
||||||
if (cfg->cb_segm.tbs == 0) {
|
if (cfg->cb_segm.tbs == 0) {
|
||||||
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
|
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
|
||||||
}
|
}
|
||||||
ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, &q->ack_ri_bits[Q_prime_ri*Qm]);
|
ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len,
|
||||||
|
beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,8 +257,8 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < grant.nof_tb; i++) {
|
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
if (grant.mcs[i].tbs) {
|
if (grant.tb_en[i]) {
|
||||||
data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs);
|
data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs);
|
||||||
if (!data_tx[i]) {
|
if (!data_tx[i]) {
|
||||||
perror("srslte_vec_malloc");
|
perror("srslte_vec_malloc");
|
||||||
|
@ -303,12 +303,11 @@ int main(int argc, char **argv) {
|
||||||
INFO(" cp=%s\n", srslte_cp_string(cell.cp));
|
INFO(" cp=%s\n", srslte_cp_string(cell.cp));
|
||||||
INFO(" phich_length=%d\n", (int) cell.phich_length);
|
INFO(" phich_length=%d\n", (int) cell.phich_length);
|
||||||
INFO(" phich_resources=%d\n", (int) cell.phich_resources);
|
INFO(" phich_resources=%d\n", (int) cell.phich_resources);
|
||||||
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
|
|
||||||
INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb);
|
INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb);
|
||||||
INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx);
|
INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx);
|
||||||
INFO(" mimo_type=%s\n", srslte_mimotype2str(pdsch_cfg.mimo_type));
|
INFO(" mimo_type=%s\n", srslte_mimotype2str(pdsch_cfg.mimo_type));
|
||||||
INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers);
|
INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers);
|
||||||
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
|
INFO(" nof_tb=%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(&pdsch_cfg.grant));
|
||||||
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
INFO(" Tranport block index %d:\n", i);
|
INFO(" Tranport block index %d:\n", i);
|
||||||
INFO(" Qm=%d\n", pdsch_cfg.grant.Qm[i]);
|
INFO(" Qm=%d\n", pdsch_cfg.grant.Qm[i]);
|
||||||
|
@ -372,11 +371,13 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int tb = 0; tb < grant.nof_tb; tb++) {
|
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
if (grant.tb_en[tb]) {
|
||||||
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
|
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
|
||||||
data_tx[tb][byte] = (uint8_t) (rand() % 256);
|
data_tx[tb][byte] = (uint8_t) (rand() % 256);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*uint8_t databit[100000];
|
/*uint8_t databit[100000];
|
||||||
srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
|
srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
|
||||||
|
@ -444,8 +445,8 @@ int main(int argc, char **argv) {
|
||||||
srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]);
|
srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < grant.nof_tb; i++) {
|
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
if (grant.mcs[i].tbs) {
|
if (grant.tb_en[i]) {
|
||||||
srslte_softbuffer_rx_reset_tbs(softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs);
|
srslte_softbuffer_rx_reset_tbs(softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,7 +465,8 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check Tx and Rx bytes */
|
/* Check Tx and Rx bytes */
|
||||||
for (int tb = 0; tb < grant.nof_tb; tb++) {
|
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
if (grant.tb_en[tb]) {
|
||||||
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
|
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
|
||||||
if (data_tx[tb][byte] != data_rx[tb][byte]) {
|
if (data_tx[tb][byte] != data_rx[tb][byte]) {
|
||||||
ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]);
|
ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]);
|
||||||
|
@ -473,11 +475,14 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check all transport blocks have been decoded OK */
|
/* Check all transport blocks have been decoded OK */
|
||||||
for (int tb = 0; tb < grant.nof_tb; tb++) {
|
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
|
if (grant.tb_en[tb]) {
|
||||||
ret |= (acks[tb]) ? SRSLTE_SUCCESS : SRSLTE_ERROR;
|
ret |= (acks[tb]) ? SRSLTE_SUCCESS : SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = SRSLTE_SUCCESS;
|
ret = SRSLTE_SUCCESS;
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ int main(int argc, char **argv) {
|
||||||
bzero(&uci_data_tx, sizeof(srslte_uci_data_t));
|
bzero(&uci_data_tx, sizeof(srslte_uci_data_t));
|
||||||
uci_data_tx.uci_cqi_len = 4;
|
uci_data_tx.uci_cqi_len = 4;
|
||||||
uci_data_tx.uci_ri_len = 0;
|
uci_data_tx.uci_ri_len = 0;
|
||||||
uci_data_tx.uci_ack_len = 0;
|
uci_data_tx.uci_ack_len = 2;
|
||||||
memcpy(&uci_data_rx, &uci_data_tx, sizeof(srslte_uci_data_t));
|
memcpy(&uci_data_rx, &uci_data_tx, sizeof(srslte_uci_data_t));
|
||||||
|
|
||||||
for (uint32_t i=0;i<20;i++) {
|
for (uint32_t i=0;i<20;i++) {
|
||||||
|
@ -180,6 +180,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
uci_data_tx.uci_ri = 1;
|
uci_data_tx.uci_ri = 1;
|
||||||
uci_data_tx.uci_ack = 1;
|
uci_data_tx.uci_ack = 1;
|
||||||
|
uci_data_tx.uci_ack_2 = 1;
|
||||||
|
|
||||||
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
|
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
|
||||||
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
|
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
|
||||||
|
@ -250,11 +251,19 @@ int main(int argc, char **argv) {
|
||||||
if (uci_data_tx.uci_ack_len) {
|
if (uci_data_tx.uci_ack_len) {
|
||||||
if (uci_data_tx.uci_ack != uci_data_rx.uci_ack) {
|
if (uci_data_tx.uci_ack != uci_data_rx.uci_ack) {
|
||||||
printf("UCI ACK bit error: %d != %d\n", uci_data_tx.uci_ack, uci_data_rx.uci_ack);
|
printf("UCI ACK bit error: %d != %d\n", uci_data_tx.uci_ack, uci_data_rx.uci_ack);
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uci_data_tx.uci_ack_len > 1) {
|
||||||
|
if (uci_data_tx.uci_ack_2 != uci_data_rx.uci_ack_2) {
|
||||||
|
printf("UCI ACK 2 bit error: %d != %d\n", uci_data_tx.uci_ack_2, uci_data_rx.uci_ack_2);
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uci_data_tx.uci_ri_len) {
|
if (uci_data_tx.uci_ri_len) {
|
||||||
if (uci_data_tx.uci_ri != uci_data_rx.uci_ri) {
|
if (uci_data_tx.uci_ri != uci_data_rx.uci_ri) {
|
||||||
printf("UCI RI bit error: %d != %d\n", uci_data_tx.uci_ri, uci_data_rx.uci_ri);
|
printf("UCI RI bit error: %d != %d\n", uci_data_tx.uci_ri, uci_data_rx.uci_ri);
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uci_data_tx.uci_cqi_len) {
|
if (uci_data_tx.uci_cqi_len) {
|
||||||
|
|
|
@ -551,24 +551,56 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg,
|
||||||
return Q_prime;
|
return Q_prime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encode_ri_ack(uint8_t data, srslte_uci_bit_type_t q_encoded_bits[6], uint8_t Qm)
|
static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit_type_t q_encoded_bits[18], uint8_t Qm)
|
||||||
{
|
{
|
||||||
q_encoded_bits[0] = data?UCI_BIT_1:UCI_BIT_0;
|
uint32_t i = 0;
|
||||||
q_encoded_bits[1] = UCI_BIT_REPETITION;
|
|
||||||
for (uint32_t i=2;i<Qm;i++) {
|
if (data_len == 1) {
|
||||||
q_encoded_bits[i] = UCI_BIT_PLACEHOLDER;
|
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
q_encoded_bits[i++] = UCI_BIT_REPETITION;
|
||||||
|
while(i < Qm) {
|
||||||
|
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
q_encoded_bits[i++] = data[1] ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
while(i<Qm) {
|
||||||
|
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
|
||||||
|
}
|
||||||
|
q_encoded_bits[i++] = (data[0]^data[1]) ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
while(i<Qm*2) {
|
||||||
|
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
|
||||||
|
}
|
||||||
|
q_encoded_bits[i++] = data[1] ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
q_encoded_bits[i++] = (data[0]^data[1]) ? UCI_BIT_1 : UCI_BIT_0;
|
||||||
|
while(i<Qm*3) {
|
||||||
|
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos)
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3])
|
||||||
{
|
{
|
||||||
uint32_t p0 = pos[0].position;
|
uint32_t p0 = pos[Qm * 0 + 0].position;
|
||||||
uint32_t p1 = pos[1].position;
|
uint32_t p1 = pos[Qm * 0 + 1].position;
|
||||||
|
uint32_t p2 = pos[Qm * 1 + 0].position;
|
||||||
|
uint32_t p3 = pos[Qm * 1 + 1].position;
|
||||||
|
uint32_t p4 = pos[Qm * 2 + 0].position;
|
||||||
|
uint32_t p5 = pos[Qm * 2 + 1].position;
|
||||||
|
|
||||||
uint32_t q0 = c_seq[p0]?q_bits[p0]:-q_bits[p0];
|
int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0];
|
||||||
uint32_t q1 = c_seq[p0]?q_bits[p1]:-q_bits[p1];
|
int32_t q1 = c_seq[p1] ? q_bits[p1] : -q_bits[p1];
|
||||||
|
int32_t q2 = c_seq[p2] ? q_bits[p2] : -q_bits[p2];
|
||||||
|
int32_t q3 = c_seq[p3] ? q_bits[p3] : -q_bits[p3];
|
||||||
|
int32_t q4 = c_seq[p4] ? q_bits[p4] : -q_bits[p4];
|
||||||
|
int32_t q5 = c_seq[p5] ? q_bits[p5] : -q_bits[p5];
|
||||||
|
|
||||||
return -(q0+q1);
|
data[0] -= q0 + q3;
|
||||||
|
data[1] -= q1 + q4;
|
||||||
|
data[2] -= q2 + q5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -577,25 +609,29 @@ static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *
|
||||||
*/
|
*/
|
||||||
int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq,
|
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,
|
float beta, uint32_t H_prime_total,
|
||||||
uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t *data)
|
uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks)
|
||||||
{
|
{
|
||||||
int32_t rx_ack = 0;
|
int32_t acks_sum[3] = {0, 0, 0};
|
||||||
|
|
||||||
if (beta < 0) {
|
if (beta < 0) {
|
||||||
fprintf(stderr, "Error beta is reserved\n");
|
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_acks, O_cqi, beta);
|
||||||
|
|
||||||
// Use the same interleaver function to get the HARQ bit position
|
// Use the same interleaver function to get the HARQ bit position
|
||||||
for (uint32_t i = 0; i < Qprime; i++) {
|
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_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);
|
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 (data) {
|
if (acks) {
|
||||||
*data = rx_ack>0;
|
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;
|
return (int) Qprime;
|
||||||
}
|
}
|
||||||
|
@ -603,7 +639,7 @@ int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_s
|
||||||
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
|
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
|
||||||
* Currently only supporting 1-bit HARQ
|
* Currently only supporting 1-bit HARQ
|
||||||
*/
|
*/
|
||||||
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t data,
|
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,
|
uint32_t O_cqi, float beta, uint32_t H_prime_total,
|
||||||
srslte_uci_bit_t *ack_bits)
|
srslte_uci_bit_t *ack_bits)
|
||||||
{
|
{
|
||||||
|
@ -612,14 +648,14 @@ int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t data,
|
||||||
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_acks, O_cqi, beta);
|
||||||
srslte_uci_bit_type_t q_encoded_bits[6];
|
srslte_uci_bit_type_t q_encoded_bits[18];
|
||||||
|
|
||||||
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
|
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++) {
|
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_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, cfg->grant.Qm, &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;
|
return (int) Qprime;
|
||||||
|
@ -632,7 +668,7 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se
|
||||||
float beta, uint32_t H_prime_total,
|
float beta, uint32_t H_prime_total,
|
||||||
uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data)
|
uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data)
|
||||||
{
|
{
|
||||||
int32_t rx_ri = 0;
|
int32_t ri_sum[3] = {0, 0, 0};
|
||||||
|
|
||||||
if (beta < 0) {
|
if (beta < 0) {
|
||||||
fprintf(stderr, "Error beta is reserved\n");
|
fprintf(stderr, "Error beta is reserved\n");
|
||||||
|
@ -644,11 +680,13 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se
|
||||||
// Use the same interleaver function to get the HARQ bit position
|
// Use the same interleaver function to get the HARQ bit position
|
||||||
for (uint32_t i=0;i<Qprime;i++) {
|
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_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
|
||||||
rx_ri += (int32_t) decode_ri_ack(q_bits, c_seq, ri_bits);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
*data = rx_ri>0;
|
*data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int) Qprime;
|
return (int) Qprime;
|
||||||
|
@ -659,22 +697,24 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se
|
||||||
* Currently only supporting 1-bit RI
|
* Currently only supporting 1-bit RI
|
||||||
*/
|
*/
|
||||||
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
|
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
|
||||||
uint8_t data,
|
uint8_t ri,
|
||||||
uint32_t O_cqi, float beta, uint32_t H_prime_total,
|
uint32_t O_cqi, float beta, uint32_t H_prime_total,
|
||||||
srslte_uci_bit_t *ri_bits)
|
srslte_uci_bit_t *ri_bits)
|
||||||
{
|
{
|
||||||
|
// FIXME: It supports RI of 1 bit only
|
||||||
|
uint8_t data[2] = {ri, 0};
|
||||||
if (beta < 0) {
|
if (beta < 0) {
|
||||||
fprintf(stderr, "Error beta is reserved\n");
|
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, 1, O_cqi, beta);
|
||||||
srslte_uci_bit_type_t q_encoded_bits[6];
|
srslte_uci_bit_type_t q_encoded_bits[18];
|
||||||
|
|
||||||
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
|
uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm);
|
||||||
|
|
||||||
for (uint32_t i=0;i<Qprime;i++) {
|
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_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, cfg->grant.Qm, &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;
|
return (int) Qprime;
|
||||||
|
|
|
@ -280,21 +280,22 @@ int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *c
|
||||||
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx,
|
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx,
|
||||||
int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type) {
|
int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type) {
|
||||||
uint32_t pmi = 0;
|
uint32_t pmi = 0;
|
||||||
|
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
|
||||||
|
|
||||||
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
|
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
|
||||||
if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
|
if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
|
||||||
if (grant->nof_tb == 1) {
|
if (nof_tb == 1) {
|
||||||
if (grant->pinfo > 0 && grant->pinfo < 5) {
|
if (grant->pinfo > 0 && grant->pinfo < 5) {
|
||||||
pmi = grant->pinfo - 1;
|
pmi = grant->pinfo - 1;
|
||||||
} else {
|
} else {
|
||||||
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, grant->pinfo);
|
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (grant->pinfo < 2) {
|
if (grant->pinfo < 2) {
|
||||||
pmi = grant->pinfo;
|
pmi = grant->pinfo;
|
||||||
} else {
|
} else {
|
||||||
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, grant->pinfo);
|
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,12 +342,15 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
|
||||||
if (dci_unpacked.rv_idx < 0) {
|
if (dci_unpacked.rv_idx < 0) {
|
||||||
uint32_t sfn = tti / 10;
|
uint32_t sfn = tti / 10;
|
||||||
uint32_t k = (sfn / 2) % 4;
|
uint32_t k = (sfn / 2) % 4;
|
||||||
for (int i = 0; i < grant.nof_tb; i++) {
|
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
|
if (grant.tb_en[i]) {
|
||||||
rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
|
rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
|
||||||
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
|
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < grant.nof_tb; i++) {
|
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
|
||||||
|
if (grant.tb_en[i]) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
rvidx[i] = (uint32_t) dci_unpacked.rv_idx;
|
rvidx[i] = (uint32_t) dci_unpacked.rv_idx;
|
||||||
|
@ -361,6 +365,7 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
|
||||||
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
|
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch(dci_msg.format) {
|
switch(dci_msg.format) {
|
||||||
case SRSLTE_DCI_FORMAT1:
|
case SRSLTE_DCI_FORMAT1:
|
||||||
|
@ -372,14 +377,14 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SRSLTE_DCI_FORMAT2:
|
case SRSLTE_DCI_FORMAT2:
|
||||||
if (grant.nof_tb == 1 && dci_unpacked.pinfo == 0) {
|
if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||||
} else {
|
} else {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SRSLTE_DCI_FORMAT2A:
|
case SRSLTE_DCI_FORMAT2A:
|
||||||
if (grant.nof_tb == 1 && dci_unpacked.pinfo == 0) {
|
if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||||
} else {
|
} else {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
||||||
|
@ -413,12 +418,14 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
|
||||||
noise_estimate,
|
noise_estimate,
|
||||||
rnti, data, acks);
|
rnti, data, acks);
|
||||||
|
|
||||||
for (int tb = 0; tb < q->pdsch_cfg.grant.nof_tb; tb++) {
|
for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||||
|
if (grant.tb_en[tb]) {
|
||||||
if (!acks[tb]) {
|
if (!acks[tb]) {
|
||||||
q->pkt_errors++;
|
q->pkt_errors++;
|
||||||
}
|
}
|
||||||
q->pkts_total++;
|
q->pkts_total++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == SRSLTE_ERROR) {
|
if (ret == SRSLTE_ERROR) {
|
||||||
} else if (ret == SRSLTE_ERROR_INVALID_INPUTS) {
|
} else if (ret == SRSLTE_ERROR_INVALID_INPUTS) {
|
||||||
|
@ -447,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
|
/* Compute the Rank Indicator (RI) and Precoder Matrix Indicator (PMI) by computing the Signal to Interference plus
|
||||||
* Noise Ratio (SINR), valid for TM4 */
|
* 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 noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
|
||||||
float best_sinr = -INFINITY;
|
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) {
|
if (q->cell.nof_ports < 2 || q->nof_rx_antennas < 2) {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
|
@ -464,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) */
|
/* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */
|
||||||
for (uint32_t nof_layers = 1; nof_layers <= 2; nof_layers++) {
|
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) {
|
if (_sinr > best_sinr + 0.1) {
|
||||||
best_sinr = _sinr;
|
best_sinr = _sinr;
|
||||||
best_pmi = q->pmi[nof_layers - 1];
|
best_pmi = (uint8_t) q->pmi[nof_layers - 1];
|
||||||
best_ri = nof_layers;
|
best_ri = (uint8_t) (nof_layers - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +516,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, f
|
||||||
|
|
||||||
|
|
||||||
/* Compute the Rank Indicator (RI) by computing the condition number, valid for TM3 */
|
/* Compute the Rank Indicator (RI) by computing the condition number, valid for TM3 */
|
||||||
int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint32_t *ri, float *cn) {
|
int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) {
|
||||||
float _cn;
|
float _cn;
|
||||||
int ret = srslte_pdsch_cn_compute(&q->pdsch, q->ce_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp), &_cn);
|
int ret = srslte_pdsch_cn_compute(&q->pdsch, q->ce_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp), &_cn);
|
||||||
|
|
||||||
|
@ -520,7 +527,7 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint32_t *ri, float *cn) {
|
||||||
|
|
||||||
/* Set rank indicator */
|
/* Set rank indicator */
|
||||||
if (!ret && ri) {
|
if (!ret && ri) {
|
||||||
*ri = (_cn > 3.0f)? 1:0;
|
*ri = (uint8_t)((_cn < 17.0f)? 1:0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -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
|
pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a
|
||||||
}
|
}
|
||||||
if (format >= SRSLTE_PUCCH_FORMAT_2) {
|
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);
|
srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_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;
|
||||||
|
|
|
@ -166,10 +166,19 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void new_grant_dl(Tgrant grant, Taction *action) {
|
void new_grant_dl(Tgrant grant, Taction *action) {
|
||||||
for (uint32_t tb = 0; tb < grant.phy_grant.dl.nof_tb; tb++) {
|
/* Fill action structure */
|
||||||
|
bzero(action, sizeof(Taction));
|
||||||
|
action->default_ack = false;
|
||||||
|
action->generate_ack = true;
|
||||||
|
action->decode_enabled = false;
|
||||||
|
|
||||||
|
/* For each subprocess... */
|
||||||
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||||
|
if (grant.tb_en[tb]) {
|
||||||
subproc[tb].new_grant_dl(grant, action);
|
subproc[tb].new_grant_dl(grant, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int get_current_tbs(uint32_t tb_idx) { return subproc[tb_idx].get_current_tbs(); }
|
int get_current_tbs(uint32_t tb_idx) { return subproc[tb_idx].get_current_tbs(); }
|
||||||
|
|
||||||
|
@ -235,12 +244,6 @@ private:
|
||||||
grant.last_tti = cur_grant.tti;
|
grant.last_tti = cur_grant.tti;
|
||||||
memcpy(&cur_grant, &grant, sizeof(Tgrant));
|
memcpy(&cur_grant, &grant, sizeof(Tgrant));
|
||||||
|
|
||||||
// Fill action structure
|
|
||||||
bzero(action, sizeof(Taction));
|
|
||||||
action->default_ack = ack;
|
|
||||||
action->generate_ack = true;
|
|
||||||
action->decode_enabled = false;
|
|
||||||
|
|
||||||
// If data has not yet been successfully decoded
|
// If data has not yet been successfully decoded
|
||||||
if (!ack) {
|
if (!ack) {
|
||||||
|
|
||||||
|
@ -262,6 +265,7 @@ private:
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
|
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
|
||||||
|
action->phy_grant.dl.tb_en[tid] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(TIME_ALIGNMENT)->is_expired()) {
|
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(TIME_ALIGNMENT)->is_expired()) {
|
||||||
|
@ -295,7 +299,6 @@ private:
|
||||||
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack,
|
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack,
|
||||||
cur_grant.tti);
|
cur_grant.tti);
|
||||||
}
|
}
|
||||||
if (ack) {
|
|
||||||
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
|
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
|
||||||
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n",
|
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n",
|
||||||
cur_grant.n_bytes[tid]);
|
cur_grant.n_bytes[tid]);
|
||||||
|
@ -310,7 +313,6 @@ private:
|
||||||
harq_entity->nof_pkts++);
|
harq_entity->nof_pkts++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
|
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ private:
|
||||||
void set_uci_sr();
|
void set_uci_sr();
|
||||||
void set_uci_periodic_cqi();
|
void set_uci_periodic_cqi();
|
||||||
void set_uci_aperiodic_cqi();
|
void set_uci_aperiodic_cqi();
|
||||||
void set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb);
|
void set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]);
|
||||||
bool srs_is_ready_to_send();
|
bool srs_is_ready_to_send();
|
||||||
float set_power(float tx_power);
|
float set_power(float tx_power);
|
||||||
void setup_tx_gain();
|
void setup_tx_gain();
|
||||||
|
|
|
@ -216,17 +216,37 @@ void phch_worker::work_imp()
|
||||||
dl_mac_grant.pid, dl_ack);
|
dl_mac_grant.pid, dl_ack);
|
||||||
}
|
}
|
||||||
if (dl_action.generate_ack_callback && dl_action.decode_enabled) {
|
if (dl_action.generate_ack_callback && dl_action.decode_enabled) {
|
||||||
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||||
// NOTE: Currently hard-coded to 1st TB only
|
if (dl_mac_grant.tb_en[tb]) {
|
||||||
for (uint32_t tb = 0; tb < 1; tb++) {
|
|
||||||
phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
|
phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
|
||||||
dl_ack[tb] = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg);
|
dl_ack[tb] = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg);
|
||||||
Debug("Calling generate ACK callback for TB %d returned=%d\n", tb, dl_ack[tb]);
|
Debug("Calling generate ACK callback for TB %d returned=%d\n", tb, dl_ack[tb]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Debug("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack);
|
Debug("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack);
|
||||||
if (dl_action.generate_ack) {
|
if (dl_action.generate_ack) {
|
||||||
set_uci_ack(dl_ack, dl_mac_grant.phy_grant.dl.nof_tb);
|
set_uci_ack(dl_ack, dl_mac_grant.tb_en);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select Rank Indicator by computing Condition Number */
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,11 +312,13 @@ void phch_worker::work_imp()
|
||||||
if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH) {
|
if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH) {
|
||||||
phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]);
|
phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]);
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t tb = 0; tb < dl_mac_grant.phy_grant.dl.nof_tb; tb++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
||||||
|
if (dl_mac_grant.tb_en[tb]) {
|
||||||
phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
|
phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update_measurements();
|
update_measurements();
|
||||||
|
|
||||||
|
@ -405,6 +427,9 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
|
||||||
grant->rnti = dl_rnti;
|
grant->rnti = dl_rnti;
|
||||||
grant->rnti_type = type;
|
grant->rnti_type = type;
|
||||||
grant->last_tti = 0;
|
grant->last_tti = 0;
|
||||||
|
grant->tb_en[0] = dci_unpacked.tb_en[0];
|
||||||
|
grant->tb_en[1] = dci_unpacked.tb_en[1];
|
||||||
|
grant->tb_cw_swap = dci_unpacked.tb_cw_swap; // FIXME: tb_cw_swap not supported
|
||||||
|
|
||||||
last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl);
|
last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl);
|
||||||
|
|
||||||
|
@ -432,8 +457,8 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
|
||||||
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||||
int ret = SRSLTE_SUCCESS;
|
int ret = SRSLTE_SUCCESS;
|
||||||
|
|
||||||
for (uint32_t tb = 0; tb < grant->nof_tb; tb++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
if (rv[tb] < 0 || rv[tb] > 3) {
|
if (grant->tb_en[tb] && (rv[tb] < 0 || rv[tb] > 3)) {
|
||||||
valid_config = false;
|
valid_config = false;
|
||||||
Error("Wrong RV (%d) for TB index %d", rv[tb], tb);
|
Error("Wrong RV (%d) for TB index %d", rv[tb], tb);
|
||||||
}
|
}
|
||||||
|
@ -452,22 +477,22 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LIBLTE_RRC_TRANSMISSION_MODE_3:
|
case LIBLTE_RRC_TRANSMISSION_MODE_3:
|
||||||
if (grant->nof_tb == 1) {
|
if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||||
} else if (grant->nof_tb == 2) {
|
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
mimo_type = SRSLTE_MIMO_TYPE_CDD;
|
||||||
} else {
|
} else {
|
||||||
Error("Wrong number of transport blocks (%d) for TM3\n", grant->nof_tb);
|
Error("Wrong number of transport blocks (%d) for TM3\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant));
|
||||||
valid_config = false;
|
valid_config = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LIBLTE_RRC_TRANSMISSION_MODE_4:
|
case LIBLTE_RRC_TRANSMISSION_MODE_4:
|
||||||
if (grant->nof_tb == 1) {
|
if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) {
|
||||||
mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||||
} else if (grant->nof_tb == 2) {
|
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) {
|
||||||
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||||
} else {
|
} else {
|
||||||
Error("Wrong number of transport blocks (%d) for TM4\n", grant->nof_tb);
|
Error("Wrong number of transport blocks (%d) for TM4\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant));
|
||||||
valid_config = false;
|
valid_config = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -513,7 +538,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
|
||||||
ret = srslte_pdsch_decode(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffers, ue_dl.sf_symbols_m,
|
ret = srslte_pdsch_decode(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffers, ue_dl.sf_symbols_m,
|
||||||
ue_dl.ce_m, noise_estimate, rnti, payload, acks);
|
ue_dl.ce_m, noise_estimate, rnti, payload, acks);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
Error("Decoding PDSCH");
|
Error("ERROR: Decoding PDSCH\n");
|
||||||
}
|
}
|
||||||
#ifdef LOG_EXECTIME
|
#ifdef LOG_EXECTIME
|
||||||
gettimeofday(&t[2], NULL);
|
gettimeofday(&t[2], NULL);
|
||||||
|
@ -521,10 +546,11 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
|
||||||
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
|
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Info("PDSCH: l_crb=%2d, harq=%d, nof_tb=%d, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d%s\n",
|
Info(
|
||||||
grant->nof_prb, harq_pid,
|
"PDSCH: l_crb=%2d, harq=%d, scheme=%s, tb_en={%s, %s}, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d, %s\n",
|
||||||
grant->nof_tb, grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx, grant->mcs[1].idx,
|
grant->nof_prb, harq_pid, srslte_mimotype2str(mimo_type), grant->tb_en[0] ? "on" : "off",
|
||||||
rv[0], rv[1], acks[0] ? "OK" : "KO", acks[1] ? "OK" : "KO",
|
grant->tb_en[1] ? "on" : "off", grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx,
|
||||||
|
grant->mcs[1].idx, rv[0], rv[1], acks[0] ? "OK" : "KO", acks[1] ? "OK" : "KO",
|
||||||
10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)),
|
10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)),
|
||||||
srslte_pdsch_last_noi(&ue_dl.pdsch),
|
srslte_pdsch_last_noi(&ue_dl.pdsch),
|
||||||
timestr);
|
timestr);
|
||||||
|
@ -660,17 +686,19 @@ void phch_worker::reset_uci()
|
||||||
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb) {
|
void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS])
|
||||||
if (nof_tb > 0) {
|
{
|
||||||
|
uint32_t nof_tb = 0;
|
||||||
|
if (tb_en[0]) {
|
||||||
uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0);
|
uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0);
|
||||||
|
nof_tb = 1;
|
||||||
|
} else {
|
||||||
|
uci_data.uci_ack = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nof_tb > 1) {
|
if (tb_en[1]) {
|
||||||
uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0);
|
uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0);
|
||||||
}
|
nof_tb = 2;
|
||||||
|
|
||||||
if (nof_tb > 2) {
|
|
||||||
Error("Number of transport blocks is not supported");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uci_data.uci_ack_len = nof_tb;
|
uci_data.uci_ack_len = nof_tb;
|
||||||
|
@ -698,7 +726,16 @@ void phch_worker::set_uci_periodic_cqi()
|
||||||
int cqi_max = phy->args->cqi_max;
|
int cqi_max = phy->args->cqi_max;
|
||||||
|
|
||||||
if (period_cqi.configured && rnti_is_set) {
|
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;
|
srslte_cqi_value_t cqi_report;
|
||||||
if (period_cqi.format_is_subband) {
|
if (period_cqi.format_is_subband) {
|
||||||
// TODO: Implement subband periodic reports
|
// TODO: Implement subband periodic reports
|
||||||
|
@ -813,11 +850,12 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
|
||||||
snprintf(timestr, 64, ", total_time=%4d us", (int) logtime_start[0].tv_usec);
|
snprintf(timestr, 64, ", total_time=%4d us", (int) logtime_start[0].tv_usec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, cfo=%.1f Hz%s\n",
|
Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n",
|
||||||
(tti+4)%10240,
|
(tti+4)%10240,
|
||||||
grant->L_prb, grant->n_prb[0],
|
grant->L_prb, grant->n_prb[0],
|
||||||
grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv,
|
grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv,
|
||||||
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_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
|
||||||
cfo*15000, timestr);
|
cfo*15000, timestr);
|
||||||
|
|
||||||
// Store metrics
|
// Store metrics
|
||||||
|
@ -859,10 +897,13 @@ 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: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%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,
|
tx_power, (tti+4)%10240,
|
||||||
last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb,
|
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.scheduling_request?"yes":"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_ri_len>0?(uci_data.uci_ri?"1":"0"):"no",
|
||||||
|
uci_data.scheduling_request?"yes":"no",
|
||||||
cfo*15000, timestr);
|
cfo*15000, timestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,6 +1039,13 @@ void phch_worker::set_ul_params(bool pregen_disabled)
|
||||||
LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI;
|
LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI;
|
||||||
period_cqi.subband_size = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic_subband_k;
|
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 */
|
/* SR configuration */
|
||||||
I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
|
I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
|
||||||
|
|
||||||
|
@ -1043,7 +1091,7 @@ int phch_worker::read_ce_abs(float *ce_abs) {
|
||||||
bzero(ce_abs, sizeof(float)*sz);
|
bzero(ce_abs, sizeof(float)*sz);
|
||||||
int g = (sz - 12*cell.nof_prb)/2;
|
int g = (sz - 12*cell.nof_prb)/2;
|
||||||
for (i = 0; i < 12*cell.nof_prb; i++) {
|
for (i = 0; i < 12*cell.nof_prb; i++) {
|
||||||
ce_abs[g+i] = 20 * log10(cabs(ue_dl.ce[0][i]));
|
ce_abs[g+i] = 20 * log10f(cabsf(ue_dl.ce_m[0][0][i]));
|
||||||
if (isinf(ce_abs[g+i])) {
|
if (isinf(ce_abs[g+i])) {
|
||||||
ce_abs[g+i] = -80;
|
ce_abs[g+i] = -80;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue