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

📄 genviterbi.pl

📁 从国外ECC网站上找到的
💻 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 */
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 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 cache
if($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 + -