SUPER experimental new version of 2D table lookup. See #270
This commit is contained in:
parent
9b96707036
commit
91206ac90e
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue