#!/usr/bin/perl -w

# simple script for calculating lambdacorr value to afr*constant

# l-tlb is the value in the lambda tabel[i,j]
# %VE is the relative change after ve*lambda
# lambda is lambda
# afr is real afr
# afr_m is afr * constant
# points is equidistant constants living in AVR
# interp is interpolated points
# diff is difference between interp and afr_m
# afrI is interpolated points converted to afr


$offset = 200; # table is biased (stoich is decimal 56)
$mult=1024;  # mult by 1024 (easy to divide in avr)

for ($i=0; $i<256; $i++) {
    my $ve_t = ($i+$offset)/256;
    my $afr_t = 14.7 / $ve_t;
    my $lambda_t = $afr_t / 14.7;
    my $afr_mult_t = int($afr_t * $mult+0.5);

    $ve[$i] = $ve_t;
    $afr[$i] = $afr_t;
    $lambda[$i] = $lambda_t;
    $afr_mult[$i] = $afr_mult_t;
}

# insert the last element manually...
$afr_mult[256] = 2*$afr_mult[255]-$afr_mult[254];

# then interpolate
$k = 16;  # step size

for ($i=0; $i<256; $i++) {
    my $m = $i % $k;
    my $previdx = $i-$m;
    my $nextidx = $i-$m+$k;

    if ($m != 0) {
	$afr_mult_interp[$i] = linterp($afr_mult[$previdx], $afr_mult[$nextidx], $m / $k);
    } else {
	$afr_mult_interp[$i] = $afr_mult[$i];
    }

}

print "l-tbl\t%VE\tlambda\tafr\t  |\tafr_m\tpoints\tinterp\tdiff\tafrI\n";
for ($i=0; $i<256; $i++) {
    printf("%d\t%0.3f\t%0.3f\t%0.3f\t  |\t%d", $i, $ve[$i], $lambda[$i], $afr[$i], $afr_mult[$i]);

    my $m = $i % $k;
    if ($m == 0) {
	printf("\t%d\t%d\t%d\t%0.3f\t\n", $afr_mult[$i], $afr_mult_interp[$i], $afr_mult[$i]-$afr_mult_interp[$i], $afr_mult_interp[$i]/$mult);
    } else {
	printf("\t-\t%d\t%d\t%0.3f\t\n", $afr_mult_interp[$i], $afr_mult[$i]-$afr_mult_interp[$i], $afr_mult_interp[$i]/$mult);
    }
}

print "\nuint16_t PROGMEM lambdacorr_to_afr[] = {";
for ($i=0; $i<256; $i+=$k) {
    print "$afr_mult[$i], ";
}
print "$afr_mult[256]};\n";

#------ linear interpolation
sub linterp
{
	my $a = shift;
	my $b = shift;
	my $offset = shift;	# range is 0 (a) .. 1 (b)
	return $offset * $b + (1-$offset) * $a;
}

