Added CRC byte computation. Turbodecoder function to decide bytes. PUSCH and PDSCH now expect/generate bits packed in bytes

This commit is contained in:
ismagom 2015-08-07 02:18:47 +02:00
parent c90a253817
commit 76c432f777
12 changed files with 144 additions and 77 deletions

View File

@ -104,9 +104,6 @@ private:
srslte_timestamp_t tx_time;
srslte_uci_data_t uci_data;
uint16_t ul_rnti;
// FIXME: THIS IS TEMPORAL. Need to change srslte to accept bits for payload
uint8_t payload_bits[64*1024];
// UL configuration parameters
srslte_refsignal_srs_cfg_t srs_cfg;

View File

@ -148,7 +148,8 @@ void phch_worker::work_imp()
/* Decode PDSCH if instructed to do so */
dl_ack = dl_action.default_ack;
if (dl_action.decode_enabled) {
dl_ack = decode_pdsch(&dl_action.phy_grant.dl, dl_action.payload_ptr, dl_action.softbuffer, dl_action.rv, dl_action.rnti);
dl_ack = decode_pdsch(&dl_action.phy_grant.dl, dl_action.payload_ptr,
dl_action.softbuffer, dl_action.rv, dl_action.rnti);
}
if (dl_action.generate_ack_callback && dl_action.decode_enabled) {
phy->mac->tb_decoded(dl_ack, dl_mac_grant.rnti_type, dl_mac_grant.pid);
@ -192,7 +193,8 @@ void phch_worker::work_imp()
/* Transmit PUSCH, PUCCH or SRS */
bool tx_signal = false;
if (ul_action.tx_enabled) {
encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr, ul_action.current_tx_nb, ul_action.softbuffer, ul_action.rv, ul_action.rnti);
encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr,
ul_action.current_tx_nb, ul_action.softbuffer, ul_action.rv, ul_action.rnti);
tx_signal = true;
if (ul_action.expect_ack) {
phy->set_pending_ack(tti + 8, ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs);
@ -295,10 +297,8 @@ bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
if (srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols,
ue_dl.ce, 0, rnti, payload_bits) == 0)
ue_dl.ce, 0, rnti, payload) == 0)
{
// FIXME: TEMPORAL
srslte_bit_unpack_vector(payload_bits, payload, grant->mcs.tbs);
Debug("TB decoded OK\n");
return true;
} else {
@ -457,11 +457,8 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
Error("Configuring UL grant\n");
}
// FIXME: TEMPORAL
srslte_bit_pack_vector(payload, payload_bits, grant->mcs.tbs);
if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul,
payload_bits, uci_data,
payload, uci_data,
softbuffer,
rnti,
signal_buffer))

View File

@ -190,7 +190,7 @@ void config_phy() {
my_phy.set_param(srslte::ue::phy_interface_params::PUCCH_N_RB_2, 2);
my_phy.configure_ul_params();
my_phy.configure_prach_params();
}
srslte_softbuffer_rx_t softbuffer_rx;

View File

@ -223,7 +223,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t data[20000], data_packed[20000];
uint8_t data[20000];
bool go_exit = false;
@ -458,9 +458,10 @@ int main(int argc, char **argv) {
}
if (decode_pdsch) {
if (prog_args.rnti != SRSLTE_SIRNTI) {
n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync));
n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data, srslte_ue_sync_get_sfidx(&ue_sync));
} else {
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync),
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data,
srslte_ue_sync_get_sfidx(&ue_sync),
SRSLTE_SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
}
if (n < 0) {
@ -468,7 +469,6 @@ int main(int argc, char **argv) {
} else if (n > 0) {
/* Send data if socket active */
if (prog_args.net_port > 0) {
srslte_bit_unpack_vector(data_packed, data, n);
srslte_netsink_write(&net_sink, data, 1+(n-1)/8);
}

View File

@ -42,13 +42,12 @@
#include <stdint.h>
typedef struct SRSLTE_API {
unsigned long table[256];
uint8_t byte;
uint64_t table[256];
int polynom;
int order;
unsigned long crcinit;
unsigned long crcmask;
unsigned long crchighbit;
uint64_t crcinit;
uint64_t crcmask;
uint64_t crchighbit;
uint32_t srslte_crc_out;
} srslte_crc_t;
@ -57,11 +56,19 @@ SRSLTE_API int srslte_crc_init(srslte_crc_t *h,
int srslte_crc_order);
SRSLTE_API int srslte_crc_set_init(srslte_crc_t *h,
unsigned long srslte_crc_init_value);
uint64_t srslte_crc_init_value);
SRSLTE_API void srslte_crc_attach(srslte_crc_t *h,
uint8_t *data,
int len);
SRSLTE_API uint32_t srslte_crc_attach(srslte_crc_t *h,
uint8_t *data,
int len);
SRSLTE_API uint32_t srslte_crc_attach_byte(srslte_crc_t *h,
uint8_t *data,
int len);
SRSLTE_API uint32_t srslte_crc_checksum_byte(srslte_crc_t *h,
uint8_t *data,
int len);
SRSLTE_API uint32_t srslte_crc_checksum(srslte_crc_t *h,
uint8_t *data,

View File

@ -85,6 +85,10 @@ SRSLTE_API void srslte_tdec_decision(srslte_tdec_t * h,
uint8_t *output,
uint32_t long_cb);
SRSLTE_API void srslte_tdec_decision_byte(srslte_tdec_t * h,
uint8_t *output,
uint32_t long_cb);
SRSLTE_API int srslte_tdec_run_all(srslte_tdec_t * h,
srslte_llr_t * input,
uint8_t *output,

View File

@ -65,6 +65,7 @@ typedef struct SRSLTE_API {
/* buffers */
uint8_t *cb_in;
uint8_t *cb_temp;
void *cb_out;
void *e;

View File

@ -35,10 +35,10 @@
void gen_crc_table(srslte_crc_t *h) {
int i, j, ord = (h->order - 8);
unsigned long bit, crc;
uint64_t bit, crc;
for (i = 0; i < 256; i++) {
crc = ((unsigned long) i) << ord;
crc = ((uint64_t) i) << ord;
for (j = 0; j < 8; j++) {
bit = crc & h->crchighbit;
crc <<= 1;
@ -49,21 +49,20 @@ void gen_crc_table(srslte_crc_t *h) {
}
}
unsigned long crctable(srslte_crc_t *h) {
uint64_t crctable(srslte_crc_t *h, uint8_t byte) {
// Polynom order 8, 16, 24 or 32 only.
int ord = h->order - 8;
unsigned long crc = h->crcinit;
uint8_t byte = h->byte;
uint64_t crc = h->crcinit;
crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte];
h->crcinit = crc;
return (crc & h->crcmask);
}
unsigned long reversecrcbit(uint32_t crc, int nbits, srslte_crc_t *h) {
uint64_t reversecrcbit(uint32_t crc, int nbits, srslte_crc_t *h) {
unsigned long m, rmask = 0x1;
uint64_t m, rmask = 0x1;
for (m = 0; m < nbits; m++) {
if ((rmask & crc) == 0x01)
@ -74,7 +73,7 @@ unsigned long reversecrcbit(uint32_t crc, int nbits, srslte_crc_t *h) {
return (crc & h->crcmask);
}
int srslte_crc_set_init(srslte_crc_t *crc_par, unsigned long crc_init_value) {
int srslte_crc_set_init(srslte_crc_t *crc_par, uint64_t crc_init_value) {
crc_par->crcinit = crc_init_value;
if (crc_par->crcinit != (crc_par->crcinit & crc_par->crcmask)) {
@ -92,9 +91,8 @@ int srslte_crc_init(srslte_crc_t *h, uint32_t crc_poly, int crc_order) {
h->crcinit = 0x00000000;
// Compute bit masks for whole CRC and CRC high bit
h->crcmask = ((((unsigned long) 1 << (h->order - 1)) - 1) << 1)
| 1;
h->crchighbit = (unsigned long) 1 << (h->order - 1);
h->crcmask = ((((uint64_t) 1 << (h->order - 1)) - 1) << 1) | 1;
h->crchighbit = (uint64_t) 1 << (h->order - 1);
// check parameters
if (h->order % 8 != 0) {
@ -131,15 +129,16 @@ uint32_t srslte_crc_checksum(srslte_crc_t *h, uint8_t *data, int len) {
// Calculate CRC
for (i = 0; i < len8 + a; i++) {
pter = (uint8_t *) (data + 8 * i);
uint8_t byte;
if (i == len8) {
h->byte = 0x00;
byte = 0x00;
for (k = 0; k < res8; k++) {
h->byte |= ((uint8_t) *(pter + k)) << (7 - k);
byte |= ((uint8_t) *(pter + k)) << (7 - k);
}
} else {
h->byte = (uint8_t) (srslte_bit_unpack(&pter, 8) & 0xFF);
byte = (uint8_t) (srslte_bit_unpack(&pter, 8) & 0xFF);
}
crc = crctable(h);
crc = crctable(h, byte);
}
// Reverse CRC res8 positions
@ -152,14 +151,41 @@ uint32_t srslte_crc_checksum(srslte_crc_t *h, uint8_t *data, int len) {
}
// len is multiple of 8
uint32_t srslte_crc_checksum_byte(srslte_crc_t *h, uint8_t *data, int len) {
int i;
uint32_t crc = 0;
srslte_crc_set_init(h, 0);
// Calculate CRC
for (i = 0; i < len/8; i++) {
crc = crctable(h, data[i]);
}
return crc;
}
uint32_t srslte_crc_attach_byte(srslte_crc_t *h, uint8_t *data, int len) {
uint32_t checksum = srslte_crc_checksum_byte(h, data, len);
// Add CRC
for (int i=0;i<h->order/8;i++) {
data[len/8+(h->order/8-i-1)] = (checksum&(0xff<<(8*i)))>>(8*i);
}
return checksum;
}
/** Appends crc_order checksum bits to the buffer data.
* The buffer data must be len + crc_order bytes
*/
void srslte_crc_attach(srslte_crc_t *h, uint8_t *data, int len) {
uint32_t srslte_crc_attach(srslte_crc_t *h, uint8_t *data, int len) {
uint32_t checksum = srslte_crc_checksum(h, data, len);
// Add CRC
uint8_t *ptr = &data[len];
srslte_bit_pack(checksum, &ptr, h->order);
return checksum;
}

View File

@ -334,6 +334,20 @@ void srslte_tdec_decision(srslte_tdec_t * h, uint8_t *output, uint32_t long_cb)
}
}
void srslte_tdec_decision_byte(srslte_tdec_t * h, uint8_t *output, uint32_t long_cb)
{
uint32_t i, j;
// long_cb is always byte aligned
for (i = 0; i < long_cb/8; i++) {
output[i] = 0;
for (j=0;j<8;j++) {
if (h->llr2[h->interleaver.reverse[8*i+j]] > 0) {
output[i] |= 1<<(7-j);
}
}
}
}
int srslte_tdec_run_all(srslte_tdec_t * h, srslte_llr_t * input, uint8_t *output,
uint32_t nof_iterations, uint32_t long_cb)
{

View File

@ -111,6 +111,10 @@ int srslte_sch_init(srslte_sch_t *q) {
if (!q->cb_in) {
goto clean;
}
q->cb_temp = srslte_vec_malloc(sizeof(uint8_t) * SRSLTE_TCOD_MAX_LEN_CB);
if (!q->cb_temp) {
goto clean;
}
q->cb_out = srslte_vec_malloc(sizeof(float) * (3 * SRSLTE_TCOD_MAX_LEN_CB + 12));
if (!q->cb_out) {
@ -133,6 +137,9 @@ void srslte_sch_free(srslte_sch_t *q) {
if (q->cb_in) {
free(q->cb_in);
}
if (q->cb_temp) {
free(q->cb_temp);
}
if (q->cb_out) {
free(q->cb_out);
}
@ -161,8 +168,7 @@ static int encode_tb(srslte_sch_t *q,
uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,
uint8_t *data, uint8_t *e_bits)
{
uint8_t parity[24];
uint8_t *p_parity = parity;
uint8_t parity[3] = {0, 0, 0};
uint32_t par;
uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e;
@ -182,17 +188,20 @@ static int encode_tb(srslte_sch_t *q,
}
if (data) {
/* Compute transport block CRC */
par = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs);
par = srslte_crc_checksum_byte(&q->crc_tb, data, cb_segm->tbs);
/* parity bits will be appended later */
srslte_bit_pack(par, &p_parity, 24);
parity[0] = (par&(0xff<<16))>>16;
parity[1] = (par&(0xff<<8))>>8;
parity[2] = par&0xff;
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("DATA: ", 0);
srslte_vec_fprint_b(stdout, data, cb_segm->tbs);
srslte_vec_fprint_byte(stdout, data, cb_segm->tbs/8);
DEBUG("PARITY: ", 0);
srslte_vec_fprint_b(stdout, parity, 24);
srslte_vec_fprint_byte(stdout, parity, 3);
}
}
@ -230,33 +239,41 @@ static int encode_tb(srslte_sch_t *q,
/* Copy data to another buffer, making space for the Codeblock CRC */
if (i < cb_segm->C - 1) {
// Copy data
memcpy(&q->cb_in[F], &data[rp], (rlen - F) * sizeof(uint8_t));
memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - F) * sizeof(uint8_t)/8);
} else {
INFO("Last CB, appending parity: %d from %d and 24 to %d\n",
rlen - F - 24, rp, rlen - 24);
/* Append Transport Block parity bits to the last CB */
memcpy(&q->cb_in[F], &data[rp], (rlen - 24 - F) * sizeof(uint8_t));
memcpy(&q->cb_in[rlen - 24], parity, 24 * sizeof(uint8_t));
memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - 24 - F) * sizeof(uint8_t)/8);
memcpy(&q->cb_in[(rlen - 24)/8], parity, 3 * sizeof(uint8_t));
}
/* Filler bits are treated like zeros for the CB CRC calculation */
for (int j = 0; j < F; j++) {
for (int j = 0; j < F/8; j++) {
q->cb_in[j] = 0;
}
/* Attach Codeblock CRC */
if (cb_segm->C > 1) {
srslte_crc_attach(&q->crc_cb, q->cb_in, rlen);
srslte_crc_attach_byte(&q->crc_cb, q->cb_in, rlen);
}
/* pack bits to temporal buffer for encoding */
srslte_bit_pack_vector(q->cb_in, q->cb_temp, cb_len);
/* Set the filler bits to <NULL> */
for (int j = 0; j < F; j++) {
q->cb_in[j] = SRSLTE_TX_NULL;
q->cb_temp[j] = SRSLTE_TX_NULL;
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("CB#%d: ", i);
srslte_vec_fprint_b(stdout, q->cb_in, cb_len);
srslte_vec_fprint_hex(stdout, q->cb_temp, cb_len);
}
/* Turbo Encoding */
srslte_tcod_encode(&q->encoder, q->cb_in, (uint8_t*) q->cb_out, cb_len);
srslte_tcod_encode(&q->encoder, q->cb_temp, (uint8_t*) q->cb_out, cb_len);
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("CB#%d encoded: ", i);
srslte_vec_fprint_b(stdout, q->cb_out, cb_len);
@ -291,8 +308,7 @@ static int decode_tb(srslte_sch_t *q,
uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,
float *e_bits, uint8_t *data)
{
uint8_t parity[24];
uint8_t *p_parity = parity;
uint8_t parity[3] = {0, 0, 0};
uint32_t par_rx, par_tx;
uint32_t i;
uint32_t cb_len, rp, wp, rlen, F, n_e;
@ -379,14 +395,14 @@ static int decode_tb(srslte_sch_t *q,
crc_ptr = &q->crc_cb;
} else {
len_crc = cb_segm->tbs+24;
cb_in_ptr = &q->cb_in[F];
cb_in_ptr = &q->cb_in[F/8];
crc_ptr = &q->crc_tb;
}
srslte_tdec_decision(&q->decoder, q->cb_in, cb_len);
srslte_tdec_decision_byte(&q->decoder, q->cb_in, cb_len);
/* Check Codeblock CRC and stop early if incorrect */
if (!srslte_crc_checksum(crc_ptr, cb_in_ptr, len_crc)) {
if (!srslte_crc_checksum_byte(crc_ptr, cb_in_ptr, len_crc)) {
early_stop = true;
}
@ -395,21 +411,25 @@ static int decode_tb(srslte_sch_t *q,
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("CB#%d IN: ", i);
srslte_vec_fprint_b(stdout, q->cb_in, cb_len);
srslte_vec_fprint_byte(stdout, q->cb_in, cb_len/8);
}
// If CB CRC is not correct, early_stop will be false and wont continue with rest of CBs
if (F%8) {
fprintf(stderr, "Fatal Error: Number of filler bits %d is not byte aligned\n", F);
}
/* Copy data to another buffer, removing the Codeblock CRC */
if (i < cb_segm->C - 1) {
memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t));
memcpy(&data[wp/8], &q->cb_in[F/8], (rlen - F) * sizeof(uint8_t)/8);
} else {
DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n",
rlen - F - 24, wp, F, rlen - 24);
/* Append Transport Block parity bits to the last CB */
memcpy(&data[wp], &q->cb_in[F], (rlen - F - 24) * sizeof(uint8_t));
memcpy(parity, &q->cb_in[rlen - 24], 24 * sizeof(uint8_t));
memcpy(&data[wp/8], &q->cb_in[F/8], (rlen - F - 24) * sizeof(uint8_t)/8);
memcpy(parity, &q->cb_in[(rlen - 24)/8], 24 * sizeof(uint8_t)/8);
}
/* Set read/write pointers */
@ -418,17 +438,17 @@ static int decode_tb(srslte_sch_t *q,
}
if (!early_stop) {
INFO("CB %d failed. TB is erroneous.\n",i-1);
printf("CB %d failed. TB is erroneous.\n",i-1);
return SRSLTE_ERROR;
} else {
INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
// Compute transport block CRC
par_rx = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs);
par_rx = srslte_crc_checksum_byte(&q->crc_tb, data, cb_segm->tbs);
// check parity bits
par_tx = srslte_bit_unpack(&p_parity, 24);
par_tx = ((uint32_t) parity[0])<<16 | ((uint32_t) parity[1])<<8 | ((uint32_t) parity[2]);
if (!par_rx) {
INFO("\n\tCAUTION!! Received all-zero transport block\n\n", 0);
}
@ -437,7 +457,7 @@ static int decode_tb(srslte_sch_t *q,
INFO("TB decoded OK\n",i);
return SRSLTE_SUCCESS;
} else {
INFO("Error in TB parity\n",i);
INFO("Error in TB parity: par_tx=0x%x, par_rx=0x%x\n", par_tx, par_rx);
return SRSLTE_ERROR;
}

View File

@ -93,7 +93,7 @@ BuildMex(MEXNAME pdcch SOURCES pdcch_test_mex.c LIBRARIES srslte srslte_mex)
ADD_EXECUTABLE(pdsch_test pdsch_test.c)
TARGET_LINK_LIBRARIES(pdsch_test srslte)
ADD_TEST(pdsch_test_bpsk pdsch_test -l 500 -m 1 -n 50 -r 2)
ADD_TEST(pdsch_test_bpsk pdsch_test -l 504 -m 1 -n 50 -r 2)
ADD_TEST(pdsch_test_qpsk pdsch_test -l 1000 -m 2 -n 50 -r 1)
ADD_TEST(pdsch_test_qam16 pdsch_test -l 50000 -m 4 -n 100)
ADD_TEST(pdsch_test_qam64 pdsch_test -l 61664 -m 6 -n 100 -r 0)

View File

@ -170,7 +170,7 @@ int main(int argc, char **argv) {
}
}
data = malloc(sizeof(uint8_t) * tbs);
data = malloc(sizeof(uint8_t) * tbs/8);
if (!data) {
perror("malloc");
goto quit;
@ -196,8 +196,8 @@ int main(int argc, char **argv) {
if (SRSLTE_VERBOSE_ISNONE()) {
printf("Decoding TBS: %d\r",grant.mcs.tbs);
}
for (i=0;i<grant.mcs.tbs;i++) {
data[i] = rand()%2;
for (i=0;i<grant.mcs.tbs/8;i++) {
data[i] = rand()%256;
}
for (rv=0;rv<=rv_idx;rv++) {
@ -228,7 +228,8 @@ int main(int argc, char **argv) {
ret = -1;
goto quit;
} else {
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) grant.mcs.tbs/t[0].tv_usec);
printf("DECODED OK in %d:%d (%.2f Mbps)\n",
(int) t[0].tv_sec, (int) t[0].tv_usec, (float) grant.mcs.tbs/t[0].tv_usec);
}
}
ret = 0;