Changed harq object to include RV and subframe. Adapted PDSCH, PUSCH and SCH interfaces

master
ismagom 10 years ago
parent 6b8d019fce
commit 48278aca84

@ -312,7 +312,7 @@ uint32_t prbset_to_bitmask() {
return reverse(mask)>>(32-nb);
}
int update_radl() {
int update_radl(uint32_t sf_idx) {
ra_prb_t prb_alloc;
bzero(&ra_dl, sizeof(ra_pdsch_t));
@ -331,7 +331,7 @@ int update_radl() {
printf("Type new MCS index and press Enter: "); fflush(stdout);
harq_reset(&harq_process);
if (harq_setup(&harq_process, ra_dl.mcs, &prb_alloc)) {
if (harq_setup_dl(&harq_process, ra_dl.mcs, ra_dl.rv_idx, sf_idx, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return -1;
}
@ -340,7 +340,7 @@ int update_radl() {
}
/* Read new MCS from stdin */
int update_control() {
int update_control(uint32_t sf_idx) {
char input[128];
fd_set set;
@ -380,11 +380,11 @@ int update_control() {
mcs_idx = atoi(input);
}
bzero(input,sizeof(input));
if (update_radl()) {
if (update_radl(sf_idx)) {
printf("Trying with last known MCS index\n");
mcs_idx = last_mcs_idx;
prbset_num = last_prbset_num;
return update_radl();
return update_radl(sf_idx);
}
}
return 0;
@ -437,7 +437,7 @@ void *net_thread_fnc(void *arg) {
}
int main(int argc, char **argv) {
int nf, sf_idx, N_id_2;
int nf=0, sf_idx=0, N_id_2=0;
cf_t pss_signal[PSS_LEN];
float sss_signal0[SSS_LEN]; // for subframe 0
float sss_signal5[SSS_LEN]; // for subframe 5
@ -498,7 +498,7 @@ int main(int argc, char **argv) {
}
#endif
if (update_radl()) {
if (update_radl(sf_idx)) {
exit(-1);
}
@ -540,7 +540,7 @@ int main(int argc, char **argv) {
pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
/* Update DL resource allocation from control port */
if (update_control(&ra_dl)) {
if (update_control(sf_idx)) {
fprintf(stderr, "Error updating parameters from control port\n");
}
@ -570,7 +570,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (pdsch_encode(&pdsch, data, sf_symbols, sf_idx, &harq_process, ra_dl.rv_idx)) {
if (pdsch_encode(&pdsch, &harq_process, data, sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
exit(-1);
}

@ -45,11 +45,15 @@
typedef struct LIBLTE_API {
ra_mcs_t mcs;
uint32_t rv;
uint32_t sf_idx;
ra_prb_t prb_alloc;
lte_cell_t cell;
uint32_t N_symb_ul; // Number of symbols for PUSCH transmission
uint32_t nof_prb_pusch_init; // Initial resource allocation for PUSCH.
uint32_t nof_re; // Number of RE per subframe
uint32_t nof_bits; // Number of bits per subframe
uint32_t nof_symb; // Number of symbols per subframe
uint32_t nof_prb; // Number of allocated PRB per subframe.
uint32_t max_cb;
uint32_t w_buff_size;
@ -63,9 +67,17 @@ typedef struct LIBLTE_API {
LIBLTE_API int harq_init(harq_t * q,
lte_cell_t cell);
LIBLTE_API int harq_setup(harq_t *p,
ra_mcs_t mcs,
ra_prb_t *prb_alloc);
LIBLTE_API int harq_setup_dl(harq_t *p,
ra_mcs_t mcs,
uint32_t rv,
uint32_t sf_idx,
ra_prb_t *prb_alloc);
LIBLTE_API int harq_setup_ul(harq_t *p,
ra_mcs_t mcs,
uint32_t rv,
uint32_t sf_idx,
ra_prb_t *prb_alloc);
LIBLTE_API void harq_reset(harq_t *p);

@ -49,7 +49,7 @@ typedef _Complex float cf_t;
typedef struct LIBLTE_API {
lte_cell_t cell;
uint32_t max_symbols;
uint32_t max_re;
bool rnti_is_set;
uint16_t rnti;
@ -79,30 +79,20 @@ LIBLTE_API void pdsch_free(pdsch_t *q);
LIBLTE_API int pdsch_set_rnti(pdsch_t *q,
uint16_t rnti);
LIBLTE_API int pdsch_encode(pdsch_t *q,
LIBLTE_API int pdsch_encode(pdsch_t *q,
harq_t *harq_process,
uint8_t *data,
cf_t *sf_symbols[MAX_PORTS],
uint32_t nsubframe,
harq_t *harq_process,
uint32_t rv_idx);
cf_t *sf_symbols[MAX_PORTS]);
LIBLTE_API int pdsch_decode(pdsch_t *q,
harq_t *harq_process,
cf_t *sf_symbols,
cf_t *ce[MAX_PORTS],
float noise_estimate,
uint8_t *data,
uint32_t nsubframe,
harq_t *harq_process,
uint32_t rv_idx);
uint8_t *data);
LIBLTE_API float pdsch_average_noi(pdsch_t *q);
LIBLTE_API uint32_t pdsch_last_noi(pdsch_t *q);
LIBLTE_API int pdsch_get(pdsch_t *q,
cf_t *sf_symbols,
cf_t *pdsch_symbols,
ra_prb_t *prb_alloc,
uint32_t subframe);
#endif

@ -49,7 +49,7 @@ typedef _Complex float cf_t;
typedef struct LIBLTE_API {
lte_cell_t cell;
uint32_t max_symbols;
uint32_t max_re;
bool rnti_is_set;
uint16_t rnti;
@ -84,40 +84,28 @@ LIBLTE_API int pusch_init(pusch_t *q,
LIBLTE_API void pusch_free(pusch_t *q);
LIBLTE_API int pusch_set_rnti(pusch_t *q,
uint16_t rnti);
uint16_t rnti);
LIBLTE_API int pusch_encode(pusch_t *q,
harq_t *harq_process,
uint8_t *data,
cf_t *sf_symbols,
uint32_t nsubframe,
harq_t *harq_process,
uint32_t rv_idx);
cf_t *sf_symbols);
LIBLTE_API int pusch_uci_encode(pusch_t *q,
harq_t *harq_process,
uint8_t *data,
uci_data_t uci_data,
cf_t *sf_symbols,
uint32_t subframe,
harq_t *harq_process,
uint32_t rv_idx);
cf_t *sf_symbols);
LIBLTE_API int pusch_decode(pusch_t *q,
harq_t *harq_process,
cf_t *sf_symbols,
cf_t *ce,
float noise_estimate,
uint8_t *data,
uint32_t nsubframe,
harq_t *harq_process,
uint32_t rv_idx);
uint8_t *data);
LIBLTE_API float pusch_average_noi(pusch_t *q);
LIBLTE_API uint32_t pusch_last_noi(pusch_t *q);
LIBLTE_API int pusch_get(pusch_t *q,
cf_t *sf_symbols,
cf_t *pusch_symbols,
ra_prb_t *prb_alloc,
uint32_t subframe);
#endif

@ -79,42 +79,31 @@ LIBLTE_API float sch_average_noi(sch_t *q);
LIBLTE_API uint32_t sch_last_noi(sch_t *q);
LIBLTE_API int dlsch_encode(sch_t *q,
harq_t *harq_process,
uint8_t *data,
uint8_t *e_bits,
uint32_t tbs,
uint32_t nb_e,
harq_t *harq_process,
uint32_t rv_idx);
uint8_t *e_bits);
LIBLTE_API int dlsch_decode(sch_t *q,
harq_t *harq_process,
float *e_bits,
uint8_t *data,
uint32_t tbs,
uint32_t nb_e,
harq_t *harq_process,
uint32_t rv_idx);
uint8_t *data);
LIBLTE_API int ulsch_encode(sch_t *q,
harq_t *harq_process,
uint8_t *data,
uint8_t *g_bits,
harq_t *harq_process,
uint32_t rv_idx,
uint8_t *q_bits);
LIBLTE_API int ulsch_uci_encode(sch_t *q,
harq_t *harq_process,
uint8_t *data,
uci_data_t uci_data,
uint8_t *g_bits,
harq_t *harq_process,
uint32_t rv_idx,
uint8_t *q_bits);
LIBLTE_API int ulsch_decode(sch_t *q,
harq_t *harq_process,
float *e_bits,
uint8_t *data,
uint32_t tbs,
uint32_t nb_e,
harq_t *harq_process,
uint32_t rv_idx);
uint8_t *data);
#endif

@ -183,23 +183,64 @@ void harq_reset(harq_t *q) {
bzero(&q->prb_alloc, sizeof(ra_prb_t));
}
int harq_setup(harq_t *q, ra_mcs_t mcs, ra_prb_t *prb_alloc) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL)
{
q->mcs = mcs;
memcpy(&q->prb_alloc, prb_alloc, sizeof(ra_prb_t));
q->N_symb_ul = 2*(CP_NSYMB(q->cell.cp)-1);
q->nof_prb_pusch_init = q->prb_alloc.slot[0].nof_prb;
codeblock_segmentation(&q->cb_segm, mcs.tbs);
static int harq_setup_common(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_prb_t *prb_alloc) {
if (mcs.tbs != q->mcs.tbs) {
codeblock_segmentation(&q->cb_segm, mcs.tbs);
if (q->cb_segm.C > q->max_cb) {
fprintf(stderr, "Codeblock segmentation returned more CBs (%d) than allocated (%d)\n",
q->cb_segm.C, q->max_cb);
return LIBLTE_ERROR;
}
}
memcpy(&q->prb_alloc, prb_alloc, sizeof(ra_prb_t));
q->mcs = mcs;
q->sf_idx = sf_idx;
q->rv = rv;
return LIBLTE_SUCCESS;
}
int harq_setup_dl(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_prb_t *prb_alloc) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
rv < 4 &&
sf_idx < 10)
{
ret = harq_setup_common(q, mcs, rv, sf_idx, prb_alloc);
if (ret) {
return ret;
}
// Number of symbols, RE and bits per subframe for DL
q->nof_re = q->prb_alloc.re_sf[q->sf_idx];
q->nof_symb = 2*CP_NSYMB(q->cell.cp)-q->prb_alloc.lstart;
q->nof_bits = q->nof_re * lte_mod_bits_x_symbol(q->mcs.mod);
q->nof_prb = q->prb_alloc.slot[0].nof_prb;
ret = LIBLTE_SUCCESS;
}
return ret;
}
int harq_setup_ul(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_prb_t *prb_alloc) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
rv < 4 &&
sf_idx < 10)
{
ret = harq_setup_common(q, mcs, rv, sf_idx, prb_alloc);
if (ret) {
return ret;
}
// Number of symbols, RE and bits per subframe for UL
q->nof_symb = 2*(CP_NSYMB(q->cell.cp)-1);
q->nof_re = q->nof_symb*q->prb_alloc.slot[0].nof_prb*RE_X_RB;
q->nof_bits = q->nof_re * lte_mod_bits_x_symbol(q->mcs.mod);
q->nof_prb = q->prb_alloc.slot[0].nof_prb;
ret = LIBLTE_SUCCESS;
}
return ret;

@ -208,10 +208,10 @@ int pdsch_init(pdsch_t *q, lte_cell_t cell) {
ret = LIBLTE_ERROR;
q->cell = cell;
q->max_symbols = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.nof_prb, q->max_symbols);
q->cell.nof_prb, q->max_re);
if (precoding_init(&q->precoding, SF_LEN_RE(cell.nof_prb, cell.cp))) {
fprintf(stderr, "Error initializing precoding\n");
@ -224,7 +224,7 @@ int pdsch_init(pdsch_t *q, lte_cell_t cell) {
}
}
demod_soft_init(&q->demod, q->max_symbols);
demod_soft_init(&q->demod, q->max_re);
demod_soft_alg_set(&q->demod, APPROX);
sch_init(&q->dl_sch);
@ -232,26 +232,26 @@ int pdsch_init(pdsch_t *q, lte_cell_t cell) {
q->rnti_is_set = false;
// Allocate floats for reception (LLRs)
q->pdsch_e = vec_malloc(sizeof(float) * q->max_symbols * lte_mod_bits_x_symbol(LTE_QAM64));
q->pdsch_e = vec_malloc(sizeof(float) * q->max_re * lte_mod_bits_x_symbol(LTE_QAM64));
if (!q->pdsch_e) {
goto clean;
}
q->pdsch_d = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->pdsch_d = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->pdsch_d) {
goto clean;
}
for (i = 0; i < q->cell.nof_ports; i++) {
q->ce[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->ce[i] = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->ce[i]) {
goto clean;
}
q->pdsch_x[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->pdsch_x[i] = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->pdsch_x[i]) {
goto clean;
}
q->pdsch_symbols[i] = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->pdsch_symbols[i] = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->pdsch_symbols[i]) {
goto clean;
}
@ -306,7 +306,7 @@ int pdsch_set_rnti(pdsch_t *q, uint16_t rnti) {
uint32_t i;
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
if (sequence_pdsch(&q->seq_pdsch[i], rnti, 0, 2 * i, q->cell.id,
q->max_symbols * lte_mod_bits_x_symbol(LTE_QAM64))) {
q->max_re * lte_mod_bits_x_symbol(LTE_QAM64))) {
return LIBLTE_ERROR;
}
}
@ -318,30 +318,23 @@ int pdsch_set_rnti(pdsch_t *q, uint16_t rnti) {
/** Decodes the PDSCH from the received symbols
*/
int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate, uint8_t *data, uint32_t subframe,
harq_t *harq_process, uint32_t rv_idx)
int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate, uint8_t *data)
{
/* Set pointers for layermapping & precoding */
uint32_t i, n;
cf_t *x[MAX_LAYERS];
uint32_t nof_symbols, nof_bits, nof_bits_e;
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
subframe < 10 &&
harq_process != NULL)
data != NULL &&
harq != NULL)
{
if (q->rnti_is_set) {
nof_bits = harq_process->mcs.tbs;
nof_symbols = harq_process->prb_alloc.re_sf[subframe];
nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod);
INFO("Decoding PDSCH 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);
INFO("Decoding PDSCH SF: %d, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
@ -350,17 +343,17 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq_process->prb_alloc, subframe);
if (n != nof_symbols) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->prb_alloc, harq->sf_idx);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
return LIBLTE_ERROR;
}
/* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) {
n = pdsch_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);
n = pdsch_get(q, ce[i], q->ce[i], &harq->prb_alloc, harq->sf_idx);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
return LIBLTE_ERROR;
}
}
@ -369,12 +362,12 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d,
nof_symbols, noise_estimate);
harq->nof_re, noise_estimate);
} else {
predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports,
nof_symbols, noise_estimate);
harq->nof_re, noise_estimate);
layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports,
nof_symbols / q->cell.nof_ports);
harq->nof_re / q->cell.nof_ports);
}
/* demodulate symbols
@ -382,13 +375,13 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
* thus we don't need tot set it in the LLRs normalization
*/
demod_soft_sigma_set(&q->demod, sqrt(0.5));
demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols);
demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, harq->nof_re);
/* descramble */
scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, nof_bits_e);
scrambling_f_offset(&q->seq_pdsch[harq->sf_idx], q->pdsch_e, 0, harq->nof_bits);
return dlsch_decode(&q->dl_sch, q->pdsch_e, data, nof_bits, nof_bits_e, harq_process, rv_idx);
return dlsch_decode(&q->dl_sch, harq, q->pdsch_e, data);
} else {
fprintf(stderr, "Must call pdsch_set_rnti() before calling pdsch_decode()\n");
return LIBLTE_ERROR;
@ -402,19 +395,16 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission
*/
int pdsch_encode(pdsch_t *q, uint8_t *data, cf_t *sf_symbols[MAX_PORTS], uint32_t subframe,
harq_t *harq_process, uint32_t rv_idx)
int pdsch_encode(pdsch_t *q, harq_t *harq, uint8_t *data, cf_t *sf_symbols[MAX_PORTS])
{
int i;
uint32_t nof_symbols, nof_bits, 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 &&
data != NULL &&
subframe < 10 &&
harq_process != NULL)
harq != NULL)
{
if (q->rnti_is_set) {
@ -424,28 +414,24 @@ int pdsch_encode(pdsch_t *q, uint8_t *data, cf_t *sf_symbols[MAX_PORTS], uint32_
}
}
nof_bits = harq_process->mcs.tbs;
nof_symbols = harq_process->prb_alloc.re_sf[subframe];
nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod);
if (harq_process->mcs.tbs == 0) {
if (harq->mcs.tbs == 0) {
return LIBLTE_ERROR_INVALID_INPUTS;
}
if (nof_bits > nof_bits_e) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e);
if (harq->mcs.tbs > harq->nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
return LIBLTE_ERROR_INVALID_INPUTS;
}
if (nof_symbols > q->max_symbols) {
if (harq->nof_re > q->max_re) {
fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
nof_symbols, q->max_symbols, q->cell.nof_prb);
harq->nof_re, q->max_re, q->cell.nof_prb);
return LIBLTE_ERROR_INVALID_INPUTS;
}
INFO("Encoding PDSCH 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);
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
@ -453,27 +439,27 @@ int pdsch_encode(pdsch_t *q, uint8_t *data, cf_t *sf_symbols[MAX_PORTS], uint32_
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
if (dlsch_encode(&q->dl_sch, data, q->pdsch_e, nof_bits, nof_bits_e, harq_process, rv_idx)) {
if (dlsch_encode(&q->dl_sch, harq, data, q->pdsch_e)) {
fprintf(stderr, "Error encoding TB\n");
return LIBLTE_ERROR;
}
scrambling_b_offset(&q->seq_pdsch[subframe], (uint8_t*) q->pdsch_e, 0, nof_bits_e);
scrambling_b_offset(&q->seq_pdsch[harq->sf_idx], (uint8_t*) q->pdsch_e, 0, harq->nof_bits);
mod_modulate(&q->mod[harq_process->mcs.mod], (uint8_t*) q->pdsch_e, q->pdsch_d, nof_bits_e);
mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pdsch_e, q->pdsch_d, harq->nof_bits);
/* TODO: only diversity supported */
if (q->cell.nof_ports > 1) {
layermap_diversity(q->pdsch_d, x, q->cell.nof_ports, nof_symbols);
layermap_diversity(q->pdsch_d, x, q->cell.nof_ports, harq->nof_re);
precoding_diversity(&q->precoding, x, q->pdsch_symbols, q->cell.nof_ports,
nof_symbols / q->cell.nof_ports);
harq->nof_re / q->cell.nof_ports);
} else {
memcpy(q->pdsch_symbols[0], q->pdsch_d, nof_symbols * sizeof(cf_t));
memcpy(q->pdsch_symbols[0], q->pdsch_d, harq->nof_re * sizeof(cf_t));
}
/* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) {
pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], &harq_process->prb_alloc, subframe);
pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], &harq->prb_alloc, harq->sf_idx);
}
ret = LIBLTE_SUCCESS;
} else {

@ -102,10 +102,10 @@ int pusch_init(pusch_t *q, lte_cell_t cell) {
ret = LIBLTE_ERROR;
q->cell = cell;
q->max_symbols = q->cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
q->max_re = q->cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
INFO("Init PUSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.nof_prb, q->max_symbols);
q->cell.nof_prb, q->max_re);
for (i = 0; i < 4; i++) {
if (modem_table_lte(&q->mod[i], modulations[i], true)) {
@ -113,7 +113,7 @@ int pusch_init(pusch_t *q, lte_cell_t cell) {
}
}
demod_soft_init(&q->demod, q->max_symbols);
demod_soft_init(&q->demod, q->max_re);
demod_soft_alg_set(&q->demod, APPROX);
sch_init(&q->dl_sch);
@ -129,26 +129,26 @@ int pusch_init(pusch_t *q, lte_cell_t cell) {
q->rnti_is_set = false;
// Allocate floats for reception (LLRs). Buffer casted to uint8_t for transmission
q->pusch_q = vec_malloc(sizeof(float) * q->max_symbols * lte_mod_bits_x_symbol(LTE_QAM64));
q->pusch_q = vec_malloc(sizeof(float) * q->max_re * lte_mod_bits_x_symbol(LTE_QAM64));
if (!q->pusch_q) {
goto clean;
}
// Allocate floats for reception (LLRs). Buffer casted to uint8_t for transmission
q->pusch_g = vec_malloc(sizeof(float) * q->max_symbols * lte_mod_bits_x_symbol(LTE_QAM64));
q->pusch_g = vec_malloc(sizeof(float) * q->max_re * lte_mod_bits_x_symbol(LTE_QAM64));
if (!q->pusch_g) {
goto clean;
}
q->pusch_d = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->pusch_d = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->pusch_d) {
goto clean;
}
q->ce = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->ce = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->ce) {
goto clean;
}
q->pusch_z = vec_malloc(sizeof(cf_t) * q->max_symbols);
q->pusch_z = vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->pusch_z) {
goto clean;
}
@ -204,7 +204,7 @@ int pusch_set_rnti(pusch_t *q, uint16_t rnti) {
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
if (sequence_pusch(&q->seq_pusch[i], rnti, 2 * i, q->cell.id,
q->max_symbols * lte_mod_bits_x_symbol(LTE_QAM64))) {
q->max_re * lte_mod_bits_x_symbol(LTE_QAM64))) {
return LIBLTE_ERROR;
}
}
@ -216,61 +216,53 @@ 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, float noise_estimate, uint8_t *data, uint32_t subframe,
harq_t *harq_process, uint32_t rv_idx)
int pusch_decode(pusch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint8_t *data)
{
/* Set pointers for layermapping & precoding */
uint32_t n;
uint32_t nof_symbols, nof_bits, nof_bits_e;
if (q != NULL &&
sf_symbols != NULL &&
data != NULL &&
subframe < 10 &&
harq_process != NULL)
harq != NULL)
{
if (q->rnti_is_set) {
nof_bits = 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);
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);
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
/* extract symbols */
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);
n = pusch_get(q, sf_symbols, q->pusch_d, &harq->prb_alloc, harq->sf_idx);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
return LIBLTE_ERROR;
}
/* extract channel estimates */
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);
n = pusch_get(q, ce, q->ce, &harq->prb_alloc, harq->sf_idx);
if (n != harq->nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n);
return LIBLTE_ERROR;
}
predecoding_single(&q->equalizer, q->pusch_d, q->ce, q->pusch_z,
nof_symbols, noise_estimate);
harq->nof_re, 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);
harq->prb_alloc.slot[0].nof_prb, harq->nof_symb);
/* 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
*/
demod_soft_sigma_set(&q->demod, sqrt(0.5));
demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pusch_d, q->pusch_q, nof_symbols);
demod_soft_table_set(&q->demod, &q->mod[harq->mcs.mod]);
demod_soft_demodulate(&q->demod, q->pusch_d, q->pusch_q, harq->nof_re);
/* descramble */
scrambling_f_offset(&q->seq_pusch[subframe], q->pusch_q, 0, nof_bits_e);
scrambling_f_offset(&q->seq_pusch[harq->sf_idx], q->pusch_q, 0, harq->nof_bits);
return ulsch_decode(&q->dl_sch, q->pusch_q, data, nof_bits, nof_bits_e, harq_process, rv_idx);
return ulsch_decode(&q->dl_sch, harq, q->pusch_q, data);
} else {
fprintf(stderr, "Must call pusch_set_rnti() before calling pusch_decode()\n");
return LIBLTE_ERROR;
@ -280,68 +272,59 @@ int pusch_decode(pusch_t *q, cf_t *sf_symbols, cf_t *ce, float noise_estimate, u
}
}
int pusch_encode(pusch_t *q, uint8_t *data, cf_t *sf_symbols, uint32_t subframe,
harq_t *harq_process, uint32_t rv_idx)
int pusch_encode(pusch_t *q, harq_t *harq_process, uint8_t *data, cf_t *sf_symbols)
{
uci_data_t uci_data;
bzero(&uci_data, sizeof(uci_data_t));
return pusch_uci_encode(q, data, uci_data, sf_symbols, subframe, harq_process, rv_idx);
return pusch_uci_encode(q, harq_process, data, uci_data, sf_symbols);
}
/** 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, uint32_t subframe,
harq_t *harq_process, uint32_t rv_idx)
int pusch_uci_encode(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_data, cf_t *sf_symbols)
{
uint32_t nof_symbols, nof_bits_ulsch, nof_bits_e;
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
data != NULL &&
subframe < 10 &&
harq_process != NULL)
if (q != NULL &&
data != NULL &&
harq != NULL)
{
if (q->rnti_is_set) {
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);
if (harq_process->mcs.tbs == 0) {
if (harq->mcs.tbs == 0) {
return LIBLTE_ERROR_INVALID_INPUTS;
}
if (nof_bits_ulsch > nof_bits_e) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits_ulsch / nof_bits_e);
if (harq->mcs.tbs > harq->nof_bits) {
fprintf(stderr, "Invalid code rate %.2f\n", (float) harq->mcs.tbs / harq->nof_bits);
return LIBLTE_ERROR_INVALID_INPUTS;
}
if (nof_symbols > q->max_symbols) {
if (harq->nof_re > q->max_re) {
fprintf(stderr,
"Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n",
nof_symbols, q->max_symbols, q->cell.nof_prb);
harq->nof_re, q->max_re, q->cell.nof_prb);
return LIBLTE_ERROR_INVALID_INPUTS;
}
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);
INFO("Encoding PUSCH SF: %d, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv);
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, harq, data, uci_data, q->pusch_g, q->pusch_q))
{
fprintf(stderr, "Error encoding TB\n");
return LIBLTE_ERROR;
}
scrambling_b_offset_pusch(&q->seq_pusch[subframe], (uint8_t*) q->pusch_q, 0, nof_bits_e);
scrambling_b_offset_pusch(&q->seq_pusch[harq->sf_idx], (uint8_t*) q->pusch_q, 0, harq->nof_bits);
mod_modulate(&q->mod[harq_process->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, nof_bits_e);
mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, harq->nof_bits);
dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z,
harq_process->prb_alloc.slot[0].nof_prb, harq_process->N_symb_ul);
harq->prb_alloc.slot[0].nof_prb, harq->nof_symb);
/* mapping to resource elements */
pusch_put(q, q->pusch_z, sf_symbols, &harq_process->prb_alloc, subframe);
pusch_put(q, q->pusch_z, sf_symbols, &harq->prb_alloc, harq->sf_idx);
ret = LIBLTE_SUCCESS;
} else {

@ -116,8 +116,7 @@ uint32_t sch_last_noi(sch_t *q) {
/* Encode a transport block according to 36.212 5.3.2
*
*/
static int encode_tb(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uint32_t nb_e,
harq_t *harq_process, uint32_t rv_idx)
static int encode_tb(sch_t *q, harq_t *harq, uint8_t *data, uint8_t *e_bits, uint32_t nof_e_bits)
{
uint8_t parity[24];
uint8_t *p_parity = parity;
@ -125,26 +124,26 @@ static int encode_tb(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uin
uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e;
int ret = LIBLTE_ERROR_INVALID_INPUTS;
uint32_t Qm = lte_mod_bits_x_symbol(harq_process->mcs.mod);
uint32_t Qm = lte_mod_bits_x_symbol(harq->mcs.mod);
if (q != NULL &&
data != NULL &&
harq_process != NULL)
harq != NULL)
{
uint32_t Gp = nb_e / Qm;
uint32_t gamma = Gp%harq_process->cb_segm.C;
uint32_t Gp = nof_e_bits / Qm;
uint32_t gamma = Gp%harq->cb_segm.C;
if (rv_idx == 0) {
if (harq->rv == 0) {
/* Compute transport block CRC */
par = crc_checksum(&q->crc_tb, data, tbs);
par = crc_checksum(&q->crc_tb, data, harq->mcs.tbs);
/* parity bits will be appended later */
bit_pack(par, &p_parity, 24);
if (VERBOSE_ISDEBUG()) {
DEBUG("DATA: ", 0);
vec_fprint_b(stdout, data, tbs);
vec_fprint_b(stdout, data, harq->mcs.tbs);
DEBUG("PARITY: ", 0);
vec_fprint_b(stdout, parity, 24);
}
@ -152,37 +151,37 @@ static int encode_tb(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uin
wp = 0;
rp = 0;
for (i = 0; i < harq_process->cb_segm.C; i++) {
for (i = 0; i < harq->cb_segm.C; i++) {
/* Get read lengths */
if (i < harq_process->cb_segm.C2) {
cb_len = harq_process->cb_segm.K2;
if (i < harq->cb_segm.C2) {
cb_len = harq->cb_segm.K2;
} else {
cb_len = harq_process->cb_segm.K1;
cb_len = harq->cb_segm.K1;
}
if (harq_process->cb_segm.C > 1) {
if (harq->cb_segm.C > 1) {
rlen = cb_len - 24;
} else {
rlen = cb_len;
}
if (i == 0) {
F = harq_process->cb_segm.F;
F = harq->cb_segm.F;
} else {
F = 0;
}
if (i <= harq_process->cb_segm.C - gamma - 1) {
n_e = Qm * (Gp/harq_process->cb_segm.C);
if (i <= harq->cb_segm.C - gamma - 1) {
n_e = Qm * (Gp/harq->cb_segm.C);
} else {
n_e = Qm * ((uint32_t) ceilf((float) Gp/harq_process->cb_segm.C));
n_e = Qm * ((uint32_t) ceilf((float) Gp/harq->cb_segm.C));
}
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
cb_len, rlen - F, wp, rp, F, n_e);
if (rv_idx == 0) {
if (harq->rv == 0) {
/* Copy data to another buffer, making space for the Codeblock CRC */
if (i < harq_process->cb_segm.C - 1) {
if (i < harq->cb_segm.C - 1) {
// Copy data
memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(uint8_t));
} else {
@ -197,7 +196,7 @@ static int encode_tb(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uin
q->cb_in[j] = 0;
}
/* Attach Codeblock CRC */
if (harq_process->cb_segm.C > 1) {
if (harq->cb_segm.C > 1) {
crc_attach(&q->crc_cb, q->cb_in, rlen);
}
/* Set the filler bits to <NULL> */
@ -214,9 +213,9 @@ static int encode_tb(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uin
}
/* Rate matching */
if (rm_turbo_tx(harq_process->pdsch_w_buff_c[i], harq_process->w_buff_size,
if (rm_turbo_tx(harq->pdsch_w_buff_c[i], harq->w_buff_size,
(uint8_t*) q->cb_out, 3 * cb_len + 12,
&e_bits[wp], n_e, rv_idx))
&e_bits[wp], n_e, harq->rv))
{
fprintf(stderr, "Error in rate matching\n");
return LIBLTE_ERROR;
@ -236,59 +235,58 @@ static int encode_tb(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uin
/* Decode a transport block according to 36.212 5.3.2
*
*/
static int decode_tb(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint32_t nb_e,
harq_t *harq_process, uint32_t rv_idx)
static int decode_tb(sch_t *q, harq_t *harq, float *e_bits, uint8_t *data, uint32_t nof_e_bits)
{
uint8_t parity[24];
uint8_t *p_parity = parity;
uint32_t par_rx, par_tx;
uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e;
uint32_t Qm = lte_mod_bits_x_symbol(harq_process->mcs.mod);
uint32_t Qm = lte_mod_bits_x_symbol(harq->mcs.mod);
if (q != NULL &&
data != NULL &&
harq_process != NULL)
harq != NULL)
{
rp = 0;
rp = 0;
wp = 0;
uint32_t Gp = nb_e / Qm;
uint32_t gamma = Gp%harq_process->cb_segm.C;
uint32_t Gp = nof_e_bits / Qm;
uint32_t gamma = Gp%harq->cb_segm.C;
bool early_stop = true;
for (i = 0; i < harq_process->cb_segm.C && early_stop; i++) {
for (i = 0; i < harq->cb_segm.C && early_stop; i++) {
/* Get read/write lengths */
if (i < harq_process->cb_segm.C2) {
cb_len = harq_process->cb_segm.K2;
if (i < harq->cb_segm.C2) {
cb_len = harq->cb_segm.K2;
} else {
cb_len = harq_process->cb_segm.K1;
cb_len = harq->cb_segm.K1;
}
if (harq_process->cb_segm.C == 1) {
if (harq->cb_segm.C == 1) {
rlen = cb_len;
} else {
rlen = cb_len - 24;
}
if (i == 0) {
F = harq_process->cb_segm.F;
F = harq->cb_segm.F;
} else {
F = 0;
}
if (i <= harq_process->cb_segm.C - gamma - 1) {
n_e = Qm * (Gp/harq_process->cb_segm.C);
if (i <= harq->cb_segm.C - gamma - 1) {
n_e = Qm * (Gp/harq->cb_segm.C);
} else {
n_e = Qm * ((uint32_t) ceilf((float) Gp/harq_process->cb_segm.C));
n_e = Qm * ((uint32_t) ceilf((float) Gp/harq->cb_segm.C));
}
INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
cb_len, rlen - F, wp, rp, F, n_e);
/* Rate Unmatching */
if (rm_turbo_rx(harq_process->pdsch_w_buff_f[i], harq_process->w_buff_size,
if (rm_turbo_rx(harq->pdsch_w_buff_f[i], harq->w_buff_size,
&e_bits[rp], n_e,
(float*) q->cb_out, 3 * cb_len + 12, rv_idx, F)) {
(float*) q->cb_out, 3 * cb_len + 12, harq->rv, F)) {
fprintf(stderr, "Error in rate matching\n");
return LIBLTE_ERROR;
}
@ -311,12 +309,12 @@ static int decode_tb(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint3
tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len);
q->nof_iterations++;
if (harq_process->cb_segm.C > 1) {
if (harq->cb_segm.C > 1) {
len_crc = cb_len;
cb_in_ptr = q->cb_in;
crc_ptr = &q->crc_cb;
} else {
len_crc = tbs+24;
len_crc = harq->mcs.tbs+24;
cb_in_ptr = &q->cb_in[F];
crc_ptr = &q->crc_tb;
}
@ -339,7 +337,7 @@ static int decode_tb(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint3
// If CB CRC is not correct, early_stop will be false and wont continue with rest of CBs
/* Copy data to another buffer, removing the Codeblock CRC */
if (i < harq_process->cb_segm.C - 1) {
if (i < harq->cb_segm.C - 1) {
memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t));
} else {
DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n",
@ -362,7 +360,7 @@ static int decode_tb(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint3
INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
// Compute transport block CRC
par_rx = crc_checksum(&q->crc_tb, data, tbs);
par_rx = crc_checksum(&q->crc_tb, data, harq->mcs.tbs);
// check parity bits
par_tx = bit_unpack(&p_parity, 24);
@ -385,21 +383,18 @@ static int decode_tb(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint3
}
}
int dlsch_decode(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint32_t nb_e,
harq_t *harq_process, uint32_t rv_idx)
int dlsch_decode(sch_t *q, harq_t *harq, float *e_bits, uint8_t *data)
{
return decode_tb(q, e_bits, data, tbs, nb_e, harq_process, rv_idx);
return decode_tb(q, harq, e_bits, data, harq->nof_bits);
}
int dlsch_encode(sch_t *q, uint8_t *data, uint8_t *e_bits, uint32_t tbs, uint32_t nb_e,
harq_t *harq_process, uint32_t rv_idx) {
return encode_tb(q, data, e_bits, tbs, nb_e, harq_process, rv_idx);
int dlsch_encode(sch_t *q, harq_t *harq, uint8_t *data, uint8_t *e_bits) {
return encode_tb(q, harq, data, e_bits, harq->nof_bits);
}
int ulsch_decode(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint32_t nb_e,
harq_t *harq_process, uint32_t rv_idx)
int ulsch_decode(sch_t *q, harq_t *harq, float *e_bits, uint8_t *data)
{
return decode_tb(q, e_bits, data, tbs, nb_e, harq_process, rv_idx);
return decode_tb(q, harq, e_bits, data, harq->nof_bits);
}
@ -426,17 +421,15 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uin
}
int ulsch_encode(sch_t *q, uint8_t *data, uint8_t *g_bits,
harq_t *harq_process, uint32_t rv_idx, uint8_t *q_bits)
int ulsch_encode(sch_t *q, harq_t *harq, uint8_t *data, uint8_t *g_bits, uint8_t *q_bits)
{
uci_data_t uci_data;
bzero(&uci_data, sizeof(uci_data_t));
return ulsch_uci_encode(q, data, uci_data, g_bits, harq_process, rv_idx, q_bits);
return ulsch_uci_encode(q, harq, data, uci_data, g_bits, q_bits);
}
int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bits,
harq_t *harq_process, uint32_t rv_idx, uint8_t *q_bits)
int ulsch_uci_encode(sch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_data, uint8_t *g_bits, uint8_t *q_bits)
{
int ret;
@ -444,9 +437,9 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi
uint32_t Q_prime_cqi = 0;
uint32_t Q_prime_ack = 0;
uint32_t Q_prime_ri = 0;
uint32_t Q_m = lte_mod_bits_x_symbol(harq_process->mcs.mod);
uint32_t Q_m = lte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t nof_symbols = 12*harq_process->prb_alloc.slot[0].nof_prb*RE_X_RB;
uint32_t nof_symbols = 12*harq->prb_alloc.slot[0].nof_prb*RE_X_RB;
uint32_t nb_q = nof_symbols * Q_m;
bzero(q_bits, sizeof(uint8_t) * nb_q);
@ -454,10 +447,10 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi
// Encode RI
if (uci_data.uci_ri_len > 0) {
float beta = uci_data.beta_ri;
if (harq_process->mcs.tbs == 0) {
if (harq->mcs.tbs == 0) {
beta /= uci_data.beta_cqi;
}
ret = uci_encode_ri(uci_data.uci_ri, uci_data.uci_cqi_len, beta, harq_process, nb_q/Q_m, q_bits);
ret = uci_encode_ri(uci_data.uci_ri, uci_data.uci_cqi_len, beta, harq, nb_q/Q_m, q_bits);
if (ret < 0) {
return ret;
}
@ -468,7 +461,7 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi
if (uci_data.uci_cqi_len > 0) {
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, g_bits);
if (ret < 0) {
return ret;
}
@ -478,25 +471,24 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi
e_offset += Q_prime_cqi*Q_m;
// Encode UL-SCH
if (harq_process->mcs.tbs > 0) {
if (harq->mcs.tbs > 0) {
uint32_t G = nb_q/Q_m - Q_prime_ri - Q_prime_cqi;
ret = encode_tb(q, data, &g_bits[e_offset], harq_process->mcs.tbs,
G*Q_m, harq_process, rv_idx);
ret = encode_tb(q, harq, data, &g_bits[e_offset], G*Q_m);
if (ret) {
return ret;
}
}
// Interleave UL-SCH (and RI and CQI)
ulsch_interleave(g_bits, Q_m, nb_q/Q_m, harq_process->N_symb_ul, q_bits);
ulsch_interleave(g_bits, Q_m, nb_q/Q_m, harq->nof_symb, q_bits);
// Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) {
float beta = uci_data.beta_ack;
if (harq_process->mcs.tbs == 0) {
if (harq->mcs.tbs == 0) {
beta /= uci_data.beta_cqi;
}
ret = uci_encode_ack(uci_data.uci_ack, uci_data.uci_cqi_len, beta, harq_process, nb_q/Q_m, q_bits);
ret = uci_encode_ack(uci_data.uci_ack, uci_data.uci_cqi_len, beta, harq, nb_q/Q_m, q_bits);
if (ret < 0) {
return ret;
}

@ -114,21 +114,21 @@ void uci_cqi_free(uci_cqi_pusch_t *q) {
}
static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, harq_t *harq_process) {
uint32_t M_sc = harq_process->prb_alloc.slot[0].nof_prb * RE_X_RB;
static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, harq_t *harq) {
uint32_t M_sc = harq->prb_alloc.slot[0].nof_prb * RE_X_RB;
uint32_t K = harq_process->cb_segm.C1*harq_process->cb_segm.K1 +
harq_process->cb_segm.C2*harq_process->cb_segm.K2;
uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 +
harq->cb_segm.C2*harq->cb_segm.K2;
uint32_t Q_prime = 0;
if (K > 0) {
uint32_t M_sc_init = harq_process->nof_prb_pusch_init * RE_X_RB;
uint32_t M_sc_init = harq->nof_prb * RE_X_RB;
uint32_t L = (O<11)?0:8;
uint32_t x = (uint32_t) ceilf((float) (O+L)*M_sc_init*harq_process->N_symb_ul*beta/K);
uint32_t x = (uint32_t) ceilf((float) (O+L)*M_sc_init*harq->nof_symb*beta/K);
Q_prime = MIN(x, M_sc * harq_process->N_symb_ul - Q_prime_ri);
Q_prime = MIN(x, M_sc * harq->nof_symb - Q_prime_ri);
} else {
Q_prime = 12*harq_process->prb_alloc.slot[0].nof_prb*RE_X_RB - Q_prime_ri;
Q_prime = 12*harq->prb_alloc.slot[0].nof_prb*RE_X_RB - Q_prime_ri;
}
return Q_prime;
@ -218,11 +218,11 @@ int uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[CQI
/* Encode UCI CQI/PMI as described in 5.2.2.6 of 36.212
*/
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, uint8_t *q_bits)
{
uint32_t Q_prime = Q_prime_cqi(cqi_len, beta, Q_prime_ri, harq_process);
uint32_t Q_m = lte_mod_bits_x_symbol(harq_process->mcs.mod);
uint32_t Q_prime = Q_prime_cqi(cqi_len, beta, Q_prime_ri, harq);
uint32_t Q_m = lte_mod_bits_x_symbol(harq->mcs.mod);
int ret = LIBLTE_ERROR;
if (cqi_len <= 11) {
@ -286,11 +286,11 @@ static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_i
}
static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, harq_t *harq_process) {
uint32_t M_sc = harq_process->prb_alloc.slot[0].nof_prb * RE_X_RB;
static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, harq_t *harq) {
uint32_t M_sc = harq->prb_alloc.slot[0].nof_prb * RE_X_RB;
uint32_t K = harq_process->cb_segm.C1*harq_process->cb_segm.K1 +
harq_process->cb_segm.C2*harq_process->cb_segm.K2;
uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 +
harq->cb_segm.C2*harq->cb_segm.K2;
// If not carrying UL-SCH, get Q_prime according to 5.2.4.1
if (K == 0) {
@ -301,9 +301,9 @@ static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, harq_t *h
}
}
uint32_t M_sc_init = harq_process->nof_prb_pusch_init * RE_X_RB;
uint32_t M_sc_init = harq->nof_prb * RE_X_RB;
uint32_t x = (uint32_t) ceilf((float) O*M_sc_init*harq_process->N_symb_ul*beta/K);
uint32_t x = (uint32_t) ceilf((float) O*M_sc_init*harq->nof_symb*beta/K);
uint32_t Q_prime = MIN(x, 4*M_sc);
@ -321,16 +321,16 @@ static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Q_m)
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ
*/
int uci_encode_ack(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq_process, uint32_t H_prime_total, uint8_t *q_bits)
int uci_encode_ack(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq, uint32_t H_prime_total, uint8_t *q_bits)
{
uint32_t Q_m = lte_mod_bits_x_symbol(harq_process->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq_process);
uint32_t Q_m = lte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq);
uint8_t q_encoded_bits[6];
encode_ri_ack(data, q_encoded_bits, Q_m);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack(q_encoded_bits, i, Q_m, H_prime_total, harq_process->N_symb_ul, harq_process->cell.cp, q_bits);
uci_ulsch_interleave_ack(q_encoded_bits, i, Q_m, H_prime_total, harq->nof_symb, harq->cell.cp, q_bits);
}
return (int) Qprime;
@ -340,16 +340,16 @@ int uci_encode_ack(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq_proces
/* Encode UCI RI bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit RI
*/
int uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq_process, uint32_t H_prime_total, uint8_t *q_bits)
int uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq, uint32_t H_prime_total, uint8_t *q_bits)
{
uint32_t Q_m = lte_mod_bits_x_symbol(harq_process->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq_process);
uint32_t Q_m = lte_mod_bits_x_symbol(harq->mcs.mod);
uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq);
uint8_t q_encoded_bits[6];
encode_ri_ack(data, q_encoded_bits, Q_m);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri(q_encoded_bits, i, Q_m, H_prime_total, harq_process->N_symb_ul, harq_process->cell.cp, q_bits);
uci_ulsch_interleave_ri(q_encoded_bits, i, Q_m, H_prime_total, harq->nof_symb, harq->cell.cp, q_bits);
}
return (int) Qprime;

@ -78,7 +78,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field RV not found in dlsch config\n");
return;
}
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) {
@ -94,24 +94,24 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mxFree(mod_str);
if (harq_setup(&harq_process, mcs, &prb_alloc)) {
if (harq_setup_dl(&harq_process, mcs, rv, 0, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
harq_process.nof_bits = mxGetScalar(OUTLEN);
uint32_t nof_bits_e = (uint32_t) mxGetScalar(OUTLEN);
uint8_t *e_bits = vec_malloc(nof_bits_e * sizeof(uint8_t));
uint8_t *e_bits = vec_malloc(harq_process.nof_bits* sizeof(uint8_t));
if (!e_bits) {
return;
}
if (dlsch_encode(&dlsch, trblkin, e_bits, mcs.tbs, nof_bits_e, &harq_process, rv)) {
if (dlsch_encode(&dlsch, &harq_process, trblkin, e_bits)) {
mexErrMsgTxt("Error encoding TB\n");
return;
}
if (nlhs >= 1) {
mexutils_write_uint8(e_bits, &plhs[0], nof_bits_e, 1);
mexutils_write_uint8(e_bits, &plhs[0], harq_process.nof_bits, 1);
}
sch_free(&dlsch);

@ -284,12 +284,11 @@ int main(int argc, char **argv) {
goto goout;
}
if (ra_dl.mcs.tbs > 0) {
if (harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) {
if (harq_setup_dl(&harq_process, ra_dl.mcs, ra_dl.rv_idx, sf_idx, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto goout;
}
if (pdsch_decode(&pdsch, fft_buffer, ce, chest_dl_get_noise_estimate(&chest),
data, sf_idx, &harq_process, ra_dl.rv_idx)) {
if (pdsch_decode(&pdsch, &harq_process, fft_buffer, ce, chest_dl_get_noise_estimate(&chest), data)) {
fprintf(stderr, "Error decoding PDSCH\n");
goto goout;
} else {

@ -194,17 +194,17 @@ int main(int argc, char **argv) {
if (VERBOSE_ISNONE()) {
printf("Decoding TBS: %d\r",mcs.tbs);
}
if (harq_setup(&harq_process, mcs, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
for (i=0;i<mcs.tbs;i++) {
data[i] = rand()%2;
}
for (rv=0;rv<=rv_idx;rv++) {
if (pdsch_encode(&pdsch, data, slot_symbols, subframe, &harq_process, rv)) {
if (harq_setup_dl(&harq_process, mcs, rv, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
if (pdsch_encode(&pdsch, &harq_process, data, slot_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
goto quit;
}
@ -220,7 +220,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[1], NULL);
int r = pdsch_decode(&pdsch, slot_symbols[0], ce, 0, data, subframe, &harq_process, rv);
int r = pdsch_decode(&pdsch, &harq_process, slot_symbols[0], ce, 0, data);
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (r) {

@ -162,7 +162,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
if (harq_setup(&harq_process, mcs, &prb_alloc)) {
if (harq_setup_dl(&harq_process, mcs, rv, sf_idx, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
@ -209,7 +209,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
int r = pdsch_decode(&pdsch, input_fft, ce, noise_power, data, sf_idx, &harq_process, rv);
int r = pdsch_decode(&pdsch, &harq_process, input_fft, ce, noise_power, data);
if (nlhs >= 1) {

@ -160,11 +160,6 @@ int main(int argc, char **argv) {
goto quit;
}
if (harq_setup(&harq_process, mcs, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
for (uint32_t i=0;i<mcs.tbs;i++) {
data[i] = 1;
}
@ -192,15 +187,24 @@ int main(int argc, char **argv) {
uci_data.uci_ri = 1;
uci_data.uci_ack = 1;
uint32_t nof_symbols = 12*harq_process.prb_alloc.slot[0].nof_prb*RE_X_RB;
if (harq_setup_ul(&harq_process, mcs, 0, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
if (pusch_uci_encode(&pusch, data, uci_data, sf_symbols, subframe, &harq_process, 0)) {
if (pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
if (rv_idx > 0) {
if (pusch_uci_encode(&pusch, data, uci_data, sf_symbols, subframe, &harq_process, rv_idx)) {
if (harq_setup_ul(&harq_process, mcs, rv_idx, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
if (pusch_uci_encode(&pusch, &harq_process, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}

@ -146,38 +146,38 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", lte_mod_bits_x_symbol(mcs.mod), prb_alloc.slot[0].nof_prb, rv);
if (harq_setup(&harq_process, mcs, &prb_alloc)) {
if (harq_setup_ul(&harq_process, mcs, 0, 0, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
uint32_t nof_symbols = 12*harq_process.prb_alloc.slot[0].nof_prb*RE_X_RB;
uint32_t nof_q_bits = nof_symbols * lte_mod_bits_x_symbol(harq_process.mcs.mod);
uint8_t *q_bits = vec_malloc(nof_q_bits * sizeof(uint8_t));
uint8_t *q_bits = vec_malloc(harq_process.nof_bits * sizeof(uint8_t));
if (!q_bits) {
return;
}
uint8_t *g_bits = vec_malloc(nof_q_bits * sizeof(uint8_t));
uint8_t *g_bits = vec_malloc(harq_process.nof_bits * sizeof(uint8_t));
if (!g_bits) {
return;
}
if (ulsch_uci_encode(&ulsch, trblkin, uci_data, g_bits, &harq_process, 0, q_bits))
if (ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits))
{
mexErrMsgTxt("Error encoding TB\n");
return;
}
if (rv > 0) {
if (ulsch_uci_encode(&ulsch, trblkin, uci_data, g_bits, &harq_process, rv, q_bits))
{
if (harq_setup_ul(&harq_process, mcs, rv, 0, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
if (ulsch_uci_encode(&ulsch, &harq_process, trblkin, uci_data, g_bits, q_bits)) {
mexErrMsgTxt("Error encoding TB\n");
return;
}
}
if (nlhs >= 1) {
mexutils_write_uint8(q_bits, &plhs[0], nof_q_bits, 1);
mexutils_write_uint8(q_bits, &plhs[0], harq_process.nof_bits, 1);
}
sch_free(&ulsch);

@ -251,16 +251,15 @@ int ue_dl_decode_sib(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, ui
rvidx = ra_dl.rv_idx;
}
if (rvidx == 0) {
if (harq_setup(&q->harq_process[0], ra_dl.mcs, &ra_dl.prb_alloc)) {
if (harq_setup_dl(&q->harq_process[0], ra_dl.mcs, rvidx, sf_idx, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return LIBLTE_ERROR;
}
}
if (q->harq_process[0].mcs.mod > 0) {
ret = pdsch_decode(&q->pdsch, q->sf_symbols, q->ce,
chest_dl_get_noise_estimate(&q->chest),
data, sf_idx,
&q->harq_process[0], rvidx);
ret = pdsch_decode(&q->pdsch, &q->harq_process[0], q->sf_symbols,
q->ce, chest_dl_get_noise_estimate(&q->chest),
data);
if (ret == LIBLTE_ERROR) {
q->pkt_errors++;
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {

Loading…
Cancel
Save