186 lines
3.8 KiB
C
186 lines
3.8 KiB
C
|
/* Switch to K=9 r=1/3 Viterbi decoder with optional Intel or PowerPC SIMD
|
||
|
* Copyright Aug 2006, 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_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
|
||
|
}
|
||
|
}
|