/* Switch to K=9 r=1/3 Viterbi decoder with optional Intel or PowerPC SIMD * Copyright Aug 2006, Phil Karn, KA9Q */ #include #include #include #include "fec.h" /* Create a new instance of a Viterbi decoder */ void *create_viterbi39(int len) { find_cpu_mode(); switch (Cpu_mode) { case PORT: default: return create_viterbi39_port(len); #ifdef __VEC__ case ALTIVEC: return create_viterbi39_av(len); #endif #ifdef __i386__ case MMX: return create_viterbi39_mmx(len); case SSE: return create_viterbi39_sse(len); case SSE2: return create_viterbi39_sse2(len); #endif #ifdef __x86_64__ case SSE2: return create_viterbi39_port(len); #endif } } void set_viterbi39_polynomial(int polys[3]) { switch (Cpu_mode) { case PORT: default: set_viterbi39_polynomial_port(polys); break; #ifdef __VEC__ case ALTIVEC: set_viterbi39_polynomial_av(polys); break; #endif #ifdef __i386__ case MMX: set_viterbi39_polynomial_mmx(polys); break; case SSE: set_viterbi39_polynomial_sse(polys); break; case SSE2: set_viterbi39_polynomial_sse2(polys); break; #endif #ifdef __x86_64__ case SSE2: set_viterbi39_polynomial_port(polys); break; #endif } } /* Initialize Viterbi decoder for start of new frame */ int init_viterbi39(void *p, int starting_state) { switch (Cpu_mode) { case PORT: default: return init_viterbi39_port(p, starting_state); #ifdef __VEC__ case ALTIVEC: return init_viterbi39_av(p, starting_state); #endif #ifdef __i386__ case MMX: return init_viterbi39_mmx(p, starting_state); case SSE: return init_viterbi39_sse(p, starting_state); case SSE2: return init_viterbi39_sse2(p, starting_state); #endif #ifdef __x86_64__ case SSE2: return init_viterbi39_port(p, starting_state); #endif } } /* Viterbi chainback */ int chainback_viterbi39( 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_viterbi39_port(p, data, nbits, endstate); #ifdef __VEC__ case ALTIVEC: return chainback_viterbi39_av(p, data, nbits, endstate); #endif #ifdef __i386__ case MMX: return chainback_viterbi39_mmx(p, data, nbits, endstate); case SSE: return chainback_viterbi39_sse(p, data, nbits, endstate); case SSE2: return chainback_viterbi39_sse2(p, data, nbits, endstate); #endif #ifdef __x86_64__ case SSE2: return chainback_viterbi39_port(p, data, nbits, endstate); #endif } } /* Delete instance of a Viterbi decoder */ void delete_viterbi39(void *p) { switch (Cpu_mode) { case PORT: default: delete_viterbi39_port(p); break; #ifdef __VEC__ case ALTIVEC: delete_viterbi39_av(p); break; #endif #ifdef __i386__ case MMX: delete_viterbi39_mmx(p); break; case SSE: delete_viterbi39_sse(p); break; case SSE2: delete_viterbi39_sse2(p); break; #endif #ifdef __x86_64__ case SSE2: delete_viterbi39_port(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_viterbi39_blk(void *p, unsigned char syms[], int nbits) { switch (Cpu_mode) { case PORT: default: return update_viterbi39_blk_port(p, syms, nbits); #ifdef __VEC__ case ALTIVEC: return update_viterbi39_blk_av(p, syms, nbits); #endif #ifdef __i386__ case MMX: return update_viterbi39_blk_mmx(p, syms, nbits); case SSE: return update_viterbi39_blk_sse(p, syms, nbits); case SSE2: return update_viterbi39_blk_sse2(p, syms, nbits); #endif #ifdef __x86_64__ case SSE2: return update_viterbi39_blk_port(p, syms, nbits); #endif } }