crc_byte.c 10.9 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22 23 24
/* file: crc_byte.c
   purpose: generate 3GPP LTE CRCs. Byte-oriented implementation of CRC's
   author: raymond.knopp@eurecom.fr
25
   date: 21.10.2009
26 27 28 29 30 31 32

   Original UMTS version by
   P. Humblet
   May 10, 2001
   Modified in June, 2001, to include  the length non multiple of 8
*/

33
#define USE_INTEL_CRC __SSE4_1__
34

35
#include "coding_defs.h"
Khalid Ahmed's avatar
Khalid Ahmed committed
36
#include "assertions.h"
Laurent THOMAS's avatar
Laurent THOMAS committed
37
#if USE_INTEL_CRC 
38
#include "crc.h"
39
#endif
40 41
/*ref 36-212 v8.6.0 , pp 8-9 */
/* the highest degree is set by default */
Guy De Souza's avatar
Guy De Souza committed
42

yilmazt's avatar
yilmazt committed
43 44 45 46 47 48
unsigned int             poly24a = 0x864cfb00;   // 1000 0110 0100 1100 1111 1011
												 // D^24 + D^23 + D^18 + D^17 + D^14 + D^11 + D^10 + D^7 + D^6 + D^5 + D^4 + D^3 + D + 1
unsigned int             poly24b = 0x80006300;   // 1000 0000 0000 0000 0110 0011
											     // D^24 + D^23 + D^6 + D^5 + D + 1
unsigned int             poly24c = 0xb2b11700;   // 1011 0010 1011 0001 0001 0111
												 // D^24+D^23+D^21+D^20+D^17+D^15+D^13+D^12+D^8+D^4+D^2+D+1
Guy De Souza's avatar
Guy De Souza committed
49

50 51 52
unsigned int             poly16 = 0x10210000;    // 0001 0000 0010 0001            D^16 + D^12 + D^5 + 1
unsigned int             poly12 = 0x80F00000;    // 1000 0000 1111                 D^12 + D^11 + D^3 + D^2 + D + 1
unsigned int             poly8 = 0x9B000000;     // 1001 1011                      D^8  + D^7  + D^4 + D^3 + D + 1
53 54 55
uint32_t poly6 = 0x84000000; // 10000100000... -> D^6+D^5+1
uint32_t poly11 = 0xc4200000; //11000100001000... -> D^11+D^10+D^9+D^5+1

56 57
/*********************************************************

58
For initialization && verification purposes,
59 60 61 62 63
   bit by bit implementation with any polynomial

The first bit is in the MSB of each byte

*********************************************************/
yilmazt's avatar
yilmazt committed
64
unsigned int crcbit (unsigned char * inputptr,
65 66
		     int octetlen,
		     unsigned int poly)
67
{
yilmazt's avatar
yilmazt committed
68
  unsigned int i, crc = 0, c;
69

70 71
  while (octetlen-- > 0) {
    c = (*inputptr++) << 24;
72

73 74 75 76 77
    for (i = 8; i != 0; i--) {
      if ((1 << 31) & (c ^ crc))
        crc = (crc << 1) ^ poly;
      else
        crc <<= 1;
78

79 80 81
      c <<= 1;
    }
  }
82

83 84 85 86 87 88 89 90
  return crc;
}

/*********************************************************

crc table initialization

*********************************************************/
yilmazt's avatar
yilmazt committed
91 92 93
static unsigned int        crc24aTable[256];
static unsigned int        crc24bTable[256];
static unsigned int        crc24cTable[256];
94 95
static unsigned short      crc16Table[256];
static unsigned short      crc12Table[256];
96
static unsigned short      crc11Table[256];
97
static unsigned char       crc8Table[256];
98
static unsigned char       crc6Table[256];
99

Laurent THOMAS's avatar
Laurent THOMAS committed
100
#if USE_INTEL_CRC
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
static DECLARE_ALIGNED(struct crc_pclmulqdq_ctx lte_crc24a_pclmulqdq, 16) = {
        0x64e4d700,     /**< k1 */
        0x2c8c9d00,     /**< k2 */
        0xd9fe8c00,     /**< k3 */
        0xf845fe24,     /**< q */
        0x864cfb00,     /**< p */
        0ULL            /**< res */
};
__m128i crc_xmm_be_le_swap128;

DECLARE_ALIGNED(const uint8_t crc_xmm_shift_tab[48], 16) = {
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

120
#endif
121

122 123
void crcTableInit (void)
{
yilmazt's avatar
yilmazt committed
124
  unsigned char c = 0;
125

126 127 128
  do {
    crc24aTable[c] = crcbit (&c, 1, poly24a);
    crc24bTable[c] = crcbit (&c, 1, poly24b);
yilmazt's avatar
yilmazt committed
129
    crc24cTable[c] = crcbit (&c, 1, poly24c);
130 131
    crc16Table[c] = (unsigned short) (crcbit (&c, 1, poly16) >> 16);
    crc12Table[c] = (unsigned short) (crcbit (&c, 1, poly12) >> 16);
132
    crc11Table[c] = (unsigned short) (crcbit (&c, 1, poly11) >> 16);
133
    crc8Table[c] = (unsigned char) (crcbit (&c, 1, poly8) >> 24);
134
    crc6Table[c] = (unsigned char) (crcbit (&c, 1, poly6) >> 24);
135
  } while (++c);
Laurent THOMAS's avatar
Laurent THOMAS committed
136
#if USE_INTEL_CRC
137 138
    crc_xmm_be_le_swap128 = _mm_setr_epi32(0x0c0d0e0f, 0x08090a0b,
					   0x04050607, 0x00010203);
139

140
#endif
141
}
142

143 144
/*********************************************************

145
Byte by byte LUT implementations,
146
assuming initial byte is 0 padded (in MSB) if necessary
147
can use SIMD optimized Intel CRC for LTE/NR 24a/24b variants
148
*********************************************************/
149

yilmazt's avatar
yilmazt committed
150 151
unsigned int crc24a (unsigned char * inptr,
					 int bitlen)
152
{
153
  int octetlen = bitlen / 8;  /* Change in octets */
154

155
  if ( bitlen % 8 || !USE_INTEL_CRC ) {
156 157
  unsigned int      crc = 0;
  int resbit= (bitlen % 8);
158
    
159
  while (octetlen-- > 0) {
160
    //   printf("crc24a: in %x => crc %x\n",crc,*inptr);
161 162
    crc = (crc << 8) ^ crc24aTable[(*inptr++) ^ (crc >> 24)];
  }
163

164 165 166
  if (resbit > 0)
    crc = (crc << resbit) ^ crc24aTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
  return crc;
167 168 169
  }
  #if USE_INTEL_CRC
  else {
170
  return crc32_calc_pclmulqdq(inptr, octetlen, 0,
171
                              &lte_crc24a_pclmulqdq);
172
  }
173
  #endif
174

175 176
}

Laurent THOMAS's avatar
Laurent THOMAS committed
177
#if USE_INTEL_CRC
178 179 180 181 182 183 184 185
static DECLARE_ALIGNED(struct crc_pclmulqdq_ctx lte_crc24b_pclmulqdq, 16) = {
        0x80140500,     /**< k1 */
        0x42000100,     /**< k2 */
        0x90042100,     /**< k3 */
        0xffff83ff,     /**< q */
        0x80006300,     /**< p */
        0ULL            /**< res */
};
186
#endif
yilmazt's avatar
yilmazt committed
187
unsigned int crc24b (unsigned char * inptr,
188
	   	     int bitlen)
189
{
190 191
  int octetlen = bitlen / 8;  /* Change in octets */
  
192
  if ( bitlen % 8 || !USE_INTEL_CRC ) {
193 194
  unsigned int crc = 0;
  int resbit = (bitlen % 8);
195

196
  while (octetlen-- > 0) {
197
    //    printf("crc24b: in %x => crc %x (%x)\n",crc,*inptr,crc24bTable[(*inptr) ^ (crc >> 24)]);
198 199
    crc = (crc << 8) ^ crc24bTable[(*inptr++) ^ (crc >> 24)];
  }
200

201 202
  if (resbit > 0)
    crc = (crc << resbit) ^ crc24bTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
203

204
  return crc;
205 206 207
  }
#if USE_INTEL_CRC
  else {
208
  return crc32_calc_pclmulqdq(inptr, octetlen, 0,
209
                              &lte_crc24b_pclmulqdq);
210
  }
211
#endif
212 213
}

yilmazt's avatar
yilmazt committed
214 215 216 217 218 219 220 221 222 223 224 225
unsigned int crc24c (unsigned char * inptr,
					 int bitlen)
{
  int octetlen, resbit;
  unsigned int crc = 0;
  octetlen = bitlen / 8;        /* Change in octets */
  resbit = (bitlen % 8);

  while (octetlen-- > 0) {
    crc = (crc << 8) ^ crc24cTable[(*inptr++) ^ (crc >> 24)];
  }

226
  if (resbit > 0) {
yilmazt's avatar
yilmazt committed
227
    crc = (crc << resbit) ^ crc24cTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
228
  }
yilmazt's avatar
yilmazt committed
229 230 231 232

  return crc;
}

233 234 235 236 237 238 239
unsigned int
crc16 (unsigned char * inptr, int bitlen)
{
  int             octetlen, resbit;
  unsigned int             crc = 0;
  octetlen = bitlen / 8;        /* Change in octets */
  resbit = (bitlen % 8);
240

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
  while (octetlen-- > 0) {

    crc = (crc << 8) ^ (crc16Table[(*inptr++) ^ (crc >> 24)] << 16);
  }

  if (resbit > 0)
    crc = (crc << resbit) ^ (crc16Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 16);

  return crc;
}

unsigned int
crc12 (unsigned char * inptr, int bitlen)
{
  int             octetlen, resbit;
  unsigned int             crc = 0;
  octetlen = bitlen / 8;        /* Change in octets */
  resbit = (bitlen % 8);
259

260 261 262
  while (octetlen-- > 0) {
    crc = (crc << 8) ^ (crc12Table[(*inptr++) ^ (crc >> 24)] << 16);
  }
263

264 265
  if (resbit > 0)
    crc = (crc << resbit) ^ (crc12Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 16);
266

267 268 269
  return crc;
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
unsigned int
crc11 (unsigned char * inptr, int bitlen)
{
  int             octetlen, resbit;
  unsigned int             crc = 0;
  octetlen = bitlen / 8;        /* Change in octets */
  resbit = (bitlen % 8);

  while (octetlen-- > 0) {
    crc = (crc << 8) ^ (crc11Table[(*inptr++) ^ (crc >> 24)] << 16);
  }

  if (resbit > 0)
    crc = (crc << resbit) ^ (crc11Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 16);

  return crc;
}

288 289 290 291 292 293 294
unsigned int
crc8 (unsigned char * inptr, int bitlen)
{
  int             octetlen, resbit;
  unsigned int             crc = 0;
  octetlen = bitlen / 8;        /* Change in octets */
  resbit = (bitlen % 8);
295

296 297 298
  while (octetlen-- > 0) {
    crc = crc8Table[(*inptr++) ^ (crc >> 24)] << 24;
  }
299

300 301
  if (resbit > 0)
    crc = (crc << resbit) ^ (crc8Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24);
302

303 304 305
  return crc;
}

306 307 308 309 310 311 312 313 314 315 316 317 318
unsigned int
crc6 (unsigned char * inptr, int bitlen)
{
  int             octetlen, resbit;
  unsigned int             crc = 0;
  octetlen = bitlen / 8;        /* Change in octets */
  resbit = (bitlen % 8);

  while (octetlen-- > 0) {
    crc = crc6Table[(*inptr++) ^ (crc >> 24)] << 24;
  }

  if (resbit > 0)
Francesco Mani's avatar
Francesco Mani committed
319
    crc = (crc << resbit) ^ (crc6Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24);
320 321 322 323

  return crc;
}

324 325
int check_crc(uint8_t* decoded_bytes, uint32_t n, uint32_t F, uint8_t crc_type)
{
Guy De Souza's avatar
Guy De Souza committed
326
  uint32_t crc=0,oldcrc=0;
327
  uint8_t crc_len=0;
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

  switch (crc_type) {
  case CRC24_A:
  case CRC24_B:
    crc_len=3;
    break;

  case CRC16:
    crc_len=2;
    break;

  case CRC8:
    crc_len=1;
    break;

  default:
Khalid Ahmed's avatar
Khalid Ahmed committed
344
    AssertFatal(1,"Invalid crc_type \n");
345 346
  }

Guy De Souza's avatar
Guy De Souza committed
347 348
  for (int i=0; i<crc_len; i++)
    oldcrc |= (decoded_bytes[(n>>3)-crc_len+i])<<((crc_len-1-i)<<3);
349 350 351 352 353

  switch (crc_type) {
    
  case CRC24_A:
    oldcrc&=0x00ffffff;
Guy De Souza's avatar
Guy De Souza committed
354 355
    crc = crc24a(decoded_bytes,
		 n-24)>>8;
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    
    break;
    
  case CRC24_B:
      oldcrc&=0x00ffffff;
      crc = crc24b(decoded_bytes,
                   n-24)>>8;
      
      break;

    case CRC16:
      oldcrc&=0x0000ffff;
      crc = crc16(decoded_bytes,
                  n-16)>>16;
      
      break;

    case CRC8:
      oldcrc&=0x000000ff;
      crc = crc8(decoded_bytes,
                 n-8)>>24;
      break;
Khalid Ahmed's avatar
Khalid Ahmed committed
378 379 380

    default:
      AssertFatal(1,"Invalid crc_type \n");
381 382
    }

383

384 385 386 387 388 389
    if (crc == oldcrc)
      return(1);
    else
      return(0);

}
390 391


392 393 394
#ifdef DEBUG_CRC
/*******************************************************************/
/**
395
   Test code
396 397 398 399 400 401 402 403
********************************************************************/

#include <stdio.h>

main()
{
  unsigned char test[] = "Thebigredfox";
  crcTableInit();
404
  printf("%x\n", crcbit(test, sizeof(test) - 1, poly24a));
405 406 407 408 409 410
  printf("%x\n", crc24(test, (sizeof(test) - 1)*8));
  printf("%x\n", crcbit(test, sizeof(test) - 1, poly8));
  printf("%x\n", crc8(test, (sizeof(test) - 1)*8));
}
#endif

411