14e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* K=7 r=1/2 Viterbi decoder with optional Intel or PowerPC SIMD
24e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * Copyright Feb 2004, Phil Karn, KA9Q
34e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi */
44e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <stdio.h>
54e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <stdlib.h>
64e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <memory.h>
74e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include "fec.h"
84e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
94e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Create a new instance of a Viterbi decoder */
104e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid *create_viterbi27(int len){
114e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  find_cpu_mode();
124e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
134e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  switch(Cpu_mode){
144e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case PORT:
154e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  default:
164e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return create_viterbi27_port(len);
174e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
184e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case ALTIVEC:
194e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return create_viterbi27_av(len);
204e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
214e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
224e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case MMX:
234e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return create_viterbi27_mmx(len);
244e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE:
254e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return create_viterbi27_sse(len);
264e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE2:
274e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return create_viterbi27_sse2(len);
284e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
294e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
304e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
314e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
324e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid set_viterbi27_polynomial(int polys[2]){
334e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  switch(Cpu_mode){
344e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case PORT:
354e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  default:
364e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    set_viterbi27_polynomial_port(polys);
374e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
384e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
394e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case ALTIVEC:
404e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    set_viterbi27_polynomial_av(polys);
414e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
424e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
434e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
444e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case MMX:
454e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    set_viterbi27_polynomial_mmx(polys);
464e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
474e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE:
484e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    set_viterbi27_polynomial_sse(polys);
494e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
504e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE2:
514e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    set_viterbi27_polynomial_sse2(polys);
524e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
534e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
544e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
554e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
564e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
574e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Initialize Viterbi decoder for start of new frame */
584e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiint init_viterbi27(void *p,int starting_state){
594e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    switch(Cpu_mode){
604e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case PORT:
614e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    default:
624e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return init_viterbi27_port(p,starting_state);
634e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
644e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case ALTIVEC:
654e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return init_viterbi27_av(p,starting_state);
664e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
674e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
684e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case MMX:
694e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return init_viterbi27_mmx(p,starting_state);
704e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case SSE:
714e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return init_viterbi27_sse(p,starting_state);
724e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case SSE2:
734e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return init_viterbi27_sse2(p,starting_state);
744e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
754e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    }
764e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
774e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
784e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Viterbi chainback */
794e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiint chainback_viterbi27(
804e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      void *p,
814e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      unsigned char *data, /* Decoded output data */
824e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      unsigned int nbits, /* Number of data bits */
834e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      unsigned int endstate){ /* Terminal encoder state */
844e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
854e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    switch(Cpu_mode){
864e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case PORT:
874e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    default:
884e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return chainback_viterbi27_port(p,data,nbits,endstate);
894e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
904e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case ALTIVEC:
914e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return chainback_viterbi27_av(p,data,nbits,endstate);
924e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
934e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
944e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case MMX:
954e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return chainback_viterbi27_mmx(p,data,nbits,endstate);
964e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case SSE:
974e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return chainback_viterbi27_sse(p,data,nbits,endstate);
984e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case SSE2:
994e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      return chainback_viterbi27_sse2(p,data,nbits,endstate);
1004e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
1014e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    }
1024e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
1034e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1044e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Delete instance of a Viterbi decoder */
1054e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid delete_viterbi27(void *p){
1064e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    switch(Cpu_mode){
1074e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case PORT:
1084e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    default:
1094e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      delete_viterbi27_port(p);
1104e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      break;
1114e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
1124e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case ALTIVEC:
1134e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      delete_viterbi27_av(p);
1144e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      break;
1154e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
1164e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
1174e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case MMX:
1184e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      delete_viterbi27_mmx(p);
1194e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      break;
1204e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case SSE:
1214e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      delete_viterbi27_sse(p);
1224e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      break;
1234e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    case SSE2:
1244e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      delete_viterbi27_sse2(p);
1254e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      break;
1264e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
1274e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    }
1284e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
1294e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1304e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Update decoder with a block of demodulated symbols
1314e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * Note that nbits is the number of decoded data bits, not the number
1324e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * of symbols!
1334e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi */
1344e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiint update_viterbi27_blk(void *p,unsigned char syms[],int nbits){
1354e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if(p == NULL)
1364e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return -1;
1374e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1384e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  switch(Cpu_mode){
1394e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case PORT:
1404e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  default:
1414e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    update_viterbi27_blk_port(p,syms,nbits);
1424e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
1434e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
1444e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case ALTIVEC:
1454e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    update_viterbi27_blk_av(p,syms,nbits);
1464e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
1474e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
1484e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
1494e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case MMX:
1504e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    update_viterbi27_blk_mmx(p,syms,nbits);
1514e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
1524e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE:
1534e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    update_viterbi27_blk_sse(p,syms,nbits);
1544e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
1554e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE2:
1564e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    update_viterbi27_blk_sse2(p,syms,nbits);
1574e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    break;
1584e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
1594e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
1604e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  return 0;
1614e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
162