#!/usr/bin/perl -w
#
# MAF Tune

# usage:  perl mft.pl maf.csv log1.csv [log2.csv [log3.csv [...]]] > newmaf.csv

sub parse_log($);
sub freq_to_bin($)
{
    my $f = shift(@_);

    die "Freq $f out of range" if ($f < 1500 || $f > 11500);

    return int(($f - 1500) / 125);
}

@oldmaf = ( );

open MAF, "<$ARGV[0]" || die "Could not open MAF file $ARGV[0]";

$line = readline MAF;
chomp($line);

@oldmaf = split /,/, $line;

die "Old MAF file $ARGV[0] has incorrect number of elements\n" 
    if ($#oldmaf != 80);

close MAF;


@ft_sum = 
( 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
);

@ft_cnt = 
( 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
);
@ft_avg = 
( 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
);

    
for ($i = 1; $i <= $#ARGV; $i++)
{
    parse_log($ARGV[$i]);
}


## Compute the smoothed average

for ($i = 0; $i <= 80; $i++)
{
    $cnt = $ft_cnt[$i] * 4;
    $sum = $ft_sum[$i] * 4;

    if ($i > 0)
    {
        $cnt += $ft_cnt[$i - 1];
        $sum += $ft_sum[$i - 1];
    }
    if ($i < 80)
    {
        $cnt += $ft_cnt[$i + 1];
        $sum += $ft_sum[$i + 1];
    }

    if ($cnt > 0)
    {
        $ft_avg[$i] = $sum / $cnt;
    }
}

## Now fill in the gaps.  Every where the AVG is 0, linear interpolate.
## At the ends, just replicate the nearest value.

# fill left edge
for ($i = 0; $i <= 80; $i++) { last if ($ft_avg[$i] > 0); }
for ($j = 0; $j < $i; $j++)  { $ft_avg[$j] = $ft_avg[$i]; }

# fill right edge
for ($i = 80; $i >= 0; $i--) { last if ($ft_avg[$i] > 0); }
for ($j = 80; $j > $i; $j--) { $ft_avg[$j] = $ft_avg[$i]; }


$l = 0;
for ($i = 0; $i < 80; $i++)
{
    if ($ft_avg[$i] > 0)
    {
        if ($l < $i - 1)
        {
            $len  = $i - $l - 1;
            $step = ($ft_avg[$i] - $ft_avg[$l]) / $len;
            $avg  = $ft_avg[$l] + $step;
            for ($j = $l + 1; $j < $i; $j++)
            {
                $ft_avg[$j] = $avg;
                $avg += $step;
            }
        }

        $l = $i;
    }
}

## Compute new MAF merely by scaling the old.

@newmaf = @oldmaf;

for ($i = 0; $i <= 80; $i++)
{
    $newmaf[$i] = $oldmaf[$i] * $ft_avg[$i];
}

## Print out the new CSV file in three rows:  New, Multiplier, Old


print join(",", @newmaf), "\n";
print join(",", @ft_avg), "\n";
print join(",", @oldmaf), "\n";


############################################################################
############################################################################
############################################################################


sub parse_log($)
{
    my $lf = shift(@_);
    my ($i, $scol, $lcol, $mcol, $acol, $bin, $line);
    my @field;

    open LOG, "<$lf" || die "Could not open LOG file $lf";


    ## Look for the following items:
    ## "Short Term Fuel Trim Bank 1 (SAE) %"
    ## "Long Term Fuel Trim Bank 1 (SAE) %"
    ## "Mass Air Flow Hz"
    ## "Air Fuel Ratio Commanded Lo Res afr"


    # Look for start of data.
    while (<LOG>)
    {
        last if (/^\[Data\]/);
    }

    $line = readline LOG;
    chomp($line);

    @field = split /,/, $line;

    $scol = $lcol = $mcol = $acol = -1;

    for ($i = 0; $i <= $#field; $i++)
    {
        $scol = $i if ($field[$i] eq "Short Term Fuel Trim Bank 1 (SAE) %");
        $lcol = $i if ($field[$i] eq "Long Term Fuel Trim Bank 1 (SAE) %");
        $mcol = $i if ($field[$i] eq "Mass Air Flow Hz");
        $acol = $i if ($field[$i] eq "Air Fuel Ratio Commanded Lo Res afr");
    }

    die "Could not find STFT in $lf" if ($scol == -1);
    die "Could not find LTFT in $lf" if ($lcol == -1);
    die "Could not find MAF in $lf"  if ($mcol == -1);
    die "Could not find AFR in $lf"  if ($acol == -1);

    while (<LOG>)
    {
        chomp;
        @field = split /,/;

        next if (abs($field[$acol] - 14.7) > 0.1);

        $bin = freq_to_bin($field[$mcol]);

        $ft_sum[$bin] += (100.0 + $field[$lcol] + $field[$scol])/100.0;
        $ft_cnt[$bin]++;
    }

    close LOG;
}
