SUPER experimental new version of 2D table lookup. See #270

This commit is contained in:
Josh Stewart 2019-10-29 22:50:46 +11:00
parent 9b96707036
commit 91206ac90e
5 changed files with 193 additions and 17 deletions

View File

@ -97,11 +97,13 @@ static inline byte correctionWUE()
{
byte WUEValue;
//Possibly reduce the frequency this runs at (Costs about 50 loops per second)
if (currentStatus.coolant > (WUETable.axisX[9] - CALIBRATION_TEMPERATURE_OFFSET))
//if (currentStatus.coolant > (WUETable.axisX[9] - CALIBRATION_TEMPERATURE_OFFSET))
if (currentStatus.coolant > (table2D_getAxisValue(&WUETable, 9) - CALIBRATION_TEMPERATURE_OFFSET))
{
//This prevents us doing the 2D lookup if we're already up to temp
BIT_CLEAR(currentStatus.engine, BIT_ENGINE_WARMUP);
WUEValue = WUETable.values[9]; //Set the current value to be whatever the final value on the curve is.
//WUEValue = WUETable.values[9]; //Set the current value to be whatever the final value on the curve is.
WUEValue = table2D_getAxisValue(&WUETable, 9);
}
else
{
@ -298,8 +300,7 @@ Uses a 2D enrichment table (WUETable) where the X axis is engine temp and the Y
static inline byte correctionBatVoltage()
{
byte batValue = 100;
if (currentStatus.battery10 > (injectorVCorrectionTable.axisX[5])) { batValue = injectorVCorrectionTable.values[injectorVCorrectionTable.xSize-1]; } //This prevents us doing the 2D lookup if the voltage is above maximum
else { batValue = table2D_getValue(&injectorVCorrectionTable, currentStatus.battery10); }
batValue = table2D_getValue(&injectorVCorrectionTable, currentStatus.battery10);
return batValue;
}
@ -311,8 +312,7 @@ This corrects for changes in air density from movement of the temperature
static inline byte correctionIATDensity()
{
byte IATValue = 100;
if ( (currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET) > (IATDensityCorrectionTable.axisX[8])) { IATValue = IATDensityCorrectionTable.values[IATDensityCorrectionTable.xSize-1]; } //This prevents us doing the 2D lookup if the intake temp is above maximum
else { IATValue = table2D_getValue(&IATDensityCorrectionTable, currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); }//currentStatus.IAT is the actual temperature, values in IATDensityCorrectionTable.axisX are temp+offset
IATValue = table2D_getValue(&IATDensityCorrectionTable, currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //currentStatus.IAT is the actual temperature, values in IATDensityCorrectionTable.axisX are temp+offset
return IATValue;
}

View File

@ -263,7 +263,7 @@ void idleControl()
doStep();
}
else if( (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < iacStepTable.axisX[IDLE_TABLE_SIZE-1])
else if( (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < table2D_getAxisValue(&iacStepTable, (IDLE_TABLE_SIZE-1)) )
{
//Standard running
//We must also have more than zero RPM for the running state

View File

@ -57,78 +57,95 @@ void initialiseAll()
//Repoint the 2D table structs to the config pages that were just loaded
taeTable.valueSize = SIZE_BYTE; //Set this table to use byte values
taeTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
taeTable.xSize = 4;
taeTable.values = configPage4.taeValues;
taeTable.axisX = configPage4.taeBins;
maeTable.valueSize = SIZE_BYTE; //Set this table to use byte values
maeTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
maeTable.xSize = 4;
maeTable.values = configPage4.maeRates;
maeTable.axisX = configPage4.maeBins;
WUETable.valueSize = SIZE_BYTE; //Set this table to use byte values
WUETable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
WUETable.xSize = 10;
WUETable.values = configPage2.wueValues;
WUETable.axisX = configPage4.wueBins;
ASETable.valueSize = SIZE_BYTE;
ASETable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
ASETable.xSize = 4;
ASETable.values = configPage2.asePct;
ASETable.axisX = configPage2.aseBins;
ASECountTable.valueSize = SIZE_BYTE;
ASECountTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
ASECountTable.xSize = 4;
ASECountTable.values = configPage2.aseCount;
ASECountTable.axisX = configPage2.aseBins;
PrimingPulseTable.valueSize = SIZE_BYTE;
PrimingPulseTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
PrimingPulseTable.xSize = 4;
PrimingPulseTable.values = configPage2.primePulse;
PrimingPulseTable.axisX = configPage2.primeBins;
crankingEnrichTable.valueSize = SIZE_BYTE;
crankingEnrichTable.valueSize = SIZE_BYTE;
crankingEnrichTable.axisSize = SIZE_BYTE;
crankingEnrichTable.xSize = 4;
crankingEnrichTable.values = configPage10.crankingEnrichValues;
crankingEnrichTable.axisX = configPage10.crankingEnrichBins;
dwellVCorrectionTable.valueSize = SIZE_BYTE;
dwellVCorrectionTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
dwellVCorrectionTable.xSize = 6;
dwellVCorrectionTable.values = configPage4.dwellCorrectionValues;
dwellVCorrectionTable.axisX = configPage6.voltageCorrectionBins;
injectorVCorrectionTable.valueSize = SIZE_BYTE;
injectorVCorrectionTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
injectorVCorrectionTable.xSize = 6;
injectorVCorrectionTable.values = configPage6.injVoltageCorrectionValues;
injectorVCorrectionTable.axisX = configPage6.voltageCorrectionBins;
IATDensityCorrectionTable.valueSize = SIZE_BYTE;
IATDensityCorrectionTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
IATDensityCorrectionTable.xSize = 9;
IATDensityCorrectionTable.values = configPage6.airDenRates;
IATDensityCorrectionTable.axisX = configPage6.airDenBins;
IATRetardTable.valueSize = SIZE_BYTE;
IATRetardTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
IATRetardTable.xSize = 6;
IATRetardTable.values = configPage4.iatRetValues;
IATRetardTable.axisX = configPage4.iatRetBins;
CLTAdvanceTable.valueSize = SIZE_BYTE;
CLTAdvanceTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
CLTAdvanceTable.xSize = 6;
CLTAdvanceTable.values = (byte*)configPage4.cltAdvValues;
CLTAdvanceTable.axisX = configPage4.cltAdvBins;
rotarySplitTable.valueSize = SIZE_BYTE;
rotarySplitTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
rotarySplitTable.xSize = 8;
rotarySplitTable.values = configPage10.rotarySplitValues;
rotarySplitTable.axisX = configPage10.rotarySplitBins;
flexFuelTable.valueSize = SIZE_BYTE;
flexFuelTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
flexFuelTable.xSize = 6;
flexFuelTable.values = configPage10.flexFuelAdj;
flexFuelTable.axisX = configPage10.flexFuelBins;
flexAdvTable.valueSize = SIZE_BYTE;
flexAdvTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
flexAdvTable.xSize = 6;
flexAdvTable.values = configPage10.flexAdvAdj;
flexAdvTable.axisX = configPage10.flexAdvBins;
flexBoostTable.valueSize = SIZE_INT;
flexBoostTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins (NOTE THIS IS DIFFERENT TO THE VALUES!!)
flexBoostTable.xSize = 6;
flexBoostTable.values16 = configPage10.flexBoostAdj;
flexBoostTable.values = configPage10.flexBoostAdj;
flexBoostTable.axisX = configPage10.flexBoostBins;
knockWindowStartTable.valueSize = SIZE_BYTE;
knockWindowStartTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
knockWindowStartTable.xSize = 6;
knockWindowStartTable.values = configPage10.knock_window_angle;
knockWindowStartTable.axisX = configPage10.knock_window_rpms;
knockWindowDurationTable.valueSize = SIZE_BYTE;
knockWindowDurationTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
knockWindowDurationTable.xSize = 6;
knockWindowDurationTable.values = configPage10.knock_window_dur;
knockWindowDurationTable.axisX = configPage10.knock_window_rpms;

View File

@ -12,14 +12,16 @@ The 2D table can contain either 8-bit (byte) or 16-bit (int) values
The valueSize variable should be set to either 8 or 16 to indicate this BEFORE the table is used
*/
struct table2D {
//Used 5414 RAM with original version
byte valueSize;
byte axisSize;
byte xSize;
byte *values;
byte *axisX;
void *values;
void *axisX;
int16_t *values16;
int16_t *axisX16;
//int16_t *values16;
//int16_t *axisX16;
//Store the last X and Y coordinates in the table. This is used to make the next check faster
int16_t lastXMax;
@ -33,6 +35,8 @@ struct table2D {
//void table2D_setSize(struct table2D targetTable, byte newSize);
void table2D_setSize(struct table2D, byte);
int16_t table2D_getAxisValue(struct table2D, byte);
int16_t table2D_getRawValue(struct table2D, byte);
struct table3D {

View File

@ -11,6 +11,7 @@ Note that this may clear some of the existing values of the table
#include "table.h"
#include "globals.h"
/*
void table2D_setSize(struct table2D* targetTable, byte newSize)
{
//Table resize is ONLY permitted during system initialisation.
@ -33,6 +34,7 @@ void table2D_setSize(struct table2D* targetTable, byte newSize)
} //Byte or int
} //initialisationComplete
}
*/
void table3D_setSize(struct table3D *targetTable, byte newSize)
@ -56,7 +58,8 @@ ie: Given a value on the X axis, it returns a Y value that coresponds to the poi
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
*/
int table2D_getValue(struct table2D *fromTable, int X_in)
/*
int table2D_getValue_orig(struct table2D *fromTable, int X_in)
{
int returnValue = 0;
bool valueFound = false;
@ -184,9 +187,7 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
unsigned int n = xMaxValue - xMinValue;
//Float version
/*
int yVal = (m / n) * (abs(fromTable.values[xMax] - fromTable.values[xMin]));
*/
//int yVal = (m / n) * (abs(fromTable.values[xMax] - fromTable.values[xMin]));
//Non-Float version
uint16_t yVal;
@ -216,6 +217,160 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
return returnValue;
}
*/
int table2D_getValue(struct table2D *fromTable, int X_in)
{
//Orig memory usage = 5414
int returnValue = 0;
bool valueFound = false;
//Copy the from table values (bytes or ints) into common int temp arrays
int tempAxisX[fromTable->xSize];
int tempValues[fromTable->xSize];
for(byte x=0; x< fromTable->xSize; x++)
{
if(fromTable->valueSize == SIZE_INT) { tempValues[x] = ((int16_t*)((*fromTable).values))[x]; }
else if(fromTable->valueSize == SIZE_BYTE) { tempValues[x] = ((uint8_t*)((*fromTable).values))[x]; }
if(fromTable->axisSize == SIZE_INT) { tempAxisX[x] = ((int16_t*)((*fromTable).axisX))[x]; }
else if(fromTable->axisSize == SIZE_BYTE) { tempAxisX[x] = ((uint8_t*)((*fromTable).axisX))[x]; }
}
int X = X_in;
int xMinValue, xMaxValue;
int xMin = 0;
int xMax = 0;
xMinValue = tempAxisX[0];
xMaxValue = tempAxisX[fromTable->xSize-1];
//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;
}
//If the requested X value is greater/small than the maximum/minimum bin, reset X to be that value
else if(X > xMaxValue)
{
returnValue = tempValues[fromTable->xSize-1];
valueFound = true;
}
else if(X < xMinValue)
{
returnValue = tempValues[0];
valueFound = true;
}
//Finally if none of that is found
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 the requested X value is greater/small than the maximum/minimum bin, reset X to be that value
//Failsafe, this should've been handled above
if(X > xMaxValue) { X = xMaxValue; }
if(X < xMinValue) { X = xMinValue; }
//1st check is whether we're still in the same X bin as last time
if ( (X <= tempAxisX[fromTable->lastXMax]) && (X > tempAxisX[fromTable->lastXMin]) )
{
xMaxValue = tempAxisX[fromTable->lastXMax];
xMinValue = tempAxisX[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 == tempAxisX[x]) || (x == 0) )
{
returnValue = tempValues[x]; //Simply return the coresponding value
valueFound = true;
break;
}
else
{
//Normal case
if ( (X <= tempAxisX[x]) && (X > tempAxisX[x-1]) )
{
xMaxValue = tempAxisX[x];
xMinValue = tempAxisX[x-1];
xMax = x;
fromTable->lastXMax = xMax;
xMin = x-1;
fromTable->lastXMin = xMin;
break;
}
}
}
}
} //X_in same as last time
if (valueFound == false)
{
int16_t m = X - xMinValue;
int16_t n = xMaxValue - xMinValue;
//Float version
/*
int yVal = (m / n) * (abs(fromTable.values[xMax] - fromTable.values[xMin]));
*/
//Non-Float version
int16_t yVal;
yVal = ((long)(m << 6) / n) * (abs(tempValues[xMax] - tempValues[xMin]));
yVal = (yVal >> 6);
if (tempValues[xMax] > tempValues[xMin]) { yVal = tempValues[xMin] + yVal; }
else { yVal = tempValues[xMin] - yVal; }
returnValue = yVal;
}
fromTable->lastInput = X_in;
fromTable->lastOutput = returnValue;
return returnValue;
}
/**
* @brief Returns an axis (bin) value from the 2D table. This works regardless of whether that axis is bytes or int16_ts
*
* @param fromTable
* @param X_in
* @return int16_t
*/
int16_t table2D_getAxisValue(struct table2D *fromTable, byte X_in)
{
int returnValue = 0;
if(fromTable->axisSize == SIZE_INT) { returnValue = ((int16_t*)((*fromTable).axisX))[X_in]; }
else if(fromTable->axisSize == SIZE_BYTE) { returnValue = ((uint8_t*)((*fromTable).axisX))[X_in]; }
return returnValue;
}
/**
* @brief Returns an value from the 2D table given an index value. No interpolation is performed
*
* @param fromTable
* @param X_in
* @return int16_t
*/
int16_t table2D_getRawValue(struct table2D *fromTable, byte X_index)
{
int returnValue = 0;
if(fromTable->valueSize == SIZE_INT) { returnValue = ((int16_t*)((*fromTable).values))[X_index]; }
else if(fromTable->valueSize == SIZE_BYTE) { returnValue = ((uint8_t*)((*fromTable).values))[X_index]; }
return returnValue;
}
//This function pulls a value from a 3D table given a target for X and Y coordinates.