📄 turboencoder.c
字号:
/*
*******************************************************************************
* ansi c source code
* file name:
* TurboEncoder.c
* abstract:
* to implement the encoder of turbo code specified in the EV-DO specification
* reference:
* EV-DO specification
* author:
* Wang Jiaheng 2004-12-06
* revision history:
* Wang Jiaheng 2004-12-06 original version
* Wang Jiaheng 2005-02-04 revised version
*******************************************************************************
*/
/*
*******************************************************************************
* constants and define declarations
*******************************************************************************
*/
/* maximum packer size in turbo code */
#define MAX_TURBO_PACKET_SIZE 4096
/*
*******************************************************************************
* local object definition
*******************************************************************************
*/
/* turbo interleaver lookup table for n = 3 */
unsigned int turbo_lookup_table_3[32] =
{ 1, 1, 3, 5, 1, 5, 1, 5,
3, 5, 3, 5, 3, 5, 5, 1,
3, 5, 3, 5, 3, 5, 5, 5,
1, 5, 1, 5, 3, 5, 5, 3
};
/* turbo interleaver lookup table for n = 4 */
unsigned int turbo_lookup_table_4[32] =
{ 5, 15, 5, 15, 1, 9, 9, 15,
13, 15, 7, 11, 15, 3, 15, 5,
13, 15, 9, 3, 1, 3, 15, 1,
13, 1, 9, 15, 11, 3, 15, 5};
/* turbo interleaver lookup table for n = 5 */
unsigned int turbo_lookup_table_5[32] =
{
27, 3, 1, 15, 13, 17, 23, 13,
9, 3, 15, 3, 13, 1, 13, 29,
21, 19, 1, 3, 29, 17, 25, 29,
9, 13, 23, 13, 13, 1, 13, 13
};
/* turbo interleaver lookup table for n = 6 */
unsigned int turbo_lookup_table_6[32] =
{
3, 27, 15, 13, 29, 5, 1, 31,
3, 9, 15, 31, 17, 5, 39, 1,
19, 27, 15, 13, 45, 5, 33, 15,
13, 9, 15, 31, 17, 5, 15, 33
};
/* turbo interleaver lookup table for n = 7 */
unsigned int turbo_lookup_table_7[32] =
{
15, 127, 89, 1, 31, 15, 61, 47,
127, 17, 119, 15, 57, 123, 95, 5,
85, 17, 55, 57, 15, 41, 93, 87,
63, 15, 13, 15, 81, 57, 31, 69
};
/* for storing the new addresses after turbo interleaving */
int turbo_interleaved_addr[MAX_TURBO_PACKET_SIZE];
/* length of the new addresses after turbo interleaving */
int turbo_interleaved_len;
/* shift register used in constituent encoder 1 */
int turbo_encoder_shift_reg_1[3];
/* shift register used in constituent encoder 2 */
int turbo_encoder_shift_reg_2[3];
/*
*******************************************************************************
* function definition
*******************************************************************************
*/
/*
*******************************************************************************
* description:
* calculate the new addresses of interleaved bits
* input:
* packet_size: number of bits in one packet
* output:
* turbo_interleaved_addr: the new addresses of interleaved bits (global)
* return: if ok, return 1; otherwise retrun 0.
* function reference:
* author:
* Wang Jiaheng, 2004-12-06 created
* Wang Jiaheng, 2005-02-04 revised
*******************************************************************************
*/
int SetTurboInterleaver(int packet_size)
{
unsigned int n;
unsigned int bit_num;
unsigned int n_turbo;
unsigned int n_mask;
unsigned int count;
unsigned int cnt_msb_n;
unsigned int cnt_lsb_5;
unsigned int cnt_lsb_5_rev;
unsigned int lookup_bit_n;
unsigned int *p_lookup_table;
unsigned int address_new;
/* calculate n_turbo and n_mask */
n_turbo = packet_size - 6;
switch ( packet_size )
{
case 256:
n = 3;
n_mask = 0x07;
p_lookup_table = turbo_lookup_table_3;
break;
case 512:
n = 4;
n_mask = 0x0F;
p_lookup_table = turbo_lookup_table_4;
break;
case 1024:
n = 5;
n_mask = 0x1F;
p_lookup_table = turbo_lookup_table_5;
break;
case 2048:
n = 6;
n_mask = 0x3F;
p_lookup_table = turbo_lookup_table_6;
break;
case 3072:
case 4096:
n = 7;
n_mask = 0x7F;
p_lookup_table = turbo_lookup_table_7;
break;
default:
return 0;
}
bit_num = 0;
count = 0;
/* start generating interleaved addresses */
while ( bit_num < n_turbo )
{
/* obtain the 5 LSBs of the counter */
cnt_lsb_5 = count & 0x1F;
/* obtain n bits from the lookup table */
lookup_bit_n = p_lookup_table[cnt_lsb_5];
/* reverse the 5 LSBs */
cnt_lsb_5_rev = ((cnt_lsb_5 & 0x1) << 4) | ((cnt_lsb_5 & 0x2) << 2) | (cnt_lsb_5 & 0x4) | ((cnt_lsb_5 & 0x8) >> 2) | ((cnt_lsb_5 & 0x10) >> 4);
/* obtain the n MSBs of the counter */
cnt_msb_n = (count >> 5) & n_mask;
/* add 1 to n MSBs and get n LSBs */
cnt_msb_n = (cnt_msb_n + 1) & n_mask;
/* multiply n lookup bits and obtain n LSBs */
cnt_msb_n = (cnt_msb_n * lookup_bit_n) & n_mask;
/* generate an interleaved address */
address_new = (cnt_lsb_5_rev << n) | cnt_msb_n;
/* check the validity of the new address */
if ( address_new < n_turbo )
{
turbo_interleaved_addr[bit_num] = address_new;
bit_num++;
}
/* increment the counter */
count++;
}
turbo_interleaved_len = n_turbo;
return 1;
}
/*
*******************************************************************************
* description:
* initialize the turbo encoder
* input:
* packet_size: number of bits in one packet
* output:
* turbo_interleaved_addr: the new addresses of interleaved bits (global)
* return: if ok, return 1; otherwise retrun 0.
* function reference:
* author:
* Wang Jiaheng, 2004-12-15 created
*******************************************************************************
*/
int SetTurboEncoder(int packet_size)
{
int i;
for (i = 0; i < 3; i++)
{
turbo_encoder_shift_reg_1[i] = 0;
turbo_encoder_shift_reg_2[i] = 0;
}
if ( !SetTurboInterleaver(packet_size) )
{
return 0;
}
return 1;
}
/*
*******************************************************************************
* description:
* run the recursive systematic convolutional encoder with one bit input and
* three bits output
* input:
* shift_reg: the shift register used in the encoder
* bit_in: one input bit
* output:
* bit_out: output bits encoded from one input bit
* function reference:
* EV-DO specification
* author:
* Wang Jiaheng, 2004-12-06 created
*******************************************************************************
*/
void RunRecConvEncoder(int shift_reg[], int bit_in, int bit_out[])
{
int rec_sum;
rec_sum = bit_in ^ shift_reg[1] ^ shift_reg[2];
bit_out[0] = bit_in;
bit_out[1] = rec_sum ^ shift_reg[0] ^ shift_reg[2];
bit_out[2] = rec_sum ^ shift_reg[0] ^ shift_reg[1] ^ shift_reg[2];
shift_reg[2] = shift_reg[1];
shift_reg[1] = shift_reg[0];
shift_reg[0] = rec_sum;
}
/*
*******************************************************************************
* description:
* run the turbo encoder with a packet input and a encoded bit sequence output
* input:
* bit_in: input bit sequence
* len_in: length of input bit sequence
* encode_rate: the encoding rate (3 or 5)
* output:
* bit_out: encoded output bit sequence
* *p_len_out: length of the output bit sequence
* if ok, return 1; otherwise retrun 0.
* function reference:
* Interleaver.c
* author:
* Wang Jiaheng, 2004-12-06 created
* Wang Jiaheng, 2005-02-04 revised
*******************************************************************************
*/
int RunTurboEncoder(int bit_in[], int len_in, int encode_rate, int bit_out[], int *p_len_out)
{
int k;
int valid_len;
int len_out;
int encoded_bit_1[3];
int encoded_bit_2[3];
valid_len = len_in - 6;
len_out = 0;
switch ( encode_rate )
{
/* 1/2 encoding rate */
case 2:
/* encode the first valid_len bits */
for (k = 0; k < valid_len; k++)
{
RunRecConvEncoder(turbo_encoder_shift_reg_1, bit_in[k], encoded_bit_1);
RunRecConvEncoder(turbo_encoder_shift_reg_2, bit_in[turbo_interleaved_addr[k]], encoded_bit_2);
if ( k % 2 == 0 )
{
bit_out[len_out++] = encoded_bit_1[0];
bit_out[len_out++] = encoded_bit_1[1];
}
else
{
bit_out[len_out++] = encoded_bit_1[0];
bit_out[len_out++] = encoded_bit_2[1];
}
}
/* produce the encoded tail bits of the encoder 1 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[2];
turbo_encoder_shift_reg_1[2] = turbo_encoder_shift_reg_1[1];
turbo_encoder_shift_reg_1[1] = turbo_encoder_shift_reg_1[0];
turbo_encoder_shift_reg_1[0] = 0;
}
/* produce the encoded tail bits of the encoder 2 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[2];
turbo_encoder_shift_reg_2[2] = turbo_encoder_shift_reg_2[1];
turbo_encoder_shift_reg_2[1] = turbo_encoder_shift_reg_2[0];
turbo_encoder_shift_reg_2[0] = 0;
}
break;
/* 1/3 encoding rate */
case 3:
/* encode the first valid_len bits */
for (k = 0; k < valid_len; k++)
{
RunRecConvEncoder(turbo_encoder_shift_reg_1, bit_in[k], encoded_bit_1);
RunRecConvEncoder(turbo_encoder_shift_reg_2, bit_in[turbo_interleaved_addr[k]], encoded_bit_2);
bit_out[len_out++] = encoded_bit_1[0];
bit_out[len_out++] = encoded_bit_1[1];
bit_out[len_out++] = encoded_bit_2[1];
}
/* produce the encoded tail bits of the encoder 1 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[2];
turbo_encoder_shift_reg_1[2] = turbo_encoder_shift_reg_1[1];
turbo_encoder_shift_reg_1[1] = turbo_encoder_shift_reg_1[0];
turbo_encoder_shift_reg_1[0] = 0;
}
/* produce the encoded tail bits of the encoder 2 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[2];
turbo_encoder_shift_reg_2[2] = turbo_encoder_shift_reg_2[1];
turbo_encoder_shift_reg_2[1] = turbo_encoder_shift_reg_2[0];
turbo_encoder_shift_reg_2[0] = 0;
}
break;
/* 1/4 encoding rate */
case 4:
/* encode the first valid_len bits */
for (k = 0; k < valid_len; k++)
{
RunRecConvEncoder(turbo_encoder_shift_reg_1, bit_in[k], encoded_bit_1);
RunRecConvEncoder(turbo_encoder_shift_reg_2, bit_in[turbo_interleaved_addr[k]], encoded_bit_2);
if ( k % 2 == 0 )
{
bit_out[len_out++] = encoded_bit_1[0];
bit_out[len_out++] = encoded_bit_1[1];
bit_out[len_out++] = encoded_bit_1[2];
bit_out[len_out++] = encoded_bit_2[2];
}
else
{
bit_out[len_out++] = encoded_bit_1[0];
bit_out[len_out++] = encoded_bit_1[1];
bit_out[len_out++] = encoded_bit_2[1];
bit_out[len_out++] = encoded_bit_2[2];
}
}
/* produce the encoded tail bits of the encoder 1 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
turbo_encoder_shift_reg_1[2] = turbo_encoder_shift_reg_1[1];
turbo_encoder_shift_reg_1[1] = turbo_encoder_shift_reg_1[0];
turbo_encoder_shift_reg_1[0] = 0;
}
/* produce the encoded tail bits of the encoder 2 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
turbo_encoder_shift_reg_2[2] = turbo_encoder_shift_reg_2[1];
turbo_encoder_shift_reg_2[1] = turbo_encoder_shift_reg_2[0];
turbo_encoder_shift_reg_2[0] = 0;
}
break;
/* 1/5 encoding rate */
case 5:
/* encode the first valid_len bits */
for (k = 0; k < valid_len; k++)
{
RunRecConvEncoder(turbo_encoder_shift_reg_1, bit_in[k], encoded_bit_1);
RunRecConvEncoder(turbo_encoder_shift_reg_2, bit_in[turbo_interleaved_addr[k]], encoded_bit_2);
bit_out[len_out++] = encoded_bit_1[0];
bit_out[len_out++] = encoded_bit_1[1];
bit_out[len_out++] = encoded_bit_1[2];
bit_out[len_out++] = encoded_bit_2[1];
bit_out[len_out++] = encoded_bit_2[2];
}
/* produce the encoded tail bits of the encoder 1 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
bit_out[len_out++] = turbo_encoder_shift_reg_1[0] ^ turbo_encoder_shift_reg_1[1] ^ turbo_encoder_shift_reg_1[2];
turbo_encoder_shift_reg_1[2] = turbo_encoder_shift_reg_1[1];
turbo_encoder_shift_reg_1[1] = turbo_encoder_shift_reg_1[0];
turbo_encoder_shift_reg_1[0] = 0;
}
/* produce the encoded tail bits of the encoder 2 */
for (k = 0; k < 3; k++)
{
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
bit_out[len_out++] = turbo_encoder_shift_reg_2[0] ^ turbo_encoder_shift_reg_2[1] ^ turbo_encoder_shift_reg_2[2];
turbo_encoder_shift_reg_2[2] = turbo_encoder_shift_reg_2[1];
turbo_encoder_shift_reg_2[1] = turbo_encoder_shift_reg_2[0];
turbo_encoder_shift_reg_2[0] = 0;
}
break;
default:
return 0;
}
*p_len_out = len_out;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -