blob: 563f40a282472a1ee688a2d9e5f0e9f2260f10ac [file] [log] [blame]
Bill Yi4e213d52015-06-23 13:53:11 -07001/* 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
11typedef union { char c[256]; __m64 v[32];} decision_t;
12typedef union { unsigned char c[256]; __m64 v[32];} metric_t;
13
14unsigned char Mettab29_1[256][128] __attribute__ ((aligned(8)));
15unsigned char Mettab29_2[256][128] __attribute__ ((aligned(8)));
16static 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 */
21struct 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 */
30void *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
49void 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 */
69int 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 */
86int 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 */
111void delete_viterbi29_mmx(void *p){
112 struct v29 *vp = p;
113
114 if(vp != NULL){
115 free(vp->decisions);
116 free(vp);
117 }
118}