mirror of https://github.com/pvnis/srsRAN_4G.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.4 KiB
C
191 lines
4.4 KiB
C
/**
|
|
*
|
|
* \section COPYRIGHT
|
|
*
|
|
* Copyright 2013-2015 Software Radio Systems Limited
|
|
*
|
|
* \section LICENSE
|
|
*
|
|
* This file is part of the srsLTE library.
|
|
*
|
|
* srsLTE is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* srsLTE is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* A copy of the GNU Affero General Public License can be found in
|
|
* the LICENSE file in the top-level directory of this distribution
|
|
* and at http://www.gnu.org/licenses/.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "srslte/utils/bit.h"
|
|
#include "srslte/fec/crc.h"
|
|
|
|
void gen_crc_table(srslte_crc_t *h) {
|
|
|
|
int i, j, ord = (h->order - 8);
|
|
uint64_t bit, crc;
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
crc = ((uint64_t) i) << ord;
|
|
for (j = 0; j < 8; j++) {
|
|
bit = crc & h->crchighbit;
|
|
crc <<= 1;
|
|
if (bit)
|
|
crc ^= h->polynom;
|
|
}
|
|
h->table[i] = crc & h->crcmask;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
for (m = 0; m < nbits; m++) {
|
|
if ((rmask & crc) == 0x01)
|
|
crc = (crc ^ h->polynom) >> 1;
|
|
else
|
|
crc = crc >> 1;
|
|
}
|
|
return (crc & h->crcmask);
|
|
}
|
|
|
|
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)) {
|
|
printf("ERROR, invalid crcinit in crc_set_init().\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int srslte_crc_init(srslte_crc_t *h, uint32_t crc_poly, int crc_order) {
|
|
|
|
// Set crc working default parameters
|
|
h->polynom = crc_poly;
|
|
h->order = crc_order;
|
|
h->crcinit = 0x00000000;
|
|
|
|
// Compute bit masks for whole CRC and CRC high bit
|
|
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) {
|
|
fprintf(stderr, "ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n",
|
|
h->order);
|
|
return -1;
|
|
}
|
|
|
|
if (srslte_crc_set_init(h, h->crcinit)) {
|
|
fprintf(stderr, "Error setting CRC init word\n");
|
|
return -1;
|
|
}
|
|
|
|
// generate lookup table
|
|
gen_crc_table(h);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t srslte_crc_checksum(srslte_crc_t *h, uint8_t *data, int len) {
|
|
int i, k, len8, res8, a = 0;
|
|
uint32_t crc = 0;
|
|
uint8_t *pter;
|
|
|
|
srslte_crc_set_init(h, 0);
|
|
|
|
// Pack bits into bytes
|
|
len8 = (len >> 3);
|
|
res8 = (len - (len8 << 3));
|
|
if (res8 > 0) {
|
|
a = 1;
|
|
}
|
|
|
|
// Calculate CRC
|
|
for (i = 0; i < len8 + a; i++) {
|
|
pter = (uint8_t *) (data + 8 * i);
|
|
uint8_t byte;
|
|
if (i == len8) {
|
|
byte = 0x00;
|
|
for (k = 0; k < res8; k++) {
|
|
byte |= ((uint8_t) *(pter + k)) << (7 - k);
|
|
}
|
|
} else {
|
|
byte = (uint8_t) (srslte_bit_pack(&pter, 8) & 0xFF);
|
|
}
|
|
crc = crctable(h, byte);
|
|
}
|
|
|
|
// Reverse CRC res8 positions
|
|
if (a == 1) {
|
|
crc = reversecrcbit(crc, 8 - res8, h);
|
|
}
|
|
|
|
//Return CRC value
|
|
return crc;
|
|
|
|
}
|
|
|
|
// 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
|
|
*/
|
|
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_unpack(checksum, &ptr, h->order);
|
|
return checksum;
|
|
}
|
|
|