/* K=7 r=1/2 Viterbi decoder with optional Intel or PowerPC SIMD * Copyright Feb 2004, Phil Karn, KA9Q */ #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "fec.h" /* Create a new instance of a Viterbi decoder */ void *create_viterbi27(int len){ find_cpu_mode(); switch(Cpu_mode){ case PORT: default: return create_viterbi27_port(len); #ifdef __VEC__ case ALTIVEC: return create_viterbi27_av(len); #endif #ifdef __i386__ case MMX: return create_viterbi27_mmx(len); case SSE: return create_viterbi27_sse(len); case SSE2: return create_viterbi27_sse2(len); #endif } } void set_viterbi27_polynomial(int polys[2]){ switch(Cpu_mode){ case PORT: default: set_viterbi27_polynomial_port(polys); break; #ifdef __VEC__ case ALTIVEC: set_viterbi27_polynomial_av(polys); break; #endif #ifdef __i386__ case MMX: set_viterbi27_polynomial_mmx(polys); break; case SSE: set_viterbi27_polynomial_sse(polys); break; case SSE2: set_viterbi27_polynomial_sse2(polys); break; #endif } } /* Initialize Viterbi decoder for start of new frame */ int init_viterbi27(void *p,int starting_state){ switch(Cpu_mode){ case PORT: default: return init_viterbi27_port(p,starting_state); #ifdef __VEC__ case ALTIVEC: return init_viterbi27_av(p,starting_state); #endif #ifdef __i386__ case MMX: return init_viterbi27_mmx(p,starting_state); case SSE: return init_viterbi27_sse(p,starting_state); case SSE2: return init_viterbi27_sse2(p,starting_state); #endif } } /* Viterbi chainback */ int chainback_viterbi27( void *p, unsigned char *data, /* Decoded output data */ unsigned int nbits, /* Number of data bits */ unsigned int endstate){ /* Terminal encoder state */ switch(Cpu_mode){ case PORT: default: return chainback_viterbi27_port(p,data,nbits,endstate); #ifdef __VEC__ case ALTIVEC: return chainback_viterbi27_av(p,data,nbits,endstate); #endif #ifdef __i386__ case MMX: return chainback_viterbi27_mmx(p,data,nbits,endstate); case SSE: return chainback_viterbi27_sse(p,data,nbits,endstate); case SSE2: return chainback_viterbi27_sse2(p,data,nbits,endstate); #endif } } /* Delete instance of a Viterbi decoder */ void delete_viterbi27(void *p){ switch(Cpu_mode){ case PORT: default: delete_viterbi27_port(p); break; #ifdef __VEC__ case ALTIVEC: delete_viterbi27_av(p); break; #endif #ifdef __i386__ case MMX: delete_viterbi27_mmx(p); break; case SSE: delete_viterbi27_sse(p); break; case SSE2: delete_viterbi27_sse2(p); break; #endif } } /* Update decoder with a block of demodulated symbols * Note that nbits is the number of decoded data bits, not the number * of symbols! */ int update_viterbi27_blk(void *p,unsigned char syms[],int nbits){ if(p == NULL) return -1; switch(Cpu_mode){ case PORT: default: update_viterbi27_blk_port(p,syms,nbits); break; #ifdef __VEC__ case ALTIVEC: update_viterbi27_blk_av(p,syms,nbits); break; #endif #ifdef __i386__ case MMX: update_viterbi27_blk_mmx(p,syms,nbits); break; case SSE: update_viterbi27_blk_sse(p,syms,nbits); break; case SSE2: update_viterbi27_blk_sse2(p,syms,nbits); break; #endif } return 0; }