#!/usr/bin/perl -w 

# collect_data_16ch.pl

# 6 April 2015

# This script just runs in the following order:
# 1. generate_plot_data_16add.pl
# 2. generate_plot_data_16add_bot.pl

# Then it takes the output of these two files and combines them.
# First file:
# 1 2 3 4 5 6 7 8

# Second file
# 9 A B C D E F 0

# Output
# 1 2 3 4 5 6 7 8 9 A B C D E F 0

# Check that have the correct number of strings on the input line
if ($#ARGV != 2)
{
	print "Usage:  collect_data_16ch.pl <slot> <number of words to read> <output file>\n";
	exit(1);
}

# START OF generate_plot_data_16add.pl

# Setup some variables for items that might change in the future
@ADDRESSES = ("100000","200000","300000","400000","500000","600000","700000","800000","900000","A00000","B00000","C00000","D00000","E00000","F00000","1000000"); # Addresses to read

# Get slot of the board
$SLOT = $ARGV[0];
# Get the number of words to read
$WORDS = $ARGV[1];

# Get the output file name and open a stream to that file
$output = $ARGV[2];
open (TMPFILE, ">v4.out");


### OLD collect_data_v4_16Ch.pl
print "\nRunning initial vme write commands\n";
`./vme7700 write $SLOT 3c 1`;
`./vme7700 write $SLOT 44 1`;
`./vme7700 write $SLOT 48 1`;
`./vme7700 write $SLOT 14 1`;



`./vme7700 write $SLOT 44 1`;
`./vme7700 write $SLOT 48 1`;



`./vme7700 write $SLOT 4 40`;
`./vme7700 write $SLOT 8 1400`;
`./vme7700 write $SLOT c ffff`;
`./vme7700 write $SLOT 10 20`;
`./vme7700 write $SLOT 34 1`;

print "\nRunning initial vme read commands\n";
`./vme7700 read $SLOT 0`;
`./vme7700 read $SLOT 4`;
`./vme7700 read $SLOT 8`;
`./vme7700 read $SLOT c`;
`./vme7700 read $SLOT 10`;

`./vme7700 write $SLOT 3c 0`;

print "\nFinished initial vme read commands\n";

# First step is to prepare the board

`./vme7700 write $SLOT 34 0`;
`sleep 1`;

print "\nRunning vme7700 write $SLOT 3c 1\n";
# Start of runme_bilbo_slot10------------------
`./vme7700 write $SLOT 3c 1`;

print "\nRunning vme7700 read $SLOT 3c\n";
`./vme7700 read $SLOT 3c`;

print "\nReading data from addresses...\n";

$channel = 0;

foreach $address (@ADDRESSES)
{
	# Print address for debug
	print "$address\n";

	# Initialize $i for arrays
	$i = 0;

	# Put all the hexvalues in a variable hexvalues
	@hexvalues = `./vme7700_block read $SLOT $address $WORDS`;
	
	# There are two channels read with each block, so use nextchannel as well as channel
	$nextchannel = $channel + 1;

	foreach $value (@hexvalues)
	{
		# Convert each hex value to dec and break up by channel
		# 001122aa => 0011 is for channel 1, and 22aa is for channel 0
		$hex1=substr($value,0,4);
		$hex2=substr($value,4,4);
		$data[$channel][$i]=hex($hex2);
		$data[$nextchannel][$i]=hex($hex1);
		$i++;
	}
	$channel=$channel+2;
}	

# Write a 0 to 3c and read again
print "Running vme7700 write $SLOT 3c 0\n";
# Start of runme_bilbo_slot10------------------
`./vme7700 write $SLOT 3c 0`;

print "\nRunning vme7700 read $SLOT 3c\n";
`./vme7700 read $SLOT 3c`;

print "\nReset the board";
`./vme7700 write $SLOT 3c 1`;
`./vme7700 write $SLOT 44 1`;
`./vme7700 write $SLOT 3c 0`;

# Write the data array to the output file, remember to increment by 2
print "\nWriting the output file...\n";

for( $j=0; $j<$WORDS; $j++)
{
	for($ch=0; $ch<$channel; $ch++)
	{
		print TMPFILE "$data[$ch][$j]\t";
	}
	print TMPFILE "\n";
}

close TMPFILE;

# Now have a file (v4.out) that looks like this:
# 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320

## END of old collect_data_v4_16Ch

## START collect_data_v5.pl
# Rearrange above output to look like this:
#
# 40	80		120		160  200  240  280  320
# 30	70		110		150  190  230  270  310
# 20	60		100		140  180  220  260  300
# 10	50		90		130  170  210  250  290

open (TMPFILE, "v4.out");
open (TMPFILE2, ">v5.out");

while ($value=<TMPFILE>)
{
	chop $value;
 	my @a = split(" ",$value);
	print TMPFILE2 "$a[3]\t$a[7]\t$a[11]\t$a[15]\t$a[19]\t$a[23]\t$a[27]\t$a[31]\n";
	print TMPFILE2 "$a[2]\t$a[6]\t$a[10]\t$a[14]\t$a[18]\t$a[22]\t$a[26]\t$a[30]\n";
	print TMPFILE2 "$a[1]\t$a[5]\t$a[9]\t$a[13]\t$a[17]\t$a[21]\t$a[25]\t$a[29]\n";
	print TMPFILE2 "$a[0]\t$a[4]\t$a[8]\t$a[12]\t$a[16]\t$a[20]\t$a[24]\t$a[28]\n";
}	

close TMPFILE;
close TMPFILE2;

## END of collect_data_v5

# START reverse_bit_11.pl

# sample INPUT DATA (this input is produced as the output from collect_data_v5.pl)
# 2735	2277	2286	2275 1  2  3  4
# 2724	2276	2284	2269 5  6  7  8
# 823	2278	2283	2273 9  10 11 12
# 843	2275	2283	2270 13 14 15 16
# 276	2277	2288	2275 17 18 19 20

# Above  
# 687 229 238 227 2049 2050 2051 2052
# 676 228 236 221 2053 2054 2055 2056
# 311 230 235 225 2057 2058 2059 2060
# 331 227 235 222 2061 2062 2063 2064
# 20 229 240 227  2065 2066 2067 2068

# This script reads in these values, changes them to binary, reverses the
# first bit and changes the number back to decimal.

# EXAMPLE
# For the first value above (2735)
# 1.  Change to binary 101010101111
# 2.  Reverses the first bit 001010101111
#     Note that Mircea calls this bit[11], but in the array here, it's in the 0 position
# 3.  Convert that number back to decimal (687) and write it to a new file.

open (TMPFILE2, "v5.out");
open (OUTFILE, ">top.out");

while($value = <TMPFILE2>)
{
	chomp $value;  # Delete any carriage returns at the end of the line
	my @array = split(" ", $value); # Split the line read in to an array $array[0]=687, $array[1]=229, etc.
	my $size = @array; # Get the size of @array to use in the next loop statement
	for ($i = 0; $i < $size; $i++) # For each element in @array, do the following:
	{
		my $bin = sprintf("%014b", $array[$i]); # Convert the number to binary
		my @bits = split(//,$bin); # Split each digit into an entry in @bits array
		# Reverse the value of the first bit (Mircea's bit 11, the array's bit 0)
		if ($bits[0] == 0)
		{
			$bits[0] = 1;
		} else {
			$bits[0] = 0;
		}
		local $" = '', # Set the space want between each bit when turn it back into a string
		$swapped = "@bits"; # Turn the values in @bits into a string, which is the binary number
		$dec = bin2dec($swapped); # Convert the binary number to a decimal number (function at bottom)
		print OUTFILE "$dec "; # Write the value to the output file
	}
	print OUTFILE "\n"; # Write a return to the output value when finish converting all the values on the line
}

close TMPFILE2; # Close the input file
close OUTFILE; # Close the output file

# END OF generate_plot_data_16add.pl

# START OF generate_plot_data_16add_bot.pl

# Setup some variables for items that might change in the future
@ADDRESSES = ("2100000","2200000","2300000","2400000","2500000","2600000","2700000","2800000","2900000","2A00000","2B00000","2C00000","2D00000","2E00000","2F00000","3000000"); # Addresses to read

# Get slot of the board
$SLOT = $ARGV[0];
# Get the number of words to read
$WORDS = $ARGV[1];

# Get the output file name and open a stream to that file
$output = $ARGV[2];
open (TMPFILE, ">v4.out");


### OLD collect_data_v4_16Ch.pl
print "\nRunning initial vme write commands\n";
`./vme7700 write $SLOT 400003c 1`;
`./vme7700 write $SLOT 4000044 1`;
`./vme7700 write $SLOT 4000048 1`;
`./vme7700 write $SLOT 4000014 1`;



`./vme7700 write $SLOT 4000044 1`;
`./vme7700 write $SLOT 4000048 1`;



`./vme7700 write $SLOT 4000004 40`;
`./vme7700 write $SLOT 4000008 1400`;
`./vme7700 write $SLOT 400000c ffff`;
`./vme7700 write $SLOT 4000010 20`;
`./vme7700 write $SLOT 4000034 1`;

print "\nRunning initial vme read commands\n";
`./vme7700 read $SLOT 4000000`;
`./vme7700 read $SLOT 4000004`;
`./vme7700 read $SLOT 4000008`;
`./vme7700 read $SLOT 400000c`;
`./vme7700 read $SLOT 4000010`;

`./vme7700 write $SLOT 400003c 0`;

print "\nFinished initial vme read commands\n";

# First step is to prepare the board

`./vme7700 write $SLOT 4000034 0`;
`sleep 1`;

print "\nRunning vme7700 write $SLOT 3c 1\n";
# Start of runme_bilbo_slot10------------------
`./vme7700 write $SLOT 400003c 1`;

print "\nRunning vme7700 read $SLOT 3c\n";
`./vme7700 read $SLOT 400003c`;

print "\nReading data from addresses...\n";

$channel = 0;

foreach $address (@ADDRESSES)
{
	# Print address for debug
	print "$address\n";

	# Initialize $i for arrays
	$i = 0;

	# Put all the hexvalues in a variable hexvalues
	@hexvalues = `./vme7700_block read $SLOT $address $WORDS`;
	
	# There are two channels read with each block, so use nextchannel as well as channel
	$nextchannel = $channel + 1;

	foreach $value (@hexvalues)
	{
		# Convert each hex value to dec and break up by channel
		# 001122aa => 0011 is for channel 1, and 22aa is for channel 0
		$hex1=substr($value,0,4);
		$hex2=substr($value,4,4);
		$data[$channel][$i]=hex($hex2);
		$data[$nextchannel][$i]=hex($hex1);
		$i++;
	}
	$channel=$channel+2;
}	

# Write a 0 to 3c and read again
print "Running vme7700 write $SLOT 3c 0\n";
# Start of runme_bilbo_slot10------------------
`./vme7700 write $SLOT 400003c 0`;

print "\nRunning vme7700 read $SLOT 3c\n";
`./vme7700 read $SLOT 400003c`;

print "\nReset the board";
`./vme7700 write $SLOT 400003c 1`;
`./vme7700 write $SLOT 4000044 1`;
`./vme7700 write $SLOT 400003c 0`;

# Write the data array to the output file, remember to increment by 2
print "\nWriting the output file...\n";

for( $j=0; $j<$WORDS; $j++)
{
	for($ch=0; $ch<$channel; $ch++)
	{
		print TMPFILE "$data[$ch][$j]\t";
	}
	print TMPFILE "\n";
}

close TMPFILE;

# Now have a file (v4.out) that looks like this:
# 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320

## END of old collect_data_v4_16Ch

## START collect_data_v5.pl
# Rearrange above output to look like this:
#
# 40	80		120		160  200  240  280  320
# 30	70		110		150  190  230  270  310
# 20	60		100		140  180  220  260  300
# 10	50		90		130  170  210  250  290

open (TMPFILE, "v4.out");
open (TMPFILE2, ">v5.out");

while ($value=<TMPFILE>)
{
	chop $value;
 	my @a = split(" ",$value);
	print TMPFILE2 "$a[3]\t$a[7]\t$a[11]\t$a[15]\t$a[19]\t$a[23]\t$a[27]\t$a[31]\n";
	print TMPFILE2 "$a[2]\t$a[6]\t$a[10]\t$a[14]\t$a[18]\t$a[22]\t$a[26]\t$a[30]\n";
	print TMPFILE2 "$a[1]\t$a[5]\t$a[9]\t$a[13]\t$a[17]\t$a[21]\t$a[25]\t$a[29]\n";
	print TMPFILE2 "$a[0]\t$a[4]\t$a[8]\t$a[12]\t$a[16]\t$a[20]\t$a[24]\t$a[28]\n";
}	

close TMPFILE;
close TMPFILE2;

## END of collect_data_v5

# START reverse_bit_11.pl

# sample INPUT DATA (this input is produced as the output from collect_data_v5.pl)
# 2735	2277	2286	2275 1  2  3  4
# 2724	2276	2284	2269 5  6  7  8
# 823	2278	2283	2273 9  10 11 12
# 843	2275	2283	2270 13 14 15 16
# 276	2277	2288	2275 17 18 19 20

# Above  
# 687 229 238 227 2049 2050 2051 2052
# 676 228 236 221 2053 2054 2055 2056
# 311 230 235 225 2057 2058 2059 2060
# 331 227 235 222 2061 2062 2063 2064
# 20 229 240 227  2065 2066 2067 2068

# This script reads in these values, changes them to binary, reverses the
# first bit and changes the number back to decimal.

# EXAMPLE
# For the first value above (2735)
# 1.  Change to binary 101010101111
# 2.  Reverses the first bit 001010101111
#     Note that Mircea calls this bit[11], but in the array here, it's in the 0 position
# 3.  Convert that number back to decimal (687) and write it to a new file.

open (TMPFILE2, "v5.out");
open (OUTFILE, ">bot.out");

while($value = <TMPFILE2>)
{
	chomp $value;  # Delete any carriage returns at the end of the line
	my @array = split(" ", $value); # Split the line read in to an array $array[0]=687, $array[1]=229, etc.
	my $size = @array; # Get the size of @array to use in the next loop statement
	for ($i = 0; $i < $size; $i++) # For each element in @array, do the following:
	{
		my $bin = sprintf("%014b", $array[$i]); # Convert the number to binary
		my @bits = split(//,$bin); # Split each digit into an entry in @bits array
		# Reverse the value of the first bit (Mircea's bit 11, the array's bit 0)
		if ($bits[0] == 0)
		{
			$bits[0] = 1;
		} else {
			$bits[0] = 0;
		}
		local $" = '', # Set the space want between each bit when turn it back into a string
		$swapped = "@bits"; # Turn the values in @bits into a string, which is the binary number
		$dec = bin2dec($swapped); # Convert the binary number to a decimal number (function at bottom)
		print OUTFILE "$dec "; # Write the value to the output file
	}
	print OUTFILE "\n"; # Write a return to the output value when finish converting all the values on the line
}

close TMPFILE2; # Close the input file
close OUTFILE; # Close the output file

# END OF generate_plot_data_16add_bot.pl

# Start of combining files (top.out and bot.out)
# Simply use linux paste command
`paste top.out bot.out > $output`;


# Convert a binary number to a decimal number (I didn't write this, but it does the job)
sub bin2dec {
	unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}
