www.pudn.com > viterbi_binary_punct.rar > viterbi_binary_punct.c


// ------------------------------------------------------------------------
// File: viterbi_binary_punct.c
// Date: April 1, 2002
// Description: Viterbi decoder, maximum likelihood decoding. For a
//              rate-1/n convolutional code. Correlation metric.
//
// Maximum of 1024 states; max. truncation length = 1024
//
// The puncturing rule must be in a separate file.
//
// CAUTION: The row order of the puncturing rule is reversed from that
//          in the book. Specify the rule starting from the last row
//          down to the first one. See the example files in this
//          directory: "rule_kn.data" specifies the puncturing rule for
//          a rate-k/n code derived from a rate-1/2 convolutional code.
//
//          If you give the wrong puncturing rule, the results will be
//          evident. Try it out. 
//
// ------------------------------------------------------------------------
#include 
#include 
#include 
#include 
#include 

#define MAX_RANDOM LONG_MAX 

// Use the compiling directive -DSHOW_PROGRESS to see how the decoder
// converges to the decoded sequence by monitoring the survivor memory
#ifdef SHOW_PROGRESS
#define DELTA 1
#endif

int k2=1, n2, m2;
int length;
int NUM_STATES, OUT_SYM, NUM_TRANS;

long TRUNC_LENGTH;
int punct[10][10];                       // Puncturing rule

double RATE;
double INIT_SNR, FINAL_SNR, SNR_INC;
long NUMSIM;

FILE *fp, *fp_ber, *fp_punct;

int g2[10][10];
unsigned int memory2, output;            /* Memory and output */
unsigned int data2;                      /* Data */

unsigned long seed;                      /* Seed for random generator */
unsigned int data_symbol[1024];          /* 1-bit data sequence */
long index;                              /* Index for memory management*/
double transmitted[10];                  /* Transmitted signals/branch */
double snr, amp;
double received[10];                     /* Received signals/branch */

int fflush();

// Data structures used for trellis sections and survivors
struct trel {
  int init;                /* initial state */
  int data;                /* data symbol */
  int final;               /* final state */
  double output[10];  /* output coded symbols (branch label) */
}; 
struct surv {
  double metric;           /* metric */
  int data[1024];  /* estimated data symbols */
  int state[1024];  /* state sequence */
};

// A trellis section is an array of branches, indexed by an initial
//   state and a k_2-bit input data. The values read
//   are the final state and the output symbols 
struct trel trellis[1024][100];

/* A survivor is a sequence of states and estimated data, of length
   equal to TRUNC_LENGTH, together with its corresponding metric.
   A total of NUM_STATES survivors are needed */
struct surv survivor[1024], surv_temp[1024];

/* Function prototypes */
void encoder2(void);           /* Encoder for C_{O2} */
int random_data(void);         /* Random data generator */
void transmit(void);           /* Encoder & BPSK modulator */
void awgn(void);               /* Add AWGN */
void viterbi(void);            /* Viterbi decoder */
double comp_metric(double rec, double ref); /* Metric calculator */
void open_files(void);         /* Open files for output */
void close_files(void);        /* Close files */


main(int argc, char *argv[])
{

register int i, j, k;
int init, data, final, output;
register int error;
unsigned long error_count;
char name[40], name1[40], name2[40];

  // Command line processing
  if (argc != 9)
    {
      printf("Usage %s file_trellis file_rule file_ber truncation snr_init snr_final snr_inc num_sim\n", argv[0]);
      exit(0);
    }

  sscanf(argv[1],"%s", name1);
  sscanf(argv[2],"%s", name);
  sscanf(argv[3],"%s", name2);
  sscanf(argv[4],"%ld", &TRUNC_LENGTH);
  sscanf(argv[5],"%lf", &INIT_SNR);
  sscanf(argv[6],"%lf", &FINAL_SNR);
  sscanf(argv[7],"%lf", &SNR_INC);
  sscanf(argv[8],"%ld", &NUMSIM);

printf("\nSimulation of Viterbi decoding over an AWGN channel\n");
printf("%ld simulations per Eb/No (dB) point\n", NUMSIM);


  fp_ber = fopen(name2,"w");

  /* Open file with trellis data */
  if (!(fp = fopen(name1,"r")))
    {
    printf("Error opening file!\n");
    exit(1);
    }

  fscanf(fp, "%d %d", &n2, &m2);

  RATE = 1.0 / (double) n2;

  fscanf(fp, "%d %d %d", &NUM_STATES, &OUT_SYM, &NUM_TRANS);
  for (j=0; j> 5) & 1 );
}







void transmit()
{
  /* Encode and modulate a 1-bit data sequence */
  int i;

  encoder2(); /* */

  /* Modulate: {0,1} --> {+1,-1} */
  for (i=(OUT_SYM-1); i >=0; i--)
    if ( (output >> i) & 0x01 )
      transmitted[OUT_SYM-1-i] = -1.0;  /* if bit = 1 */
    else
      transmitted[OUT_SYM-1-i] =  1.0;  /* if bit = 0 */
}






void encoder2()
{
  // Binary convolutional encoder, rate 1/n2 
  register int i, j, result, temp;
  
  temp = memory2;
  output = 0;

  temp = (temp<<1) ^ data_symbol[index % TRUNC_LENGTH];

  for (i=0; i=0; j--)
       result ^= ( ( temp & g2[i][0] ) >> j ) & 1;
     output = ( output<<1 ) ^ result;
   }

  memory2 = temp ;

}






void awgn()
{
  /* Add AWGN to transmitted sequence */
  double u1,u2,s,noise,randmum;
  int i;

  for (i=0; i= 1);
      noise = u1 * sqrt( (-2.0*log(s))/s );
      received[i] = transmitted[i] + noise/amp;
    }
}








void viterbi()
{
  double aux_metric, surv_metric[NUM_STATES];
  register int i,j,k;

  for (i=0; i=0; k--)
            {
            // Computation only for unpunctured positions:
            if (punct[k][(index%length)])
	      aux_metric += comp_metric(received[k],trellis[i][j].output[k]);
            }
	  aux_metric += survivor[i].metric;

	  /* compare with survivor metric at final state */
	  /* We compare CORRELATIONS */

          if ( aux_metric > surv_metric[trellis[i][j].final] )
	    { /* Good candidate found */

	      surv_metric[trellis[i][j].final] = aux_metric;

	      /* Update data and state paths */
	      for (k=0; k