mirror of https://github.com/PentHertz/srsLTE.git
Added DFT Transform Precoding. Added PUSCH matlab test. Added UCI PUCCH coding
This commit is contained in:
parent
908e4f0373
commit
6b8d019fce
|
@ -58,15 +58,37 @@ typedef struct LIBLTE_API {
|
|||
uint32_t position_subband; // L-bit width
|
||||
} cqi_ue_subband_t;
|
||||
|
||||
/* Table 5.2.3.3.1-1: Fields for channel quality information feedback for wideband CQI reports
|
||||
(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and
|
||||
transmission mode 8 configured without PMI/RI reporting).
|
||||
This is for PUCCH Format 2 reports
|
||||
*/
|
||||
typedef struct LIBLTE_API {
|
||||
uint8_t wideband_cqi; // 4-bit width
|
||||
} cqi_format2_wideband_t;
|
||||
|
||||
LIBLTE_API void cqi_hl_subband_pack(cqi_hl_subband_t *msg,
|
||||
typedef struct LIBLTE_API {
|
||||
uint8_t subband_cqi; // 4-bit width
|
||||
uint8_t subband_label; // 1- or 2-bit width
|
||||
} cqi_format2_subband_t;
|
||||
|
||||
|
||||
LIBLTE_API int cqi_hl_subband_pack(cqi_hl_subband_t *msg,
|
||||
uint32_t N,
|
||||
uint8_t *buff,
|
||||
uint32_t buff_len);
|
||||
|
||||
LIBLTE_API void cqi_ue_subband_pack(cqi_ue_subband_t *msg,
|
||||
LIBLTE_API int cqi_ue_subband_pack(cqi_ue_subband_t *msg,
|
||||
uint32_t L,
|
||||
uint8_t *buff,
|
||||
uint32_t buff_len);
|
||||
|
||||
LIBLTE_API int cqi_format2_wideband_pack(cqi_format2_wideband_t *msg,
|
||||
uint8_t *buff,
|
||||
uint32_t buff_len);
|
||||
|
||||
LIBLTE_API int cqi_format2_subband_pack(cqi_format2_subband_t *msg,
|
||||
uint8_t *buff,
|
||||
uint32_t buff_len);
|
||||
|
||||
#endif // CQI_
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef PUCH_
|
||||
#ifndef PUSCH_
|
||||
#define PUSCH_
|
||||
|
||||
#include "liblte/config.h"
|
||||
|
@ -39,12 +39,13 @@
|
|||
#include "liblte/phy/phch/regs.h"
|
||||
#include "liblte/phy/phch/sch.h"
|
||||
#include "liblte/phy/phch/harq.h"
|
||||
#include "liblte/phy/filter/dft_precoding.h"
|
||||
|
||||
#define TDEC_MAX_ITERATIONS 5
|
||||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
/* PDSCH object */
|
||||
/* PUSCH object */
|
||||
typedef struct LIBLTE_API {
|
||||
lte_cell_t cell;
|
||||
|
||||
|
@ -52,11 +53,14 @@ typedef struct LIBLTE_API {
|
|||
bool rnti_is_set;
|
||||
uint16_t rnti;
|
||||
|
||||
dft_precoding_t dft_precoding;
|
||||
|
||||
precoding_t equalizer;
|
||||
|
||||
/* buffers */
|
||||
// void buffers are shared for tx and rx
|
||||
cf_t *ce[MAX_PORTS];
|
||||
cf_t *pusch_symbols[MAX_PORTS];
|
||||
cf_t *pusch_x[MAX_PORTS];
|
||||
cf_t *ce;
|
||||
cf_t *pusch_z;
|
||||
cf_t *pusch_d;
|
||||
|
||||
void *pusch_q;
|
||||
|
@ -84,7 +88,7 @@ LIBLTE_API int pusch_set_rnti(pusch_t *q,
|
|||
|
||||
LIBLTE_API int pusch_encode(pusch_t *q,
|
||||
uint8_t *data,
|
||||
cf_t *sf_symbols[MAX_PORTS],
|
||||
cf_t *sf_symbols,
|
||||
uint32_t nsubframe,
|
||||
harq_t *harq_process,
|
||||
uint32_t rv_idx);
|
||||
|
@ -92,14 +96,14 @@ LIBLTE_API int pusch_encode(pusch_t *q,
|
|||
LIBLTE_API int pusch_uci_encode(pusch_t *q,
|
||||
uint8_t *data,
|
||||
uci_data_t uci_data,
|
||||
cf_t *sf_symbols[MAX_PORTS],
|
||||
cf_t *sf_symbols,
|
||||
uint32_t subframe,
|
||||
harq_t *harq_process,
|
||||
uint32_t rv_idx);
|
||||
|
||||
LIBLTE_API int pusch_decode(pusch_t *q,
|
||||
cf_t *sf_symbols,
|
||||
cf_t *ce[MAX_PORTS],
|
||||
cf_t *ce,
|
||||
float noise_estimate,
|
||||
uint8_t *data,
|
||||
uint32_t nsubframe,
|
||||
|
|
|
@ -65,7 +65,7 @@ typedef struct LIBLTE_API {
|
|||
crc_t crc_tb;
|
||||
crc_t crc_cb;
|
||||
|
||||
uci_cqi_t uci_cqi;
|
||||
uci_cqi_pusch_t uci_cqi;
|
||||
|
||||
} sch_t;
|
||||
|
||||
|
|
|
@ -34,13 +34,16 @@
|
|||
#include "liblte/phy/phch/harq.h"
|
||||
#include "liblte/phy/fec/crc.h"
|
||||
|
||||
#define MAX_CQI_LEN 512
|
||||
#define MAX_CQI_LEN_PUSCH 512
|
||||
#define MAX_CQI_LEN_PUCCH 13
|
||||
#define CQI_CODED_PUCCH_B 20
|
||||
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
crc_t crc;
|
||||
uint8_t tmp_cqi[MAX_CQI_LEN];
|
||||
uint8_t encoded_cqi[3*MAX_CQI_LEN];
|
||||
} uci_cqi_t;
|
||||
uint8_t tmp_cqi[MAX_CQI_LEN_PUSCH];
|
||||
uint8_t encoded_cqi[3*MAX_CQI_LEN_PUSCH];
|
||||
} uci_cqi_pusch_t;
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
uint8_t *uci_cqi;
|
||||
|
@ -54,17 +57,21 @@ typedef struct LIBLTE_API {
|
|||
float beta_ack;
|
||||
} uci_data_t;
|
||||
|
||||
LIBLTE_API int uci_cqi_init(uci_cqi_t *q);
|
||||
LIBLTE_API int uci_cqi_init(uci_cqi_pusch_t *q);
|
||||
|
||||
LIBLTE_API void uci_cqi_free(uci_cqi_t *q);
|
||||
LIBLTE_API void uci_cqi_free(uci_cqi_pusch_t *q);
|
||||
|
||||
LIBLTE_API int uci_encode_cqi(uci_cqi_t *q,
|
||||
uint8_t *cqi_data,
|
||||
uint32_t cqi_len,
|
||||
float beta,
|
||||
uint32_t Q_prime_ri,
|
||||
harq_t *harq_process,
|
||||
uint8_t *q_bits);
|
||||
LIBLTE_API int uci_encode_cqi_pusch(uci_cqi_pusch_t *q,
|
||||
uint8_t *cqi_data,
|
||||
uint32_t cqi_len,
|
||||
float beta,
|
||||
uint32_t Q_prime_ri,
|
||||
harq_t *harq_process,
|
||||
uint8_t *q_bits);
|
||||
|
||||
LIBLTE_API int uci_encode_cqi_pucch(uint8_t *cqi_data,
|
||||
uint32_t cqi_len,
|
||||
uint8_t b_bits[CQI_CODED_PUCCH_B]);
|
||||
|
||||
LIBLTE_API int uci_encode_ack(uint8_t data,
|
||||
uint32_t O_cqi,
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "liblte/phy/fec/rm_turbo.h"
|
||||
|
||||
#include "liblte/phy/filter/filter2d.h"
|
||||
#include "liblte/phy/filter/dft_precoding.h"
|
||||
|
||||
#include "liblte/phy/io/binsource.h"
|
||||
#include "liblte/phy/io/filesink.h"
|
||||
|
@ -86,17 +87,18 @@
|
|||
#include "liblte/phy/mimo/precoding.h"
|
||||
#include "liblte/phy/mimo/layermap.h"
|
||||
|
||||
#include "liblte/phy/phch/regs.h"
|
||||
#include "liblte/phy/phch/cqi.h"
|
||||
#include "liblte/phy/phch/dci.h"
|
||||
#include "liblte/phy/phch/pdcch.h"
|
||||
#include "liblte/phy/phch/pdsch.h"
|
||||
#include "liblte/phy/phch/harq.h"
|
||||
#include "liblte/phy/phch/pbch.h"
|
||||
#include "liblte/phy/phch/pcfich.h"
|
||||
#include "liblte/phy/phch/pdcch.h"
|
||||
#include "liblte/phy/phch/pdsch.h"
|
||||
#include "liblte/phy/phch/phich.h"
|
||||
|
||||
#include "liblte/phy/phch/sch.h"
|
||||
|
||||
#include "liblte/phy/phch/pusch.h"
|
||||
#include "liblte/phy/phch/ra.h"
|
||||
#include "liblte/phy/phch/regs.h"
|
||||
#include "liblte/phy/phch/sch.h"
|
||||
#include "liblte/phy/phch/uci.h"
|
||||
|
||||
#include "liblte/phy/ue/ue_sync.h"
|
||||
|
|
|
@ -41,17 +41,37 @@
|
|||
#include "liblte/phy/utils/debug.h"
|
||||
|
||||
|
||||
void cqi_hl_subband_pack(cqi_hl_subband_t *msg, uint32_t N, uint8_t *buff, uint32_t buff_len)
|
||||
int cqi_hl_subband_pack(cqi_hl_subband_t *msg, uint32_t N, uint8_t *buff, uint32_t buff_len)
|
||||
{
|
||||
uint8_t *body_ptr = buff;
|
||||
bit_pack(msg->wideband_cqi, &body_ptr, 4);
|
||||
bit_pack(msg->subband_diff_cqi, &body_ptr, 2*N);
|
||||
|
||||
return 4+2*N;
|
||||
}
|
||||
|
||||
void cqi_ue_subband_pack(cqi_ue_subband_t *msg, uint32_t L, uint8_t *buff, uint32_t buff_len)
|
||||
int cqi_ue_subband_pack(cqi_ue_subband_t *msg, uint32_t L, uint8_t *buff, uint32_t buff_len)
|
||||
{
|
||||
uint8_t *body_ptr = buff;
|
||||
bit_pack(msg->wideband_cqi, &body_ptr, 4);
|
||||
bit_pack(msg->subband_diff_cqi, &body_ptr, 2);
|
||||
bit_pack(msg->subband_diff_cqi, &body_ptr, L);
|
||||
|
||||
return 4+2+L;
|
||||
}
|
||||
|
||||
int cqi_format2_wideband_pack(cqi_format2_wideband_t *msg, uint8_t *buff, uint32_t buff_len)
|
||||
{
|
||||
uint8_t *body_ptr = buff;
|
||||
bit_pack(msg->wideband_cqi, &body_ptr, 4);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int cqi_format2_subband_pack(cqi_format2_subband_t *msg, uint8_t *buff, uint32_t buff_len)
|
||||
{
|
||||
uint8_t *body_ptr = buff;
|
||||
bit_pack(msg->subband_cqi, &body_ptr, 4);
|
||||
bit_pack(msg->subband_label, &body_ptr, 1);
|
||||
return 4+1;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "liblte/phy/utils/bit.h"
|
||||
#include "liblte/phy/utils/debug.h"
|
||||
#include "liblte/phy/utils/vector.h"
|
||||
|
||||
#include "liblte/phy/filter/dft_precoding.h"
|
||||
|
||||
#define MAX_PUSCH_RE(cp) (2 * CP_NSYMB(cp) * 12)
|
||||
|
||||
|
@ -118,6 +118,14 @@ int pusch_init(pusch_t *q, lte_cell_t cell) {
|
|||
|
||||
sch_init(&q->dl_sch);
|
||||
|
||||
dft_precoding_init(&q->dft_precoding, cell.nof_prb);
|
||||
|
||||
/* This is for equalization at receiver */
|
||||
if (precoding_init(&q->equalizer, SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
q->rnti_is_set = false;
|
||||
|
||||
// Allocate floats for reception (LLRs). Buffer casted to uint8_t for transmission
|
||||
|
@ -136,19 +144,13 @@ int pusch_init(pusch_t *q, lte_cell_t cell) {
|
|||
goto clean;
|
||||
}
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
q->ce[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
|
||||
if (!q->ce[i]) {
|
||||
goto clean;
|
||||
}
|
||||
q->pusch_x[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
|
||||
if (!q->pusch_x[i]) {
|
||||
goto clean;
|
||||
}
|
||||
q->pusch_symbols[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
|
||||
if (!q->pusch_symbols[i]) {
|
||||
goto clean;
|
||||
}
|
||||
q->ce = vec_malloc(sizeof(cf_t) * q->max_symbols);
|
||||
if (!q->ce) {
|
||||
goto clean;
|
||||
}
|
||||
q->pusch_z = vec_malloc(sizeof(cf_t) * q->max_symbols);
|
||||
if (!q->pusch_z) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
ret = LIBLTE_SUCCESS;
|
||||
|
@ -172,17 +174,16 @@ void pusch_free(pusch_t *q) {
|
|||
if (q->pusch_g) {
|
||||
free(q->pusch_g);
|
||||
}
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
if (q->ce[i]) {
|
||||
free(q->ce[i]);
|
||||
}
|
||||
if (q->pusch_x[i]) {
|
||||
free(q->pusch_x[i]);
|
||||
}
|
||||
if (q->pusch_symbols[i]) {
|
||||
free(q->pusch_symbols[i]);
|
||||
}
|
||||
if (q->ce) {
|
||||
free(q->ce);
|
||||
}
|
||||
if (q->pusch_z) {
|
||||
free(q->pusch_z);
|
||||
}
|
||||
|
||||
dft_precoding_free(&q->dft_precoding);
|
||||
|
||||
precoding_free(&q->equalizer);
|
||||
|
||||
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
|
||||
sequence_free(&q->seq_pusch[i]);
|
||||
|
@ -215,13 +216,12 @@ int pusch_set_rnti(pusch_t *q, uint16_t rnti) {
|
|||
|
||||
/** Decodes the PUSCH from the received symbols
|
||||
*/
|
||||
int pusch_decode(pusch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate, uint8_t *data, uint32_t subframe,
|
||||
int pusch_decode(pusch_t *q, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data, uint32_t subframe,
|
||||
harq_t *harq_process, uint32_t rv_idx)
|
||||
{
|
||||
|
||||
/* Set pointers for layermapping & precoding */
|
||||
uint32_t i, n;
|
||||
cf_t *x[MAX_LAYERS];
|
||||
uint32_t n;
|
||||
uint32_t nof_symbols, nof_bits, nof_bits_e;
|
||||
|
||||
if (q != NULL &&
|
||||
|
@ -233,35 +233,32 @@ int pusch_decode(pusch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
|
|||
|
||||
if (q->rnti_is_set) {
|
||||
nof_bits = harq_process->mcs.tbs;
|
||||
nof_symbols = harq_process->prb_alloc.re_sf[subframe];
|
||||
nof_symbols = 2*harq_process->prb_alloc.slot[0].nof_prb*RE_X_RB*(CP_NSYMB(q->cell.cp)-1);
|
||||
nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod);
|
||||
|
||||
|
||||
INFO("Decoding PUSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||
subframe, lte_mod_string(harq_process->mcs.mod), nof_bits, nof_symbols, nof_bits_e, rv_idx);
|
||||
|
||||
/* number of layers equals number of ports */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
x[i] = q->pusch_x[i];
|
||||
}
|
||||
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
|
||||
|
||||
/* extract symbols */
|
||||
n = pusch_get(q, sf_symbols, q->pusch_symbols[0], &harq_process->prb_alloc, subframe);
|
||||
n = pusch_get(q, sf_symbols, q->pusch_d, &harq_process->prb_alloc, subframe);
|
||||
if (n != nof_symbols) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
/* extract channel estimates */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
n = pusch_get(q, ce[i], q->ce[i], &harq_process->prb_alloc, subframe);
|
||||
if (n != nof_symbols) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
n = pusch_get(q, ce, q->ce, &harq_process->prb_alloc, subframe);
|
||||
if (n != nof_symbols) {
|
||||
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
predecoding_single(&q->equalizer, q->pusch_d, q->ce, q->pusch_z,
|
||||
nof_symbols, noise_estimate);
|
||||
|
||||
dft_predecoding(&q->dft_precoding, q->pusch_z, q->pusch_d,
|
||||
harq_process->prb_alloc.slot[0].nof_prb, harq_process->N_symb_ul);
|
||||
|
||||
/* demodulate symbols
|
||||
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
|
||||
* thus we don't need tot set it in the LLRs normalization
|
||||
|
@ -278,13 +275,12 @@ int pusch_decode(pusch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
|
|||
fprintf(stderr, "Must call pusch_set_rnti() before calling pusch_decode()\n");
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
int pusch_qncode(pusch_t *q, uint8_t *data, cf_t *sf_symbols[MAX_PORTS], uint32_t subframe,
|
||||
int pusch_encode(pusch_t *q, uint8_t *data, cf_t *sf_symbols, uint32_t subframe,
|
||||
harq_t *harq_process, uint32_t rv_idx)
|
||||
{
|
||||
uci_data_t uci_data;
|
||||
|
@ -295,28 +291,19 @@ int pusch_qncode(pusch_t *q, uint8_t *data, cf_t *sf_symbols[MAX_PORTS], uint32_
|
|||
/** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission
|
||||
*/
|
||||
int pusch_uci_encode(pusch_t *q, uint8_t *data, uci_data_t uci_data,
|
||||
cf_t *sf_symbols[MAX_PORTS], uint32_t subframe,
|
||||
cf_t *sf_symbols, uint32_t subframe,
|
||||
harq_t *harq_process, uint32_t rv_idx)
|
||||
{
|
||||
int i;
|
||||
uint32_t nof_symbols, nof_bits_ulsch, nof_bits_e;
|
||||
/* Set pointers for layermapping & precoding */
|
||||
cf_t *x[MAX_LAYERS];
|
||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
int ret = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if (q != NULL &&
|
||||
if (q != NULL &&
|
||||
data != NULL &&
|
||||
subframe < 10 &&
|
||||
harq_process != NULL)
|
||||
{
|
||||
|
||||
if (q->rnti_is_set) {
|
||||
for (i=0;i<q->cell.nof_ports;i++) {
|
||||
if (sf_symbols[i] == NULL) {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
nof_bits_ulsch = harq_process->mcs.tbs;
|
||||
nof_symbols = 2*harq_process->prb_alloc.slot[0].nof_prb*RE_X_RB*(CP_NSYMB(q->cell.cp)-1);
|
||||
nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod);
|
||||
|
@ -340,12 +327,6 @@ int pusch_uci_encode(pusch_t *q, uint8_t *data, uci_data_t uci_data,
|
|||
INFO("Encoding PUSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
|
||||
subframe, lte_mod_string(harq_process->mcs.mod), nof_bits_ulsch, nof_symbols, nof_bits_e, rv_idx);
|
||||
|
||||
/* number of layers equals number of ports */
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
x[i] = q->pusch_x[i];
|
||||
}
|
||||
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
|
||||
|
||||
if (ulsch_uci_encode(&q->dl_sch, data, uci_data, q->pusch_g, harq_process, rv_idx, q->pusch_q))
|
||||
{
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
|
@ -356,11 +337,11 @@ int pusch_uci_encode(pusch_t *q, uint8_t *data, uci_data_t uci_data,
|
|||
|
||||
mod_modulate(&q->mod[harq_process->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, nof_bits_e);
|
||||
|
||||
/* mapping to resource elements */
|
||||
dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z,
|
||||
harq_process->prb_alloc.slot[0].nof_prb, harq_process->N_symb_ul);
|
||||
|
||||
for (i = 0; i < q->cell.nof_ports; i++) {
|
||||
pusch_put(q, q->pusch_symbols[i], sf_symbols[i], &harq_process->prb_alloc, subframe);
|
||||
}
|
||||
/* mapping to resource elements */
|
||||
pusch_put(q, q->pusch_z, sf_symbols, &harq_process->prb_alloc, subframe);
|
||||
|
||||
ret = LIBLTE_SUCCESS;
|
||||
} else {
|
||||
|
|
|
@ -467,7 +467,7 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi
|
|||
// Encode CQI
|
||||
if (uci_data.uci_cqi_len > 0) {
|
||||
|
||||
ret = uci_encode_cqi(&q->uci_cqi, uci_data.uci_cqi, uci_data.uci_cqi_len, uci_data.beta_cqi,
|
||||
ret = uci_encode_cqi_pusch(&q->uci_cqi, uci_data.uci_cqi, uci_data.uci_cqi_len, uci_data.beta_cqi,
|
||||
Q_prime_ri, harq_process, g_bits);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include "liblte/phy/utils/debug.h"
|
||||
|
||||
/* Table 5.2.2.6.4-1: Basis sequence for (32, O) code */
|
||||
static uint8_t M_basis_seq[32][11]={
|
||||
static uint8_t M_basis_seq_pusch[32][11]={
|
||||
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||
{1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 },
|
||||
{1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 },
|
||||
|
@ -79,14 +79,38 @@ static uint8_t M_basis_seq[32][11]={
|
|||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
int uci_cqi_init(uci_cqi_t *q) {
|
||||
|
||||
static uint8_t M_basis_seq_pucch[20][13]={
|
||||
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
|
||||
{1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0},
|
||||
{1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1},
|
||||
{1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1},
|
||||
{1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1},
|
||||
{1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1},
|
||||
{1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1},
|
||||
{1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1},
|
||||
{1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1},
|
||||
{1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1},
|
||||
{1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1},
|
||||
{1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1},
|
||||
{1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1},
|
||||
{1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1},
|
||||
{1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1},
|
||||
{1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1},
|
||||
{1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1},
|
||||
{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},
|
||||
};
|
||||
|
||||
int uci_cqi_init(uci_cqi_pusch_t *q) {
|
||||
if (crc_init(&q->crc, LTE_CRC8, 8)) {
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
return LIBLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void uci_cqi_free(uci_cqi_t *q) {
|
||||
void uci_cqi_free(uci_cqi_pusch_t *q) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -112,17 +136,17 @@ static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, harq_t
|
|||
|
||||
/* Encode UCI CQI/PMI for payloads equal or lower to 11 bits (Sec 5.2.2.6.4)
|
||||
*/
|
||||
int encode_cqi_short(uci_cqi_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_bits, uint32_t Q)
|
||||
int encode_cqi_short(uci_cqi_pusch_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_bits, uint32_t Q)
|
||||
{
|
||||
if (nof_bits < MAX_CQI_LEN &&
|
||||
q != NULL &&
|
||||
data != NULL &&
|
||||
if (nof_bits < MAX_CQI_LEN_PUSCH &&
|
||||
q != NULL &&
|
||||
data != NULL &&
|
||||
q_bits != NULL)
|
||||
{
|
||||
for (int i=0;i<32;i++) {
|
||||
q->encoded_cqi[i] = 0;
|
||||
for (int n=0;n<nof_bits;n++) {
|
||||
q->encoded_cqi[i] += (data[n] * M_basis_seq[i][n]);
|
||||
q->encoded_cqi[i] += (data[n] * M_basis_seq_pusch[i][n]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,13 +161,13 @@ int encode_cqi_short(uci_cqi_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_
|
|||
|
||||
/* Encode UCI CQI/PMI for payloads greater than 11 bits (go through CRC, conv coder and rate match)
|
||||
*/
|
||||
int encode_cqi_long(uci_cqi_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_bits, uint32_t Q)
|
||||
int encode_cqi_long(uci_cqi_pusch_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_bits, uint32_t Q)
|
||||
{
|
||||
convcoder_t encoder;
|
||||
|
||||
if (nof_bits + 8 < MAX_CQI_LEN &&
|
||||
q != NULL &&
|
||||
data != NULL &&
|
||||
if (nof_bits + 8 < MAX_CQI_LEN_PUSCH &&
|
||||
q != NULL &&
|
||||
data != NULL &&
|
||||
q_bits != NULL)
|
||||
{
|
||||
|
||||
|
@ -173,9 +197,27 @@ int encode_cqi_long(uci_cqi_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_b
|
|||
}
|
||||
}
|
||||
|
||||
/* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212
|
||||
*/
|
||||
int uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[CQI_CODED_PUCCH_B])
|
||||
{
|
||||
if (cqi_len <= MAX_CQI_LEN_PUCCH) {
|
||||
for (uint32_t i=0;i<CQI_CODED_PUCCH_B;i++) {
|
||||
uint64_t x=0;
|
||||
for (uint32_t n=0;n<cqi_len;n++) {
|
||||
x += cqi_data[n]*M_basis_seq_pucch[n][i];
|
||||
}
|
||||
b_bits[i] = (uint8_t) (x%2);
|
||||
}
|
||||
return LIBLTE_SUCCESS;
|
||||
} else {
|
||||
return LIBLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode UCI CQI/PMI as described in 5.2.2.6 of 36.212
|
||||
*/
|
||||
int uci_encode_cqi(uci_cqi_t *q, uint8_t *cqi_data, uint32_t cqi_len, float beta, uint32_t Q_prime_ri,
|
||||
int uci_encode_cqi_pusch(uci_cqi_pusch_t *q, uint8_t *cqi_data, uint32_t cqi_len, float beta, uint32_t Q_prime_ri,
|
||||
harq_t *harq_process, uint8_t *q_bits)
|
||||
{
|
||||
|
||||
|
@ -313,3 +355,4 @@ int uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq_process
|
|||
return (int) Qprime;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ ADD_EXECUTABLE(pusch_test pusch_test.c)
|
|||
TARGET_LINK_LIBRARIES(pusch_test lte_phy)
|
||||
|
||||
BuildMex(MEXNAME ulsch_encode SOURCES ulsch_encode_test_mex.c LIBRARIES lte_phy liblte_mex)
|
||||
BuildMex(MEXNAME pusch_encode SOURCES pusch_encode_test_mex.c LIBRARIES lte_phy liblte_mex)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -50,20 +50,19 @@ lte_mod_t modulation = LTE_QPSK;
|
|||
uint32_t rv_idx = 0;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [cpsrnfvmt] -l TBS \n", prog);
|
||||
printf("Usage: %s [csrnfvmt] -l TBS \n", prog);
|
||||
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
|
||||
printf("\t-c cell id [Default %d]\n", cell.id);
|
||||
printf("\t-s subframe [Default %d]\n", subframe);
|
||||
printf("\t-r rv_idx [Default %d]\n", rv_idx);
|
||||
printf("\t-f cfi [Default %d]\n", cfi);
|
||||
printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports);
|
||||
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
|
||||
printf("\t-v [set verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "lcpnfvmtsr")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "lcnfvmtsr")) != -1) {
|
||||
switch(opt) {
|
||||
case 'm':
|
||||
switch(atoi(argv[optind])) {
|
||||
|
@ -94,9 +93,6 @@ void parse_args(int argc, char **argv) {
|
|||
case 'l':
|
||||
tbs = atoi(argv[optind]);
|
||||
break;
|
||||
case 'p':
|
||||
cell.nof_ports = atoi(argv[optind]);
|
||||
break;
|
||||
case 'n':
|
||||
cell.nof_prb = atoi(argv[optind]);
|
||||
break;
|
||||
|
@ -115,11 +111,10 @@ void parse_args(int argc, char **argv) {
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
pusch_t pusch;
|
||||
uint32_t i, j;
|
||||
uint8_t *data = NULL;
|
||||
cf_t *ce[MAX_PORTS];
|
||||
cf_t *ce;
|
||||
uint32_t nof_re;
|
||||
cf_t *slot_symbols[MAX_PORTS];
|
||||
cf_t *sf_symbols;
|
||||
int ret = -1;
|
||||
struct timeval t[3];
|
||||
ra_mcs_t mcs;
|
||||
|
@ -134,26 +129,18 @@ int main(int argc, char **argv) {
|
|||
mcs.mod = modulation;
|
||||
|
||||
prb_alloc.slot[0].nof_prb = 1;
|
||||
//for (i=0;i<prb_alloc.slot[0].nof_prb;i++) {
|
||||
// prb_alloc.slot[0].prb_idx[i] = true;
|
||||
//}
|
||||
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
|
||||
|
||||
/* init memory */
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
ce[i] = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!ce[i]) {
|
||||
perror("malloc");
|
||||
goto quit;
|
||||
}
|
||||
for (j=0;j<nof_re;j++) {
|
||||
ce[i][j] = 1;
|
||||
}
|
||||
slot_symbols[i] = calloc(sizeof(cf_t) , nof_re);
|
||||
if (!slot_symbols[i]) {
|
||||
perror("malloc");
|
||||
goto quit;
|
||||
}
|
||||
ce = malloc(sizeof(cf_t) * nof_re);
|
||||
if (!ce) {
|
||||
perror("malloc");
|
||||
goto quit;
|
||||
}
|
||||
sf_symbols = calloc(sizeof(cf_t) , nof_re);
|
||||
if (!sf_symbols) {
|
||||
perror("malloc");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
data = malloc(sizeof(uint8_t) * mcs.tbs);
|
||||
|
@ -178,7 +165,7 @@ int main(int argc, char **argv) {
|
|||
goto quit;
|
||||
}
|
||||
|
||||
for (i=0;i<mcs.tbs;i++) {
|
||||
for (uint32_t i=0;i<mcs.tbs;i++) {
|
||||
data[i] = 1;
|
||||
}
|
||||
|
||||
|
@ -188,7 +175,7 @@ int main(int argc, char **argv) {
|
|||
printf("Encoding rv_idx=%d\n",rv_idx);
|
||||
|
||||
uint8_t tmp[20];
|
||||
for (i=0;i<20;i++) {
|
||||
for (uint32_t i=0;i<20;i++) {
|
||||
tmp[i] = 1;
|
||||
}
|
||||
uci_data_t uci_data;
|
||||
|
@ -206,35 +193,17 @@ int main(int argc, char **argv) {
|
|||
uci_data.uci_ack = 1;
|
||||
|
||||
uint32_t nof_symbols = 12*harq_process.prb_alloc.slot[0].nof_prb*RE_X_RB;
|
||||
uint32_t nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process.mcs.mod);
|
||||
|
||||
bzero(pusch.pusch_q, nof_bits_e*sizeof(uint8_t));
|
||||
|
||||
|
||||
if (ulsch_uci_encode(&pusch.dl_sch, data, uci_data, pusch.pusch_g, &harq_process, 0, pusch.pusch_q))
|
||||
{
|
||||
if (pusch_uci_encode(&pusch, data, uci_data, sf_symbols, subframe, &harq_process, 0)) {
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (rv_idx > 0) {
|
||||
if (ulsch_uci_encode(&pusch.dl_sch, data, uci_data, pusch.pusch_g, &harq_process, rv_idx, pusch.pusch_q))
|
||||
{
|
||||
if (pusch_uci_encode(&pusch, data, uci_data, sf_symbols, subframe, &harq_process, rv_idx)) {
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
vec_fprint_b(stdout, pusch.pusch_q, nof_bits_e);
|
||||
|
||||
/* combine outputs */
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (j=0;j<nof_re;j++) {
|
||||
if (i > 0) {
|
||||
slot_symbols[0][j] += slot_symbols[i][j];
|
||||
}
|
||||
ce[i][j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&t[1], NULL);
|
||||
|
@ -255,13 +224,11 @@ quit:
|
|||
pusch_free(&pusch);
|
||||
harq_free(&harq_process);
|
||||
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
if (ce[i]) {
|
||||
free(ce[i]);
|
||||
}
|
||||
if (slot_symbols[i]) {
|
||||
free(slot_symbols[i]);
|
||||
}
|
||||
if (ce) {
|
||||
free(ce);
|
||||
}
|
||||
if (sf_symbols) {
|
||||
free(sf_symbols);
|
||||
}
|
||||
if (data) {
|
||||
free(data);
|
||||
|
|
Loading…
Reference in New Issue