📄 turbodecoder.c
字号:
/*
*******************************************************************************
* description:
* mas(a,b)= ln(exp(a) + exp(b)) = max(a, b) + ln(1 + exp(-|a-b|)
* input:
* a, b: any value
* output:
* return: the value of function mas(a, b)
* function reference:
* author:
* Wang Jiaheng, 2004-12-23 created
*******************************************************************************
*/
double RunMas(double a, double b)
{
int i;
double dis;
double term;
double max_one;
/* select the bigger one */
if ( a > b )
{
max_one = a;
dis = a - b;
}
else
{
max_one = b;
dis = b - a;
}
/* compute the correction term */
term = 0;
for (i = 0; i < MAX_CORRECT_TERM_NUM; i++)
if ( dis <=turbo_correct_term[i][0] )
{
term = turbo_correct_term[i][1];
break;
}
//else term=0;
return (max_one + term);
}
/*
*******************************************************************************
* description:
* to execute the Log-Map algorithm for decoding
* input:
* apriori_llr: the a-priori LLR sequence
* decode_len: length of the a-priori LLR sequence
* gamma_exp: the middle exponential values of gamma
* output:
* aposteriori_llr: the a-posteriori LLRs of every bit
* function reference:
* author:
* Wang Jiaheng, 2004-12-23 created
* Wang Jiaheng, 2004-02-04 revised
*******************************************************************************
*/
void RunLogMap(int decode_len, double apriori_llr[], double gamma_mid[MAX_TURBO_STATE_NUM][2][MAX_TURBO_PACKET_SIZE], double aposteriori_llr[])
{
int k, m;
double temp_0;
double temp_1;
double metric_0;
double metric_1;
/* compute the value of gamma */
for (k = 0; k < decode_len; k++)
{
temp_0 = 0.475 * apriori_llr[k];
temp_1 = -temp_0;
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
/* previous state with +1 */
turbo_gamma[m][0][k] = temp_0 + gamma_mid[m][0][k];
/* previous state with -1 */
turbo_gamma[m][1][k] = temp_1 + gamma_mid[m][1][k];
}
}
/* for test
pf = fopen("gamma.txt", "w");
for (k = 0; k < decode_len; k++)
{
fprintf(pf, "%-4d | ", k);
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
fprintf(pf, "%12f | ", turbo_gamma[m][0][k]);
fprintf(pf, "%12f | ", turbo_gamma[m][1][k]);
}
fprintf(pf, "\n\n");
}
fclose(pf); */
/* initialize the first alfa */
turbo_alfa[0][0] = 0;
for (m = 1; m < MAX_TURBO_STATE_NUM; m++)
{
turbo_alfa[m][0] = MAX_NEGATIVE;
}
for (k = 1; k < decode_len; k++)
{
/* compute the alfa at the kth time */
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
/* previous states with +1 */
temp_0 = turbo_gamma[ turbo_prev_state[m][0] ][0][k - 1] + turbo_alfa[ turbo_prev_state[m][0] ][k - 1];
/* previous states with -1 */
temp_1 = turbo_gamma[ turbo_prev_state[m][1] ][1][k - 1] + turbo_alfa[ turbo_prev_state[m][1] ][k - 1];
/* run the mas(a,b) function */
turbo_alfa[m][k] = RunMas(temp_0, temp_1);
}
}
/* for test
pf = fopen("alfa.txt", "w");
for (k = 0; k < decode_len; k++)
{
fprintf(pf, "%-4d | ", k);
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
fprintf(pf, "%12f | ", turbo_alfa[m][k]);
}
fprintf(pf, "\n\n");
}
fclose(pf);*/
/* initialize the last beta */
turbo_beta[0][decode_len - 1] = 0;
for (m = 1; m < MAX_TURBO_STATE_NUM; m++)
{
turbo_beta[m][decode_len - 1] = MAX_NEGATIVE;
}
for (k = decode_len - 1; k > 0; k--)
{
/* compute the beta at the kth time */
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
/* posterior states with +1 */
temp_0 = turbo_gamma[m][0][k] + turbo_beta[ turbo_post_state[m][0] ][k];
/* posterior states with -1 */
temp_1 = turbo_gamma[m][1][k] + turbo_beta[ turbo_post_state[m][1] ][k];
/* run the mas(a,b) function */
turbo_beta[m][k - 1] = RunMas(temp_0, temp_1);
}
}
/* for test
pf = fopen("beta.txt", "w");
for (k = 0; k < decode_len; k++)
{
fprintf(pf, "%-4d | ", k);
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
fprintf(pf, "%12f | ", turbo_beta[m][k]);
}
fprintf(pf, "\n\n");
}
fclose(pf);*/
/* compute the aposteriori LLR */
for (k = 0; k < decode_len; k++)
{
/* states with +1 */
metric_0 = turbo_alfa[0][k] + turbo_gamma[0][0][k] + turbo_beta[ turbo_post_state[0][0] ][k];
temp_0 = turbo_alfa[1][k] + turbo_gamma[1][0][k] + turbo_beta[ turbo_post_state[1][0] ][k];
metric_0 = RunMas(metric_0, temp_0);
/* states with -1 */
metric_1 = turbo_alfa[0][k] + turbo_gamma[0][1][k] + turbo_beta[ turbo_post_state[0][1] ][k];
temp_1 = turbo_alfa[1][k] + turbo_gamma[1][1][k] + turbo_beta[ turbo_post_state[1][1] ][k];
metric_1 = RunMas(metric_1, temp_1);
for (m = 2; m < MAX_TURBO_STATE_NUM; m++)
{
/* states with +1 */
temp_0 = turbo_alfa[m][k] + turbo_gamma[m][0][k] + turbo_beta[ turbo_post_state[m][0] ][k];
metric_0 = RunMas(metric_0, temp_0);
/* states with -1 */
temp_1 = turbo_alfa[m][k] + turbo_gamma[m][1][k] + turbo_beta[ turbo_post_state[m][1] ][k];
metric_1 = RunMas(metric_1, temp_1);
}
aposteriori_llr[k] = metric_0 - metric_1;
}
/* for test
pf = fopen("llr.txt", "w");
for (k = 0; k < decode_len; k++)
{
fprintf(pf, "%-4d | ", k);
fprintf(pf, "%12f\n\n", turbo_aposteriori_llr[k]);
}
fclose(pf);*/
}
/*
*******************************************************************************
* description:
* run the turbo decoder with a encoded bit sequence input and a packet output
* input:
* sym_in: input symbols sequence
* len_in: length of input symbols sequence
* encode_rate: the encoding rate (2, 3, 4 or 5)
* ch_rely: channel reliability (2a/noise_var)
* iterate_num: number of iterating decoding
* 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:
* EV-DO specification
* author:
* Wang Jiaheng, 2004-12-23 created
* Wang Jiaheng, 2004-02-04 revised
*******************************************************************************
*/
int RunTurboDecoder(double sym_in[], int len_in, int encode_rate, double ch_rely, int iterate_num, int bit_out[], int *p_len_out)
{
int k, m;
int packet_size;
int decode_len;
int valid_len;
double sum_0, sum_1;
double half_lc;
/* compute the packet size and check it */
packet_size = len_in / encode_rate;
switch ( packet_size )
{
case 256:
break;
case 512:
break;
case 1024:
break;
case 2048:
break;
case 3072:
break;
case 4096:
break;
default:
return 0;
}
/* compute other lengths */
decode_len = packet_size - 3;
valid_len = packet_size - 6;
if ( valid_len != turbo_interleaved_len )
{
return 0;
}
/* rebuild the received symbols for decoder 1 and 2 */
if ( !RebuildSymbol(sym_in, valid_len, decode_len, encode_rate) )
{
return 0;
}
/* compute the middle values for gamma in the Max-log-Map algorithm */
half_lc = ch_rely / 2;
for (k = 0; k < decode_len; k++)
{
/* for the constituent encoder 1 */
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
sum_0 = turbo_recv_sym_1[0][k] * turbo_trellis_output[m][0][0];
sum_0 += turbo_recv_sym_1[1][k] * turbo_trellis_output[m][0][1];
sum_0 += turbo_recv_sym_1[2][k] * turbo_trellis_output[m][0][2];
sum_1 = turbo_recv_sym_1[0][k] * turbo_trellis_output[m][1][0];
sum_1 += turbo_recv_sym_1[1][k] * turbo_trellis_output[m][1][1];
sum_1 += turbo_recv_sym_1[2][k] * turbo_trellis_output[m][1][2];
turbo_gamma_mid_1[m][0][k] = half_lc * sum_0;
turbo_gamma_mid_1[m][1][k] = half_lc * sum_1;
}
/* for the constituent encoder 2 */
for (m = 0; m < MAX_TURBO_STATE_NUM; m++)
{
sum_0 = turbo_recv_sym_2[0][k] * turbo_trellis_output[m][0][0];
sum_0 += turbo_recv_sym_2[1][k] * turbo_trellis_output[m][0][1];
sum_0 += turbo_recv_sym_2[2][k] * turbo_trellis_output[m][0][2];
sum_1 = turbo_recv_sym_2[0][k] * turbo_trellis_output[m][1][0];
sum_1 += turbo_recv_sym_2[1][k] * turbo_trellis_output[m][1][1];
sum_1 += turbo_recv_sym_2[2][k] * turbo_trellis_output[m][1][2];
turbo_gamma_mid_2[m][0][k] = half_lc * sum_0;
turbo_gamma_mid_2[m][1][k] = half_lc * sum_1;
}
}
/* initialize the a-priori LLR sequence to 0 */
memset(turbo_apriori_llr_1, 0, MAX_TURBO_PACKET_SIZE * sizeof(double));
memset(turbo_apriori_llr_2, 0, MAX_TURBO_PACKET_SIZE * sizeof(double));
/* start iterative decoding */
for (m = 0; m < iterate_num; m++)
{
/* run the decoder 1 */
RunLogMap(decode_len, turbo_apriori_llr_1, turbo_gamma_mid_1, turbo_aposteriori_llr_1);
/* compute the extrinsic information as the a-priori LLR for the edcoder 2 */
for (k = 0; k < decode_len; k++)
{
turbo_apriori_llr_1[k] = turbo_aposteriori_llr_1[k] - 0.95 * turbo_apriori_llr_1[k] - ch_rely * turbo_recv_sym_1[0][k];
}
/* interleave the extrinsic LLR */
for (k = 0; k < valid_len; k++)
{
turbo_apriori_llr_2[k] = turbo_apriori_llr_1[ turbo_interleaved_addr[k] ];
}
for (k = valid_len; k < decode_len; k++)
{
turbo_apriori_llr_2[k] = 0;
}
/* run the decoder 2 */
RunLogMap(decode_len, turbo_apriori_llr_2, turbo_gamma_mid_2, turbo_aposteriori_llr_2);
/* compute the extrinsic LLR as the a-priori LLR for the edcoder 1 */
for (k = 0; k < decode_len; k++)
{
turbo_apriori_llr_2[k] = turbo_aposteriori_llr_2[k] - 0.95 * turbo_apriori_llr_2[k] - ch_rely * turbo_recv_sym_2[0][k];
}
/* deinterleave the extrinsic LLR */
for (k = 0; k < valid_len; k++)
{
turbo_apriori_llr_1[ turbo_interleaved_addr[k] ] = turbo_apriori_llr_2[k];
}
for (k = valid_len; k < decode_len; k++)
{
turbo_apriori_llr_1[k] = 0;
}
}
/* deinterleave the a-posteriori LLRs generated by the decoder 2 */
for (k = 0; k < valid_len; k++)
{
turbo_aposteriori_llr_1[ turbo_interleaved_addr[k] ] = turbo_aposteriori_llr_2[k];
}
/* make a hard decision according to the a-posteriori LLR sequence */
for (k = 0; k < valid_len; k++)
{
if ( turbo_aposteriori_llr_1[k] >= 0 )
{
bit_out[k] = 0;
}
else
{
bit_out[k] = 1;
}
}
for (k = valid_len; k < packet_size; k++)
{
bit_out[k] = 0;
}
*p_len_out = packet_size;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -