Big table lookup optimisation
This commit is contained in:
parent
a9c2a2dec7
commit
f34c03c98e
|
@ -188,7 +188,7 @@ byte correctionsAFRClosedLoop()
|
||||||
if (configPage1.algorithm == 0) { yValue = currentStatus.MAP; }
|
if (configPage1.algorithm == 0) { yValue = currentStatus.MAP; }
|
||||||
else { yValue = currentStatus.TPS; }
|
else { yValue = currentStatus.TPS; }
|
||||||
|
|
||||||
currentStatus.afrTarget = get3DTableValue(afrTable, yValue, currentStatus.RPM); //Perform the target lookup
|
currentStatus.afrTarget = get3DTableValue(&afrTable, yValue, currentStatus.RPM); //Perform the target lookup
|
||||||
|
|
||||||
//Check which algorithm is used, simple or PID
|
//Check which algorithm is used, simple or PID
|
||||||
if (configPage3.egoAlgorithm == 0)
|
if (configPage3.egoAlgorithm == 0)
|
||||||
|
|
|
@ -391,20 +391,20 @@ void loop()
|
||||||
if (configPage1.algorithm == 0) //Check with fuelling algorithm is being used
|
if (configPage1.algorithm == 0) //Check with fuelling algorithm is being used
|
||||||
{
|
{
|
||||||
//Speed Density
|
//Speed Density
|
||||||
currentStatus.VE = get3DTableValue(fuelTable, currentStatus.MAP, currentStatus.RPM); //Perform lookup into fuel map for RPM vs MAP value
|
currentStatus.VE = get3DTableValue(&fuelTable, currentStatus.MAP, currentStatus.RPM); //Perform lookup into fuel map for RPM vs MAP value
|
||||||
currentStatus.PW = PW_SD(req_fuel_uS, currentStatus.VE, currentStatus.MAP, currentStatus.corrections, inj_opentime_uS);
|
currentStatus.PW = PW_SD(req_fuel_uS, currentStatus.VE, currentStatus.MAP, currentStatus.corrections, inj_opentime_uS);
|
||||||
if (configPage2.FixAng == 0) //Check whether the user has set a fixed timing angle
|
if (configPage2.FixAng == 0) //Check whether the user has set a fixed timing angle
|
||||||
{ currentStatus.advance = get3DTableValue(ignitionTable, currentStatus.MAP, currentStatus.RPM); } //As above, but for ignition advance
|
{ currentStatus.advance = get3DTableValue(&ignitionTable, currentStatus.MAP, currentStatus.RPM); } //As above, but for ignition advance
|
||||||
else
|
else
|
||||||
{ currentStatus.advance = configPage2.FixAng; }
|
{ currentStatus.advance = configPage2.FixAng; }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Alpha-N
|
//Alpha-N
|
||||||
currentStatus.VE = get3DTableValue(fuelTable, currentStatus.TPS, currentStatus.RPM); //Perform lookup into fuel map for RPM vs TPS value
|
currentStatus.VE = get3DTableValue(&fuelTable, currentStatus.TPS, currentStatus.RPM); //Perform lookup into fuel map for RPM vs TPS value
|
||||||
currentStatus.PW = PW_AN(req_fuel_uS, currentStatus.VE, currentStatus.TPS, currentStatus.corrections, inj_opentime_uS); //Calculate pulsewidth using the Alpha-N algorithm (in uS)
|
currentStatus.PW = PW_AN(req_fuel_uS, currentStatus.VE, currentStatus.TPS, currentStatus.corrections, inj_opentime_uS); //Calculate pulsewidth using the Alpha-N algorithm (in uS)
|
||||||
if (configPage2.FixAng == 0) //Check whether the user has set a fixed timing angle
|
if (configPage2.FixAng == 0) //Check whether the user has set a fixed timing angle
|
||||||
{ currentStatus.advance = get3DTableValue(ignitionTable, currentStatus.TPS, currentStatus.RPM); } //As above, but for ignition advance
|
{ currentStatus.advance = get3DTableValue(&ignitionTable, currentStatus.TPS, currentStatus.RPM); } //As above, but for ignition advance
|
||||||
else
|
else
|
||||||
{ currentStatus.advance = configPage2.FixAng; }
|
{ currentStatus.advance = configPage2.FixAng; }
|
||||||
}
|
}
|
||||||
|
|
5
table.h
5
table.h
|
@ -31,6 +31,9 @@ struct table3D {
|
||||||
int axisX[xSize];
|
int axisX[xSize];
|
||||||
int axisY[ySize];
|
int axisY[ySize];
|
||||||
|
|
||||||
|
//Store the last X and Y coordinates in the table. This is used to make the next check faster
|
||||||
|
byte lastXMax, lastXMin;
|
||||||
|
byte lastYMax, lastYMin;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -46,7 +49,7 @@ Eg: 2x2 table
|
||||||
(1,0) = 1
|
(1,0) = 1
|
||||||
|
|
||||||
*/
|
*/
|
||||||
int get3DTableValue(struct table3D, int, int);
|
int get3DTableValue(struct table3D *fromTable, int, int);
|
||||||
int table2D_getValue(struct table2D, int);
|
int table2D_getValue(struct table2D, int);
|
||||||
|
|
||||||
#endif // TABLE_H
|
#endif // TABLE_H
|
||||||
|
|
142
table.ino
142
table.ino
|
@ -134,13 +134,13 @@ int table2D_getValue(struct table2D fromTable, int X)
|
||||||
|
|
||||||
//This function pulls a value from a 3D table given a target for X and Y coordinates.
|
//This function pulls a value from a 3D table given a target for X and Y coordinates.
|
||||||
//It performs a 2D linear interpolation as descibred in: http://www.megamanual.com/v22manual/ve_tuner.pdf
|
//It performs a 2D linear interpolation as descibred in: http://www.megamanual.com/v22manual/ve_tuner.pdf
|
||||||
int get3DTableValue(struct table3D fromTable, int Y, int X)
|
int get3DTableValue(struct table3D *fromTable, int Y, int X)
|
||||||
{
|
{
|
||||||
//Loop through the X axis bins for the min/max pair
|
//Loop through the X axis bins for the min/max pair
|
||||||
//Note: For the X axis specifically, rather than looping from tableAxisX[0] up to tableAxisX[max], we start at tableAxisX[Max] and go down.
|
//Note: For the X axis specifically, rather than looping from tableAxisX[0] up to tableAxisX[max], we start at tableAxisX[Max] and go down.
|
||||||
// This is because the important tables (fuel and injection) will have the highest RPM at the top of the X axis, so starting there will mean the best case occurs when the RPM is highest (And hence the CPU is needed most)
|
// This is because the important tables (fuel and injection) will have the highest RPM at the top of the X axis, so starting there will mean the best case occurs when the RPM is highest (And hence the CPU is needed most)
|
||||||
int xMinValue = fromTable.axisX[0];
|
int xMinValue = fromTable->axisX[0];
|
||||||
int xMaxValue = fromTable.axisX[fromTable.xSize-1];
|
int xMaxValue = fromTable->axisX[fromTable->xSize-1];
|
||||||
byte xMin = 0;
|
byte xMin = 0;
|
||||||
byte xMax = 0;
|
byte xMax = 0;
|
||||||
|
|
||||||
|
@ -148,31 +148,59 @@ int get3DTableValue(struct table3D fromTable, int Y, int X)
|
||||||
if(X > xMaxValue) { X = xMaxValue; }
|
if(X > xMaxValue) { X = xMaxValue; }
|
||||||
if(X < xMinValue) { X = xMinValue; }
|
if(X < xMinValue) { X = xMinValue; }
|
||||||
|
|
||||||
for (byte x = fromTable.xSize-1; x >= 0; x--)
|
//1st check is whether we're still in the same X bin as last time
|
||||||
|
if ( (X <= fromTable->axisX[fromTable->lastXMax]) && (X > fromTable->axisX[fromTable->lastXMin]) )
|
||||||
{
|
{
|
||||||
//Checks the case where the X value is exactly what was requested
|
xMaxValue = fromTable->axisX[fromTable->lastXMax];
|
||||||
if ( (X == fromTable.axisX[x]) || (x == 0) )
|
xMinValue = fromTable->axisX[fromTable->lastXMin];
|
||||||
|
xMax = fromTable->lastXMax;
|
||||||
|
xMin = fromTable->lastXMin;
|
||||||
|
}
|
||||||
|
//2nd check is whether we're in the next RPM bin (To the right)
|
||||||
|
else if ( ((fromTable->lastXMax + 1) < fromTable->xSize ) && (X <= fromTable->axisX[fromTable->lastXMax +1 ]) && (X > fromTable->axisX[fromTable->lastXMin + 1]) ) //First make sure we're not already at the last X bin
|
||||||
|
{
|
||||||
|
fromTable->lastXMax = xMax = fromTable->lastXMax + 1;
|
||||||
|
fromTable->lastXMin = xMin = fromTable->lastXMin + 1;
|
||||||
|
xMaxValue = fromTable->axisX[fromTable->lastXMax];
|
||||||
|
xMinValue = fromTable->axisX[fromTable->lastXMin];
|
||||||
|
}
|
||||||
|
//3rd check is to look at the previous bin (to the left)
|
||||||
|
else if ( (fromTable->lastXMin > 0 ) && (X <= fromTable->axisX[fromTable->lastXMax - 1]) && (X > fromTable->axisX[fromTable->lastXMin - 1]) ) //First make sure we're not already at the first X bin
|
||||||
|
{
|
||||||
|
fromTable->lastXMax = xMax = fromTable->lastXMax - 1;
|
||||||
|
fromTable->lastXMin = xMin = fromTable->lastXMin - 1;
|
||||||
|
xMaxValue = fromTable->axisX[fromTable->lastXMax];
|
||||||
|
xMinValue = fromTable->axisX[fromTable->lastXMin];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//If it's not caught by one of the above scenarios, give up and just run the loop
|
||||||
|
{
|
||||||
|
for (byte x = fromTable->xSize-1; x >= 0; x--)
|
||||||
{
|
{
|
||||||
xMaxValue = fromTable.axisX[x];
|
//Checks the case where the X value is exactly what was requested
|
||||||
xMinValue = fromTable.axisX[x];
|
if ( (X == fromTable->axisX[x]) || (x == 0) )
|
||||||
xMax = x;
|
{
|
||||||
xMin = x;
|
xMaxValue = fromTable->axisX[x];
|
||||||
break;
|
xMinValue = fromTable->axisX[x];
|
||||||
|
fromTable->lastXMax = xMax = x;
|
||||||
|
fromTable->lastXMin = xMin = x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Normal case
|
||||||
|
if ( (X <= fromTable->axisX[x]) && (X > fromTable->axisX[x-1]) )
|
||||||
|
{
|
||||||
|
xMaxValue = fromTable->axisX[x];
|
||||||
|
xMinValue = fromTable->axisX[x-1];
|
||||||
|
fromTable->lastXMax = xMax = x;
|
||||||
|
fromTable->lastXMin = xMin = x-1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Normal case
|
|
||||||
if ( (X <= fromTable.axisX[x]) && (X > fromTable.axisX[x-1]) )
|
|
||||||
{
|
|
||||||
xMaxValue = fromTable.axisX[x];
|
|
||||||
xMinValue = fromTable.axisX[x-1];
|
|
||||||
xMax = x;
|
|
||||||
xMin = x-1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Loop through the Y axis bins for the min/max pair
|
//Loop through the Y axis bins for the min/max pair
|
||||||
int yMaxValue = fromTable.axisY[0];
|
int yMaxValue = fromTable->axisY[0];
|
||||||
int yMinValue = fromTable.axisY[fromTable.ySize-1];
|
int yMinValue = fromTable->axisY[fromTable->ySize-1];
|
||||||
byte yMin = 0;
|
byte yMin = 0;
|
||||||
byte yMax = 0;
|
byte yMax = 0;
|
||||||
|
|
||||||
|
@ -180,26 +208,54 @@ int get3DTableValue(struct table3D fromTable, int Y, int X)
|
||||||
if(Y > yMaxValue) { Y = yMaxValue; }
|
if(Y > yMaxValue) { Y = yMaxValue; }
|
||||||
if(Y < yMinValue) { Y = yMinValue; }
|
if(Y < yMinValue) { Y = yMinValue; }
|
||||||
|
|
||||||
for (byte y = fromTable.ySize-1; y >= 0; y--)
|
//1st check is whether we're still in the same Y bin as last time
|
||||||
|
if ( (Y >= fromTable->axisY[fromTable->lastYMax]) && (Y < fromTable->axisY[fromTable->lastYMin]) )
|
||||||
{
|
{
|
||||||
//Checks the case where the Y value is exactly what was requested
|
yMaxValue = fromTable->axisY[fromTable->lastYMax];
|
||||||
if ( (Y == fromTable.axisY[y]) || (y==0) )
|
yMinValue = fromTable->axisY[fromTable->lastYMin];
|
||||||
|
yMax = fromTable->lastYMax;
|
||||||
|
yMin = fromTable->lastYMin;
|
||||||
|
}
|
||||||
|
//2nd check is whether we're in the next MAP/TPS bin (Next one up)
|
||||||
|
else if ( (fromTable->lastYMin > 0 ) && (Y <= fromTable->axisY[fromTable->lastYMin - 1 ]) && (Y > fromTable->axisY[fromTable->lastYMax - 1]) ) //First make sure we're not already at the top Y bin
|
||||||
|
{
|
||||||
|
fromTable->lastYMax = yMax = fromTable->lastYMax - 1;
|
||||||
|
fromTable->lastYMin = yMin = fromTable->lastYMin - 1;
|
||||||
|
yMaxValue = fromTable->axisY[fromTable->lastYMax];
|
||||||
|
yMinValue = fromTable->axisY[fromTable->lastYMin];
|
||||||
|
}
|
||||||
|
//3rd check is to look at the previous bin (Next one down)
|
||||||
|
else if ( ((fromTable->lastYMax + 1) < fromTable->ySize) && (Y <= fromTable->axisY[fromTable->lastYMin + 1]) && (Y > fromTable->axisY[fromTable->lastYMax + 1]) ) //First make sure we're not already at the bottom Y bin
|
||||||
|
{
|
||||||
|
fromTable->lastYMax = yMax = fromTable->lastYMax + 1;
|
||||||
|
fromTable->lastYMin = yMin = fromTable->lastYMin + 1;
|
||||||
|
yMaxValue = fromTable->axisY[fromTable->lastYMax];
|
||||||
|
yMinValue = fromTable->axisY[fromTable->lastYMin];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//If it's not caught by one of the above scenarios, give up and just run the loop
|
||||||
|
{
|
||||||
|
for (byte y = fromTable->ySize-1; y >= 0; y--)
|
||||||
{
|
{
|
||||||
yMaxValue = fromTable.axisY[y];
|
//Checks the case where the Y value is exactly what was requested
|
||||||
yMinValue = fromTable.axisY[y];
|
if ( (Y == fromTable->axisY[y]) || (y==0) )
|
||||||
yMax = y;
|
{
|
||||||
yMin = y;
|
yMaxValue = fromTable->axisY[y];
|
||||||
break;
|
yMinValue = fromTable->axisY[y];
|
||||||
|
fromTable->lastYMax = yMax = y;
|
||||||
|
fromTable->lastYMin = yMin = y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Normal case
|
||||||
|
if ( (Y >= fromTable->axisY[y]) && (Y < fromTable->axisY[y-1]) )
|
||||||
|
{
|
||||||
|
yMaxValue = fromTable->axisY[y];
|
||||||
|
yMinValue = fromTable->axisY[y-1];
|
||||||
|
fromTable->lastYMax = yMax = y;
|
||||||
|
fromTable->lastYMin = yMin = y-1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Normal case
|
|
||||||
if ( (Y >= fromTable.axisY[y]) && (Y < fromTable.axisY[y-1]) )
|
|
||||||
{
|
|
||||||
yMaxValue = fromTable.axisY[y];
|
|
||||||
yMinValue = fromTable.axisY[y-1];
|
|
||||||
yMax = y;
|
|
||||||
yMin = y-1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,10 +271,10 @@ int get3DTableValue(struct table3D fromTable, int Y, int X)
|
||||||
C D
|
C D
|
||||||
|
|
||||||
*/
|
*/
|
||||||
int A = fromTable.values[yMin][xMin];
|
int A = fromTable->values[yMin][xMin];
|
||||||
int B = fromTable.values[yMin][xMax];
|
int B = fromTable->values[yMin][xMax];
|
||||||
int C = fromTable.values[yMax][xMin];
|
int C = fromTable->values[yMax][xMin];
|
||||||
int D = fromTable.values[yMax][xMax];
|
int D = fromTable->values[yMax][xMax];
|
||||||
|
|
||||||
//Create some normalised position values
|
//Create some normalised position values
|
||||||
//These are essentially percentages (between 0 and 1) of where the desired value falls between the nearest bins on each axis
|
//These are essentially percentages (between 0 and 1) of where the desired value falls between the nearest bins on each axis
|
||||||
|
|
Loading…
Reference in New Issue