⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 viterbi.c

📁 这是用python语言写的一个数字广播的信号处理工具包。利用它
💻 C
字号:
/* * Copyright 1995 Phil Karn, KA9Q * Copyright 2008 Free Software Foundation, Inc. *  * This file is part of GNU Radio *  * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. *  * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. *//*  * Viterbi decoder for K=7 rate=1/2 convolutional code * Some modifications from original Karn code by Matt Ettus */#include "viterbi.h"/* The two generator polynomials for the NASA Standard K=7 code. * Since these polynomials are known to be optimal for this constraint * length there is not much point in changing them. But if you do, you * will have to regenerate the BUTTERFLY macro calls in viterbi() */#define	POLYA	0x6d#define	POLYB	0x4f/* The basic Viterbi decoder operation, called a "butterfly" * operation because of the way it looks on a trellis diagram. Each * butterfly involves an Add-Compare-Select (ACS) operation on the two nodes * where the 0 and 1 paths from the current node merge at the next step of * the trellis. * * The code polynomials are assumed to have 1's on both ends. Given a * function encode_state() that returns the two symbols for a given * encoder state in the low two bits, such a code will have the following * identities for even 'n' < 64: * * 	encode_state(n) = encode_state(n+65) *	encode_state(n+1) = encode_state(n+64) = (3 ^ encode_state(n)) * * Any convolutional code you would actually want to use will have * these properties, so these assumptions aren't too limiting. * * Doing this as a macro lets the compiler evaluate at compile time the * many expressions that depend on the loop index and encoder state and * emit them as immediate arguments. * This makes an enormous difference on register-starved machines such * as the Intel x86 family where evaluating these expressions at runtime * would spill over into memory. */#define	BUTTERFLY(i,sym) { \	int m0,m1;\\	/* ACS for 0 branch */\	m0 = state[i].metric + mets[sym];	/* 2*i */\	m1 = state[i+32].metric + mets[3^sym];	/* 2*i + 64 */\	if(m0 > m1){\		next[2*i].metric = m0;\		next[2*i].path = state[i].path << 1;\	} else {\		next[2*i].metric = m1;\		next[2*i].path = (state[i+32].path << 1)|1;\	}\	/* ACS for 1 branch */\	m0 = state[i].metric + mets[3^sym];	/* 2*i + 1 */\	m1 = state[i+32].metric + mets[sym];	/* 2*i + 65 */\	if(m0 > m1){\		next[2*i+1].metric = m0;\		next[2*i+1].path = state[i].path << 1;\	} else {\		next[2*i+1].metric = m1;\		next[2*i+1].path = (state[i+32].path << 1)|1;\	}\}extern unsigned char Partab[];	/* Parity lookup table *//* Convolutionally encode data into binary symbols */unsigned charencode(unsigned char *symbols,       unsigned char *data,       unsigned int nbytes,       unsigned char encstate){  int i;    while(nbytes-- != 0){    for(i=7;i>=0;i--){      encstate = (encstate << 1) | ((*data >> i) & 1);      *symbols++ = Partab[encstate & POLYA];      *symbols++ = Partab[encstate & POLYB];    }    data++;  }    return encstate;}/* Viterbi decoder */intviterbi(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 bitcnt = 0;  int mets[4];  long bestmetric;  int beststate,i;  struct viterbi_state state0[64],state1[64],*state,*next;    state = state0;  next = state1;    /* Initialize starting metrics to prefer 0 state */  state[0].metric = 0;  for(i=1;i<64;i++)    state[i].metric = -999999;  state[0].path = 0;    for(bitcnt = 0;bitcnt < nbits;bitcnt++){    /* Read input symbol pair and compute all possible branch     * metrics     */    mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]];    mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]];    mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]];    mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]];    symbols += 2;    /* These macro calls were generated by genbut.c */    BUTTERFLY(0,0);    BUTTERFLY(1,1);    BUTTERFLY(2,3);    BUTTERFLY(3,2);    BUTTERFLY(4,3);    BUTTERFLY(5,2);    BUTTERFLY(6,0);    BUTTERFLY(7,1);    BUTTERFLY(8,0);    BUTTERFLY(9,1);    BUTTERFLY(10,3);    BUTTERFLY(11,2);    BUTTERFLY(12,3);    BUTTERFLY(13,2);    BUTTERFLY(14,0);    BUTTERFLY(15,1);    BUTTERFLY(16,2);    BUTTERFLY(17,3);    BUTTERFLY(18,1);    BUTTERFLY(19,0);    BUTTERFLY(20,1);    BUTTERFLY(21,0);    BUTTERFLY(22,2);    BUTTERFLY(23,3);    BUTTERFLY(24,2);    BUTTERFLY(25,3);    BUTTERFLY(26,1);    BUTTERFLY(27,0);    BUTTERFLY(28,1);    BUTTERFLY(29,0);    BUTTERFLY(30,2);    BUTTERFLY(31,3);        /* Swap current and next states */    if(bitcnt & 1){      state = state0;      next = state1;    } else {      state = state1;      next = state0;    }    // ETTUS    //if(bitcnt > nbits-7){    /* In tail, poison non-zero nodes */    //for(i=1;i<64;i += 2)    //	state[i].metric = -9999999;    //}    /* Produce output every 8 bits once path memory is full */    if((bitcnt % 8) == 5 && bitcnt > 32){      /* Find current best path */      bestmetric = state[0].metric;      beststate = 0;      for(i=1;i<64;i++){	if(state[i].metric > bestmetric){	  bestmetric = state[i].metric;	  beststate = i;	}      }#ifdef	notdef      printf("metrics[%d] = %d state = %lx\n",beststate,	     state[beststate].metric,state[beststate].path);#endif      *data++ = state[beststate].path >> 24;    }      }  /* Output remaining bits from 0 state */  // ETTUS  Find best state instead  bestmetric = state[0].metric;  beststate = 0;  for(i=1;i<64;i++){    if(state[i].metric > bestmetric){      bestmetric = state[i].metric;      beststate = i;    }  }  if((i = bitcnt % 8) != 6)    state[beststate].path <<= 6-i;    *data++ = state[beststate].path >> 24;  *data++ = state[beststate].path >> 16;  *data++ = state[beststate].path >> 8;  *data = state[beststate].path;  //printf ("BS = %d\tBSM = %d\tM0 = %d\n",beststate,state[beststate].metric,state[0].metric);  *metric = state[beststate].metric;  return 0;}voidviterbi_chunks_init(struct viterbi_state* state) {  // Initialize starting metrics to prefer 0 state  int i;  state[0].metric = 0;  state[0].path = 0;  for(i=1;i<64;i++)    state[i].metric = -999999;}voidviterbi_butterfly8(unsigned char *symbols, int mettab[2][256], struct viterbi_state *state0, struct viterbi_state *state1){  unsigned int bitcnt;  int mets[4];    struct viterbi_state *state, *next;  state = state0;  next = state1;  // Operate on 16 symbols (8 bits) at a time  for(bitcnt = 0;bitcnt < 8;bitcnt++){    // Read input symbol pair and compute all possible branch metrics    mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]];    mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]];    mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]];    mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]];    symbols += 2;        // These macro calls were generated by genbut.c     BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2);    BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1);    BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2);    BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1);    BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0);    BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3);    BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0);    BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3);        // Swap current and next states    if(bitcnt & 1){      state = state0;      next = state1;    } else {      state = state1;      next = state0;    }  }}voidviterbi_butterfly2(unsigned char *symbols, int mettab[2][256], struct viterbi_state *state0, struct viterbi_state *state1){  //unsigned int bitcnt;  int mets[4];    struct viterbi_state *state, *next;  state = state0;  next = state1;  // Operate on 4 symbols (2 bits) at a time    // Read input symbol pair and compute all possible branch metrics  mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]];  mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]];  mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]];  mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]];    // These macro calls were generated by genbut.c   BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2);  BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1);  BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2);  BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1);  BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0);  BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3);  BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0);  BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3);    state = state1;  next = state0;    // Read input symbol pair and compute all possible branch metrics  mets[0] = mettab[0][symbols[2]] + mettab[0][symbols[3]];  mets[1] = mettab[0][symbols[2]] + mettab[1][symbols[3]];  mets[2] = mettab[1][symbols[2]] + mettab[0][symbols[3]];  mets[3] = mettab[1][symbols[2]] + mettab[1][symbols[3]];    // These macro calls were generated by genbut.c   BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2);  BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1);  BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2);  BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1);  BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0);  BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3);  BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0);  BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3);}unsigned charviterbi_get_output(struct viterbi_state *state, unsigned char *outbuf) {  // Produce output every 8 bits once path memory is full   //  if((bitcnt % 8) == 5 && bitcnt > 32) {    //  Find current best path  unsigned int i,beststate;  int bestmetric;    bestmetric = state[0].metric;  beststate = 0;  for(i=1;i<64;i++)    if(state[i].metric > bestmetric) {      bestmetric = state[i].metric;      beststate = i;    }  *outbuf =  state[beststate].path >> 24;  return bestmetric;}//printf ("BS = %d\tBSM = %d\tM0 = %d\n",beststate,state[beststate].metric,state[0].metric);// In tail, poison non-zero nodes//if(bits_out > packet_size-7)//  for(i=1;i<64;i += 2)//    state[i].metric = -9999999;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -