Add better 3D table caching
This commit is contained in:
parent
e449f319c2
commit
554f58eb28
|
@ -772,6 +772,7 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
//This should never happen. It means there's an invalid offset value coming through
|
//This should never happen. It means there's an invalid offset value coming through
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fuelTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case veSetPage:
|
case veSetPage:
|
||||||
|
@ -794,7 +795,7 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
if (valueOffset < 272)
|
if (valueOffset < 272)
|
||||||
{
|
{
|
||||||
//X Axis
|
//X Axis
|
||||||
ignitionTable.axisX[(valueOffset - 256)] = (int)(newValue) * TABLE_RPM_MULTIPLIER; //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct
|
ignitionTable.axisX[(valueOffset - 256)] = (int)(newValue) * TABLE_RPM_MULTIPLIER; //The RPM values sent by TunerStudio are divided by 100, need to multiple it back by 100 to make it correct
|
||||||
}
|
}
|
||||||
else if(valueOffset < 288)
|
else if(valueOffset < 288)
|
||||||
{
|
{
|
||||||
|
@ -803,6 +804,7 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
ignitionTable.axisY[tempOffset] = (int)(newValue) * TABLE_LOAD_MULTIPLIER;
|
ignitionTable.axisY[tempOffset] = (int)(newValue) * TABLE_LOAD_MULTIPLIER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ignitionTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ignSetPage:
|
case ignSetPage:
|
||||||
|
@ -825,7 +827,7 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
if (valueOffset < 272)
|
if (valueOffset < 272)
|
||||||
{
|
{
|
||||||
//X Axis
|
//X Axis
|
||||||
afrTable.axisX[(valueOffset - 256)] = int(newValue) * TABLE_RPM_MULTIPLIER; //The RPM values sent by megasquirt are divided by 100, need to multiply it back by 100 to make it correct (TABLE_RPM_MULTIPLIER)
|
afrTable.axisX[(valueOffset - 256)] = int(newValue) * TABLE_RPM_MULTIPLIER; //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct (TABLE_RPM_MULTIPLIER)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -835,6 +837,7 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
afrTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case afrSetPage:
|
case afrSetPage:
|
||||||
|
@ -891,6 +894,9 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
tempOffset = valueOffset - 232;
|
tempOffset = valueOffset - 232;
|
||||||
stagingTable.axisY[(7 - tempOffset)] = int(newValue) * TABLE_LOAD_MULTIPLIER;
|
stagingTable.axisY[(7 - tempOffset)] = int(newValue) * TABLE_LOAD_MULTIPLIER;
|
||||||
}
|
}
|
||||||
|
boostTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
|
vvtTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
|
stagingTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case seqFuelPage:
|
case seqFuelPage:
|
||||||
|
@ -910,6 +916,10 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
else if (valueOffset < 186) { tempOffset = valueOffset - 180; trim4Table.axisX[tempOffset] = int(newValue) * TABLE_RPM_MULTIPLIER; } //New value is on the X (RPM) axis of the table. The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct (TABLE_RPM_MULTIPLIER)
|
else if (valueOffset < 186) { tempOffset = valueOffset - 180; trim4Table.axisX[tempOffset] = int(newValue) * TABLE_RPM_MULTIPLIER; } //New value is on the X (RPM) axis of the table. The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct (TABLE_RPM_MULTIPLIER)
|
||||||
else if (valueOffset < 192) { tempOffset = valueOffset - 186; trim4Table.axisY[(5 - tempOffset)] = int(newValue) * TABLE_LOAD_MULTIPLIER; } //New value is on the Y (Load) axis of the table
|
else if (valueOffset < 192) { tempOffset = valueOffset - 186; trim4Table.axisY[(5 - tempOffset)] = int(newValue) * TABLE_LOAD_MULTIPLIER; } //New value is on the Y (Load) axis of the table
|
||||||
|
|
||||||
|
trim1Table.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
|
trim2Table.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
|
trim3Table.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
|
trim4Table.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case canbusPage:
|
case canbusPage:
|
||||||
|
@ -954,6 +964,7 @@ void receiveValue(uint16_t valueOffset, byte newValue)
|
||||||
//This should never happen. It means there's an invalid offset value coming through
|
//This should never happen. It means there's an invalid offset value coming through
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fuelTable2.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct table2D {
|
||||||
//Store the last input and output for caching
|
//Store the last input and output for caching
|
||||||
int16_t lastInput;
|
int16_t lastInput;
|
||||||
int16_t lastOutput;
|
int16_t lastOutput;
|
||||||
byte cacheTime; //TRacks when the last cache value was set so it can expire after x seconds. A timeout is required to pickup when a tuning value is changed, otherwise the old cached value will continue to be returned as the X value isn't changing.
|
byte cacheTime; //Tracks when the last cache value was set so it can expire after x seconds. A timeout is required to pickup when a tuning value is changed, otherwise the old cached value will continue to be returned as the X value isn't changing.
|
||||||
};
|
};
|
||||||
|
|
||||||
//void table2D_setSize(struct table2D targetTable, byte newSize);
|
//void table2D_setSize(struct table2D targetTable, byte newSize);
|
||||||
|
@ -52,6 +52,11 @@ struct table3D {
|
||||||
//Store the last X and Y coordinates in the table. This is used to make the next check faster
|
//Store the last X and Y coordinates in the table. This is used to make the next check faster
|
||||||
byte lastXMax, lastXMin;
|
byte lastXMax, lastXMin;
|
||||||
byte lastYMax, lastYMin;
|
byte lastYMax, lastYMin;
|
||||||
|
|
||||||
|
//Store the last input and output values, again for caching purposes
|
||||||
|
int16_t lastXInput, lastYInput;
|
||||||
|
byte lastOutput; //This will need changing if we ever have 16-bit table values
|
||||||
|
bool cacheIsValid; ///< This tracks whether the tables cache should be used. Ordinarily this is true, but is set to false whenever TunerStudio sends a new value for the table
|
||||||
};
|
};
|
||||||
|
|
||||||
//void table3D_setSize(struct table3D *targetTable, byte);
|
//void table3D_setSize(struct table3D *targetTable, byte);
|
||||||
|
|
|
@ -48,177 +48,17 @@ void table3D_setSize(struct table3D *targetTable, byte newSize)
|
||||||
targetTable->axisY = (int16_t *)malloc(newSize * sizeof(int16_t));
|
targetTable->axisY = (int16_t *)malloc(newSize * sizeof(int16_t));
|
||||||
targetTable->xSize = newSize;
|
targetTable->xSize = newSize;
|
||||||
targetTable->ySize = newSize;
|
targetTable->ySize = newSize;
|
||||||
|
targetTable->cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values
|
||||||
} //initialisationComplete
|
} //initialisationComplete
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This function simply pulls a 1D linear interpolated (ie averaged) value from a 2D table
|
This function pulls a 1D linear interpolated (ie averaged) value from a 2D table
|
||||||
ie: Given a value on the X axis, it returns a Y value that coresponds to the point on the curve between the nearest two defined X values
|
ie: Given a value on the X axis, it returns a Y value that coresponds to the point on the curve between the nearest two defined X values
|
||||||
|
|
||||||
This function must take into account whether a table contains 8-bit or 16-bit values.
|
This function must take into account whether a table contains 8-bit or 16-bit values.
|
||||||
Unfortunately this means many of the lines are duplicated depending on this
|
Unfortunately this means many of the lines are duplicated depending on this
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
int table2D_getValue_orig(struct table2D *fromTable, int X_in)
|
|
||||||
{
|
|
||||||
int returnValue = 0;
|
|
||||||
bool valueFound = false;
|
|
||||||
|
|
||||||
int X = X_in;
|
|
||||||
int xMinValue, xMaxValue;
|
|
||||||
int xMin = 0;
|
|
||||||
int xMax = 0;
|
|
||||||
|
|
||||||
//Check whether the X input is the same as last time this ran
|
|
||||||
if( (X_in == fromTable->lastInput) && (fromTable->cacheTime == currentStatus.secl) )
|
|
||||||
{
|
|
||||||
returnValue = fromTable->lastOutput;
|
|
||||||
valueFound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fromTable->cacheTime = currentStatus.secl; //As we're not using the cache value, set the current secl value to track when this new value was calc'd
|
|
||||||
|
|
||||||
if (fromTable->valueSize == SIZE_BYTE)
|
|
||||||
{
|
|
||||||
//Byte version
|
|
||||||
xMinValue = fromTable->axisX[0];
|
|
||||||
xMaxValue = fromTable->axisX[fromTable->xSize-1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//int version
|
|
||||||
xMinValue = fromTable->axisX16[0];
|
|
||||||
xMaxValue = fromTable->axisX16[fromTable->xSize-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
//If the requested X value is greater/small than the maximum/minimum bin, reset X to be that value
|
|
||||||
if(X > xMaxValue) { X = xMaxValue; }
|
|
||||||
if(X < xMinValue) { X = xMinValue; }
|
|
||||||
|
|
||||||
|
|
||||||
if (fromTable->valueSize == SIZE_BYTE)
|
|
||||||
{
|
|
||||||
//**** Byte version ****
|
|
||||||
|
|
||||||
//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]) )
|
|
||||||
{
|
|
||||||
xMaxValue = fromTable->axisX[fromTable->lastXMax];
|
|
||||||
xMinValue = fromTable->axisX[fromTable->lastXMin];
|
|
||||||
xMax = fromTable->lastXMax;
|
|
||||||
xMin = fromTable->lastXMin;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//If we're not in the same bin, loop through to find where we are
|
|
||||||
for (int x = fromTable->xSize-1; x >= 0; x--)
|
|
||||||
{
|
|
||||||
//Checks the case where the X value is exactly what was requested
|
|
||||||
if ( (X == fromTable->axisX[x]) || (x == 0) )
|
|
||||||
{
|
|
||||||
returnValue = fromTable->values[x]; //Simply return the coresponding value
|
|
||||||
valueFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Normal case
|
|
||||||
if ( (X <= fromTable->axisX[x]) && (X > fromTable->axisX[x-1]) )
|
|
||||||
{
|
|
||||||
xMaxValue = fromTable->axisX[x];
|
|
||||||
xMinValue = fromTable->axisX[x-1];
|
|
||||||
xMax = x;
|
|
||||||
fromTable->lastXMax = xMax;
|
|
||||||
xMin = x-1;
|
|
||||||
fromTable->lastXMin = xMin;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// **** INT VERSION ****
|
|
||||||
|
|
||||||
//1st check is whether we're still in the same X bin as last time
|
|
||||||
if ( (X <= fromTable->axisX16[fromTable->lastXMax]) && (X > fromTable->axisX16[fromTable->lastXMin]) )
|
|
||||||
{
|
|
||||||
xMaxValue = fromTable->axisX16[fromTable->lastXMax];
|
|
||||||
xMinValue = fromTable->axisX16[fromTable->lastXMin];
|
|
||||||
xMax = fromTable->lastXMax;
|
|
||||||
xMin = fromTable->lastXMin;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//If we're not in the same bin, loop through to find where we are
|
|
||||||
for (int x = fromTable->xSize-1; x >= 0; x--)
|
|
||||||
{
|
|
||||||
//Checks the case where the X value is exactly what was requested
|
|
||||||
if ( (X == fromTable->axisX16[x]) || (x == 0) )
|
|
||||||
{
|
|
||||||
returnValue = fromTable->values16[x]; //Simply return the coresponding value
|
|
||||||
valueFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Normal case
|
|
||||||
if ( (X <= fromTable->axisX16[x]) && (X > fromTable->axisX16[x-1]) )
|
|
||||||
{
|
|
||||||
xMaxValue = fromTable->axisX16[x];
|
|
||||||
xMinValue = fromTable->axisX16[x-1];
|
|
||||||
xMax = x;
|
|
||||||
fromTable->lastXMax = xMax;
|
|
||||||
xMin = x-1;
|
|
||||||
fromTable->lastXMin = xMin;
|
|
||||||
break;
|
|
||||||
} //Found in loop
|
|
||||||
} //Exact hit
|
|
||||||
} //For loop
|
|
||||||
} //In cache or not
|
|
||||||
} //byte or int values
|
|
||||||
} //X_in same as last time
|
|
||||||
|
|
||||||
if (valueFound == false)
|
|
||||||
{
|
|
||||||
unsigned int m = X - xMinValue;
|
|
||||||
unsigned int n = xMaxValue - xMinValue;
|
|
||||||
|
|
||||||
//Float version
|
|
||||||
//int yVal = (m / n) * (abs(fromTable.values[xMax] - fromTable.values[xMin]));
|
|
||||||
|
|
||||||
//Non-Float version
|
|
||||||
uint16_t yVal;
|
|
||||||
if (fromTable->valueSize == SIZE_BYTE)
|
|
||||||
{
|
|
||||||
//Byte version
|
|
||||||
yVal = ((long)(m << 6) / n) * (abs(fromTable->values[xMax] - fromTable->values[xMin]));
|
|
||||||
yVal = (yVal >> 6);
|
|
||||||
|
|
||||||
if (fromTable->values[xMax] > fromTable->values[xMin]) { yVal = fromTable->values[xMin] + yVal; }
|
|
||||||
else { yVal = fromTable->values[xMin] - yVal; }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//int version
|
|
||||||
yVal = ((long)(m << 6) / n) * (abs(fromTable->values16[xMax] - fromTable->values16[xMin]));
|
|
||||||
yVal = (yVal >> 6);
|
|
||||||
|
|
||||||
if (fromTable->values[xMax] > fromTable->values16[xMin]) { yVal = fromTable->values16[xMin] + yVal; }
|
|
||||||
else { yVal = fromTable->values16[xMin] - yVal; }
|
|
||||||
}
|
|
||||||
returnValue = yVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
fromTable->lastInput = X_in;
|
|
||||||
fromTable->lastOutput = returnValue;
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int table2D_getValue(struct table2D *fromTable, int X_in)
|
int table2D_getValue(struct table2D *fromTable, int X_in)
|
||||||
{
|
{
|
||||||
//Orig memory usage = 5414
|
//Orig memory usage = 5414
|
||||||
|
@ -374,6 +214,14 @@ int get3DTableValue(struct table3D *fromTable, int Y_in, int X_in)
|
||||||
if(X > xMaxValue) { X = xMaxValue; }
|
if(X > xMaxValue) { X = xMaxValue; }
|
||||||
if(X < xMinValue) { X = xMinValue; }
|
if(X < xMinValue) { X = xMinValue; }
|
||||||
|
|
||||||
|
//0th check is whether the same X and Y values are being sent as last time. If they are, this not only prevents a lookup of the axis, but prevents the interpolation calcs being performed
|
||||||
|
if( (X_in == fromTable->lastXInput) && (Y_in == fromTable->lastYInput) && (fromTable->cacheIsValid == true))
|
||||||
|
{
|
||||||
|
return fromTable->lastOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Commence the lookups on the X and Y axis
|
||||||
|
|
||||||
//1st check is whether we're still in the same X bin as last time
|
//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]) )
|
if ( (X <= fromTable->axisX[fromTable->lastXMax]) && (X > fromTable->axisX[fromTable->lastXMin]) )
|
||||||
{
|
{
|
||||||
|
@ -558,5 +406,12 @@ int get3DTableValue(struct table3D *fromTable, int Y_in, int X_in)
|
||||||
int r = (p * q) >> 8;
|
int r = (p * q) >> 8;
|
||||||
tableResult = ( (A * m) + (B * n) + (C * o) + (D * r) ) >> 8;
|
tableResult = ( (A * m) + (B * n) + (C * o) + (D * r) ) >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Update the tables cache data
|
||||||
|
fromTable->lastXInput = X_in;
|
||||||
|
fromTable->lastYInput = Y_in;
|
||||||
|
fromTable->lastOutput = tableResult;
|
||||||
|
fromTable->cacheIsValid = true;
|
||||||
|
|
||||||
return tableResult;
|
return tableResult;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue