📄 convdec.c
字号:
/* | Project: WCDMA simulation environment | Module: Convolutional decoder | Author: Tommi Makelainen | Date: January 20, 1999 | | History: | January 20, 1999 Tommi Makelainen | Modified Rorabaugh's example code | to rate 1/2 and 1/3 codes with constraint length | K=9 (i.e. length of memory shift register). | | Copyright disclaimer: | This software was developed at the National Institute of Standards | and Technology by employees of the Federal Government in the course | of their official duties. Pursuant to title 17 Section 105 of the | United States Code this software is not subject to copyright | protection and is in the public domain. | | We would appreciate acknowledgement if the software is used. | */#include <stdlib.h> #include <stdio.h>#include "mealy.h"#include "metrics.h"#include "convdec.h"#include "config_wcdma.h" /* * Static data structures. */static int previous_state[50][256];static int *prev_state[50];/* ------------------------------------------------------------------ *//* * Function: wcdma_dec_R1o3_k9_init * Desc.: Initializes convolutional decoder (R=1/3, K=9) using * Viterbi algorithm. * * Note: */void wcdma_dec_R1o3_k9_init( ViterbiDecoder* this, /* IN: decoder data */ int info_length, /* IN: combined length of input data and tail */ int decoding_depth, /* IN: depth of a path in trellis */ int tail_length, /* IN: length of encoder tail */ MealyEncoder* encoder, /* IN: encoder data */ MetricTable* decoding_metric) /* IN: data to calculate trellis path weights */{ this->Decoding_Metric = decoding_metric; this->Info_Length = info_length; this->Tail_Length = tail_length; this->Decoding_depth = decoding_depth; this->Frame_Length = info_length + tail_length; this->Tx_Encoder = encoder; this->Numb_Encdr_States = 256; this->Numb_Inp_Symbs = 2; return;} /* wcdma_dec_R1o3_k9_init *//* ------------------------------------------------------------------ *//* * Function: init_prev_state_vecs * Desc.: Initializes vectors indicating trellis structure. */static void init_prev_state_vecs(int decoding_depth) { int i; for (i=0; i < decoding_depth+1; i++) { prev_state[i] = previous_state[i]; } /* for */ return;} /* init_prev_state_vecs *//* ------------------------------------------------------------------ *//* * Function: shift_prev_state_vecs * Desc.: Remove the oldest level from the encoding trellis. */static void shift_prev_state_vecs(int decoding_depth) { int i; int* temp_ptr = prev_state[1];#ifdef WCDMA_DEBUG_OUTPUT printf("Shifting state vectors ");#endif /* WCDMA_DEBUG_OUTPUT */ for (i=1; i < decoding_depth; i++) { prev_state[i] = prev_state[i+1];#ifdef WCDMA_DEBUG_OUTPUT printf("%d<-%d, ", i, i+1);#endif /* WCDMA_DEBUG_OUTPUT */ } /* for */ prev_state[decoding_depth] = temp_ptr;#ifdef WCDMA_DEBUG_OUTPUT printf("%d <- 1\n", decoding_depth);#endif /* WCDMA_DEBUG_OUTPUT */ return;} /* shift_prev_state_vecs *//* ------------------------------------------------------------------ *//* * Function: get_prev_state * Desc.: Returns the previous state for a state in the encoding trellis. */static int get_prev_state(int level, int curr_state) { return(prev_state[level][curr_state]);}/* ------------------------------------------------------------------ *//* * Function: set_previous state. * Desc.: Sets the previous state for a state in the trellis. */static void set_previous_state(int level, int curr_state, int earlier_state) { *(prev_state[level]+curr_state) = earlier_state; return;}/* ------------------------------------------------------------------ *//* * Function: wcdma_dec_R1o3_k9_conv * Desc.: Decodes convolutional code (R=1/3, K=9) using * Viterbi algorithm. */void wcdma_dec_R1o3_k9_conv( ViterbiDecoder* this, /* IN: decoder state information */ int rx_symbols[], /* IN: vector of received symbols */ double soft_bits[], /* IN: vector of soft symbols */ int rx_size, /* IN: length of received symbols */ int tail[], /* IN: tail bits */ int tail_size, /* IN: length of tail */ int decoded_bits[]) /* OUT: vector of decoded bits */{ int state, level, temp_level; int inp_symb, tx_symb, rx_symb; int new_state; unsigned int state_unvisited[256]; double old_path_metric, branch_metric; double path_metric; double survivor_metrics[2][256]; int rx_index, tail_index; int info_symb_size; double soft_bit; double best_path_metric; int best_path_state; int output_index; int current, next; unsigned int state_active[2][256]; int last_state; int prev_state_on_path,state_on_path; /* * Init path metrics and active state tables. * If state is active, then we can combine two paths. * If state is inactive, then we have't gone through the state. */ for(state=0; state < this->Numb_Encdr_States; state++) { survivor_metrics[0][state] = 0; survivor_metrics[1][state] = 0; state_active[0][state] = FALSE; state_active[1][state] = FALSE; } state_active[0][0] = TRUE; output_index = 0; /* * Data structures. */ current = 0; next = 1; init_prev_state_vecs(this->Decoding_depth); /* * Loop over the received symbols. */ info_symb_size = rx_size + tail_size; tail_index = 0; for (rx_index=0; rx_index < info_symb_size; rx_index++) { /* * Init variables. */ for(state=0; state < this->Numb_Encdr_States; state++) { state_unvisited[state] = TRUE; state_active[next][state] = FALSE; } best_path_metric = -10000000.0; /* Init to a very big path metric */ if (rx_index < this->Decoding_depth-1) { level = rx_index + 1; } else { level = this->Decoding_depth-1 + 1; } /* * Get received input symbol. After going through * received symbols, fill the shift register with * tail symbols. */ if (rx_index < rx_size) { rx_symb = rx_symbols[rx_index]; soft_bit = soft_bits[rx_index]; } else { rx_symb = tail[tail_index++]; soft_bit = 1.0; }#ifdef WCDMA_DEBUG_OUTPUT printf("current rx byte = %d\n",rx_symb);#endif /* WCDMA_DEBUG_OUTPUT */ /* * Loop over all the encoder states and calculate a path metric * for each of them. */ for (state=0; state < this->Numb_Encdr_States; state++) { /* * If state was not active on the previous level, jump it over. */ if (state_active[current][state] == FALSE) continue; /* fprintf(fptr," looping state = %d\n",state); */ /* * Loop over all candidate input symbols (0,1). */ for (inp_symb=0; inp_symb < 2; inp_symb++) { /* * Get the encoder output for this encoder state and input symbol. */ tx_symb = MealyEncoder_GetOutput(this->Tx_Encoder, state, inp_symb); /* * Calculate an individual branch metric and a total path metric. */ branch_metric = MetricTable_R1o3_GetBranchMetric( this->Decoding_Metric, rx_symb, soft_bit, tx_symb); old_path_metric = survivor_metrics[current][state]; path_metric = old_path_metric + branch_metric; new_state = MealyEncoder_GetNextState( this->Tx_Encoder, state, inp_symb); /* * Store the current best candidate. */ if (path_metric > best_path_metric) { best_path_metric = path_metric; best_path_state = state; } /* * If this is the first time we visit this state, * store the branch metrics and previous state. */ if(state_unvisited[new_state]) { survivor_metrics[next][new_state] = path_metric; state_active[next][new_state] = TRUE; state_unvisited[new_state] = FALSE; set_previous_state(level, new_state, state); } else { /* * if the path metric is smaller than the current * store value, replace the current survivor path. */ if(path_metric > survivor_metrics[next][new_state]) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -