tableLookup.c File Reference

Table access functions. More...

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

Go to the source code of this file.

Defines

#define TABLELOOKUP_C

Functions

unsigned short lookupPagedMainTableCellValue (mainTable *Table, unsigned short realRPM, unsigned short realLoad, unsigned char RAMPage)
 Main table read function.
unsigned short lookupTwoDTableUS (twoDTableUS *Table, unsigned short Value)
 Two D table read function.
unsigned short setAxisValue (unsigned short index, unsigned short value, unsigned short axis[], unsigned short length, unsigned short errorBase)
 Set an axis value.
unsigned short setPagedMainTableCellValue (unsigned char RPageValue, mainTable *Table, unsigned short RPMIndex, unsigned short LoadIndex, unsigned short cellValue)
 Set a main table cell value.
unsigned short setPagedMainTableRPMValue (unsigned char RPageValue, mainTable *Table, unsigned short RPMIndex, unsigned short RPMValue)
 Set an RPM axis value.
unsigned short setPagedMainTableLoadValue (unsigned char RPageValue, mainTable *Table, unsigned short LoadIndex, unsigned short LoadValue)
 Set a load axis value.
unsigned short setPagedTwoDTableCellValue (unsigned char RPageValue, twoDTableUS *Table, unsigned short cellIndex, unsigned short cellValue)
 Set a two D table cell value.
unsigned short setPagedTwoDTableAxisValue (unsigned char RPageValue, twoDTableUS *Table, unsigned short axisIndex, unsigned short axisValue)
 Set a two D axis value.
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.

Author:
Fred Cooke

Definition in file tableLookup.c.


Define Documentation

#define TABLELOOKUP_C

Definition at line 37 of file tableLookup.c.


Function Documentation

unsigned short lookupPagedMainTableCellValue ( mainTable Table,
unsigned short  realRPM,
unsigned short  realLoad,
unsigned char  RAMPage 
)

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.
Author:
Fred Cooke
Parameters:
Table is a pointer to the table to read from.
realRPM is the current RPM for which a table value is required.
realLoad is the current load for which a table value is required.
RAMPage is the RAM page that the table is stored in.
Returns:
The interpolated value for the location specified.

Definition at line 113 of file tableLookup.c.

References mainTable::Load, mainTable::LoadLength, RPAGE, mainTable::RPM, mainTable::RPMLength, and mainTable::Table.

Referenced by generateDerivedVars().

00113                                                                                                                                       {
00114 
00115     /* Save the RPAGE value for restoration and switch pages. */
00116     unsigned char oldRPage = RPAGE;
00117     RPAGE = RAMPage;
00118 
00119     /* Find the bounding axis values and indices for RPM */
00120     unsigned char lowRPMIndex = 0;
00121     unsigned char highRPMIndex = Table->RPMLength - 1;
00122     /* If never set in the loop, low value will equal high value and will be on the edge of the map */
00123     unsigned short lowRPMValue = Table->RPM[0];
00124     unsigned short highRPMValue = Table->RPM[Table->RPMLength -1];
00125 
00126     unsigned char RPMIndex;
00127     for(RPMIndex=0;RPMIndex<Table->RPMLength;RPMIndex++){
00128         if(Table->RPM[RPMIndex] < realRPM){
00129             lowRPMValue = Table->RPM[RPMIndex];
00130             lowRPMIndex = RPMIndex;
00131         }else if(Table->RPM[RPMIndex] > realRPM){
00132             highRPMValue = Table->RPM[RPMIndex];
00133             highRPMIndex = RPMIndex;
00134             break;
00135         }else if(Table->RPM[RPMIndex] == realRPM){
00136             lowRPMValue = Table->RPM[RPMIndex];
00137             highRPMValue = Table->RPM[RPMIndex];
00138             lowRPMIndex = RPMIndex;
00139             highRPMIndex = RPMIndex;
00140             break;
00141         }
00142     }
00143 
00144     /* Find the bounding cell values and indices for Load */
00145     unsigned char lowLoadIndex = 0;
00146     unsigned char highLoadIndex = Table->LoadLength -1;
00147     /* If never set in the loop, low value will equal high value and will be on the edge of the map */
00148     unsigned short lowLoadValue = Table->Load[0];
00149     unsigned short highLoadValue = Table->Load[Table->LoadLength -1];
00150 
00151     unsigned char LoadIndex;
00152     for(LoadIndex=0;LoadIndex<Table->LoadLength;LoadIndex++){
00153         if(Table->Load[LoadIndex] < realLoad){
00154             lowLoadValue = Table->Load[LoadIndex];
00155             lowLoadIndex = LoadIndex;
00156         }else if(Table->Load[LoadIndex] > realLoad){
00157             highLoadValue = Table->Load[LoadIndex];
00158             highLoadIndex = LoadIndex;
00159             break;
00160         }else if(Table->Load[LoadIndex] == realLoad){
00161             lowLoadValue = Table->Load[LoadIndex];
00162             highLoadValue = Table->Load[LoadIndex];
00163             lowLoadIndex = LoadIndex;
00164             highLoadIndex = LoadIndex;
00165             break;
00166         }
00167     }
00168 
00169     /* Obtain the four corners surrounding the spot of interest */
00170     unsigned short lowRPMLowLoad = Table->Table[(Table->LoadLength * lowRPMIndex) + lowLoadIndex];
00171     unsigned short lowRPMHighLoad = Table->Table[(Table->LoadLength * lowRPMIndex) + highLoadIndex];
00172     unsigned short highRPMLowLoad = Table->Table[(Table->LoadLength * highRPMIndex) + lowLoadIndex];
00173     unsigned short highRPMHighLoad = Table->Table[(Table->LoadLength * highRPMIndex) + highLoadIndex];
00174 
00175     /* Restore the ram page before doing the math */
00176     RPAGE = oldRPage;
00177 
00178     /* Find the two side values to interpolate between by interpolation */
00179     unsigned short lowRPMIntLoad = lowRPMLowLoad + (((signed long)((signed long)lowRPMHighLoad - lowRPMLowLoad) * (realLoad - lowLoadValue))/ (highLoadValue - lowLoadValue));
00180     unsigned short highRPMIntLoad = highRPMLowLoad + (((signed long)((signed long)highRPMHighLoad - highRPMLowLoad) * (realLoad - lowLoadValue))/ (highLoadValue - lowLoadValue));
00181 
00182     /* Interpolate between the two side values and return the result */
00183     return lowRPMIntLoad + (((signed long)((signed long)highRPMIntLoad - lowRPMIntLoad) * (realRPM - lowRPMValue))/ (highRPMValue - lowRPMValue));
00184 }

unsigned short lookupTwoDTableUS ( twoDTableUS Table,
unsigned short  Value 
)

Two D table read function.

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

Author:
Fred Cooke
Parameters:
Table is a pointer to the table to read from.
Value is the position value used to lookup the return value.
Returns:
the interpolated value for the position specified

Definition at line 198 of file tableLookup.c.

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

Referenced by generateDerivedVars().

00198                                                                            {
00199 
00200     /* Find the bounding axis indices, axis values and lookup values */
00201     unsigned char lowIndex = 0;
00202     unsigned char highIndex = 15;
00203     /* If never set in the loop, low value will equal high value and will be on the edge of the map */
00204     unsigned short lowAxisValue = Table->Axis[0];
00205     unsigned short highAxisValue = Table->Axis[15];
00206     unsigned short lowLookupValue = Table->Values[0];
00207     unsigned short highLookupValue = Table->Values[15];
00208 
00209     unsigned char Index;
00210     for(Index=0;Index<16;Index++){
00211         if(Table->Axis[Index] < Value){
00212             lowIndex = Index;
00213             lowAxisValue = Table->Axis[Index];
00214             lowLookupValue = Table->Values[Index];
00215         }else if(Table->Axis[Index] > Value){
00216             highIndex = Index;
00217             highAxisValue = Table->Axis[Index];
00218             highLookupValue = Table->Values[Index];
00219             break;
00220         }else if(Table->Axis[Index] == Value){
00221             return Table->Values[Index]; // If right on, just return the value
00222         }
00223     }
00224 
00225 
00226     /* Interpolate and return the value */
00227     return lowLookupValue + (((signed long)((signed long)highLookupValue - lowLookupValue) * (Value - lowAxisValue))/ (highAxisValue - lowAxisValue));
00228 }

unsigned short setAxisValue ( unsigned short  index,
unsigned short  value,
unsigned short  axis[],
unsigned short  length,
unsigned short  errorBase 
)

Set an axis value.

Sets the value of an axis cell in a table. This is used when configuring a table via a communication interface.

Author:
Fred Cooke
Parameters:
index The position of the axis cell to adjust.
value The value to set the axis cell to.
axis A pointer to the axis array to adjust.
length The length of the axis array.
errorBase The base value to add error code offsets to.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 246 of file tableLookup.c.

References invalidAxisIndex, and invalidAxisOrder.

Referenced by setPagedMainTableLoadValue(), setPagedMainTableRPMValue(), and setPagedTwoDTableAxisValue().

00246                                                                                                                                                {
00247     if(index >= length){
00248         return errorBase + invalidAxisIndex;
00249     }else{
00250         if(index > 0){
00251             /* Ensure value isn't lower than the one below */
00252             if(axis[index - 1] > value){
00253                 return errorBase + invalidAxisOrder;
00254             }
00255         }
00256         if(index < (length -1)){
00257             /* Ensure value isn't higher than the one above */
00258             if(value > axis[index + 1]){
00259                 return errorBase + invalidAxisOrder;
00260             }
00261         }
00262     }
00263 
00264     /* If we got this far all is well, set the value */
00265     axis[index] = value;
00266     return 0;
00267 }

unsigned short setPagedMainTableCellValue ( unsigned char  RPageValue,
mainTable Table,
unsigned short  RPMIndex,
unsigned short  LoadIndex,
unsigned short  cellValue 
)

Set a main table cell value.

Sets the value of a cell in a main table. This is used when configuring a table via a communication interface.

Author:
Fred Cooke
Parameters:
RPageValue The page of RAM that the table is in.
Table A pointer to the table to adjust.
RPMIndex The RPM position of the cell to adjust.
LoadIndex The load position of the cell to adjust.
cellValue The value to set the cell to.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 285 of file tableLookup.c.

References invalidMainTableLoadIndex, invalidMainTableRPMIndex, mainTable::LoadLength, RPAGE, and mainTable::Table.

Referenced by decodePacketAndRespond().

00285                                                                                                                                                                   {
00286     unsigned char oldRPage = RPAGE;
00287     unsigned short errorID = 0;
00288     RPAGE = RPageValue;
00289     if(RPMIndex < Table->RPMLength){
00290         if(LoadIndex < Table->LoadLength){
00291             Table->Table[(Table->LoadLength * RPMIndex) + LoadIndex] = cellValue;
00292         }else{
00293             errorID = invalidMainTableLoadIndex;
00294         }
00295     }else{
00296         errorID = invalidMainTableRPMIndex;
00297     }
00298     RPAGE = oldRPage;
00299     return errorID;
00300 }

unsigned short setPagedMainTableLoadValue ( unsigned char  RPageValue,
mainTable Table,
unsigned short  LoadIndex,
unsigned short  LoadValue 
)

Set a load axis value.

Sets the value of a load axis cell in a table. This is used when configuring the table via a comms interface.

Author:
Fred Cooke
Parameters:
RPageValue The page of RAM that the table is in.
Table is a pointer to the table to adjust.
LoadIndex The load position of the cell to adjust.
LoadValue The value to set the load axis cell to.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 340 of file tableLookup.c.

References errorBaseMainTableLoad, mainTable::Load, mainTable::LoadLength, RPAGE, and setAxisValue().

Referenced by decodePacketAndRespond().

00340                                                                                                                                          {
00341     unsigned char oldRPage = RPAGE;
00342     RPAGE = RPageValue;
00343     unsigned short errorID = setAxisValue(LoadIndex, LoadValue, Table->Load, Table->LoadLength, errorBaseMainTableLoad);
00344     RPAGE = oldRPage;
00345     return errorID;
00346 }

Here is the call graph for this function:

unsigned short setPagedMainTableRPMValue ( unsigned char  RPageValue,
mainTable Table,
unsigned short  RPMIndex,
unsigned short  RPMValue 
)

Set an RPM axis value.

Sets the value of an RPM axis cell in a table. This is used when configuring the table via a comms interface.

Author:
Fred Cooke
Parameters:
RPageValue The page of RAM that the table is in.
Table is a pointer to the table to adjust.
RPMIndex The RPM position of the cell to adjust.
RPMValue The value to set the RPM axis cell to.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 317 of file tableLookup.c.

References errorBaseMainTableRPM, RPAGE, mainTable::RPM, mainTable::RPMLength, and setAxisValue().

Referenced by decodePacketAndRespond().

00317                                                                                                                                       {
00318     unsigned char oldRPage = RPAGE;
00319     RPAGE = RPageValue;
00320     unsigned short errorID = setAxisValue(RPMIndex, RPMValue, Table->RPM, Table->RPMLength, errorBaseMainTableRPM);
00321     RPAGE = oldRPage;
00322     return errorID;
00323 }

Here is the call graph for this function:

unsigned short setPagedTwoDTableAxisValue ( unsigned char  RPageValue,
twoDTableUS Table,
unsigned short  axisIndex,
unsigned short  axisValue 
)

Set a two D axis value.

Sets the value of an axis cell in a table. This is used when configuring the table via a comms interface.

Author:
Fred Cooke
Parameters:
RPageValue The page of RAM that the table is in.
Table is a pointer to the table to adjust.
axisIndex The position of the axis cell to adjust.
axisValue The value to set the axis cell to.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 390 of file tableLookup.c.

References twoDTableUS::Axis, errorBaseTwoDTableAxis, RPAGE, and setAxisValue().

Referenced by decodePacketAndRespond().

00390                                                                                                                                            {
00391     unsigned char oldRPage = RPAGE;
00392     RPAGE = RPageValue;
00393     unsigned short errorID = setAxisValue(axisIndex, axisValue, Table->Axis, 16, errorBaseTwoDTableAxis);
00394     RPAGE = oldRPage;
00395     return errorID;
00396 }

Here is the call graph for this function:

unsigned short setPagedTwoDTableCellValue ( unsigned char  RPageValue,
twoDTableUS Table,
unsigned short  cellIndex,
unsigned short  cellValue 
)

Set a two D table cell value.

Sets the value of a cell in a two D table. This is used when configuring the table via a comms interface.

Author:
Fred Cooke
Parameters:
RPageValue The page of RAM that the table is in.
Table is a pointer to the table to adjust.
cellIndex The position of the cell to adjust.
cellValue The value to set the cell to.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 363 of file tableLookup.c.

References invalidTwoDTableIndex, RPAGE, and twoDTableUS::Values.

Referenced by decodePacketAndRespond().

00363                                                                                                                                            {
00364     if(cellIndex > 15){
00365         return invalidTwoDTableIndex;
00366     }else{
00367         unsigned char oldRPage = RPAGE;
00368         RPAGE = RPageValue;
00369         Table->Values[cellIndex] = cellValue;
00370         RPAGE = oldRPage;
00371         return 0;
00372     }
00373 }

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....
Author:
Fred Cooke
Parameters:
Table is a pointer to the table to be validated.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 410 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().

00410                                                   {
00411     /* If required and only if required extend this to take r and f pages and check */
00412     /* any main table, not just a freshly received untrusted ones in linear space   */
00413 
00414     if(Table->RPMLength > MAINTABLE_MAX_RPM_LENGTH){
00415         return invalidMainTableRPMLength;
00416     }else if(Table->LoadLength > MAINTABLE_MAX_LOAD_LENGTH){
00417         return invalidMainTableLoadLength;
00418     }else if((Table->RPMLength * Table->LoadLength) > MAINTABLE_MAX_MAIN_LENGTH){
00419         return invalidMainTableMainLength;
00420     }else{
00421         /* Check the order of the RPM axis */
00422         unsigned char i;
00423         for(i=0;i<(Table->RPMLength - 1);i++){
00424             if(Table->RPM[i] > Table->RPM[i+1]){
00425                 return invalidMainTableRPMOrder;
00426             }
00427         }
00428         /* Check the order of the Load axis */
00429         unsigned char j;
00430         for(j=0;j<(Table->LoadLength - 1);j++){
00431             if(Table->Load[j] > Table->Load[j+1]){
00432                 return invalidMainTableLoadOrder;
00433             }
00434         }
00435         /* If we made it this far all is well */
00436         return 0;
00437     }
00438 }

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.

Author:
Fred Cooke
Parameters:
Table is a pointer to the table to be validated.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 452 of file tableLookup.c.

References twoDTableUS::Axis, invalidTwoDTableAxisOrder, and TWODTABLEUS_LENGTH.

Referenced by decodePacketAndRespond().

00452                                                     {
00453     /* Check the order of the axis */
00454     unsigned char i;
00455     for(i=0;i<(TWODTABLEUS_LENGTH - 1);i++){
00456         if(Table->Axis[i] > Table->Axis[i+1]){
00457             return invalidTwoDTableAxisOrder;
00458         }
00459     }
00460     return 0;
00461 }

Generated on Sat Oct 16 21:29:22 2010 for FreeEMS by  doxygen 1.6.3