| /* K=15 r=1/6 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_viterbi615(int len){ |
| |
| find_cpu_mode(); |
| |
| switch(Cpu_mode){ |
| case PORT: |
| default: |
| return create_viterbi615_port(len); |
| #ifdef __VEC__ |
| case ALTIVEC: |
| return create_viterbi615_av(len); |
| #endif |
| #ifdef __i386__ |
| case MMX: |
| return create_viterbi615_mmx(len); |
| case SSE: |
| return create_viterbi615_sse(len); |
| case SSE2: |
| return create_viterbi615_sse2(len); |
| #endif |
| } |
| } |
| |
| void set_viterbi615_polynomial(int polys[6]){ |
| |
| switch(Cpu_mode){ |
| case PORT: |
| default: |
| set_viterbi615_polynomial_port(polys); |
| break; |
| #ifdef __VEC__ |
| case ALTIVEC: |
| set_viterbi615_polynomial_av(polys); |
| break; |
| #endif |
| #ifdef __i386__ |
| case MMX: |
| set_viterbi615_polynomial_mmx(polys); |
| break; |
| case SSE: |
| set_viterbi615_polynomial_sse(polys); |
| break; |
| case SSE2: |
| set_viterbi615_polynomial_sse2(polys); |
| break; |
| #endif |
| } |
| } |
| |
| /* Initialize Viterbi decoder for start of new frame */ |
| int init_viterbi615(void *p,int starting_state){ |
| switch(Cpu_mode){ |
| case PORT: |
| default: |
| return init_viterbi615_port(p,starting_state); |
| #ifdef __VEC__ |
| case ALTIVEC: |
| return init_viterbi615_av(p,starting_state); |
| #endif |
| #ifdef __i386__ |
| case MMX: |
| return init_viterbi615_mmx(p,starting_state); |
| case SSE: |
| return init_viterbi615_sse(p,starting_state); |
| case SSE2: |
| return init_viterbi615_sse2(p,starting_state); |
| #endif |
| } |
| } |
| |
| /* Viterbi chainback */ |
| int chainback_viterbi615( |
| 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_viterbi615_port(p,data,nbits,endstate); |
| #ifdef __VEC__ |
| case ALTIVEC: |
| return chainback_viterbi615_av(p,data,nbits,endstate); |
| #endif |
| #ifdef __i386__ |
| case MMX: |
| return chainback_viterbi615_mmx(p,data,nbits,endstate); |
| case SSE: |
| return chainback_viterbi615_sse(p,data,nbits,endstate); |
| case SSE2: |
| return chainback_viterbi615_sse2(p,data,nbits,endstate); |
| #endif |
| } |
| } |
| |
| /* Delete instance of a Viterbi decoder */ |
| void delete_viterbi615(void *p){ |
| switch(Cpu_mode){ |
| case PORT: |
| default: |
| delete_viterbi615_port(p); |
| break; |
| #ifdef __VEC__ |
| case ALTIVEC: |
| delete_viterbi615_av(p); |
| break; |
| #endif |
| #ifdef __i386__ |
| case MMX: |
| delete_viterbi615_mmx(p); |
| break; |
| case SSE: |
| delete_viterbi615_sse(p); |
| break; |
| case SSE2: |
| delete_viterbi615_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_viterbi615_blk(void *p,unsigned char syms[],int nbits){ |
| switch(Cpu_mode){ |
| case PORT: |
| default: |
| return update_viterbi615_blk_port(p,syms,nbits); |
| #ifdef __VEC__ |
| case ALTIVEC: |
| return update_viterbi615_blk_av(p,syms,nbits); |
| #endif |
| #ifdef __i386__ |
| case MMX: |
| return update_viterbi615_blk_mmx(p,syms,nbits); |
| case SSE: |
| return update_viterbi615_blk_sse(p,syms,nbits); |
| case SSE2: |
| return update_viterbi615_blk_sse2(p,syms,nbits); |
| #endif |
| } |
| } |
| |