/* Test viterbi decoder speeds */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/times.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include "viterbi29.h"
#include "parity.h"

#if HAVE_GETOPT_LONG
struct option Options[] = {
  {"frame-length",1,NULL,'l'},
  {"frame-count",1,NULL,'n'},
  {NULL},
};
#endif

int main(int argc,char *argv[]){
  int i,d,tr;
  int sr=0,trials = 1000,errcnt=0,framebits=2048;
  int *bits,*symbols;
  void *vp;
  extern char *optarg;
  unsigned char *data;
  struct tms start,finish;
  double extime;

  printf("%s, polynomials 0x%x 0x%x\n",id_viterbi29,V29POLYA,V29POLYB);
#if HAVE_GETOPT_LONG
  while((d = getopt_long(argc,argv,"l:n:t",Options,NULL)) != EOF){
#else
  while((d = getopt(argc,argv,"l:n:t")) != EOF){
#endif
    switch(d){
    case 'l':
      framebits = atoi(optarg);
      break;
    case 'n':
      trials = atoi(optarg);
      break;
    }
  }
  bits = malloc((framebits+8)*sizeof(int));
  data = malloc(framebits/8);
  symbols = malloc(2*(framebits+8)*sizeof(int));

  if((vp = create_viterbi29(framebits)) == NULL){
    printf("create_viterbi29 failed\n");
    exit(1);
  }
  /* Encode a frame of random data */
  for(i=0;i<framebits+8;i++){
    bits[i] = (i < framebits) ? (random() & 1) : 0;
    //bits[i] = 1; 
    sr = (sr << 1) | bits[i];
    symbols[2*i] = parity(sr & V29POLYA) ? 15:0;
    symbols[2*i+1] = parity(sr & V29POLYB) ? 15:0;
  }

  /* Decode it and make sure we get the right answer */
  /* Initialize Viterbi decoder */
  init_viterbi29(vp,0);
  
  /* Decode block */
  for(i=0;i<framebits+8;i++){
    d = update_viterbi29(vp,symbols[2*i],symbols[2*i+1]);
    if(d){
      printf("%d: normalize %d\n",i,d);
    }
  }
  /* Do Viterbi chainback */
  chainback_viterbi29(vp,data,framebits,0);
  for(i=0;i<framebits;i++){
    d = data[i/8] & (0x80 >> (i%8)) ? 1 : 0;
    if(d != bits[i]){
      printf("bit %d: %d %d\n",i,bits[i],d);
      errcnt++;
    }
  }
  if(errcnt == 0){
    printf("No decoder errors\n");
  }
  /* Do time trials */
  times(&start);
  for(tr=0;tr < trials;tr++){
    /* Initialize Viterbi decoder */
    init_viterbi29(vp,0);
    
    /* Decode block */
    for(i=0;i<framebits;i++){
      update_viterbi29(vp,symbols[2*i],symbols[2*i+1]);
    }
    /* Do Viterbi chainback */
    chainback_viterbi29(vp,data,framebits,0);
  }
  times(&finish);
  emms_viterbi29();
  extime = ((double)(finish.tms_utime-start.tms_utime))/CLK_TCK;
  printf("Execution time for %d %d-bit frames: %.2f sec\n",trials,
	 framebits,extime);
  printf("decoder speed: %g bits/s\n",trials*framebits/extime);
  
  exit(0);
}



syntax highlighted by Code2HTML, v. 0.9.1