1/* K=7 r=1/2 Viterbi decoder with optional Intel or PowerPC SIMD
2 * Copyright Feb 2004, Phil Karn, KA9Q
3 */
4#include <stdio.h>
5#include <stdlib.h>
6#include <memory.h>
7#include "fec.h"
8
9/* Create a new instance of a Viterbi decoder */
10void *create_viterbi27(int len){
11  find_cpu_mode();
12
13  switch(Cpu_mode){
14  case PORT:
15  default:
16    return create_viterbi27_port(len);
17#ifdef __VEC__
18  case ALTIVEC:
19    return create_viterbi27_av(len);
20#endif
21#ifdef __i386__
22  case MMX:
23    return create_viterbi27_mmx(len);
24  case SSE:
25    return create_viterbi27_sse(len);
26  case SSE2:
27    return create_viterbi27_sse2(len);
28#endif
29  }
30}
31
32void set_viterbi27_polynomial(int polys[2]){
33  switch(Cpu_mode){
34  case PORT:
35  default:
36    set_viterbi27_polynomial_port(polys);
37    break;
38#ifdef __VEC__
39  case ALTIVEC:
40    set_viterbi27_polynomial_av(polys);
41    break;
42#endif
43#ifdef __i386__
44  case MMX:
45    set_viterbi27_polynomial_mmx(polys);
46    break;
47  case SSE:
48    set_viterbi27_polynomial_sse(polys);
49    break;
50  case SSE2:
51    set_viterbi27_polynomial_sse2(polys);
52    break;
53#endif
54  }
55}
56
57/* Initialize Viterbi decoder for start of new frame */
58int init_viterbi27(void *p,int starting_state){
59    switch(Cpu_mode){
60    case PORT:
61    default:
62      return init_viterbi27_port(p,starting_state);
63#ifdef __VEC__
64    case ALTIVEC:
65      return init_viterbi27_av(p,starting_state);
66#endif
67#ifdef __i386__
68    case MMX:
69      return init_viterbi27_mmx(p,starting_state);
70    case SSE:
71      return init_viterbi27_sse(p,starting_state);
72    case SSE2:
73      return init_viterbi27_sse2(p,starting_state);
74#endif
75    }
76}
77
78/* Viterbi chainback */
79int chainback_viterbi27(
80      void *p,
81      unsigned char *data, /* Decoded output data */
82      unsigned int nbits, /* Number of data bits */
83      unsigned int endstate){ /* Terminal encoder state */
84
85    switch(Cpu_mode){
86    case PORT:
87    default:
88      return chainback_viterbi27_port(p,data,nbits,endstate);
89#ifdef __VEC__
90    case ALTIVEC:
91      return chainback_viterbi27_av(p,data,nbits,endstate);
92#endif
93#ifdef __i386__
94    case MMX:
95      return chainback_viterbi27_mmx(p,data,nbits,endstate);
96    case SSE:
97      return chainback_viterbi27_sse(p,data,nbits,endstate);
98    case SSE2:
99      return chainback_viterbi27_sse2(p,data,nbits,endstate);
100#endif
101    }
102}
103
104/* Delete instance of a Viterbi decoder */
105void delete_viterbi27(void *p){
106    switch(Cpu_mode){
107    case PORT:
108    default:
109      delete_viterbi27_port(p);
110      break;
111#ifdef __VEC__
112    case ALTIVEC:
113      delete_viterbi27_av(p);
114      break;
115#endif
116#ifdef __i386__
117    case MMX:
118      delete_viterbi27_mmx(p);
119      break;
120    case SSE:
121      delete_viterbi27_sse(p);
122      break;
123    case SSE2:
124      delete_viterbi27_sse2(p);
125      break;
126#endif
127    }
128}
129
130/* Update decoder with a block of demodulated symbols
131 * Note that nbits is the number of decoded data bits, not the number
132 * of symbols!
133 */
134int update_viterbi27_blk(void *p,unsigned char syms[],int nbits){
135  if(p == NULL)
136    return -1;
137
138  switch(Cpu_mode){
139  case PORT:
140  default:
141    update_viterbi27_blk_port(p,syms,nbits);
142    break;
143#ifdef __VEC__
144  case ALTIVEC:
145    update_viterbi27_blk_av(p,syms,nbits);
146    break;
147#endif
148#ifdef __i386__
149  case MMX:
150    update_viterbi27_blk_mmx(p,syms,nbits);
151    break;
152  case SSE:
153    update_viterbi27_blk_sse(p,syms,nbits);
154    break;
155  case SSE2:
156    update_viterbi27_blk_sse2(p,syms,nbits);
157    break;
158#endif
159  }
160  return 0;
161}
162