tableLookup.c

Go to the documentation of this file.
00001 /*      tableLookup.c
00002 
00003         Copyright 2008 Fred Cooke
00004 
00005         This file is part of the FreeEMS project.
00006 
00007         FreeEMS software is free software: you can redistribute it and/or modify
00008         it under the terms of the GNU General Public License as published by
00009         the Free Software Foundation, either version 3 of the License, or
00010         (at your option) any later version.
00011 
00012         FreeEMS software is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU General Public License for more details.
00016 
00017         You should have received a copy of the GNU General Public License
00018         along with any FreeEMS software.  If not, see <http://www.gnu.org/licenses/>.
00019 
00020         We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org
00021 
00022         Thank you for choosing FreeEMS to run your engine! */
00023 
00024 #define TABLELOOKUP_C
00025 #include "inc/freeEMS.h"
00026 #include "inc/commsISRs.h"
00027 #include "inc/tableLookup.h"
00028 
00029 
00030 /* Yet to be implemented :
00031 
00032 unsigned char lookup8Bit3dUC(
00033 unsigned short lookup16Bit2dUS(
00034 unsigned char lookup8Bit2dUC(
00035 signed short lookup16Bit3dSS(
00036 signed short lookup16Bit3dSS(
00037 signed char lookup8Bit3D( */
00038 
00039 
00040 /* Take a table with two movable axis sets and two axis lengths,
00041  * loop to find which pairs of axis values and indexs we are between,
00042  * interpolate two pairs down to two values,
00043  * interpolate two values down to one value.
00044  *
00045  * 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.
00046  *
00047  * 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.
00048  *
00049  * 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.
00050  *
00051  * Reminder : X/RPM is horizontal, Y/Load is vertical */
00052 unsigned short lookupMainTable(mainTable *Table, unsigned short realRPM, unsigned short realLoad){
00053 
00054         /* Find the bounding axis values and indices for RPM */
00055         unsigned char lowRPMIndex = 0;
00056         unsigned char highRPMIndex = Table->RPMLength - 1;
00057         /* If never set in the loop, low value will equal high value and will be on the edge of the map */
00058         unsigned short lowRPMValue = Table->RPM[0];
00059         unsigned short highRPMValue = Table->RPM[Table->RPMLength -1];
00060 
00061         unsigned char RPMIndex;
00062         for(RPMIndex=0;RPMIndex<Table->RPMLength;RPMIndex++){
00063                 if(Table->RPM[RPMIndex] < realRPM){
00064                         lowRPMValue = Table->RPM[RPMIndex];
00065                         lowRPMIndex = RPMIndex;
00066                 }else if(Table->RPM[RPMIndex] > realRPM){
00067                         highRPMValue = Table->RPM[RPMIndex];
00068                         highRPMIndex = RPMIndex;
00069                         break;
00070                 }else if(Table->RPM[RPMIndex] == realRPM){
00071                         lowRPMValue = Table->RPM[RPMIndex];
00072                         highRPMValue = Table->RPM[RPMIndex];
00073                         lowRPMIndex = RPMIndex;
00074                         highRPMIndex = RPMIndex;
00075                         break;
00076                 }
00077         }
00078 
00079 
00080         /* Find the bounding cell values and indices for Load */
00081         unsigned char lowLoadIndex = 0;
00082         unsigned char highLoadIndex = Table->LoadLength -1;
00083         /* If never set in the loop, low value will equal high value and will be on the edge of the map */
00084         unsigned short lowLoadValue = Table->Load[0];
00085         unsigned short highLoadValue = Table->Load[Table->LoadLength -1];
00086 
00087         unsigned char LoadIndex;
00088         for(LoadIndex=0;LoadIndex<Table->LoadLength;LoadIndex++){
00089                 if(Table->Load[LoadIndex] < realLoad){
00090                         lowLoadValue = Table->Load[LoadIndex];
00091                         lowLoadIndex = LoadIndex;
00092                 }else if(Table->Load[LoadIndex] > realLoad){
00093                         highLoadValue = Table->Load[LoadIndex];
00094                         highLoadIndex = LoadIndex;
00095                         break;
00096                 }else if(Table->Load[LoadIndex] == realLoad){
00097                         lowLoadValue = Table->Load[LoadIndex];
00098                         highLoadValue = Table->Load[LoadIndex];
00099                         lowLoadIndex = LoadIndex;
00100                         highLoadIndex = LoadIndex;
00101                         break;
00102                 }
00103         }
00104 
00105 
00106         /* Obtain the four corners surrounding the spot of interest */
00107         unsigned short lowRPMLowLoad = Table->Table[(Table->LoadLength * lowRPMIndex) + lowLoadIndex];
00108         unsigned short lowRPMHighLoad = Table->Table[(Table->LoadLength * lowRPMIndex) + highLoadIndex];
00109         unsigned short highRPMLowLoad = Table->Table[(Table->LoadLength * highRPMIndex) + lowLoadIndex];
00110         unsigned short highRPMHighLoad = Table->Table[(Table->LoadLength * highRPMIndex) + highLoadIndex];
00111 
00112 
00113         /* Find the two side values to interpolate between by interpolation */
00114         unsigned short lowRPMIntLoad = lowRPMLowLoad + (((signed long)((signed long)lowRPMHighLoad - lowRPMLowLoad) * (realLoad - lowLoadValue))/ (highLoadValue - lowLoadValue));
00115         unsigned short highRPMIntLoad = highRPMLowLoad + (((signed long)((signed long)highRPMHighLoad - highRPMLowLoad) * (realLoad - lowLoadValue))/ (highLoadValue - lowLoadValue));
00116 
00117 
00118         /* Interpolate between the two side values and return the result */
00119         return lowRPMIntLoad + (((signed long)((signed long)highRPMIntLoad - lowRPMIntLoad) * (realRPM - lowRPMValue))/ (highRPMValue - lowRPMValue));
00120 }
00121 
00122 
00123 unsigned short lookupTwoDTableUS(twoDTableUS * Table, unsigned short Value){
00124 
00125         /* Find the bounding axis indices, axis values and lookup values */
00126         unsigned char lowIndex = 0;
00127         unsigned char highIndex = 15;
00128         /* If never set in the loop, low value will equal high value and will be on the edge of the map */
00129         unsigned short lowAxisValue = Table->Axis[0];
00130         unsigned short highAxisValue = Table->Axis[15];
00131         unsigned short lowLookupValue = Table->Values[0];
00132         unsigned short highLookupValue = Table->Values[15];
00133 
00134         unsigned char Index;
00135         for(Index=0;Index<16;Index++){
00136                 if(Table->Axis[Index] < Value){
00137                         lowIndex = Index;
00138                         lowAxisValue = Table->Axis[Index];
00139                         lowLookupValue = Table->Values[Index];
00140                 }else if(Table->Axis[Index] > Value){
00141                         highIndex = Index;
00142                         highAxisValue = Table->Axis[Index];
00143                         highLookupValue = Table->Values[Index];
00144                         break;
00145                 }else if(Table->Axis[Index] == Value){
00146                         return Table->Values[Index]; // If right on, just return the value
00147                 }
00148         }
00149 
00150 
00151         /* Interpolate and return the value */
00152         return lowLookupValue + (((signed long)((signed long)highLookupValue - lowLookupValue) * (Value - lowAxisValue))/ (highAxisValue - lowAxisValue));
00153 }
00154 
00155 
00156 /* Save the page value to a variable, change the page value, read the table, change the page back and return the value */
00157 unsigned short lookupPagedMainTableCellValue(mainTable *Table, unsigned short realRPM, unsigned short realLoad, unsigned char RPageValue){
00158         unsigned char oldRPage = RPAGE;
00159         RPAGE = RPageValue;
00160         unsigned short returnValue = lookupMainTable(Table, realRPM, realLoad);
00161         RPAGE = oldRPage;
00162         return returnValue;
00163 }
00164 
00165 
00166 unsigned short setPagedMainTableCellValue(mainTable* Table, unsigned short RPMIndex, unsigned short LoadIndex, unsigned short cellValue, unsigned char RPageValue){
00167         unsigned char oldRPage = RPAGE;
00168         unsigned short errorID = NO_ERROR_ALL_A_OK;
00169         RPAGE = RPageValue;
00170         if(RPMIndex < Table->RPMLength){
00171                 if(LoadIndex < Table->LoadLength){
00172                         Table->Table[(Table->LoadLength * RPMIndex) + LoadIndex] = cellValue;
00173                 }else{
00174                         errorID = invalidMainTableLoadIndex;
00175                 }
00176         }else{
00177                 errorID = invalidMainTableRPMIndex;
00178         }
00179         RPAGE = oldRPage;
00180         return errorID;
00181 }
00182 
00183 
00184 unsigned short setPagedMainTableRPMValue(mainTable* Table, unsigned short RPMIndex, unsigned short RPMValue, unsigned char RPageValue){
00185         unsigned char oldRPage = RPAGE;
00186         unsigned short errorID = NO_ERROR_ALL_A_OK;
00187         RPAGE = RPageValue;
00188         if(RPMIndex < Table->RPMLength){
00189                 Table->RPM[RPMIndex] = RPMValue;
00190         }else{
00191                 errorID = invalidMainTableRPMIndex;
00192         }
00193         RPAGE = oldRPage;
00194         return errorID;
00195 }
00196 
00197 
00198 unsigned short setPagedMainTableLoadValue(mainTable* Table, unsigned short LoadIndex, unsigned short LoadValue, unsigned char RPageValue){
00199         unsigned char oldRPage = RPAGE;
00200         unsigned short errorID = NO_ERROR_ALL_A_OK;
00201         RPAGE = RPageValue;
00202         if(LoadIndex < Table->LoadLength){
00203                 Table->Load[LoadIndex] = LoadValue;
00204         }else{
00205                 errorID = invalidMainTableLoadIndex;
00206         }
00207         RPAGE = oldRPage;
00208         return errorID;
00209 }
00210 
00211 
00212 /* Check that the configuration of the table is valid */
00213 unsigned short validateMainTable(mainTable* Table){
00214         if(Table->RPMLength > MAINTABLE_MAX_RPM_LENGTH){
00215                 return invalidMainTableRPMLength;
00216         }else if(Table->LoadLength > MAINTABLE_MAX_LOAD_LENGTH){
00217                 return invalidMainTableLoadLength;
00218         }else if((Table->RPMLength * Table->LoadLength) > MAINTABLE_MAX_MAIN_LENGTH){
00219                 return invalidMainTableMainLength;
00220         }else{
00221                 /* Check the order of the RPM axis */
00222                 unsigned char i;
00223                 for(i=0;i<(Table->RPMLength - 1);i++){
00224                         if(Table->RPM[i] > Table->RPM[i+1]){
00225                                 return invalidMainTableRPMOrder;
00226                         }
00227                 }
00228                 /* Check the order of the Load axis */
00229                 unsigned char j;
00230                 for(j=0;j<(Table->LoadLength - 1);j++){
00231                         if(Table->Load[j] > Table->Load[j+1]){
00232                                 return invalidMainTableLoadOrder;
00233                         }
00234                 }
00235                 /* If we made it this far all is well */
00236                 return NO_ERROR_ALL_A_OK;
00237         }
00238 }
00239 
00240 /* Check that the configuration of the table is valid */
00241 unsigned short validateTwoDTable(twoDTableUS* Table){
00242         /* Check the order of the axis */
00243         unsigned char i;
00244         for(i=0;i<(TWODTABLEUS_LENGTH - 1);i++){
00245                 if(Table->Axis[i] > Table->Axis[i+1]){
00246                         return invalidTwoDTableAxisOrder;
00247                 }
00248         }
00249         return NO_ERROR_ALL_A_OK;
00250 }

Generated on Mon Nov 10 21:18:50 2008 for freeems by  doxygen 1.5.2