#!/usr/bin/env perl
#
# DS comment: yes, this is a horribly ugly and long perl script... please don't look at it :-)
# if you do: first we have some global counters and constants, and then two main functions for I/O (readLogs & writeOutput)
# - and two help functions to get the info for capacitors corrections,  
#   and a conversion between voltage and current for the OpAmp's
#
use strict;
my $debug = 3; #print flag: 0=quiet, 1=basic info, 2,3=progressively more info

# I/0 variables
my $chipQRdatabasefile = "/home/tpc/work/database/chipQR.txt";
my $topdir = "../logs"; # where to store summary info
my $outputstring ="";

my ($sampadir, $station) = @ARGV; 
if (not defined $station) {
    print "Please provide sampadir and station arguments\n";
    exit;
}
print "sampadir $sampadir station $station\n"; 

my $sampastring = "sampa";
my @dirarr = split /$sampastring/, $sampadir;
my $chipnum = $dirarr[1];
if ( ($chipnum < 1) || ($chipnum > 999999) ) {
    print "invalid chipnum $chipnum derived from sampadir $sampadir argument\n";
    exit;
}
my $QRCode = `grep ^$chipnum $chipQRdatabasefile | awk '{print "SAMPA "\$NF}'`;
chomp $QRCode;
$outputstring .= "QR ${QRCode}\nChip ${chipnum}\nSta ${station}\n";

# global variables
my $nGain = 2;
my $nParity = 2;
my $nChan = 32;
my $nDCRef = 6; # 6 ref voltages 
my $nDCCurr = 5; # 5 currents

# counters for all checks
my $fileCount = 0;
my $fileCheckCount = 0;
my $dcRefCount = 0; my $dcRefErrCount = 0;
my $dcCurrCount = 0; my $dcCurrErrCount = 0;
my $syncCount = 0; my $syncErrCount = 0;
my $baselineCount = 0; my $baselineErrCount = 0; 
my $stdevCount = 0; my $stdevErrCount = 0; 
my $pedAnaCount = 0; my $pedAnaErrCount = 0; 
my $rmsAnaCount = 0; my $rmsAnaErrCount = 0; 
my $gainCount = 0; my $gainErrCount = 0; 
my $risetimeCount = 0; my $risetimeErrCount = 0; 
my $xtalkCount = 0; my $xtalkErrCount = 0; 
# RingOsc, i2c, Jtag, mem, DFT:
my $clockCount = 0; my $clockErrCount = 0;
my $i2cCount = 0; my $i2cErrCount = 0;
my $memCount = 0; my $memErrCount = 0;
my $dftCount = 0; my $dftErrCount = 0;
my $jtagCount = 0; my $jtagErrCount = 0;

########################################################
#flow of main program in 2 main functions (almost all action in the first one) 
readLogs();
writeOutput();
########################################################

sub readLogs {
# filename info
#my $initstring = "init.log"; # we do not check anything for the init
    my $runstring = "run.log";
    my $dcstring = "dc.log";
    my $miscstring = "misc.log";
    my $jtagfilestring = "jtag.log";
    my $dftstring = "dft.log"; # not yet in place
# DAQ files; different versions for different gains
    my $calibstring = "gain";
    my $noisestring = "stats";
    my $noiseAnastring = "noiseAna";
    my $xtalkstring = "xtalk";
    my $risetimestring = "rise_time";
    
    my $iChan = 0;
    my $iGain = 0;
    my @gainstring;
    $gainstring[0] = "20mV";
    $gainstring[1] = "30mV";
    my $iParity = 0;
    my @paritystring;
    $paritystring[0] = "even";
    $paritystring[1] = "odd";
    my @parityVal; # look at only the half of the channels with the right modulus values
    $parityVal[0] = 0;
    $parityVal[1] = 1;
    
# cuts on values
# DC
    my @DCValstring = ( "VDDA", "VREF", "VDD", "V450", "V600", "V750",
			"FE1_CURR", "FE2_CURR", "AD_CURR", "DR_CURR", "DG_CURR");
    my @minDCRef = ( 1.238, 1.093, 1.240, 0.450, 0.600, 0.750 );
    my @maxDCRef = ( 1.260, 1.110, 1.260, 0.520, 0.660, 0.811 );
    my @minDCACurr = ( 80.000, 50.000, 3.000, 35.000, 10.000 );
    my @maxDCACurr = ( 103.000, 80.000, 14.000, 46.000, 25.000 );

# run (sync) values
    my $SyncLowstring = "SYNC Low";
    my $SyncHighstring = "SYNC High";
    my $minSync = 200;
    my $maxSync = 300;
# noise files: different cuts for different gains
    my @minPedVal;
    $minPedVal[0] = 30;
    $minPedVal[1] = 20;
    my @maxPedVal;
    $maxPedVal[0] = 105;
    $maxPedVal[1] = 130;
    my @minRmsVal;
    $minRmsVal[0] = 0.2;
    $minRmsVal[1] = 0.2;
    my @maxRmsVal;
    $maxRmsVal[0] = 1.2;
    $maxRmsVal[1] = 2.0;

# calib files: different cuts for different gains
    my @minGainVal;
    $minGainVal[0] = 18.9;
    $minGainVal[1] = 27.5;
    my @maxGainVal;
    $maxGainVal[0] = 20.6;
    $maxGainVal[1] = 30.5;
    
# rise-time files: different cuts for different gains?
    my @minRiseTimeVal;
    $minRiseTimeVal[0] = 155;
    $minRiseTimeVal[1] = 160;
    my @maxRiseTimeVal;
    $maxRiseTimeVal[0] = 180;
    $maxRiseTimeVal[1] = 190;
    
# xtalk files: different cuts for different gains?
    my @minXtalkVal;
    $minXtalkVal[0] = -0.01;
    $minXtalkVal[1] = -0.01;
    my @maxXtalkVal;
    $maxXtalkVal[0] = 0.05;
    $maxXtalkVal[1] = 0.05;

# clockSpeed
    my $clockstring = "Clock speed";
    my $minClockSpeed = 130;
    my $maxClockSpeed = 170;
# i2c_read
    my $i2cstring = "i2c_read_errors";
    my $maxi2cReadErrors = 0;
# memory
    my $memorystring = "Memory";
    my $failstring = "failed";
# JTAG
    my $jtagstring = "JTAG";
    my $jtagErrstring = "ERROR";
# DFT
    my $mismatchstring = "mismatches";
    my $maxMismatches = 2;

    if ($debug > 0) { print "Checking logs for chip ${chipnum}:\n"; }
    my $chipstring = "sampa${chipnum}";
    my $logstring = ".log";
    open(my $fh, "-|", "ls $sampadir/*${logstring}");

# variables for reading files
    my $line = "";
    my $infostring = "";
    my $splitBracket = "\\\[";
    my $splitComma = "\,";
    my $splitColon = "\:";
    my $splitSpace = " ";

    while(my $filename = <$fh>) {
	chomp($filename);
	if ($debug > 1) { print "filename $filename\n"; }
    
	if ($filename =~ /$noisestring/) {
	    if ($debug > 1) { print "\n noise file\n"; }
	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";

#mean
	    if ($filename =~ /$gainstring[0]/) { $iGain = 0; }
	    else { $iGain = 1; }
	    $outputstring .= "Ped$gainstring[$iGain]";
	    $line = <$tfh>;
	    chop $line; chop $line; chop $line;
	    my @arr = split /$splitBracket/, $line;
	    my @baselinearr = split /$splitComma/, $arr[1];	
	    my $nBl = 0;
	    my $sumBl = 0;
	    foreach my $bl (@baselinearr) {
		my $result = sprintf("%.1f", $bl); 
		$outputstring .= " $result";
		if ($debug > 2) { print "bl $baselineCount $bl \n"; }
		if ( ($bl < $minPedVal[$iGain]) || ($bl > $maxPedVal[$iGain]) ) {
		    if ($debug > 0) { print "out-of-bounds bl $baselineCount : baseline $bl \n"; }
		    $baselineErrCount++;
		}
		$sumBl += $bl;
		$nBl++;
		$baselineCount++;
	    }
	    $outputstring .= "\n";
#stdev
	    $outputstring .= "Rms$gainstring[$iGain]";
	    $line = <$tfh>;
	    chop $line; chop $line;
	    @arr = split /$splitBracket/, $line;
	    my @stdevarr = split /$splitComma/, $arr[1];	
	    my $nStdev = 0;
	    my $sumStdev = 0;
	    foreach my $stdev (@stdevarr) {
		my $result = sprintf("%.2f", $stdev); 
		$outputstring .= " $result";
		if ($debug > 2) { print "stdev $stdevCount : $stdev \n"; }
		if ( ($stdev < $minRmsVal[$iGain]) || ($stdev > $maxRmsVal[$iGain]) ) {
		    if ($debug > 0) { print "out-of-bounds stdev $stdevCount : stdev $stdev \n"; }
		    $stdevErrCount++;
		}
		$sumStdev += $stdev;
		$nStdev++;
		$stdevCount++;
	    }
	    close $tfh;
	    $outputstring .= "\n";

	    if ($debug > 0) { 
		if ($nBl > 0) {
		    my $aveBl = $sumBl / $nBl;
		    print "aveBl $aveBl\n";
		}
		if ($nStdev > 0) {
		    my $aveStdev = $sumStdev / $nStdev;
		    print "aveStdev $aveStdev\n";
		}
		print "baselineCount $baselineCount baselineErrCount $baselineErrCount\n";
		print "stdevCount $stdevCount stdevErrCount $stdevErrCount\n";
	    }
	    $fileCheckCount++;
	} # end noise file   
	if ($filename =~ /$noiseAnastring/) {
	    if ($debug > 1) { print "\n noiseAna file\n"; }
	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";

	    if ($filename =~ /$gainstring[0]/) { $iGain = 0; }
	    else { $iGain = 1; }
	    my $pedstring = "PedAna$gainstring[$iGain]";
	    my $rmsstring = "RmsAna$gainstring[$iGain]";

	    $line = <$tfh>; # header
	    for ($iChan = 0; $iChan<$nChan; $iChan++) {
		$line = <$tfh>;
		chomp $line;
		$line =~ s/\s+/ /g;
		$line =~ s/^\s+//;
		my @carr = split /$splitSpace/, $line;
		my $pedVal = $carr[1];
		my $rmsVal = $carr[2];
		my $resultPed = sprintf("%.1f", $pedVal); 
		$pedstring .= " $resultPed";
		my $resultRms = sprintf("%.2f", $rmsVal); 
		$rmsstring .= " $resultRms";
		if ($debug > 2) { print "carr0 $carr[0] carr1 $carr[1] carr2 $carr[2] carr3 $carr[3]\n"; }

		if ($iGain == 0) {
		    if ( ($pedVal < $minPedVal[$iGain]) || ($pedVal > $maxPedVal[$iGain]) ) {
			if ($debug > 0) { print "out-of-bounds ped $pedAnaCount : pedVal $pedVal \n"; }
			$pedAnaErrCount++;
		    }
		    $pedAnaCount++;
		    if ( ($rmsVal < $minRmsVal[$iGain]) || ($rmsVal > $maxRmsVal[$iGain]) ) {
			if ($debug > 0) { print "out-of-bounds rms $rmsAnaCount : rmsVal $rmsVal \n"; }
			$rmsAnaErrCount++;
		    }
		    $rmsAnaCount++;
		}
	    }
	    close $tfh;
	    $outputstring .= "$pedstring\n";
	    $outputstring .= "$rmsstring\n";

	    if ($debug > 0) { 
		print "pedAnaCount $pedAnaCount pedAnaErrCount $pedAnaErrCount\n";
		print "rmsAnaCount $rmsAnaCount rmsAnaErrCount $rmsAnaErrCount\n";
	    }

	    $fileCheckCount++;
	} # end noiseAna file   
	elsif ($filename =~ /$xtalkstring/) {
	    if ($filename =~ /$paritystring[0]/) { $iParity = 0; }
	    else { $iParity = 1; }
	    if ($filename =~ /$gainstring[0]/) { $iGain = 0; }
	    else { $iGain = 1; }
	    if ($debug > 1) { print "xtalk file parity $iParity gain $iGain\n"; }
	    $outputstring .= "X$gainstring[$iGain]$paritystring[$iParity]";
	    my $xMax = 0;

	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    $line = <$tfh>; # header
	    $line = <$tfh>; # skip pulse 0
	    $line = <$tfh>; # skip pulse 1
	    $line = <$tfh>;
	    chomp $line;
	    $line =~ s/\s+/ /g;
	    $line =~ s/^\s+//;
	    my @xarr = split /$splitSpace/, $line;
	    my $nx = 0;
	    foreach my $x (@xarr) {
		if ( ($nx>0) && ($x>$xMax) ) { $xMax = $x;} 
		if ($debug > 2) { print "nx $nx x $x \n"; }
		if ( $nx > 0 ) { # skip first field
		    if ( ($x < $minXtalkVal[$iGain]) || ($x > $maxXtalkVal[$iGain]) ) {
			if ($debug > 0) { print "out-of-bounds nx $x : x $x \n"; }
			$xtalkErrCount++;
		    }
		    $xtalkCount++;
		}
		$nx++;
	    }	
	    close $tfh;
	    my $result = sprintf("%.1e", $xMax); 
	    $outputstring .= " $result\n";

	    if ($debug > 0) { 
		print "xtalkCount $xtalkCount xtalkErrCount $xtalkErrCount\n";
	    }
	    $fileCheckCount++;
	} # end xtalk file   
	elsif ($filename =~ /$calibstring/) {
	    if ($filename =~ /$paritystring[0]/) { $iParity = 0; }
	    else { $iParity = 1; }
	    if ($filename =~ /$gainstring[0]/) { $iGain = 0; }
	    else { $iGain = 1; }
	    if ($debug > 1) { print "calib file parity $iParity gain $iGain\n"; }
	    $outputstring .= "Gain$gainstring[$iGain]$paritystring[$iParity]";
	    
	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    $line = <$tfh>; # header
	    my $nsumGain = 0;
	    my $sumGain = 0;
	    my $mychan = 0;
	    if ($iParity == 1) { # skip chan 0 if odd parity
		$line = <$tfh>;
		$mychan++; 
	    } 
	    for ($iChan = 0; $iChan<($nChan/2); $iChan++) {
		$line = <$tfh>;
		chomp $line;
		$line =~ s/\s+/ /g;
		$line =~ s/^\s+//;
		my @carr = split /$splitSpace/, $line;
		my $gainVal = CapCorr( $carr[1], $mychan );
		my $result = sprintf("%.2f", $gainVal); 
		$outputstring .= " $result";
		if ($debug > 2) { print "carr0 $carr[0] carr1 $carr[1] carr2 $carr[2] carr3 $carr[3]\n"; }
		if ( ($gainVal < $minGainVal[$iGain]) || ($gainVal > $maxGainVal[$iGain]) ) {
		    if ($debug > 0) { print "out-of-bounds chan $mychan : gainval $gainVal \n"; }
		    $gainErrCount++;
		}
		$nsumGain++;
		$sumGain += $gainVal;
		$gainCount++;
		$line = <$tfh>; # skip next line
		$mychan += 2;
	    }
	    close $tfh;
	    $outputstring .= "\n";

	    if ($debug > 0) { 
		if ($nsumGain > 0) {
		    my $aveGain = $sumGain / $nsumGain;
		    print "aveGain $aveGain\n";
		}
		print "gainCount $gainCount gainErrCount $gainErrCount\n";
	    }
	    $fileCheckCount++;
	} # end calib file   
	elsif ($filename =~ /$risetimestring/) {
	    if ($filename =~ /$gainstring[0]/) { $iGain = 0; }
	    else { $iGain = 1; }
	    if ($debug > 1) { print "risetime file gain $iGain\n"; }
	    $outputstring .= "RT$gainstring[$iGain]";
	    
	    my $nsumRiseTime = 0;
	    my $sumRiseTime = 0;
	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    $line = <$tfh>; # header
	    for ($iChan = 0; $iChan<$nChan; $iChan++) {
		$line = <$tfh>;
		chomp $line;
		$line =~ s/\s+/ /g;
		$line =~ s/^\s+//;
		my @rarr = split /$splitSpace/, $line;
		if ($debug > 2) { print "rarr0 $rarr[0] rarr1 $rarr[1] rarr2 $rarr[2] rarr3 $rarr[3]\n"; }
		my $risetimeVal = $rarr[1];
		my $result = sprintf("%.1f", $risetimeVal); 
		$outputstring .= " $result";		
		if ( ($risetimeVal < $minRiseTimeVal[$iGain]) || ($risetimeVal > $maxRiseTimeVal[$iGain]) ) {
		    if ($debug > 0) { print "out-of-bounds chan $iChan : risetimeval $risetimeVal \n"; }
		    $risetimeErrCount++;
		}
		$nsumRiseTime++;
		$sumRiseTime += $risetimeVal;
		$risetimeCount++;
	    }	
	    close $tfh;
	    $outputstring .= "\n";
	    
	    if ($debug > 0) { 
		if ($nsumRiseTime > 0) {
		    my $aveRiseTime = $sumRiseTime / $nsumRiseTime;
		    print "aveRiseTime $aveRiseTime\n";
		}
		print "risetimeCount $risetimeCount risetimeErrCount $risetimeErrCount\n";
	    }
	    $fileCheckCount++;
	} # end risetime file   
	elsif ($filename =~ /$dcstring/) {
	    if ($debug > 1) { print "dc file\n"; }
	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    
	    my $iDCVal = 0;
	    $outputstring .= "VRef";
	    while ($iDCVal<$nDCRef) {
		my $line = <$tfh>; chomp $line;
		if ($line =~ /$DCValstring[$iDCVal]/) {
		    my @darr = split /$splitColon/, $line;
		    if ($debug > 2) { print "darr0 $darr[0] darr1 $darr[1] darr2 $darr[2] darr3 $darr[3]\n"; }
		    my @darr2 = split /$splitComma/, $darr[2];
		    my $dcVal = $darr2[0] + 0;
		    my $result = sprintf("%.3f", $dcVal); 
		    $outputstring .= " $result";
		    
		    if ( ($dcVal < $minDCRef[$iDCVal]) || ($dcVal > $maxDCRef[$iDCVal]) ) {
			if ($debug > 0) { print "out-of-bounds dcRef $dcRefCount : dcVal $dcVal\n"; }
			$dcRefErrCount++; 
		    }
		    $dcRefCount++; 
		    $iDCVal++;
		}
	    }	
	    $outputstring .= "\n";

	    my $voltCurrstring = "VCurr";
	    my $ampCurrstring = "ACurr";
	    while(my $line = <$tfh>) {
		chomp $line;
		if ($line =~ /$DCValstring[$iDCVal]/) {
		    my @darr = split /$splitColon/, $line;
		    if ($debug > 2) { print "darr0 $darr[0] darr1 $darr[1] darr2 $darr[2] darr3 $darr[3]\n"; }
		    my @darr2 = split /$splitComma/, $darr[2];
		    my $dcVal = $darr2[0] + 0;
		    my $iCurr = $iDCVal - $nDCRef;
		    my $mA = Volt2Amp( $dcVal, $iCurr );
		    $voltCurrstring .= " $dcVal";
		    $ampCurrstring .= " $mA";
		    
		    if ( ($mA < $minDCACurr[$iCurr]) || ($mA > $maxDCACurr[$iCurr]) ) {
			if ($debug > 0) { print "out-of-bounds dcCurr $dcCurrCount : dcVal $dcVal mA $mA\n"; }
			$dcCurrErrCount++; 
		    }
		    $dcCurrCount++; 
		    $iDCVal++;
		}
	    }	
	    close $tfh;
	    $outputstring .= "$voltCurrstring\n";
	    $outputstring .= "$ampCurrstring\n";
	    if ($debug > 0) { 
		print "dcRefCount $dcRefCount dcRefErrCount $dcRefErrCount\n";
		print "dcCurrCount $dcCurrCount dcCurrErrCount $dcCurrErrCount\n";
	    }
	    $fileCheckCount++;
	} # end dc file   
	elsif ($filename =~ /$runstring/) {
	    if ($debug > 1) { print "run file\n"; }
	    $outputstring .= "Sync";
	    
	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    while(my $line = <$tfh>) {
		chomp $line;
		if ( ($line =~ /$SyncLowstring/) || ($line =~ /$SyncLowstring/) ) {
		    my @sarr = split /$splitColon/, $line;
		    if ($debug > 2) { print "sarr0 $sarr[0] sarr1 $sarr[1]\n"; }
		    my $syncVal = $sarr[1] + 0;
		    $outputstring .= " $syncVal";
		    if ( ($syncVal < $minSync) || ($syncVal > $maxSync) ) {
			$syncErrCount++;
		    }
		    $syncCount++;
		}
	    }	
	    close $tfh;
	    $outputstring .= "\n";
	    
	    if ($debug > 0) { print "syncCount $syncCount syncErrCount $syncErrCount\n"; }
	    $fileCheckCount++;
	} # end run file   	
	elsif ($filename =~ /$miscstring/) {
	    if ($debug > 1) { print "misc file\n"; }

	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    while(my $line = <$tfh>) {
		chomp $line;

		if ($line =~ /$clockstring/) {
		    $line =~ s/\s+/ /g;
		    $line =~ s/^\s+//;
		    my @carr = split /$splitSpace/, $line;
		    if ($debug > 2) { print "clock line $line\ncarr0 $carr[0] carr1 $carr[1] carr2 $carr[2]\n"; }
		    my $clockVal = $carr[5] + 0;
		    $outputstring .= "RingOsc $clockVal\n";
		    if ( ($clockVal < $minClockSpeed) || ($clockVal > $maxClockSpeed) ) {
			$clockErrCount++;
		    }
		    $clockCount++;
		}
		elsif ($line =~ /$i2cstring/) {
		    $line =~ s/\s+/ /g;
		    $line =~ s/^\s+//;
		    my @carr = split /$splitSpace/, $line;
		    if ($debug > 2) { print "carr0 $carr[0] carr1 $carr[1]\n"; }
		    my $i2cVal = $carr[1] + 0;
		    $outputstring .= "i2cErr $i2cVal\n";
		    if ( $i2cVal > $maxi2cReadErrors ) {
			$i2cErrCount++;
		    }
		    $i2cCount++;
		}
		elsif ($line =~ /$memorystring/) {
		    $line =~ s/\s+/ /g;
		    my @marr = split /$memorystring/, $line;
		    $marr[1] =~ s/^\s+//;
		    my @carr = split /$splitSpace/, $marr[1];
		    if ($debug > 2) { print "carr0 $carr[0] carr1 $carr[1]\n"; }
		    my $memStatus = $carr[1];
		    chop $carr[4];
		    my $memVal = $carr[4] + 0;
#		    $outputstring .= "Mem $memStatus $memVal\n";
		    $outputstring .= "Mem $memVal\n";
		    if ( $memStatus eq $failstring ) {
			$memErrCount++;
		    }
		    $memCount++;
		}
	    }	
	    close $tfh;

	    if ($debug > 0) { 
		print "clockCount $clockCount clockErrCount $clockErrCount\n";
		print "i2cCount $i2cCount i2cErrCount $i2cErrCount\n";
		print "memCount $memCount memErrCount $memErrCount\n";
	    }

	    $fileCheckCount++;
	} # end misc file   	
	elsif ($filename =~ /$jtagfilestring/) {
	    if ($debug > 1) { print "jtag file\n"; }

	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    while(my $line = <$tfh>) {
		chomp $line;

		if ($line =~ /$jtagstring/) {
		    if ($line =~ /$jtagErrstring/) {
			$jtagErrCount++;
		    }
		    $jtagCount++;
		}
	    }	
	    close $tfh;

	    $outputstring .= "Jtag $jtagErrCount\n";
	    
	    if ($debug > 0) { 
		print "jtagCount $jtagCount jtagErrCount $jtagErrCount\n";
	    }

	    $fileCheckCount++;
	} # end jtag file   	
	elsif ($filename =~ /$dftstring/) {
	    if ($debug > 1) { print "dft file\n"; }

	    open( my $tfh, '<', $filename ) or die "Can't open $filename: $!";
	    while(my $line = <$tfh>) {
		chomp $line;

		if ($line =~ /$mismatchstring/) {
		    $line =~ s/\s+/ /g;
		    $line =~ s/^\s+//;
		    my @carr = split /$splitSpace/, $line;
		    if ($debug > 2) { print "mismatch line $line\ncarr2 $carr[2] carr3 $carr[3]\n"; }
		    my $mismatchVal = $carr[3] + 0;
		    $outputstring .= "DFT $mismatchVal\n";
		    if ( $mismatchVal > $maxMismatches ) {
			$dftErrCount++;
		    }
		    $dftCount++;
		}

	    }	
	    close $tfh;
	    
	    $fileCheckCount++;
	} # end dft file   	

	$fileCount++;
    }
}

sub writeOutput {
# cuts on counters
    my $nDAQFiles = 4; #4=noise, calib-odd, calib-even, delay-all 
    my $nAnaFiles = $nDAQFiles + 3; # also run xtalk analysis on calib files (2) + noiseAna (1)

    my $minDCRefOK = $nDCRef;
    my $maxDCRefNotOK = 0;
    my $minDCCurrOK = $nDCCurr;
    my $maxDCCurrNotOK = 0;
    
    my $minSyncOK = $nGain * $nDAQFiles; 
    my $maxSyncNotOK = 0;
    my $minPedOK = $nChan;# * $nGain;
    my $maxPedNotOK = 0;
    my $minRmsOK = $nChan;# * $nGain;
    my $maxRmsNotOK = 0;
    my $minGainOK = $nChan * $nGain;
    my $maxGainNotOK = 0;
    my $minRiseTimeOK = $nChan * $nGain;
    my $maxRiseTimeNotOK = 0;
    my $minXtalkOK = $nChan * $nGain;
    my $maxXtalkNotOK = 0;

    my $minClockOK = 1;
    my $maxClockNotOK = 0;
    my $mini2cOK = 1;
    my $maxi2cNotOK = 0;
    my $minMemOK = 1;
    my $maxMemNotOK = 0;
    my $minJtagOK = 10; 
    my $maxJtagNotOK = 0;
    my $minDFTOK = 1;
    my $maxDFTNotOK = 0;

    my $fileExpectedCount = ($nAnaFiles * $nGain) + 5; # +5 is for run.log, dc.log, misc.log, jtag.log, dft.log

    if ($debug>0) { print "found $fileCount files - checked $fileCheckCount - expected $fileExpectedCount\n"; }
    my $FileCountErr = 0;
    if ($fileCheckCount != $fileExpectedCount) { $FileCountErr = 1; }		
#test
    my $DCRefErr = 0;
    my $DCCurrErr = 0;
    my $SyncErr = 0;
    my $PedAnaErr = 0;
    my $RmsAnaErr = 0;
    my $GainErr = 0;
    my $RiseTimeErr = 0;
    my $XtalkErr = 0;
    my $ClockErr = 0;
    my $i2cErr = 0;
    my $MemErr = 0;
    my $JtagErr = 0;
    my $DFTErr = 0;
#
    if ( ($dcRefCount < $minDCRefOK) || ($dcRefErrCount > $maxDCRefNotOK) ) { $DCRefErr = 1; }
    if ( ($dcCurrCount < $minDCCurrOK) || ($dcCurrErrCount > $maxDCCurrNotOK) ) { $DCCurrErr = 1; }
    if ( ($syncCount < $minSyncOK) || ($syncErrCount > $maxSyncNotOK) ) { $SyncErr = 1; }
    if ( ($pedAnaCount < $minPedOK) || ($pedAnaErrCount > $maxPedNotOK) ) { $PedAnaErr = 1; }
    if ( ($rmsAnaCount < $minRmsOK) || ($rmsAnaErrCount > $maxRmsNotOK) ) { $RmsAnaErr = 1; }
    if ( ($gainCount < $minGainOK) || ($gainErrCount > $maxGainNotOK) ) { $GainErr = 1; }
    if ( ($xtalkCount < $minXtalkOK) || ($xtalkErrCount > $maxXtalkNotOK) ) { $XtalkErr = 1; }
    if ( ($risetimeCount < $minRiseTimeOK) || ($risetimeErrCount > $maxRiseTimeNotOK) ) { $RiseTimeErr = 1; }
#
    if ( ($clockCount < $minClockOK) || ($clockErrCount > $maxClockNotOK) ) { $ClockErr = 1; }
    if ( ($i2cCount < $mini2cOK) || ($i2cErrCount > $maxi2cNotOK) ) { $i2cErr = 1; }
    if ( ($memCount < $minMemOK) || ($memErrCount > $maxMemNotOK) ) { $MemErr = 1; }
    if ( ($jtagCount < $minJtagOK) || ($jtagErrCount > $maxJtagNotOK) ) { $JtagErr = 1; }
    if ( ($dftCount < $minDFTOK) || ($dftErrCount > $maxDFTNotOK) ) { $DFTErr = 1; }

    my $ErrorCode = ($FileCountErr * 1) + ($DCRefErr * 2) +  ($DCCurrErr * 4) + ($SyncErr * 8) + 
	($PedAnaErr * 0x10) + ($RmsAnaErr * 0x20) + ($GainErr * 0x40) + ($RiseTimeErr * 0x80) +
	($XtalkErr * 0x100) + ($ClockErr * 0x200) + ($i2cErr * 0x400) + ($JtagErr * 0x800) +
	($MemErr * 0x1000) + ($DFTErr * 0x2000);
    my $nErrors = $FileCountErr + $DCRefErr +  $DCCurrErr + $SyncErr + 
	$PedAnaErr + $RmsAnaErr + $GainErr + $RiseTimeErr +
	$XtalkErr + $ClockErr + $i2cErr + $JtagErr +
	$MemErr + $DFTErr;
    my $errhex = sprintf("0x%x", $ErrorCode);
    $outputstring .= "ErrCode $errhex\n";
    
    print "\nSummary: Chip $chipnum\n";
    print "QRCode $QRCode\n";
    print "FileCountErr $FileCountErr\n";
    print "DCRefErr $DCRefErr\n";
    print "DCCurrErr $DCCurrErr\n";
    print "SyncErr $SyncErr\n";
    print "PedAnaErr $PedAnaErr\n";
    print "RmsAnaErr $RmsAnaErr\n";
    print "GainErr $GainErr\n";
    print "RiseTimeErr $RiseTimeErr\n";
    print "XtalkErr $XtalkErr\n";
    print "ClockErr $ClockErr\n";
    print "i2cErr $i2cErr\n";
    print "MemErr $MemErr\n";
    print "DFTErr $DFTErr\n";
    print "JtagErr $JtagErr\n";

    print "nErrors $nErrors \n";
    print "ErrorCode $errhex \n";

# Error code logic for return code
    my $ReturnCode = 0;
#0 = Chip OK
    
    if ( ($DCRefErr > 0) || ($DCCurrErr > 0) || ($SyncErr > 0) ) { $ReturnCode = 1; } # Code 1: DC Ref voltages or current or Sync issues 
    elsif ( ($DFTErr > 0) || ($JtagErr > 0) || ($MemErr > 0) ) { $ReturnCode = 2; } # Code 2: Digital errors
    elsif ( ($ClockErr > 0) || ($i2cErr > 0) ) { $ReturnCode = 5; } # Code 5: RingOscVal error
    elsif ( ($PedAnaErr > 0) || ($RmsAnaErr > 0) || ($GainErr > 0) )  { $ReturnCode = 6; } # Code 6 errors
    elsif ( ($RiseTimeErr > 0) || ($XtalkErr > 0) )  { $ReturnCode = 7; } # Code 7 errors
#DS    elsif ( $FileCountErr > 0 ) { $ReturnCode = 2; } # Code 2: tests not completed

    print "ReturnCode $ReturnCode \n";
    $outputstring .= "RCode $ReturnCode\n";

# also print all the needed result values to ascii file (blob) for database
    my $outputFilename = "${sampadir}/result${chipnum}.log";
    my $outputSummaryFilename = "$topdir/summary.csv";
    
    open(OUTSUMMARY, ">>$outputSummaryFilename");
    print OUTSUMMARY "$chipnum $ReturnCode\n";
    close OUTSUMMARY;

    open(OUTP, ">$outputFilename");
    print OUTP "$outputstring";
    close OUTP;
}

sub Volt2Amp {
    my $volt = $_[0];
    my $id = sprintf "%.0f", $_[1];
    my $mA = 0; 
    if ( ($id >= 0) && ($id < $nDCCurr) ) {
# @marr values from ~/work/opamp/calib_sta*.log
	if ($station == 1) {
	    my @marr = ( -0.11925, -0.04784, 0.02099, -0.06971, -0.06636 ); 
	    my $m = $marr[$id]; 
	    $mA = 4 * 50.0 * ($volt - $m);
	}
	else { 
	    my @marr = ( -0.00619, -0.08952, -0.05947, -0.08405, -0.06029 ); 
	    my $m = $marr[$id]; 
	    $mA = 4 * 49.2 * ($volt - $m);
	}
    }
    
    return $mA;
}

sub CapCorr {
    my $gain = $_[0] + 0;
    my $chan = sprintf "%.0f", $_[1];

    my $corr = 1.0; 
    if ( ($chan >= 0) && ($chan < $nChan) ) {
	if ($station == 1) {
	    my @caparr = ( 
		0.99999, 1.00334, 0.991291, 1.00982, 1.00289, 1.03392, 0.984688, 1.01846, 
		1.00386, 1.01712, 1.00119, 0.986346, 0.977238, 0.996318, 1.00885, 0.976326, 
		0.979849, 1.00013, 1.0126, 0.997502, 0.969492, 1.01243, 0.989848, 1.00514, 
		1.01333, 1.0104, 0.99873, 0.996653, 0.998887, 1.01199, 0.993609, 0.990812 
		); 
	    # my $scale = 20.0 / 20.269;
	    my $scale = 1.0; #DS, unscaled
	    $corr = $caparr[$chan] * $scale; 
	}
	else { # station 2, not yet calibrated
	    my @caparr = ( 
		1.01076, 1.00423, 1.01335, 1.00718, 1.00187, 1.00374, 0.999222, 0.998755, 
		0.987168, 0.998086, 1.00046, 0.986451, 1.00473, 0.998762, 1.01739, 0.986038, 
		1.00172, 0.997992, 0.995849, 0.999144, 0.991868, 0.976614, 1.00683, 0.994169, 
		0.99998, 0.981731, 1.01026, 0.997688, 1.02123, 0.99549, 1.00377, 0.996182
		);
	    # my $scale = 20.0 / 18.991;
	    my $scale = 1.0; #DS, unscaled
	    $corr = $caparr[$chan] * $scale; 

	}
    }
    my $newgain = $gain * $corr;
    return $newgain;
}

