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