/* Viterbi decoder for arbitrary convolutional code * viterbi27 and viterbi37 for the r=1/2 and r=1/3 K=7 codes are faster * Copyright 1999 Phil Karn, KA9Q * May be used under the terms of the GNU Public License */ #include "itf_types.h" #define MAX_BITS 1024 /** Modified by Ismael. * K, N and Polys are received as parametrs */ #include #define NULL ((void *)0) extern unsigned char Partab[]; /* Parity lookup table */ int VDInit; inline int parity(int x) { x ^= (x >> 16); x ^= (x >> 8); return Partab[x & 0xff]; } #define MAX_D (1 << (MAX_K-6)) int mets[1 << MAX_RATE]; unsigned long paths[(MAX_BITS+MAX_K-1)*MAX_D]; long cmetric[1 << (MAX_K-1)],nmetric[1 << (MAX_K-1)]; int Syms[1 << MAX_K]; /* Viterbi decoder */ int viterbi( unsigned long *metric, /* Final path metric (returned value) */ unsigned char *data, /* Decoded output data */ unsigned char *symbols, /* Raw deinterleaved input symbols */ unsigned int nbits, /* Number of output bits */ int mettab[2][256], /* Metric table, [sent sym][rx symbol] */ unsigned int startstate, /* Encoder starting state */ unsigned int endstate, /* Encoder ending state */ /** added by Ismael */ int N, int K, unsigned int *Polys) { int bitcnt = -(K-1); long m0,m1; int i,j,sym; int D; int Rate = N; unsigned long *pp,mask; memset(paths,0,sizeof(paths)); if (K>=6) { D = (1 << (K-6)); } else { D = 1; } if(!VDInit){ for(i=0;i<(1<> (N-j-1)) & 1][symbols[j]]; } } symbols += N; /* Run the add-compare-select operations */ mask = 1; for(i=0;i< 1 << (K-1);i+=2){ int b1,b2; b1 = mets[Syms[i]]; nmetric[i] = m0 = cmetric[i/2] + b1; b2 = mets[Syms[i+1]]; b1 -= b2; m1 = cmetric[(i/2) + (1<<(K-2))] + b2; if(m1 > m0){ nmetric[i] = m1; *pp |= mask; } m0 -= b1; nmetric[i+1] = m0; m1 += b1; if(m1 > m0){ nmetric[i+1] = m1; *pp |= mask << 1; } mask <<= 2; if(mask == 0){ mask = 1; pp++; } } if(mask != 1){ pp++; } if(++bitcnt == nbits){ *metric = nmetric[endstate]; break; } memcpy(cmetric,nmetric,sizeof(cmetric)); } /* Chain back from terminal state to produce decoded data */ if(data == NULL) return 0;/* Discard output */ memset(data,0,(nbits+7)/8); /* round up in case nbits % 8 != 0 */ for(i=nbits-1;i >= 0;i--){ pp -= D; if(pp[endstate >> 5] & (1 << (endstate & 31))){ endstate |= (1 << (K-1)); data[i>>3] |= 0x80 >> (i&7); } endstate >>= 1; } return 0; }