Added DFT Transform Precoding. Added PUSCH matlab test. Added UCI PUCCH coding

This commit is contained in:
ismagom 2015-02-13 10:02:10 +01:00
parent 908e4f0373
commit 6b8d019fce
11 changed files with 215 additions and 168 deletions

View File

@ -58,15 +58,37 @@ typedef struct LIBLTE_API {
uint32_t position_subband; // L-bit width uint32_t position_subband; // L-bit width
} cqi_ue_subband_t; } 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, uint32_t N,
uint8_t *buff, uint8_t *buff,
uint32_t buff_len); 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, uint32_t L,
uint8_t *buff, uint8_t *buff,
uint32_t buff_len); 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_ #endif // CQI_

View File

@ -26,7 +26,7 @@
*/ */
#ifndef PUCH_ #ifndef PUSCH_
#define PUSCH_ #define PUSCH_
#include "liblte/config.h" #include "liblte/config.h"
@ -39,12 +39,13 @@
#include "liblte/phy/phch/regs.h" #include "liblte/phy/phch/regs.h"
#include "liblte/phy/phch/sch.h" #include "liblte/phy/phch/sch.h"
#include "liblte/phy/phch/harq.h" #include "liblte/phy/phch/harq.h"
#include "liblte/phy/filter/dft_precoding.h"
#define TDEC_MAX_ITERATIONS 5 #define TDEC_MAX_ITERATIONS 5
typedef _Complex float cf_t; typedef _Complex float cf_t;
/* PDSCH object */ /* PUSCH object */
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
lte_cell_t cell; lte_cell_t cell;
@ -52,11 +53,14 @@ typedef struct LIBLTE_API {
bool rnti_is_set; bool rnti_is_set;
uint16_t rnti; uint16_t rnti;
dft_precoding_t dft_precoding;
precoding_t equalizer;
/* buffers */ /* buffers */
// void buffers are shared for tx and rx // void buffers are shared for tx and rx
cf_t *ce[MAX_PORTS]; cf_t *ce;
cf_t *pusch_symbols[MAX_PORTS]; cf_t *pusch_z;
cf_t *pusch_x[MAX_PORTS];
cf_t *pusch_d; cf_t *pusch_d;
void *pusch_q; void *pusch_q;
@ -84,7 +88,7 @@ LIBLTE_API int pusch_set_rnti(pusch_t *q,
LIBLTE_API int pusch_encode(pusch_t *q, LIBLTE_API int pusch_encode(pusch_t *q,
uint8_t *data, uint8_t *data,
cf_t *sf_symbols[MAX_PORTS], cf_t *sf_symbols,
uint32_t nsubframe, uint32_t nsubframe,
harq_t *harq_process, harq_t *harq_process,
uint32_t rv_idx); 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, LIBLTE_API int pusch_uci_encode(pusch_t *q,
uint8_t *data, uint8_t *data,
uci_data_t uci_data, uci_data_t uci_data,
cf_t *sf_symbols[MAX_PORTS], cf_t *sf_symbols,
uint32_t subframe, uint32_t subframe,
harq_t *harq_process, harq_t *harq_process,
uint32_t rv_idx); uint32_t rv_idx);
LIBLTE_API int pusch_decode(pusch_t *q, LIBLTE_API int pusch_decode(pusch_t *q,
cf_t *sf_symbols, cf_t *sf_symbols,
cf_t *ce[MAX_PORTS], cf_t *ce,
float noise_estimate, float noise_estimate,
uint8_t *data, uint8_t *data,
uint32_t nsubframe, uint32_t nsubframe,

View File

@ -65,7 +65,7 @@ typedef struct LIBLTE_API {
crc_t crc_tb; crc_t crc_tb;
crc_t crc_cb; crc_t crc_cb;
uci_cqi_t uci_cqi; uci_cqi_pusch_t uci_cqi;
} sch_t; } sch_t;

View File

@ -34,13 +34,16 @@
#include "liblte/phy/phch/harq.h" #include "liblte/phy/phch/harq.h"
#include "liblte/phy/fec/crc.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 { typedef struct LIBLTE_API {
crc_t crc; crc_t crc;
uint8_t tmp_cqi[MAX_CQI_LEN]; uint8_t tmp_cqi[MAX_CQI_LEN_PUSCH];
uint8_t encoded_cqi[3*MAX_CQI_LEN]; uint8_t encoded_cqi[3*MAX_CQI_LEN_PUSCH];
} uci_cqi_t; } uci_cqi_pusch_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
uint8_t *uci_cqi; uint8_t *uci_cqi;
@ -54,11 +57,11 @@ typedef struct LIBLTE_API {
float beta_ack; float beta_ack;
} uci_data_t; } 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, LIBLTE_API int uci_encode_cqi_pusch(uci_cqi_pusch_t *q,
uint8_t *cqi_data, uint8_t *cqi_data,
uint32_t cqi_len, uint32_t cqi_len,
float beta, float beta,
@ -66,6 +69,10 @@ LIBLTE_API int uci_encode_cqi(uci_cqi_t *q,
harq_t *harq_process, harq_t *harq_process,
uint8_t *q_bits); 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, LIBLTE_API int uci_encode_ack(uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,
float beta, float beta,

View File

@ -71,6 +71,7 @@
#include "liblte/phy/fec/rm_turbo.h" #include "liblte/phy/fec/rm_turbo.h"
#include "liblte/phy/filter/filter2d.h" #include "liblte/phy/filter/filter2d.h"
#include "liblte/phy/filter/dft_precoding.h"
#include "liblte/phy/io/binsource.h" #include "liblte/phy/io/binsource.h"
#include "liblte/phy/io/filesink.h" #include "liblte/phy/io/filesink.h"
@ -86,17 +87,18 @@
#include "liblte/phy/mimo/precoding.h" #include "liblte/phy/mimo/precoding.h"
#include "liblte/phy/mimo/layermap.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/dci.h"
#include "liblte/phy/phch/pdcch.h" #include "liblte/phy/phch/harq.h"
#include "liblte/phy/phch/pdsch.h"
#include "liblte/phy/phch/pbch.h" #include "liblte/phy/phch/pbch.h"
#include "liblte/phy/phch/pcfich.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/phich.h"
#include "liblte/phy/phch/sch.h"
#include "liblte/phy/phch/pusch.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/phch/uci.h"
#include "liblte/phy/ue/ue_sync.h" #include "liblte/phy/ue/ue_sync.h"

View File

@ -41,17 +41,37 @@
#include "liblte/phy/utils/debug.h" #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; uint8_t *body_ptr = buff;
bit_pack(msg->wideband_cqi, &body_ptr, 4); bit_pack(msg->wideband_cqi, &body_ptr, 4);
bit_pack(msg->subband_diff_cqi, &body_ptr, 2*N); 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; uint8_t *body_ptr = buff;
bit_pack(msg->wideband_cqi, &body_ptr, 4); 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, 2);
bit_pack(msg->subband_diff_cqi, &body_ptr, L); 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;
}

View File

@ -41,7 +41,7 @@
#include "liblte/phy/utils/bit.h" #include "liblte/phy/utils/bit.h"
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
#include "liblte/phy/utils/vector.h" #include "liblte/phy/utils/vector.h"
#include "liblte/phy/filter/dft_precoding.h"
#define MAX_PUSCH_RE(cp) (2 * CP_NSYMB(cp) * 12) #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); 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; q->rnti_is_set = false;
// Allocate floats for reception (LLRs). Buffer casted to uint8_t for transmission // Allocate floats for reception (LLRs). Buffer casted to uint8_t for transmission
@ -136,20 +144,14 @@ int pusch_init(pusch_t *q, lte_cell_t cell) {
goto clean; goto clean;
} }
for (i = 0; i < q->cell.nof_ports; i++) { q->ce = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->ce[i] = vec_malloc(sizeof(cf_t) * q->max_symbols); if (!q->ce) {
if (!q->ce[i]) {
goto clean; goto clean;
} }
q->pusch_x[i] = vec_malloc(sizeof(cf_t) * q->max_symbols); q->pusch_z = vec_malloc(sizeof(cf_t) * q->max_symbols);
if (!q->pusch_x[i]) { if (!q->pusch_z) {
goto clean; goto clean;
} }
q->pusch_symbols[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
if (!q->pusch_symbols[i]) {
goto clean;
}
}
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
} }
@ -172,18 +174,17 @@ void pusch_free(pusch_t *q) {
if (q->pusch_g) { if (q->pusch_g) {
free(q->pusch_g); free(q->pusch_g);
} }
for (i = 0; i < q->cell.nof_ports; i++) { if (q->ce) {
if (q->ce[i]) { free(q->ce);
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->pusch_z) {
free(q->pusch_z);
} }
dft_precoding_free(&q->dft_precoding);
precoding_free(&q->equalizer);
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
sequence_free(&q->seq_pusch[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 /** 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) harq_t *harq_process, uint32_t rv_idx)
{ {
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
uint32_t i, n; uint32_t n;
cf_t *x[MAX_LAYERS];
uint32_t nof_symbols, nof_bits, nof_bits_e; uint32_t nof_symbols, nof_bits, nof_bits_e;
if (q != NULL && if (q != NULL &&
@ -233,34 +233,31 @@ int pusch_decode(pusch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
if (q->rnti_is_set) { if (q->rnti_is_set) {
nof_bits = harq_process->mcs.tbs; 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); 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", 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); 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 */ /* 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) { if (n != nof_symbols) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
/* extract channel estimates */ /* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) { n = pusch_get(q, ce, q->ce, &harq_process->prb_alloc, subframe);
n = pusch_get(q, ce[i], q->ce[i], &harq_process->prb_alloc, subframe);
if (n != nof_symbols) { if (n != nof_symbols) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
return LIBLTE_ERROR; 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 /* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
@ -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"); fprintf(stderr, "Must call pusch_set_rnti() before calling pusch_decode()\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} else { } else {
return LIBLTE_ERROR_INVALID_INPUTS; 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) harq_t *harq_process, uint32_t rv_idx)
{ {
uci_data_t uci_data; uci_data_t uci_data;
@ -295,13 +291,10 @@ 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 /** 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, 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) harq_t *harq_process, uint32_t rv_idx)
{ {
int i;
uint32_t nof_symbols, nof_bits_ulsch, nof_bits_e; 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 &&
@ -311,12 +304,6 @@ int pusch_uci_encode(pusch_t *q, uint8_t *data, uci_data_t uci_data,
{ {
if (q->rnti_is_set) { 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_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_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); 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", 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); 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)) 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"); 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); 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++) { /* mapping to resource elements */
pusch_put(q, q->pusch_symbols[i], sf_symbols[i], &harq_process->prb_alloc, subframe); pusch_put(q, q->pusch_z, sf_symbols, &harq_process->prb_alloc, subframe);
}
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
} else { } else {

View File

@ -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 // Encode CQI
if (uci_data.uci_cqi_len > 0) { 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); Q_prime_ri, harq_process, g_bits);
if (ret < 0) { if (ret < 0) {
return ret; return ret;

View File

@ -44,7 +44,7 @@
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
/* Table 5.2.2.6.4-1: Basis sequence for (32, O) code */ /* 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, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 }, {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 },
{1, 0, 0, 1, 0, 0, 1, 0, 1, 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 }, {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)) { if (crc_init(&q->crc, LTE_CRC8, 8)) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
void uci_cqi_free(uci_cqi_t *q) { void uci_cqi_free(uci_cqi_pusch_t *q) {
} }
@ -112,9 +136,9 @@ 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) /* 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 && if (nof_bits < MAX_CQI_LEN_PUSCH &&
q != NULL && q != NULL &&
data != NULL && data != NULL &&
q_bits != NULL) q_bits != NULL)
@ -122,7 +146,7 @@ int encode_cqi_short(uci_cqi_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_
for (int i=0;i<32;i++) { for (int i=0;i<32;i++) {
q->encoded_cqi[i] = 0; q->encoded_cqi[i] = 0;
for (int n=0;n<nof_bits;n++) { 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,11 +161,11 @@ 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) /* 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; convcoder_t encoder;
if (nof_bits + 8 < MAX_CQI_LEN && if (nof_bits + 8 < MAX_CQI_LEN_PUSCH &&
q != NULL && q != NULL &&
data != NULL && data != NULL &&
q_bits != 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 /* 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) 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; return (int) Qprime;
} }

View File

@ -134,6 +134,7 @@ ADD_EXECUTABLE(pusch_test pusch_test.c)
TARGET_LINK_LIBRARIES(pusch_test lte_phy) TARGET_LINK_LIBRARIES(pusch_test lte_phy)
BuildMex(MEXNAME ulsch_encode SOURCES ulsch_encode_test_mex.c LIBRARIES lte_phy liblte_mex) 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)

View File

@ -50,20 +50,19 @@ lte_mod_t modulation = LTE_QPSK;
uint32_t rv_idx = 0; uint32_t rv_idx = 0;
void usage(char *prog) { 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-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-c cell id [Default %d]\n", cell.id);
printf("\t-s subframe [Default %d]\n", subframe); printf("\t-s subframe [Default %d]\n", subframe);
printf("\t-r rv_idx [Default %d]\n", rv_idx); printf("\t-r rv_idx [Default %d]\n", rv_idx);
printf("\t-f cfi [Default %d]\n", cfi); 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-n cell.nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-v [set verbose to debug, default none]\n"); printf("\t-v [set verbose to debug, default none]\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "lcpnfvmtsr")) != -1) { while ((opt = getopt(argc, argv, "lcnfvmtsr")) != -1) {
switch(opt) { switch(opt) {
case 'm': case 'm':
switch(atoi(argv[optind])) { switch(atoi(argv[optind])) {
@ -94,9 +93,6 @@ void parse_args(int argc, char **argv) {
case 'l': case 'l':
tbs = atoi(argv[optind]); tbs = atoi(argv[optind]);
break; break;
case 'p':
cell.nof_ports = atoi(argv[optind]);
break;
case 'n': case 'n':
cell.nof_prb = atoi(argv[optind]); cell.nof_prb = atoi(argv[optind]);
break; break;
@ -115,11 +111,10 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
pusch_t pusch; pusch_t pusch;
uint32_t i, j;
uint8_t *data = NULL; uint8_t *data = NULL;
cf_t *ce[MAX_PORTS]; cf_t *ce;
uint32_t nof_re; uint32_t nof_re;
cf_t *slot_symbols[MAX_PORTS]; cf_t *sf_symbols;
int ret = -1; int ret = -1;
struct timeval t[3]; struct timeval t[3];
ra_mcs_t mcs; ra_mcs_t mcs;
@ -134,27 +129,19 @@ int main(int argc, char **argv) {
mcs.mod = modulation; mcs.mod = modulation;
prb_alloc.slot[0].nof_prb = 1; 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)); memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
/* init memory */ /* init memory */
for (i=0;i<cell.nof_ports;i++) { ce = malloc(sizeof(cf_t) * nof_re);
ce[i] = malloc(sizeof(cf_t) * nof_re); if (!ce) {
if (!ce[i]) {
perror("malloc"); perror("malloc");
goto quit; goto quit;
} }
for (j=0;j<nof_re;j++) { sf_symbols = calloc(sizeof(cf_t) , nof_re);
ce[i][j] = 1; if (!sf_symbols) {
}
slot_symbols[i] = calloc(sizeof(cf_t) , nof_re);
if (!slot_symbols[i]) {
perror("malloc"); perror("malloc");
goto quit; goto quit;
} }
}
data = malloc(sizeof(uint8_t) * mcs.tbs); data = malloc(sizeof(uint8_t) * mcs.tbs);
if (!data) { if (!data) {
@ -178,7 +165,7 @@ int main(int argc, char **argv) {
goto quit; goto quit;
} }
for (i=0;i<mcs.tbs;i++) { for (uint32_t i=0;i<mcs.tbs;i++) {
data[i] = 1; data[i] = 1;
} }
@ -188,7 +175,7 @@ int main(int argc, char **argv) {
printf("Encoding rv_idx=%d\n",rv_idx); printf("Encoding rv_idx=%d\n",rv_idx);
uint8_t tmp[20]; uint8_t tmp[20];
for (i=0;i<20;i++) { for (uint32_t i=0;i<20;i++) {
tmp[i] = 1; tmp[i] = 1;
} }
uci_data_t uci_data; uci_data_t uci_data;
@ -206,35 +193,17 @@ int main(int argc, char **argv) {
uci_data.uci_ack = 1; uci_data.uci_ack = 1;
uint32_t nof_symbols = 12*harq_process.prb_alloc.slot[0].nof_prb*RE_X_RB; 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 (pusch_uci_encode(&pusch, data, uci_data, sf_symbols, subframe, &harq_process, 0)) {
if (ulsch_uci_encode(&pusch.dl_sch, data, uci_data, pusch.pusch_g, &harq_process, 0, pusch.pusch_q))
{
fprintf(stderr, "Error encoding TB\n"); fprintf(stderr, "Error encoding TB\n");
exit(-1); exit(-1);
} }
if (rv_idx > 0) { 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"); fprintf(stderr, "Error encoding TB\n");
exit(-1); 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); gettimeofday(&t[1], NULL);
@ -255,13 +224,11 @@ quit:
pusch_free(&pusch); pusch_free(&pusch);
harq_free(&harq_process); harq_free(&harq_process);
for (i=0;i<cell.nof_ports;i++) { if (ce) {
if (ce[i]) { free(ce);
free(ce[i]);
}
if (slot_symbols[i]) {
free(slot_symbols[i]);
} }
if (sf_symbols) {
free(sf_symbols);
} }
if (data) { if (data) {
free(data); free(data);