⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 turboencoder.c

📁 信道编解码中的turbo编解码程序
💻 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 + -