1 /* K=9 r=1/2 Viterbi decoder for MMX 2 * Copyright Feb 2004, Phil Karn, KA9Q 3 * May be used under the terms of the GNU Lesser General Public License (LGPL) 4 */ 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <memory.h> 8 #include <mmintrin.h> 9 #include "fec.h" 10 11 typedef union { char c[256]; __m64 v[32];} decision_t; 12 typedef union { unsigned char c[256]; __m64 v[32];} metric_t; 13 14 unsigned char Mettab29_1[256][128] __attribute__ ((aligned(8))); 15 unsigned char Mettab29_2[256][128] __attribute__ ((aligned(8))); 16 static int Init = 0; 17 18 /* State info for instance of Viterbi decoder 19 * Don't change this without also changing references in mmxbfly29.s! 20 */ 21 struct v29 { 22 metric_t metrics1; /* path metric buffer 1 */ 23 metric_t metrics2; /* path metric buffer 2 */ 24 decision_t *dp; /* Pointer to current decision */ 25 metric_t *old_metrics,*new_metrics; /* Pointers to path metrics, swapped on every bit */ 26 decision_t *decisions; /* Beginning of decisions for block */ 27 }; 28 29 /* Create a new instance of a Viterbi decoder */ 30 void *create_viterbi29_mmx(int len){ 31 struct v29 *vp; 32 33 if(Init == 0){ 34 int polys[2] = {V29POLYA,V29POLYB}; 35 36 set_viterbi29_polynomial_mmx(polys); 37 } 38 if((vp = (struct v29 *)malloc(sizeof(struct v29))) == NULL) 39 return NULL; 40 41 if((vp->decisions = (decision_t *)malloc((len+8)*sizeof(decision_t))) == NULL){ 42 free(vp); 43 return NULL; 44 } 45 init_viterbi29(vp,0); 46 return vp; 47 } 48 49 void set_viterbi29_polynomial_mmx(int polys[2]){ 50 int state; 51 52 for(state=0;state < 128;state++){ 53 int symbol; 54 55 for(symbol = 0;symbol < 256;symbol++){ 56 int sym; 57 58 sym = parity((2*state) & abs(polys[0])) ^ (polys[0] < 0); 59 Mettab29_1[symbol][state] = (sym ? (255-symbol):symbol) / 16; 60 61 sym = parity((2*state) & abs(polys[1])) ^ (polys[1] < 0); 62 Mettab29_2[symbol][state] = (sym ? (255-symbol):symbol) / 16; 63 } 64 } 65 Init++; 66 } 67 68 /* Initialize Viterbi decoder for start of new frame */ 69 int init_viterbi29_mmx(void *p,int starting_state){ 70 struct v29 *vp = p; 71 int i; 72 73 if(p == NULL) 74 return -1; 75 for(i=0;i<256;i++) 76 vp->metrics1.c[i] = 63; 77 78 vp->old_metrics = &vp->metrics1; 79 vp->new_metrics = &vp->metrics2; 80 vp->dp = vp->decisions; 81 vp->old_metrics->c[starting_state & 255] = 0; /* Bias known start state */ 82 return 0; 83 } 84 85 /* Viterbi chainback */ 86 int chainback_viterbi29_mmx( 87 void *p, 88 unsigned char *data, /* Decoded output data */ 89 unsigned int nbits, /* Number of data bits */ 90 unsigned int endstate){ /* Terminal encoder state */ 91 92 struct v29 *vp = (struct v29 *)p; 93 decision_t *d; 94 95 if(p == NULL) 96 return -1; 97 98 d = (decision_t *)vp->decisions; 99 endstate &= 255; 100 d += 8; /* Look past tail */ 101 while(nbits-- != 0){ 102 int k; 103 104 k = d[nbits].c[endstate] & 1; 105 data[nbits>>3] = endstate = (endstate >> 1) | (k << 7); 106 } 107 return 0; 108 } 109 110 /* Delete instance of a Viterbi decoder */ 111 void delete_viterbi29_mmx(void *p){ 112 struct v29 *vp = p; 113 114 if(vp != NULL){ 115 free(vp->decisions); 116 free(vp); 117 } 118 } 119