# --COPYRIGHT--,BSD
#  Copyright (c) 2012, Texas Instruments Incorporated
#  All rights reserved.
# 
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
# 
#  *  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 
#  *  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
# 
#  *  Neither the name of Texas Instruments Incorporated nor the names of
#     its contributors may be used to endorse or promote products derived
#     from this software without specific prior written permission.
# 
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
#  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# --/COPYRIGHT--

#Perl script used to convert MSP430 .txt to C array in .h file
# format:
#   perl 430txt2c.pl src dest struct
#       src:    Source file in MSP430 .txt format
#       dest:   Destination file in .h format
#       struct: Name of output array
#


## Get input parameters
print( "\n 430txt2c.pl V1.2 \n");
print( "Texas Instruments Inc 2013 \n");

## Check if input parameters are OK
if( ( $#ARGV ) != 2 )
{
	print( "\nThis script converts an MSP430 .txt file to C array \n" );
	print( "\nUsage: \n" );
	print( "\nperl 430txt2c.pl src dest struct\n" );
	print( "\n\tsrc\t.MSP430 txt source file\n" );
	print( "\tdest\t.H file to be generated\n" );
	print( "\tstruct\tC structure\n" );
    die;
}

$file430  = $ARGV[0];
$fileH    = $ARGV[1];
$struct  = $ARGV[2];
$AddrArray;
$SizeArray;
$DataArray;
$SegmentArray;
$total_segments = 0;
$total_data_in_seg =0;
$total_data_in_file =0;

###############
# Process Input
# Get all MSP430 .txt lines
##############################
open( InFile, $file430   ) || die "Cannot open source file: $file430 \n";
while( $txtline = <InFile> )
{
    #print ($txtline);
    $ret = process_line();
   if ($ret == 0)
    {
    }

}
close_segment();    # Close last segment

###############
# Process Output
# Send to .h file
##############################
# open file to write to
open( OutFile, ">$fileH" ) || die "Cannot open destination file: $ARGV[1]\n";
##### File Header
    print OutFile ( "//\n" );
    print OutFile ("// Filename: ", $fileH, "\n");
    print OutFile ("// Generated from ", $file430, "\n");
##### File Time
    print OutFile ("// ".localtime."\n\n\n");
##### include file
    print OutFile ("#include <stdint.h>\n\n\n");
##### define size
    print OutFile ("#define ".$struct."_SIZE   ".$total_data_in_file."\n\n");
##### Address Array
    print OutFile ("const uint16_t ".$struct."_Addr[".$total_segments."] = {\n");
    print OutFile ($AddrArray."};\n\n");
##### Size Array
    print OutFile ("const uint16_t ".$struct."_Size[".$total_segments."] = {\n");
    print OutFile ($SizeArray."};\n\n");
##### Data Array
	for ($i=0; $i < $total_segments; $i+=1)
        {
			print OutFile ("const uint8_t ".$struct."_".$i."[] = {\n");
			print OutFile ($DataArray[$i]."};\n\n");
        }

##### Pointer Array
    print OutFile ("const uint8_t *".$struct."_Ptr[".$total_segments."] = {\n");
    for ($i=0; $i < $total_segments; $i+=1)
        {
			print OutFile ($struct."_".$i.",\n");
        }
	print OutFile ("};\n\n");

print "\n********File ".$fileH." generated OK! ***********\n";
    #print "\nFile ".$fileH." generated OK!\nPress Enter to close\n\n\n";
#<STDIN>;

###############
# Sub-routines
##############################
sub close_segment {
	$SizeArray = $SizeArray.$total_data_in_seg.",   // Size segment".($total_segments-1)."\n";
	$total_data_in_file+=$total_data_in_seg;
    $total_data_in_seg = $total_data_in_seg/2;
    #$DataArray = $DataArray."    ".$total_data_in_seg.",\t//Number of words in segment\n";
    $DataArray[$total_segments-1] = $SegmentArray;
	#print "\nSegment".($total_segments-1)."\n";
	#print $SegmentArray;
	#print $DataArray[$total_segments-1];
    # start next segment
    $total_data_in_seg = 0;
    $SegmentArray = "";
}

sub process_line {
    if( $txtline =~ m/^@/ ) # does string start @
    {
        # Address
        $addr = hex( substr( $txtline, 1, 6 ) );
        $addrhex = sprintf("    0x%x", $addr);
        $AddrArray = $AddrArray.$addrhex.",\t// Address segment".$total_segments."\n";
        # close previous segment
        if ($total_segments > 0)
        {
            close_segment();
        }
        $total_segments++ ;
    }
    elsif ( $txtline =~m/^(1|2|3|4|5|6|7|8|9|0|A|B|C|D|E|F)/i )
    {
        # Data
        #print ("Data: ", $txtline, "\n");
        $txt_count = $txtline;
        $count = $txt_count =~ s/((1|2|3|4|5|6|7|8|9|0|A|B|C|D|E|F))(1|2|3|4|5|6|7|8|9|0|A|B|C|D|E|F)./$1/sg;
        #print ("Count: ", $count, "\n");
        $total_data_in_seg += $count;
        for ($i=0; $i < $count; $i+=2)
        {
            $SegmentArray = $SegmentArray.sprintf("0x%02x,0x%02x,", hex( substr( $txtline, $i*3, 2 ) ), hex( substr( $txtline, $i*3+3, 2 )) );
        }
        $SegmentArray = $SegmentArray."\n";
        #print ("Data Array:".$SegmentArray);

    }
    else
    {
        #not address or data
        return 1;
    }

    return 0;
}
