diff --git a/lib/include/srslte/phy/fec/crc.h b/lib/include/srslte/phy/fec/crc.h index 030e7c6bb..9bc864831 100644 --- a/lib/include/srslte/phy/fec/crc.h +++ b/lib/include/srslte/phy/fec/crc.h @@ -63,7 +63,21 @@ SRSLTE_API uint32_t srslte_crc_attach(srslte_crc_t *h, SRSLTE_API uint32_t srslte_crc_attach_byte(srslte_crc_t *h, uint8_t *data, - int len); + int len); + +static inline void srslte_crc_checksum_put_byte(srslte_crc_t *h, uint8_t byte) { + + // Polynom order 8, 16, 24 or 32 only. + int ord = h->order - 8; + uint64_t crc = h->crcinit; + + crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte]; + h->crcinit = crc; +} + +static inline uint64_t srslte_crc_checksum_get(srslte_crc_t *h) { + return (h->crcinit & h->crcmask); +} SRSLTE_API uint32_t srslte_crc_checksum_byte(srslte_crc_t *h, uint8_t *data, diff --git a/lib/include/srslte/phy/fec/turbocoder.h b/lib/include/srslte/phy/fec/turbocoder.h index 485e83ff3..4da697461 100644 --- a/lib/include/srslte/phy/fec/turbocoder.h +++ b/lib/include/srslte/phy/fec/turbocoder.h @@ -40,6 +40,7 @@ #include "srslte/config.h" #include "srslte/phy/fec/tc_interl.h" +#include "srslte/phy/fec/crc.h" #define SRSLTE_TCOD_MAX_LEN_CB_BYTES (6144/8) @@ -68,7 +69,8 @@ SRSLTE_API int srslte_tcod_encode(srslte_tcod_t *h, uint8_t *output, uint32_t long_cb); -SRSLTE_API int srslte_tcod_encode_lut(srslte_tcod_t *h, +SRSLTE_API int srslte_tcod_encode_lut(srslte_tcod_t *h, + srslte_crc_t *crc, uint8_t *input, uint8_t *parity, uint32_t cblen_idx); diff --git a/lib/src/phy/fec/crc.c b/lib/src/phy/fec/crc.c index a2f6d7931..c97bdd6f9 100644 --- a/lib/src/phy/fec/crc.c +++ b/lib/src/phy/fec/crc.c @@ -48,17 +48,6 @@ void gen_crc_table(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; - uint64_t crc = h->crcinit; - - crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte]; - h->crcinit = crc; - return (crc & h->crcmask); -} - uint64_t reversecrcbit(uint32_t crc, int nbits, srslte_crc_t *h) { uint64_t m, rmask = 0x1; @@ -137,8 +126,9 @@ uint32_t srslte_crc_checksum(srslte_crc_t *h, uint8_t *data, int len) { } else { byte = (uint8_t) (srslte_bit_pack(&pter, 8) & 0xFF); } - crc = crctable(h, byte); + srslte_crc_checksum_put_byte(h, byte); } + crc = (uint32_t) srslte_crc_checksum_get(h); // Reverse CRC res8 positions if (a == 1) { @@ -159,8 +149,9 @@ uint32_t srslte_crc_checksum_byte(srslte_crc_t *h, uint8_t *data, int len) { // Calculate CRC for (i = 0; i < len/8; i++) { - crc = crctable(h, data[i]); + srslte_crc_checksum_put_byte(h, data[i]); } + crc = (uint32_t) srslte_crc_checksum_get(h); return crc; diff --git a/lib/src/phy/fec/test/turbocoder_test.c b/lib/src/phy/fec/test/turbocoder_test.c index f8219a4e2..59f057919 100644 --- a/lib/src/phy/fec/test/turbocoder_test.c +++ b/lib/src/phy/fec/test/turbocoder_test.c @@ -97,7 +97,7 @@ int main(int argc, char **argv) { } srslte_tcod_encode(&tcod, input_bits, output_bits, long_cb); - srslte_tcod_encode_lut(&tcod, input_bytes, parity, len); + srslte_tcod_encode_lut(&tcod, NULL, input_bytes, parity, len); srslte_bit_unpack_vector(parity, parity_bits, 2*(long_cb+4)); diff --git a/lib/src/phy/fec/turbocoder.c b/lib/src/phy/fec/turbocoder.c index 69f40dd46..c8fd5ffb4 100644 --- a/lib/src/phy/fec/turbocoder.c +++ b/lib/src/phy/fec/turbocoder.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/turbocoder.h" @@ -40,9 +41,13 @@ #define RATE 3 #define TOTALTAIL 12 -uint8_t tcod_lut_next_state[188][8][256]; -uint8_t tcod_lut_output[188][8][256]; -uint16_t tcod_per_fw[188][6144]; +typedef struct { + uint8_t next_state; + uint8_t output; +} tcod_lut_t; + +static tcod_lut_t tcod_lut[188][8][256]; +static uint16_t tcod_per_fw[188][6144]; static srslte_bit_interleaver_t tcod_interleavers[188]; static bool table_initiated = false; @@ -187,23 +192,59 @@ int srslte_tcod_encode(srslte_tcod_t *h, uint8_t *input, uint8_t *output, uint32 } /* Expects bytes and produces bytes. The systematic and parity bits are interlaced in the output */ -int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, uint8_t *parity, uint32_t cblen_idx) +int srslte_tcod_encode_lut(srslte_tcod_t *h, srslte_crc_t *crc, uint8_t *input, uint8_t *parity, uint32_t cblen_idx) { if (cblen_idx < 188) { - uint32_t long_cb = srslte_cbsegm_cbsize(cblen_idx); + uint32_t long_cb = (uint32_t) srslte_cbsegm_cbsize(cblen_idx); if (long_cb % 8) { fprintf(stderr, "Turbo coder LUT implementation long_cb must be multiple of 8\n"); return -1; } - + + /* Reset CRC */ + if (crc) { + srslte_crc_set_init(crc, 0); + } + /* Parity bits for the 1st constituent encoders */ - uint8_t state0 = 0; - for (uint32_t i=0;iorder) / 8; i++) { + uint8_t in = input[i]; + + /* Put byte in CRC and save latest checksum */ + srslte_crc_checksum_put_byte(crc, in); + + /* Run actual encoder */ + tcod_lut_t l = tcod_lut[cblen_idx][state0][in]; + parity[i] = l.output; + state0 = l.next_state; + } + + uint32_t checksum = (uint32_t) srslte_crc_checksum_get(crc); + for (int i = 0; i < crc->order / 8; i++) { + int mask_shift = 8 * (crc->order / 8 - i - 1); + int idx = (long_cb - crc->order) / 8 + i; + uint8_t in = (uint8_t) ((checksum >> mask_shift) & 0xff); + + input[idx] = in; + tcod_lut_t l = tcod_lut[cblen_idx][state0][in]; + parity[idx] = l.output; + state0 = l.next_state; + } + + } else { + /* No CRC given */ + for (uint32_t i = 0; i < long_cb / 8; i++) { + tcod_lut_t l = tcod_lut[cblen_idx][state0][input[i]]; + parity[i] = l.output; + state0 = l.next_state; + } } - parity[long_cb/8] = 0; // will put tail here later + parity[long_cb / 8] = 0; // will put tail here later /* Interleave input */ srslte_bit_interleaver_run(&tcod_interleavers[cblen_idx], input, h->temp, 0); @@ -212,10 +253,11 @@ int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, uint8_t *parity, ui /* Parity bits for the 2nd constituent encoders */ uint8_t state1 = 0; for (uint32_t i=0;itemp[i]]; + tcod_lut_t l = tcod_lut[cblen_idx][state1][h->temp[i]]; + uint8_t out = l.output; parity[long_cb/8+i] |= (out&0xf0)>>4; - parity[long_cb/8+i+1] = (out&0xf)<<4; - state1 = tcod_lut_next_state[cblen_idx][state1][h->temp[i]] % 8; + parity[long_cb/8+i+1] = (out&0xf)<<4; + state1 = l.next_state; } /* Tail bits */ @@ -318,7 +360,7 @@ void srslte_tcod_gentable() { reg_1 = (state&2)>>1; reg_2 = state&1; - tcod_lut_output[len][state][data] = 0; + tcod_lut[len][state][data].output = 0; uint8_t bit, in, out; for (uint32_t i = 0; i < 8; i++) { bit = (data&(1<<(7-i)))?1:0; @@ -330,10 +372,10 @@ void srslte_tcod_gentable() { reg_1 = reg_0; reg_0 = in; - tcod_lut_output[len][state][data] |= out<<(7-i); + tcod_lut[len][state][data].output |= out<<(7-i); } - tcod_lut_next_state[len][state][data] = reg_0<<2 | reg_1<<1 | reg_2; + tcod_lut[len][state][data].next_state = (uint8_t) ((reg_0 << 2 | reg_1 << 1 | reg_2) % 8); } } } diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index aa1f297d7..2d7290e9d 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -264,15 +264,12 @@ static int encode_tb_off(srslte_sch_t *q, /* Append Transport Block parity bits to the last CB */ memcpy(q->cb_in, &data[rp/8], (rlen - 24) * sizeof(uint8_t)/8); memcpy(&q->cb_in[(rlen - 24)/8], parity, 3 * sizeof(uint8_t)); - } - - /* Attach Codeblock CRC */ - if (cb_segm->C > 1) { - srslte_crc_attach_byte(&q->crc_cb, q->cb_in, rlen); } - /* Turbo Encoding */ - srslte_tcod_encode_lut(&q->encoder, q->cb_in, q->parity_bits, cblen_idx); + /* Turbo Encoding + * If Codeblock CRC is required it is given the CRC instance pointer, otherwise CRC pointer shall be NULL + */ + srslte_tcod_encode_lut(&q->encoder, (cb_segm->C > 1) ? &q->crc_cb : NULL, q->cb_in, q->parity_bits, cblen_idx); } DEBUG("RM cblen_idx=%d, n_e=%d, wp=%d, nof_e_bits=%d\n",cblen_idx, n_e, wp, nof_e_bits);