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

📄 genviterbi.pl

📁 维特比译码的C程序
💻 PL
字号:
# Perl script to generate C code for an encoder and# a Viterbi decoder for any specified rate 1/N, constraint length k <= 16# convolutional code.## Not recommended for large K codes, as it will generate a *very* large# program!# 24 October 1997 Phil Karn, KA9Q# Here are the polynomials for some optimum convolutional codes. Select only one# by uncommenting it# Rate 1/2 codes#@polys = (0x7,0x5);		# k=3#@polys = (0xf,0xb);		# k=4#@polys = (0x17, 0x19);		# k=5#@polys = (0x13, 0x1b);		# k=5, used in GSM?#@polys = (0x2f, 0x35);		# k=6@polys = (0x6d,0x4f);		# k=7; very popular with NASA and industry#@polys = (0x9f, 0xe5);		# k=8#@polys = (0x1af, 0x11d);	# k=9; used in IS-95 CDMA#@polys = (0x45dd, 0x69e3);	# k = 15# Rate 1/3 codes#@polys = (0x7, 0x7, 0x5);	#k = 3#@polys = (0xf, 0xb, 0xd);	#k = 4#@polys = (0x1f, 0x1b, 0x15);	#k = 5#@polys = (0x2f, 0x35, 0x39);	#k = 6#@polys = (0x4f, 0x57, 0x6d);	#k = 7; also popular with NASA and industry#@polys = (0xef, 0x9b, 0xa9);	#k = 8#@polys = (0x1ed, 0x19b, 0x127); #k = 9; used in IS-95 CDMA# end of user-configurable stuff# Figure out constraint length by looking at the polynomials$bar = 0;foreach $i (@polys){	$bar |= $i;}$k = 0;while($bar != 0){	$k++;	$bar >>= 1;}die "Max K=16 supported" if ($k > 16);$nsym = @polys;$nmets = 1 << $nsym;$smask = $nmets - 1;$K = 1 << ($k - 1);if($K/32 >= 1){	$D = $K/32;} else {	$D = 1;}print "unsigned char Partab[] = { ";for $i (0 ... 255) {	print parity($i),",";}print "};";print "/* Convolutional encoder */encode(unsigned char *symbols,unsigned char *data,unsigned int nbytes){	unsigned int encstate;	int i;	encstate = 0;	while(nbytes-- != 0){		for(i=7;i>=0;i--){			encstate = (encstate << 1) | ((*data >> i) & 1);\n";foreach $poly (@polys) {	if($k <= 8){		print "\t\t\t*symbols++ = Partab[encstate & $poly];\n";	} elsif($k <= 16){		print "\t\t\t*symbols++ = Partab[((encstate & $poly) ^ ((encstate & $poly) >> 8)) & 0xff];\n";	}}	print "\t\t}		data++;	}	return 0;}\n";print "/* 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 beststate,i;	long cmetric[$K],nmetric[$K];	register int m0,m1;	/* This next line is arguably illegal C, but it works on	 * GCC and it avoids having to reference this heavily used	 * array through a pointer. If you can't compile this, use malloc.	 */	unsigned long paths[nbits*",$D,"*sizeof(unsigned long)];	unsigned long *pp;	unsigned long dec;	int mets[$nmets];		pp = paths;	/* Initialize starting metrics to prefer 0 state */	cmetric[0] = 0;	for(i=1;i<$K;i++)		cmetric[i] = -999999;	for(;;){\n";emitbits(0);# Too much loop unrolling, and we blow out of the Pentium instruction cacheif($k <= 7) {	emitbits(1);} else {	print "\t\tmemcpy(cmetric,nmetric,",$K*4,");\n";}print"\t}	pp -= ",$D,";	/* Chain back from terminal state to produce decoded data */	memset(data,0,nbits/8);	for(i=nbits-$k;i >= 0;i--){		if(pp[beststate >> 5] & (1 << (beststate & 31))){			beststate |= $K;	/* 2^(K-1) */			data[i>>3] |= 0x80 >> (i&7);		}		beststate >>= 1;		pp -= ",$D,";	}	return 0;}\n";exit;sub emit_butterfly(@) {	my $source,$dest,$sym,$odd,$i,$j;	$i = shift;	$j = $i * 2;	$odd = shift;	$sym = shift;	if($odd){		$source = "nmetric";		$dest = "cmetric";	} else {		$source = "cmetric";		$dest = "nmetric";	}print "\t\t/* state $i, symbols ", bsplit($sym,$nsym)," */		m0 = $source\[$i] + mets[$sym];		m1 = $source\[",($i+$K/2),"] + mets[",$smask ^ $sym,"];		$dest\[",2*$i,"] = m0;		if(m1 > m0){			$dest\[",2*$i,"] = m1;			dec |= ";printf "0x%lx",1 << ((2*$i) & 31);print					";		}		m0 -= (mets[$sym] - mets[",$smask^$sym,"]);		m1 += (mets[$sym] - mets[",$smask^$sym,"]);		$dest\[",2*$i+1,"] = m0;		if(m1 > m0){			$dest\[",2*$i+1,"] = m1;			dec |= ";printf "0x%lx",1 << ((2*$i+1) & 31);print					";		}"}sub emitbits(@) {	my $sym;	$odd = shift;	if($odd){		$dest = "cmetric";	} else {		$dest = "nmetric";	}	foreach $i (0 ... $nmets-1){		print "\t\tmets[$i] = ";		@symbits = bsplit($i,$nsym);		print "mettab[",pop @symbits,"][symbols[0]]";		foreach $j (1 ... $nsym-1){			print " + mettab[",pop @symbits,"][symbols[$j]]";		}		print ";\n";	}	print "\t\tsymbols += $nsym;\n";	foreach $i (0 ... $K/2-1){		$sym = 0;		foreach $p (@polys){			$sym = $sym * 2 + parity((2*$i & $p));		}		push @stuff,join ' ',$sym,$i;		if(($i % 16) == 15){			print "\t\tdec = 0;\n";			foreach $sym (sort @stuff){				@a = split(' ',$sym);				emit_butterfly($a[1],$odd, $a[0]);			}			@stuff = ();			print "\t\t*pp++ = dec;\n";		}	}	if($K/2 < 16){			print "\t\tdec = 0;\n";			foreach $sym (sort @stuff){				@a = split(' ',$sym);				emit_butterfly($a[0],$odd, $a[1]);			}			@stuff = ();			print "\t\t*pp++ = dec;\n";	}	print "\t\tif(++bitcnt == nbits){			beststate = 0;			*metric = $dest\[beststate];			break;		}\n";}sub bsplit(){	$x = shift;	$n = shift;	my @ret;	while($n-- > 0){		push @ret,($x & 1);		$x = $x >> 1;	}	return @ret;}sub parity(){	$x = shift;	$x ^= ($x >> 16);	$x ^= ($x >> 8);	$x ^= ($x >> 4);	$x ^= ($x >> 2);	$x ^= ($x >> 1);	return ($x & 1);}

⌨️ 快捷键说明

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