FreeEMS  0.2.0-SNAPSHOT-285-g028e24c
Macros | Functions
tableLookup.c File Reference

Table access functions. More...

#include "inc/freeEMS.h"
#include "inc/commsISRs.h"
#include "inc/tableLookup.h"
#include "inc/blockDetailsLookup.h"
Include dependency graph for tableLookup.c:

Go to the source code of this file.

Macros

#define TABLELOOKUP_C

Functions

unsigned short lookupMainTable (unsigned short realRPM, unsigned short realLoad, unsigned short locationID)
 Main table read function.
unsigned short lookupTwoDTableUS (twoDTableUS *Table, unsigned short Value)
 Two D table read function.
unsigned short validateMainTable (mainTable *Table)
 Validate a main table.
unsigned short validateTwoDTable (twoDTableUS *Table)
 Validate a two D table.

Detailed Description

Table access functions.

Functions for writing to and reading from all of the different table types.

Definition in file tableLookup.c.

Macro Definition Documentation

#define TABLELOOKUP_C

Definition at line 35 of file tableLookup.c.

Function Documentation

unsigned short lookupMainTable ( unsigned short  realRPM,
unsigned short  realLoad,
unsigned short  locationID 
)

Main table read function.

Looks up a value from a main table using interpolation.

The process :

Take a table with two movable axis sets and two axis lengths, loop to find which pairs of axis values and indexs we are between, interpolate two pairs down to two values, interpolate two values down to one value.

Table size :

To reduce the table size from 19x24 to something smaller, simply reduce the RPMLength and LoadLength fields to lower values. Increasing the size of either axis is not currently possible.

Values outside the table :

Given that the axis lists are in order, a data point outside the table will give the value adjacent to it, and one outside one of the four corners will give the corner value. This is a clean and reasonable behaviour in my opinion.

Reminder : X/RPM is horizontal, Y/Load is vertical

Warning
This function relies on the axis values being a sorted list from low to high. If this is not the case behaviour is undefined and could include memory corruption and engine damage.
Parameters
realRPMis the current RPM for which a table value is required.
realLoadis the current load for which a table value is required.
locationIDthe ID to use to get the memory information to look up the table.

May go back to these: old param RAMPage is the RAM page that the table is stored in. old param Table is a pointer to the table to read from.

Returns
The interpolated value for the location specified.

Definition at line 112 of file tableLookup.c.

References block_is_main_table, blockDetails::flags, mainTable::Load, mainTable::LoadLength, lookupBlockDetails(), blockDetails::RAMAddress, blockDetails::RAMPage, RPAGE, mainTable::RPM, mainTable::RPMLength, and mainTable::Table.

Referenced by calculateFuelAndIgnition(), and generateDerivedVars().

{
blockDetails mainTableDetails;
lookupBlockDetails(locationID, &mainTableDetails);
if(!(mainTableDetails.flags & block_is_main_table)){
return 0; // Safe value, always means no fuel or TDC timing.
}
// Leave the rest of the code untouched and keep it more concise
mainTable* Table = (mainTable*)mainTableDetails.RAMAddress;
/* Save the RPAGE value for restoration and switch pages. */
unsigned char oldRPage = RPAGE;
RPAGE = mainTableDetails.RAMPage;
/* Find the bounding axis values and indices for RPM */
unsigned char lowRPMIndex = 0;
unsigned char highRPMIndex = Table->RPMLength - 1;
/* If never set in the loop, low value will equal high value and will be on the edge of the map */
unsigned short lowRPMValue = Table->RPM[0];
unsigned short highRPMValue = Table->RPM[Table->RPMLength -1];
unsigned char RPMIndex;
for(RPMIndex=0;RPMIndex<Table->RPMLength;RPMIndex++){
if(Table->RPM[RPMIndex] < realRPM){
lowRPMValue = Table->RPM[RPMIndex];
lowRPMIndex = RPMIndex;
}else if(Table->RPM[RPMIndex] > realRPM){
highRPMValue = Table->RPM[RPMIndex];
highRPMIndex = RPMIndex;
break;
}else if(Table->RPM[RPMIndex] == realRPM){
lowRPMValue = Table->RPM[RPMIndex];
highRPMValue = Table->RPM[RPMIndex];
lowRPMIndex = RPMIndex;
highRPMIndex = RPMIndex;
break;
}
}
/* Find the bounding cell values and indices for Load */
unsigned char lowLoadIndex = 0;
unsigned char highLoadIndex = Table->LoadLength -1;
/* If never set in the loop, low value will equal high value and will be on the edge of the map */
unsigned short lowLoadValue = Table->Load[0];
unsigned short highLoadValue = Table->Load[Table->LoadLength -1];
unsigned char LoadIndex;
for(LoadIndex=0;LoadIndex<Table->LoadLength;LoadIndex++){
if(Table->Load[LoadIndex] < realLoad){
lowLoadValue = Table->Load[LoadIndex];
lowLoadIndex = LoadIndex;
}else if(Table->Load[LoadIndex] > realLoad){
highLoadValue = Table->Load[LoadIndex];
highLoadIndex = LoadIndex;
break;
}else if(Table->Load[LoadIndex] == realLoad){
lowLoadValue = Table->Load[LoadIndex];
highLoadValue = Table->Load[LoadIndex];
lowLoadIndex = LoadIndex;
highLoadIndex = LoadIndex;
break;
}
}
/* Obtain the four corners surrounding the spot of interest */
unsigned short lowRPMLowLoad = Table->Table[(Table->RPMLength * lowLoadIndex) + lowRPMIndex];
unsigned short lowRPMHighLoad = Table->Table[(Table->RPMLength * highLoadIndex) + lowRPMIndex];
unsigned short highRPMLowLoad = Table->Table[(Table->RPMLength * lowLoadIndex) + highRPMIndex];
unsigned short highRPMHighLoad = Table->Table[(Table->RPMLength * highLoadIndex) + highRPMIndex];
/* Restore the RAM page before doing the math */
RPAGE = oldRPage;
/* Find the two side values to interpolate between by interpolation */
unsigned short lowRPMIntLoad = lowRPMLowLoad + (((signed long)((signed long)lowRPMHighLoad - lowRPMLowLoad) * (realLoad - lowLoadValue))/ (highLoadValue - lowLoadValue));
unsigned short highRPMIntLoad = highRPMLowLoad + (((signed long)((signed long)highRPMHighLoad - highRPMLowLoad) * (realLoad - lowLoadValue))/ (highLoadValue - lowLoadValue));
/* Interpolate between the two side values and return the result */
return lowRPMIntLoad + (((signed long)((signed long)highRPMIntLoad - lowRPMIntLoad) * (realRPM - lowRPMValue))/ (highRPMValue - lowRPMValue));
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned short lookupTwoDTableUS ( twoDTableUS Table,
unsigned short  Value 
)

Two D table read function.

Looks up a value from a two D table using interpolation.

Parameters
Tableis a pointer to the table to read from.
Valueis the position value used to lookup the return value.
Returns
the interpolated value for the position specified

Definition at line 203 of file tableLookup.c.

References twoDTableUS::Axis, and twoDTableUS::Values.

Referenced by calculateFuelAndIgnition(), decodePacketAndRespond(), generateDerivedVars(), and main().

{
/* If never set in the loop, low value will equal high value and will be on the edge of the map */
unsigned short lowAxisValue = Table->Axis[0];
unsigned short highAxisValue = Table->Axis[15];
unsigned short lowLookupValue = Table->Values[0];
unsigned short highLookupValue = Table->Values[15];
/* Find the bounding axis values and lookup values */
unsigned char Index;
for(Index=0;Index<16;Index++){
if(Table->Axis[Index] < Value){
lowAxisValue = Table->Axis[Index];
lowLookupValue = Table->Values[Index];
}else if(Table->Axis[Index] > Value){
highAxisValue = Table->Axis[Index];
highLookupValue = Table->Values[Index];
break;
}else if(Table->Axis[Index] == Value){
return Table->Values[Index]; // If right on, just return the value
}
}
/* Interpolate and return the value */
return lowLookupValue + (((signed long)((signed long)highLookupValue - lowLookupValue) * (Value - lowAxisValue))/ (highAxisValue - lowAxisValue));
}

Here is the caller graph for this function:

unsigned short validateMainTable ( mainTable Table)

Validate a main table.

Check that the configuration of the table is valid. Assumes pages are correctly set.

Todo:
more detail here....
Parameters
Tableis a pointer to the table to be validated.
Returns
An error code. Zero means success, anything else is a failure.

Definition at line 240 of file tableLookup.c.

References invalidMainTableLoadLength, invalidMainTableLoadOrder, invalidMainTableMainLength, invalidMainTableRPMLength, invalidMainTableRPMOrder, mainTable::Load, mainTable::LoadLength, MAINTABLE_MAX_LOAD_LENGTH, MAINTABLE_MAX_MAIN_LENGTH, MAINTABLE_MAX_RPM_LENGTH, mainTable::RPM, and mainTable::RPMLength.

Referenced by decodePacketAndRespond().

{
/* If required and only if required extend this to take r and f pages and check */
/* any main table, not just a freshly received untrusted ones in linear space */
}else if((Table->RPMLength * Table->LoadLength) > MAINTABLE_MAX_MAIN_LENGTH){
}else{
/* Check the order of the RPM axis */
unsigned char i;
for(i=0;i<(Table->RPMLength - 1);i++){
if(Table->RPM[i] >= Table->RPM[i+1]){
}
}
/* Check the order of the Load axis */
unsigned char j;
for(j=0;j<(Table->LoadLength - 1);j++){
if(Table->Load[j] >= Table->Load[j+1]){
}
}
/* If we made it this far all is well */
return 0;
}
}

Here is the caller graph for this function:

unsigned short validateTwoDTable ( twoDTableUS Table)

Validate a two D table.

Check that the order of the axis values is correct and therefore that the table is valid too.

Parameters
Tableis a pointer to the table to be validated.
Returns
An error code. Zero means success, anything else is a failure.

Definition at line 280 of file tableLookup.c.

References twoDTableUS::Axis, invalidTwoDTableAxisOrder, and TWODTABLEUS_LENGTH.

Referenced by decodePacketAndRespond().

{
/* Check the order of the axis */
unsigned char i;
for(i=0;i<(TWODTABLEUS_LENGTH - 1);i++){
if(Table->Axis[i] >= Table->Axis[i+1]){
}
}
return 0;
}

Here is the caller graph for this function: