328 lines
8.6 KiB
C
328 lines
8.6 KiB
C
/*
|
|
* 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
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* 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
|
|
*/
|
|
|
|
/* file: ccoding_byte_lte.c
|
|
purpose: Tail-biting convolutional code from 36-212, V8.6 2009-03. Includes CRC (8-UCI,16-DCI)and RNTI scrambling (DCI)
|
|
author: raymond.knopp@eurecom.fr
|
|
date: 21.10.2009
|
|
*/
|
|
#include "coding_defs.h"
|
|
|
|
//#define DEBUG_CCODE 1
|
|
|
|
static const unsigned short glte[] = {0133, 0171, 0165}; // {A,B}
|
|
static const unsigned short glte_rev[] = {0155, 0117, 0127}; // {A,B}
|
|
static const unsigned short gdab[] = {0133, 0171, 0145}; // {A,B}
|
|
static const unsigned short gdab_rev[] = {0155, 0117, 0123}; // {A,B}
|
|
unsigned char ccodelte_table[128]; // for transmitter
|
|
unsigned char ccodelte_table_rev[128]; // for receiver
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Encodes for an arbitrary convolutional code of rate 1/3
|
|
with a constraint length of 7 bits.
|
|
The inputs are bit packed in octets (from MSB to LSB).
|
|
An optional 8-bit CRC (3GPP) can be added.
|
|
Trellis tail-biting is included here
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
void
|
|
ccodelte_encode (int32_t numbits,
|
|
uint8_t add_crc,
|
|
uint8_t *inPtr,
|
|
uint8_t *outPtr,
|
|
uint16_t rnti) {
|
|
uint32_t state;
|
|
uint8_t c, out, first_bit;
|
|
int8_t shiftbit=0;
|
|
uint16_t c16;
|
|
uint16_t next_last_byte=0;
|
|
uint32_t crc=0;
|
|
#ifdef DEBUG_CCODE
|
|
uint32_t dummy=0;
|
|
#endif //DEBUG_CCODE
|
|
/* The input bit is shifted in position 8 of the state.
|
|
Shiftbit will take values between 1 and 8 */
|
|
state = 0;
|
|
|
|
if (add_crc == 1) {
|
|
crc = crc8(inPtr,numbits);
|
|
first_bit = 2;
|
|
c = (uint8_t)(crc>>24);
|
|
} else if (add_crc == 2) {
|
|
crc = crc16(inPtr,numbits);
|
|
#ifdef DEBUG_CCODE
|
|
printf("ccode_lte : crc %x\n",crc);
|
|
#endif
|
|
// scramble with RNTI
|
|
crc ^= (((uint32_t)rnti)<<16);
|
|
#ifdef DEBUG_CCODE
|
|
printf("ccode_lte : crc %x (rnti %x)\n",crc,rnti);
|
|
#endif
|
|
first_bit = 2;
|
|
c = (uint8_t)((crc>>16)&0xff);
|
|
} else {
|
|
next_last_byte = numbits>>3;
|
|
first_bit = (numbits-6)&7;
|
|
c = inPtr[next_last_byte-1];
|
|
}
|
|
|
|
#ifdef DEBUG_CCODE
|
|
printf("next_last_byte %x (numbits %d, %d)\n",c,numbits,next_last_byte);
|
|
#endif
|
|
|
|
// Perform Tail-biting
|
|
|
|
// get bits from last byte of input (or crc)
|
|
// for (shiftbit = first_bit; shiftbit<8; shiftbit++) {
|
|
for (shiftbit = 0 ; shiftbit <(8-first_bit) ; shiftbit++) {
|
|
if ((c&(1<<(7-first_bit-shiftbit))) != 0)
|
|
state |= (1<<shiftbit);
|
|
|
|
#ifdef DEBUG_CCODE
|
|
printf("shiftbit %d, %d -> %u \n",shiftbit,c&(1<<(7-first_bit-shiftbit)),state);
|
|
dummy+=3;
|
|
#endif
|
|
}
|
|
|
|
// get bits from next to last byte of input (not when crc is added)
|
|
if ((add_crc==0)&&((numbits&7)>0)) {
|
|
c = inPtr[next_last_byte];
|
|
|
|
// printf("last_byte %x\n",c);
|
|
// for (shiftbit = 0 ; shiftbit < (numbits&7) ; shiftbit++) {
|
|
for (shiftbit = (numbits&7)-1 ; shiftbit>=0 ; shiftbit--) {
|
|
state >>= 1;
|
|
|
|
if ((c&(1<<shiftbit)) != 0)
|
|
state |= 64;
|
|
|
|
#ifdef DEBUG_CCODE
|
|
printf("shiftbit %d, %u: %u -> %u \n",shiftbit,state>>6,dummy,state);
|
|
dummy+=3;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
state = state & 0x3f; // true initial state of Tail-biting CCode
|
|
state<<=1; // because of loop structure in CCode
|
|
#ifdef DEBUG_CCODE
|
|
printf("Initial state %u\n",state);
|
|
dummy = 0;
|
|
#endif //DEBUG_CCODE
|
|
/* Do not increment inPtr until we read the next octet */
|
|
|
|
while (numbits > 0) {
|
|
c = *inPtr++;
|
|
#ifdef DEBUG_CCODE
|
|
printf("** %x **\n",c);
|
|
#endif //DEBUG_CCODE
|
|
|
|
// for (shiftbit = 0; (shiftbit<8) && (numbits>0);shiftbit++,numbits--) {
|
|
for (shiftbit = 7; (shiftbit>=0) && (numbits>0); shiftbit--,numbits--) {
|
|
state >>= 1;
|
|
|
|
if ((c&(1<<shiftbit)) != 0) {
|
|
state |= 64;
|
|
}
|
|
|
|
out = ccodelte_table[state];
|
|
*outPtr++ = out & 1;
|
|
*outPtr++ = (out>>1)&1;
|
|
*outPtr++ = (out>>2)&1;
|
|
#ifdef DEBUG_CCODE
|
|
printf("numbits %d, input %u, outbit %u: %u -> %d (%d%d%d)\n",numbits,state>>6,dummy,state,out,out&1,(out>>1)&1,(out>>2)&1);
|
|
dummy+=3;
|
|
#endif //DEBUG_CCODE
|
|
}
|
|
}
|
|
|
|
// now code 8-bit CRC for UCI
|
|
if (add_crc == 1) {
|
|
c = (uint8_t)(crc>>24);
|
|
|
|
// for (shiftbit = 0; (shiftbit<8);shiftbit++) {
|
|
for (shiftbit = 7; (shiftbit>=0); shiftbit--) {
|
|
state >>= 1;
|
|
|
|
if ((c&(1<<shiftbit)) != 0) {
|
|
state |= 64;
|
|
}
|
|
|
|
out = ccodelte_table[state];
|
|
*outPtr++ = out & 1;
|
|
*outPtr++ = (out>>1)&1;
|
|
*outPtr++ = (out>>2)&1;
|
|
#ifdef DEBUG_CCODE
|
|
printf("crc bit %d input %u, outbit %u: %u -> %d (%u)\n",shiftbit,state>>6,dummy,state,out,ccodelte_table[state]);
|
|
dummy+=3;
|
|
#endif //DEBUG_CCODE
|
|
}
|
|
}
|
|
|
|
// now code 16-bit CRC for DCI
|
|
if (add_crc == 2) {
|
|
c16 = (uint16_t)(crc>>16);
|
|
|
|
// for (shiftbit = 0; (shiftbit<16);shiftbit++) {
|
|
for (shiftbit = 15; (shiftbit>=0); shiftbit--) {
|
|
state >>= 1;
|
|
|
|
if ((c16&(1<<shiftbit)) != 0) {
|
|
state |= 64;
|
|
}
|
|
|
|
out = ccodelte_table[state];
|
|
*outPtr++ = out & 1;
|
|
*outPtr++ = (out>>1)&1;
|
|
*outPtr++ = (out>>2)&1;
|
|
#ifdef DEBUG_CCODE
|
|
printf("crc bit %d input %u, outbit %u: %u -> %d (%u)\n",shiftbit,state>>6,dummy,state,out,ccodelte_table[state]);
|
|
dummy+=3;
|
|
#endif //DEBUG_CCODE
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Functions to initialize the code tables
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
/* Basic code table initialization for constraint length 7 */
|
|
/* Input in MSB, followed by state in 6 LSBs */
|
|
|
|
void ccodelte_init(void) {
|
|
unsigned int i, j, k, sum;
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
ccodelte_table[i] = 0;
|
|
|
|
/* Compute 3 output bits */
|
|
for (j = 0; j < 3; j++) {
|
|
sum = 0;
|
|
|
|
for (k = 0; k < 7; k++)
|
|
if ((i & glte[j]) & (1 << k))
|
|
sum++;
|
|
|
|
/* Write the sum modulo 2 in bit j */
|
|
ccodelte_table[i] |= (sum & 1) << j;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Input in LSB, followed by state in 6 MSBs */
|
|
void ccodelte_init_inv(void) {
|
|
unsigned int i, j, k, sum;
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
ccodelte_table_rev[i] = 0;
|
|
|
|
/* Compute R output bits */
|
|
for (j = 0; j < 3; j++) {
|
|
sum = 0;
|
|
|
|
for (k = 0; k < 7; k++)
|
|
if ((i & glte_rev[j]) & (1 << k))
|
|
sum++;
|
|
|
|
/* Write the sum modulo 2 in bit j */
|
|
ccodelte_table_rev[i] |= (sum & 1) << j;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ccodedab_init(void) {
|
|
unsigned int i, j, k, sum;
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
ccodelte_table[i] = 0;
|
|
|
|
/* Compute 3 output bits */
|
|
for (j = 0; j < 3; j++) {
|
|
sum = 0;
|
|
|
|
for (k = 0; k < 7; k++)
|
|
if ((i & gdab[j]) & (1 << k))
|
|
sum++;
|
|
|
|
/* Write the sum modulo 2 in bit j */
|
|
ccodelte_table[i] |= (sum & 1) << j;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Input in LSB, followed by state in 6 MSBs */
|
|
void ccodedab_init_inv(void) {
|
|
unsigned int i, j, k, sum;
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
ccodelte_table_rev[i] = 0;
|
|
|
|
/* Compute R output bits */
|
|
for (j = 0; j < 3; j++) {
|
|
sum = 0;
|
|
|
|
for (k = 0; k < 7; k++)
|
|
if ((i & gdab_rev[j]) & (1 << k))
|
|
sum++;
|
|
|
|
/* Write the sum modulo 2 in bit j */
|
|
ccodelte_table_rev[i] |= (sum & 1) << j;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************/
|
|
/**
|
|
Test program
|
|
|
|
******************************************************************/
|
|
|
|
#ifdef CCODE_MAIN
|
|
#include <stdio.h>
|
|
|
|
main() {
|
|
unsigned char test[] = "Thebigredfox";
|
|
unsigned char output[512], *inPtr, *outPtr;
|
|
unsigned int i;
|
|
test[0] = 128;
|
|
test[1] = 0;
|
|
ccodelte_init();
|
|
inPtr = test;
|
|
outPtr = output;
|
|
ccodelte_encode(21, inPtr, outPtr);
|
|
|
|
for (i = 0; i < 21*3; i++) printf("%x ", output[i]);
|
|
|
|
printf("\n");
|
|
}
|
|
#endif
|