#!/usr/bin/perl
# Converts a register-file from Chipcon SmartRF Studio software into two
# _useable_ headers, that can be directly include into a project.
#
# See also: chbaudrate.sh   - a wrapper script
#
# Copyright (C) 2005 Thor Andreassen <ta@imada.sdu.dk> 
#
# $Id: smartrf2headerfile.pl 214 2005-10-03 22:41:57Z anders $
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

use strict;
use warnings;
use File::Basename;

sub smartrf2header;
sub gendefine;

my $registersfile = "cc1000registers.h";
my $definesfile = "cc1000defines.h";

my $rxtx;
my $line;
my $smartrffile = "/dev/stdin";
my $CC1000REGISTERS = uc $registersfile; $CC1000REGISTERS =~ s/\.H$/_H/;
my $CC1000DEFINES   = uc $definesfile;   $CC1000DEFINES   =~ s/\.H$/_H/;
my $HEX = "[0-9A-F]";

my $usagemsg = "
Reads a CC1000 SmartRF(R) file from stdin and returns ANSI C compatible
short array, which can be parsed directly to the library provided by
Chipcon inc.
";

$smartrffile = $ARGV[0] if defined $ARGV[0];

$_ = "";
open SMARTRF, "$smartrffile" or die "$!"; 
while($line = <SMARTRF>) { $_ .= $line; }
close SMARTRF;

open REGISTERS, ">$registersfile" or die "$!";
open DEFINES,   ">$definesfile" or die "$!";

# Make user aware that the file was generated (by this script)
my $gen_msg = "/* This file was generated with " . basename($0) . " */\n\n";
print REGISTERS $gen_msg;
print DEFINES $gen_msg;

# Surround the definitions with cpp ifdefs so that we
# avoid redefining/redeclaring things
print REGISTERS "#ifndef $CC1000REGISTERS\n";
print REGISTERS "#define $CC1000REGISTERS 1\n\n";
print DEFINES   "#ifndef $CC1000DEFINES\n";
print DEFINES   "#define $CC1000DEFINES 1\n\n";

s/\r//gm;	# unixify ;-)

s/^\W+.*$//gm; # rm column names
s/^\s*//gm;    # rm blank or white space filled lines

# clone input
my $RX = $_;
my $TX = $_;

# Take care of the defines
while(/^09\s+($HEX{2})\s+(\w{2})/gmi) {
	$rxtx = ($2 eq "TX")? "TX": "RX";
	print DEFINES gendefine("${rxtx}_CURRENT", $1);
}

/^0B\s+($HEX{2})/gmi;
print DEFINES gendefine("PA_VALUE", $1);

while(/^0C\s+($HEX{2})\s+(\w{2})/gmi) {
	$rxtx = ($2 eq "TX")? "TX": "RX";
	print DEFINES gendefine("${rxtx}_PLL", $1);
}

# Take care of the configuration arrays
print REGISTERS smartrf2header($RX, "rx") . "\n";
print REGISTERS smartrf2header($TX, "tx");

print REGISTERS "\n#endif  /* $CC1000REGISTERS */\n";
print DEFINES   "\n#endif /* $CC1000DEFINES */\n";

close REGISTERS;
close DEFINES;


## Function definitions ##

# parse SmartRF(R) input and generate a short array which can be
# used directly with Chipcons library (application note 009)
sub smartrf2header {
	my $i = 1;
	my $mode; 
	my $str = "short ";
	($_, $mode) = @_;

	$str .= $mode . "_regs[] = {\n  ";

	/^($HEX{2})\s+($HEX{2})\s+$mode/mi;
	$str .= "0x" . sprintf("%02x", hex($1) * 2) . $2 . ", ";

	s/^00.+\n//mg; # rm main register modes

	if ($mode eq "rx") { # filter lines according to mode, 'TX' vs 'else'
		s/^.*tx\n//img;
	} else {
		s/^.*else\n//img;
	}

	while(/^($HEX{2})\s+($HEX{2})/gmi) {
		$str .= "0x" . sprintf("%02X", hex($1) * 2) . $2 . ", ";
		if(++$i % 4 == 0) { $str .= "\n  "; }
	}
	chop $str; chop $str;  # remove ',' and blank
	$str .= "\n};\n"; # end the declaration

	$str = "uint8_t ".$mode."_numregs = ". $i.";\n" . $str;

	return $str;
}

# generate a define string based on the arguments given
sub gendefine {
	return "#define $_[0] 0x$_[1]\n";
}
## End function definitions ##

