14e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* K=9 r=1/2 Viterbi decoder for MMX
24e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * Copyright Feb 2004, Phil Karn, KA9Q
34e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * May be used under the terms of the GNU Lesser General Public License (LGPL)
44e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi */
54e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <stdio.h>
64e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <stdlib.h>
74e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <memory.h>
84e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <mmintrin.h>
94e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include "fec.h"
104e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
114e213d510f437769f8a28578dd4f786fb7d16c4Bill Yitypedef union { char c[256]; __m64 v[32];} decision_t;
124e213d510f437769f8a28578dd4f786fb7d16c4Bill Yitypedef union { unsigned char c[256]; __m64 v[32];} metric_t;
134e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
144e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiunsigned char Mettab29_1[256][128] __attribute__ ((aligned(8)));
154e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiunsigned char Mettab29_2[256][128] __attribute__ ((aligned(8)));
164e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic int Init = 0;
174e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
184e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* State info for instance of Viterbi decoder
194e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * Don't change this without also changing references in mmxbfly29.s!
204e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi */
214e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistruct v29 {
224e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  metric_t metrics1; /* path metric buffer 1 */
234e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  metric_t metrics2; /* path metric buffer 2 */
244e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  decision_t *dp;          /* Pointer to current decision */
254e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  metric_t *old_metrics,*new_metrics; /* Pointers to path metrics, swapped on every bit */
264e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  decision_t *decisions;   /* Beginning of decisions for block */
274e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi};
284e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
294e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Create a new instance of a Viterbi decoder */
304e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid *create_viterbi29_mmx(int len){
314e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  struct v29 *vp;
324e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
334e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if(Init == 0){
344e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int polys[2] = {V29POLYA,V29POLYB};
354e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
364e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    set_viterbi29_polynomial_mmx(polys);
374e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
384e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if((vp = (struct v29 *)malloc(sizeof(struct v29))) == NULL)
394e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return NULL;
404e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
414e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if((vp->decisions = (decision_t *)malloc((len+8)*sizeof(decision_t))) == NULL){
424e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    free(vp);
434e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return NULL;
444e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
454e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  init_viterbi29(vp,0);
464e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  return vp;
474e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
484e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
494e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid set_viterbi29_polynomial_mmx(int polys[2]){
504e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  int state;
514e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
524e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  for(state=0;state < 128;state++){
534e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int symbol;
544e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
554e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    for(symbol = 0;symbol < 256;symbol++){
564e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      int sym;
574e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
584e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      sym = parity((2*state) & abs(polys[0])) ^ (polys[0] < 0);
594e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      Mettab29_1[symbol][state] = (sym ? (255-symbol):symbol) / 16;
604e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
614e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      sym = parity((2*state) & abs(polys[1])) ^ (polys[1] < 0);
624e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      Mettab29_2[symbol][state] = (sym ? (255-symbol):symbol) / 16;
634e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    }
644e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
654e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  Init++;
664e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
674e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
684e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Initialize Viterbi decoder for start of new frame */
694e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiint init_viterbi29_mmx(void *p,int starting_state){
704e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  struct v29 *vp = p;
714e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  int i;
724e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
734e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if(p == NULL)
744e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return -1;
754e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  for(i=0;i<256;i++)
764e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    vp->metrics1.c[i] = 63;
774e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
784e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  vp->old_metrics = &vp->metrics1;
794e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  vp->new_metrics = &vp->metrics2;
804e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  vp->dp = vp->decisions;
814e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  vp->old_metrics->c[starting_state & 255] = 0; /* Bias known start state */
824e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  return 0;
834e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
844e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
854e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Viterbi chainback */
864e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiint chainback_viterbi29_mmx(
874e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      void *p,
884e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      unsigned char *data, /* Decoded output data */
894e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      unsigned int nbits, /* Number of data bits */
904e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      unsigned int endstate){ /* Terminal encoder state */
914e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
924e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  struct v29 *vp = (struct v29 *)p;
934e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  decision_t *d;
944e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
954e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if(p == NULL)
964e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return -1;
974e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
984e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  d = (decision_t *)vp->decisions;
994e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  endstate &= 255;
1004e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  d += 8; /* Look past tail */
1014e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  while(nbits-- != 0){
1024e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int k;
1034e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1044e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    k = d[nbits].c[endstate] & 1;
1054e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    data[nbits>>3] = endstate = (endstate >> 1) | (k << 7);
1064e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
1074e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  return 0;
1084e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
1094e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1104e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Delete instance of a Viterbi decoder */
1114e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid delete_viterbi29_mmx(void *p){
1124e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  struct v29 *vp = p;
1134e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1144e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if(vp != NULL){
1154e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    free(vp->decisions);
1164e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    free(vp);
1174e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
1184e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
119