mirror of https://github.com/rusefi/speeduino.git
Merge pull request #57 from noisymime/ADC-interrupt
ADC interrupt merge Closes #56
This commit is contained in:
commit
34780378c6
12
fastAnalog.h
12
fastAnalog.h
|
@ -1,12 +0,0 @@
|
|||
#ifndef FASTANALOG_H
|
||||
#define FASTANALOG_H
|
||||
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif
|
||||
#ifndef sbi
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
#endif // FASTANALOG_H
|
||||
|
10
globals.h
10
globals.h
|
@ -406,7 +406,7 @@ byte pinInjector1; //Output pin injector 1
|
|||
byte pinInjector2; //Output pin injector 2
|
||||
byte pinInjector3; //Output pin injector 3 is on
|
||||
byte pinInjector4; //Output pin injector 4 is on
|
||||
byte pinInjector5; //Placeholder only - NOT USED
|
||||
byte pinInjector5; //Output pin injector 5 NOT USED YET
|
||||
byte pinInjector6; //Placeholder only - NOT USED
|
||||
byte pinInjector7; //Placeholder only - NOT USED
|
||||
byte pinInjector8; //Placeholder only - NOT USED
|
||||
|
@ -414,10 +414,10 @@ byte pinCoil1; //Pin for coil 1
|
|||
byte pinCoil2; //Pin for coil 2
|
||||
byte pinCoil3; //Pin for coil 3
|
||||
byte pinCoil4; //Pin for coil 4
|
||||
byte pinCoil5; //Pin for coil 4
|
||||
byte pinCoil6; //Pin for coil 4
|
||||
byte pinCoil7; //Pin for coil 4
|
||||
byte pinCoil8; //Pin for coil 4
|
||||
byte pinCoil5; //Pin for coil 5
|
||||
byte pinCoil6; //Pin for coil 6
|
||||
byte pinCoil7; //Pin for coil 7
|
||||
byte pinCoil8; //Pin for coil 8
|
||||
byte pinTrigger; //The CAS pin
|
||||
byte pinTrigger2; //The Cam Sensor pin
|
||||
byte pinTrigger3; //the 2nd cam sensor pin
|
||||
|
|
37
sensors.h
37
sensors.h
|
@ -12,7 +12,10 @@
|
|||
#define BARO_MIN 87
|
||||
#define BARO_MAX 108
|
||||
|
||||
#define ANALOG_ISR
|
||||
|
||||
volatile byte flexCounter = 0;
|
||||
volatile int AnChannel[15];
|
||||
|
||||
/*
|
||||
* Simple low pass IIR filter macro for the analog inputs
|
||||
|
@ -27,4 +30,38 @@ void flexPulse();
|
|||
|
||||
unsigned int tempReading;
|
||||
|
||||
#if defined(ANALOG_ISR)
|
||||
//Analog ISR interrupt routine
|
||||
ISR(ADC_vect)
|
||||
{
|
||||
byte nChannel;
|
||||
int result = ADCL | (ADCH << 8);
|
||||
|
||||
//ADCSRA = 0x6E; // ADC disabled by clearing bit 7(ADEN)
|
||||
//BIT_CLEAR(ADCSRA, ADIE);
|
||||
|
||||
nChannel = ADMUX & 0x07;
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
if (nChannel==7) { ADMUX = 0x40; }
|
||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
if(ADCSRB & 0x08) { nChannel += 8; } //8 to 15
|
||||
if(nChannel == 15)
|
||||
{
|
||||
ADMUX = 0x40; //channel 0
|
||||
ADCSRB = 0x00; //clear MUX5 bit
|
||||
}
|
||||
else if (nChannel == 7) //channel 7
|
||||
{
|
||||
ADMUX = 0x40;
|
||||
ADCSRB = 0x08; //Set MUX5 bit
|
||||
}
|
||||
#endif
|
||||
else { ADMUX++; }
|
||||
AnChannel[nChannel-1] = result;
|
||||
|
||||
//BIT_SET(ADCSRA, ADIE);
|
||||
//ADCSRA = 0xEE; // ADC Interrupt Flag enabled
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SENSORS_H
|
||||
|
|
105
sensors.ino
105
sensors.ino
|
@ -4,12 +4,55 @@ Copyright (C) Josh Stewart
|
|||
A full copy of the license may be found in the projects root directory
|
||||
*/
|
||||
|
||||
void initialiseADC()
|
||||
{
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
|
||||
|
||||
#if defined(ANALOG_ISR)
|
||||
//This sets the ADC (Analog to Digitial Converter) to run at 250KHz, greatly reducing analog read times (MAP/TPS)
|
||||
//the code on ISR run each conversion every 25 ADC clock, conversion run about 100KHz effectively
|
||||
//making a 6250 conversions/s on 16 channels and 12500 on 8 channels devices.
|
||||
noInterrupts(); //Interrupts should be turned off when playing with any of these registers
|
||||
|
||||
ADCSRB = 0x00; //ADC Auto Trigger Source is in Free Running mode
|
||||
ADMUX = 0x40; //Select AREF as reference, ADC Left Adjust Result, Starting at channel 0
|
||||
|
||||
//All of the below is the longhand version of: ADCSRA = 0xEE;
|
||||
#define ADFR 5 //Why the HELL isn't this defined in the same place as everything else (wiring.h)?!?!
|
||||
BIT_SET(ADCSRA,ADFR); //Set free running mode
|
||||
BIT_SET(ADCSRA,ADIE); //Set ADC interrupt enabled
|
||||
BIT_CLEAR(ADCSRA,ADIF); //Clear interrupt flag
|
||||
|
||||
// Set ADC clock to 125KHz (Prescaler = 128)
|
||||
BIT_SET(ADCSRA,ADPS2);
|
||||
BIT_SET(ADCSRA,ADPS1);
|
||||
BIT_SET(ADCSRA,ADPS0);
|
||||
|
||||
BIT_SET(ADCSRA,ADEN); //Enable ADC
|
||||
|
||||
interrupts();
|
||||
BIT_SET(ADCSRA,ADSC); //Start conversion
|
||||
|
||||
#else
|
||||
//This sets the ADC (Analog to Digitial Converter) to run at 1Mhz, greatly reducing analog read times (MAP/TPS) when using the standard analogRead() function
|
||||
//1Mhz is the fastest speed permitted by the CPU without affecting accuracy
|
||||
//Please see chapter 11 of 'Practical Arduino' (http://books.google.com.au/books?id=HsTxON1L6D4C&printsec=frontcover#v=onepage&q&f=false) for more detail
|
||||
BIT_SET(ADCSRA,ADPS2);
|
||||
BIT_CLEAR(ADCSRA,ADPS1);
|
||||
BIT_CLEAR(ADCSRA,ADPS0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void instanteneousMAPReading()
|
||||
{
|
||||
//Instantaneous MAP readings
|
||||
tempReading = analogRead(pinMAP);
|
||||
tempReading = analogRead(pinMAP);
|
||||
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = AnChannel[pinMAP-A0];
|
||||
#else
|
||||
tempReading = analogRead(pinMAP);
|
||||
tempReading = analogRead(pinMAP);
|
||||
#endif
|
||||
//Error checking
|
||||
if(tempReading >= VALID_MAP_MAX || tempReading <= VALID_MAP_MIN) { mapErrorCount += 1; }
|
||||
else { currentStatus.mapADC = tempReading; mapErrorCount = 0; }
|
||||
|
@ -34,8 +77,12 @@ void readMAP()
|
|||
|
||||
if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
|
||||
{
|
||||
tempReading = analogRead(pinMAP);
|
||||
tempReading = analogRead(pinMAP);
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = AnChannel[pinMAP-A0];
|
||||
#else
|
||||
tempReading = analogRead(pinMAP);
|
||||
tempReading = analogRead(pinMAP);
|
||||
#endif
|
||||
|
||||
//Error check
|
||||
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
|
||||
|
@ -62,8 +109,12 @@ void readMAP()
|
|||
|
||||
if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
|
||||
{
|
||||
tempReading = analogRead(pinMAP);
|
||||
tempReading = analogRead(pinMAP);
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = AnChannel[pinMAP-A0];
|
||||
#else
|
||||
tempReading = analogRead(pinMAP);
|
||||
tempReading = analogRead(pinMAP);
|
||||
#endif
|
||||
//Error check
|
||||
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
|
||||
{
|
||||
|
@ -87,8 +138,12 @@ void readTPS()
|
|||
{
|
||||
currentStatus.TPSlast = currentStatus.TPS;
|
||||
currentStatus.TPSlast_time = currentStatus.TPS_time;
|
||||
analogRead(pinTPS);
|
||||
byte tempTPS = fastMap1023toX(analogRead(pinTPS), 255); //Get the current raw TPS ADC value and map it into a byte
|
||||
#if defined(ANALOG_ISR)
|
||||
byte tempTPS = fastMap1023toX(AnChannel[pinTPS-A0], 255); //Get the current raw TPS ADC value and map it into a byte
|
||||
#else
|
||||
analogRead(pinTPS);
|
||||
byte tempTPS = fastMap1023toX(analogRead(pinTPS), 255); //Get the current raw TPS ADC value and map it into a byte
|
||||
#endif
|
||||
currentStatus.tpsADC = ADC_FILTER(tempTPS, ADCFILTER_TPS, currentStatus.tpsADC);
|
||||
//Check that the ADC values fall within the min and max ranges (Should always be the case, but noise can cause these to fluctuate outside the defined range).
|
||||
byte tempADC = currentStatus.tpsADC; //The tempADC value is used in order to allow TunerStudio to recover and redo the TPS calibration if this somehow gets corrupted
|
||||
|
@ -100,24 +155,36 @@ void readTPS()
|
|||
|
||||
void readCLT()
|
||||
{
|
||||
tempReading = analogRead(pinCLT);
|
||||
tempReading = fastMap1023toX(analogRead(pinCLT), 511); //Get the current raw CLT value
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = fastMap1023toX(AnChannel[pinCLT-A0], 511); //Get the current raw CLT value
|
||||
#else
|
||||
tempReading = analogRead(pinCLT);
|
||||
tempReading = fastMap1023toX(analogRead(pinCLT), 511); //Get the current raw CLT value
|
||||
#endif
|
||||
currentStatus.cltADC = ADC_FILTER(tempReading, ADCFILTER_CLT, currentStatus.cltADC);
|
||||
currentStatus.coolant = cltCalibrationTable[currentStatus.cltADC] - CALIBRATION_TEMPERATURE_OFFSET; //Temperature calibration values are stored as positive bytes. We subtract 40 from them to allow for negative temperatures
|
||||
}
|
||||
|
||||
void readIAT()
|
||||
{
|
||||
tempReading = analogRead(pinIAT);
|
||||
tempReading = fastMap1023toX(analogRead(pinIAT), 511); //Get the current raw IAT value
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = fastMap1023toX(AnChannel[pinIAT-A0], 511); //Get the current raw IAT value
|
||||
#else
|
||||
tempReading = analogRead(pinIAT);
|
||||
tempReading = fastMap1023toX(analogRead(pinIAT), 511); //Get the current raw IAT value
|
||||
#endif
|
||||
currentStatus.iatADC = ADC_FILTER(tempReading, ADCFILTER_IAT, currentStatus.iatADC);
|
||||
currentStatus.IAT = iatCalibrationTable[currentStatus.iatADC] - CALIBRATION_TEMPERATURE_OFFSET;
|
||||
}
|
||||
|
||||
void readO2()
|
||||
{
|
||||
tempReading = analogRead(pinO2);
|
||||
tempReading = fastMap1023toX(analogRead(pinO2), 511); //Get the current O2 value.
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = fastMap1023toX(AnChannel[pinO2-A0], 511); //Get the current O2 value.
|
||||
#else
|
||||
tempReading = analogRead(pinO2);
|
||||
tempReading = fastMap1023toX(analogRead(pinO2), 511); //Get the current O2 value.
|
||||
#endif
|
||||
currentStatus.O2ADC = ADC_FILTER(tempReading, ADCFILTER_O2, currentStatus.O2ADC);
|
||||
currentStatus.O2 = o2CalibrationTable[currentStatus.O2ADC];
|
||||
}
|
||||
|
@ -130,8 +197,12 @@ void readO2()
|
|||
|
||||
void readBat()
|
||||
{
|
||||
tempReading = analogRead(pinBat);
|
||||
tempReading = fastMap1023toX(analogRead(pinBat), 245); //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245)
|
||||
#if defined(ANALOG_ISR)
|
||||
tempReading = fastMap1023toX(AnChannel[pinBat-A0], 245); //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245)
|
||||
#else
|
||||
tempReading = analogRead(pinBat);
|
||||
tempReading = fastMap1023toX(analogRead(pinBat), 245); //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245)
|
||||
#endif
|
||||
currentStatus.battery10 = ADC_FILTER(tempReading, ADCFILTER_BAT, currentStatus.battery10);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "decoders.h"
|
||||
#include "idle.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "fastAnalog.h"
|
||||
#include "sensors.h"
|
||||
#include "src/PID_v1/PID_v1.h"
|
||||
//#include "src/DigitalWriteFast/digitalWriteFast.h"
|
||||
|
@ -210,18 +209,18 @@ void setup()
|
|||
//Need to check early on whether the coil charging is inverted. If this is not set straight away it can cause an unwanted spark at bootup
|
||||
if(configPage2.IgInv == 1) { coilHIGH = LOW, coilLOW = HIGH; }
|
||||
else { coilHIGH = HIGH, coilLOW = LOW; }
|
||||
digitalWrite(pinCoil1, coilLOW);
|
||||
digitalWrite(pinCoil2, coilLOW);
|
||||
digitalWrite(pinCoil3, coilLOW);
|
||||
digitalWrite(pinCoil4, coilLOW);
|
||||
digitalWrite(pinCoil5, coilLOW);
|
||||
endCoil1Charge();
|
||||
endCoil2Charge();
|
||||
endCoil3Charge();
|
||||
endCoil4Charge();
|
||||
endCoil5Charge();
|
||||
|
||||
//Similar for injectors, make sure they're turned off
|
||||
digitalWrite(pinInjector1, LOW);
|
||||
digitalWrite(pinInjector2, LOW);
|
||||
digitalWrite(pinInjector3, LOW);
|
||||
digitalWrite(pinInjector4, LOW);
|
||||
digitalWrite(pinInjector5, LOW);
|
||||
closeInjector1();
|
||||
closeInjector2();
|
||||
closeInjector3();
|
||||
closeInjector4();
|
||||
closeInjector5();
|
||||
|
||||
//Set the tacho output default state
|
||||
digitalWrite(pinTachOut, HIGH);
|
||||
|
@ -254,6 +253,7 @@ void setup()
|
|||
initialiseFan();
|
||||
initialiseAuxPWM();
|
||||
initialiseCorrections();
|
||||
initialiseADC();
|
||||
|
||||
//Check whether the flex sensor is enabled and if so, attach an interupt for it
|
||||
if(configPage1.flexEnabled)
|
||||
|
@ -484,20 +484,6 @@ void setup()
|
|||
//Initial values for loop times
|
||||
previousLoopTime = 0;
|
||||
currentLoopTime = micros();
|
||||
|
||||
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
|
||||
//This sets the ADC (Analog to Digitial Converter) to run at 1Mhz, greatly reducing analog read times (MAP/TPS)
|
||||
//1Mhz is the fastest speed permitted by the CPU without affecting accuracy
|
||||
//Please see chapter 11 of 'Practical Arduino' (http://books.google.com.au/books?id=HsTxON1L6D4C&printsec=frontcover#v=onepage&q&f=false) for more details
|
||||
//Can be disabled by removing the #include "fastAnalog.h" above
|
||||
#ifdef sbi
|
||||
sbi(ADCSRA,ADPS2);
|
||||
cbi(ADCSRA,ADPS1);
|
||||
cbi(ADCSRA,ADPS0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
mainLoopCount = 0;
|
||||
ignitionCount = 0;
|
||||
|
@ -1452,6 +1438,37 @@ void loop()
|
|||
//************************************************************************************************
|
||||
//Interrupts
|
||||
|
||||
#if defined(ANALOG_H)
|
||||
//Analog ISR interrupt routine
|
||||
ISR(ADC_vect)
|
||||
{
|
||||
byte nChannel;
|
||||
int result = ADCL | (ADCH << 8);
|
||||
|
||||
ADCSRA = 0x6E; // ADC Auto Trigger disabled by clearing bit 7(ADEN)
|
||||
nChannel = ADMUX & 0x07;
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
if(ADCSRB & 0x08) { nChannel+=8; } //8 to 15
|
||||
if(nChannel==15)
|
||||
{
|
||||
ADMUX = 0x40; //channel 0
|
||||
ADCSRB = 0x00; //clear MUX5 bit
|
||||
}
|
||||
else if (nChannel==7) //channel 7
|
||||
{
|
||||
ADMUX = 0x40;
|
||||
ADCSRB = 0x08; //Set MUX5 bit
|
||||
}
|
||||
#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
if (nChannel==7) { ADMUX = 0x40; }
|
||||
#endif
|
||||
else { ADMUX++; }
|
||||
AnChannel[nChannel] = result;
|
||||
|
||||
ADCSRA = 0xEE; // ADC Interrupt Flag enabled
|
||||
}
|
||||
#endif
|
||||
|
||||
//These functions simply trigger the injector/coil driver off or on.
|
||||
//NOTE: squirt status is changed as per http://www.msextra.com/doc/ms1extra/COM_RS232.htm#Acmd
|
||||
/*
|
||||
|
|
149
table.ino
149
table.ino
|
@ -379,3 +379,152 @@ int get3DTableValue(struct table3D *fromTable, int Y, int X)
|
|||
int r = (p * q) >> 8;
|
||||
return ( (A * m) + (B * n) + (C * o) + (D * r) ) >> 8;
|
||||
}
|
||||
/* Executed a benchmark on all options and this is the results
|
||||
* Stadard:226224 91 |FP Math:32240 91.89 |Clean code:34056 91, Number of loops:2500
|
||||
*
|
||||
//This function pulls a value from a 3D table given a target for X and Y coordinates.
|
||||
//It performs a 2D linear interpolation as descibred in: http://www.megamanual.com/v22manual/ve_tuner.pdf
|
||||
float get3DTableValueF(struct table3D *fromTable, int Y, int X)
|
||||
{
|
||||
float m, n, o ,p, q, r;
|
||||
byte xMin, xMax;
|
||||
byte yMin, yMax;
|
||||
int yMaxValue, yMinValue;
|
||||
int xMaxValue, xMinValue;
|
||||
|
||||
if(fromTable->lastXMin==0) {fromTable->lastXMin = fromTable->xSize-1;}
|
||||
else {xMin = fromTable->lastXMin;}
|
||||
if(fromTable->lastYMin==0) {fromTable->lastYMin = fromTable->ySize-1;}
|
||||
else {yMin = fromTable->lastYMin;}
|
||||
//yMin = fromTable->lastYMin;
|
||||
|
||||
if(xMin>fromTable->xSize-1)
|
||||
{
|
||||
fromTable->lastXMin = fromTable->xSize-1;
|
||||
xMin = fromTable->xSize-1;
|
||||
}
|
||||
if(yMin>fromTable->ySize-1)
|
||||
{
|
||||
fromTable->lastYMin = fromTable->ySize-1;
|
||||
yMin = fromTable->ySize-1;
|
||||
}
|
||||
|
||||
do //RPM axis
|
||||
{
|
||||
if(X>=fromTable->axisX[xMin]) {break;}
|
||||
xMin--;
|
||||
}while(1);
|
||||
fromTable->lastXMin = xMin + 1;
|
||||
do //MAP axis
|
||||
{
|
||||
if(Y<=fromTable->axisY[yMin]) {break;}
|
||||
yMin--;
|
||||
}while(1);
|
||||
fromTable->lastYMin = yMin + 1;
|
||||
|
||||
xMax = xMin + 1;
|
||||
yMax = yMin + 1;
|
||||
if (xMax>fromTable->xSize-1) //Overflow protection
|
||||
{
|
||||
xMax = fromTable->xSize-1;
|
||||
xMin = xMax - 1;
|
||||
}
|
||||
if (yMax>fromTable->ySize-1) //Overflow protection
|
||||
{
|
||||
yMax = fromTable->ySize-1;
|
||||
yMin = yMax - 1;
|
||||
}
|
||||
|
||||
yMaxValue = fromTable->axisY[yMax];
|
||||
yMinValue = fromTable->axisY[yMin];
|
||||
xMaxValue = fromTable->axisX[xMax];
|
||||
xMinValue = fromTable->axisX[xMin];
|
||||
|
||||
int A = fromTable->values[yMin][xMin];
|
||||
int B = fromTable->values[yMin][xMax];
|
||||
int C = fromTable->values[yMax][xMin];
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
|
||||
p = float(X - xMinValue) / (xMaxValue - xMinValue); //(RPM - RPM[1])/(RPM[2]- RPM[1])
|
||||
q = float(Y - yMinValue) / (yMaxValue - yMinValue); //(MAP - MAP[1])/(MAP[2]- MAP[1])
|
||||
|
||||
m = (1.0-p) * (1.0-q);
|
||||
n = p * (1-q);
|
||||
o = (1-p) * q;
|
||||
r = p * q;
|
||||
|
||||
return ( (A * m) + (B * n) + (C * o) + (D * r) );
|
||||
}
|
||||
|
||||
//This function pulls a value from a 3D table given a target for X and Y coordinates.
|
||||
//It performs a 2D linear interpolation as descibred in: http://www.megamanual.com/v22manual/ve_tuner.pdf
|
||||
int get3DTableValueS(struct table3D *fromTable, int Y, int X)
|
||||
{
|
||||
byte xMin, xMax;
|
||||
byte yMin, yMax;
|
||||
long p, q;
|
||||
int yMaxValue, yMinValue;
|
||||
int xMaxValue, xMinValue;
|
||||
|
||||
if(fromTable->lastXMin==0) {fromTable->lastXMin=fromTable->xSize-1;}
|
||||
else {xMin = fromTable->lastXMin;}
|
||||
if(fromTable->lastYMin==0) {fromTable->lastYMin=fromTable->ySize-1;}
|
||||
else {yMin = fromTable->lastYMin;}
|
||||
|
||||
if(xMin>fromTable->xSize-1)
|
||||
{
|
||||
fromTable->lastXMin = fromTable->xSize-1;
|
||||
xMin = fromTable->xSize-1;
|
||||
}
|
||||
if(yMin>fromTable->ySize-1)
|
||||
{
|
||||
fromTable->lastYMin = fromTable->ySize-1;
|
||||
yMin = fromTable->ySize-1;
|
||||
}
|
||||
|
||||
do //RPM axis
|
||||
{
|
||||
if(X>=fromTable->axisX[xMin]) {break;}
|
||||
xMin--;
|
||||
}while(1);
|
||||
fromTable->lastXMin = xMin + 1;
|
||||
do //MAP axis
|
||||
{
|
||||
if(Y<=fromTable->axisY[yMin]) {break;}
|
||||
yMin--;
|
||||
}while(1);
|
||||
fromTable->lastYMin = yMin + 1;
|
||||
|
||||
xMax = xMin + 1;
|
||||
yMax = yMin + 1;
|
||||
if (xMax>fromTable->xSize-1) //Overflow protection
|
||||
{
|
||||
xMax = fromTable->xSize-1;
|
||||
xMin = xMax - 1;
|
||||
}
|
||||
if (yMax>fromTable->ySize-1) //Overflow protection
|
||||
{
|
||||
yMax = fromTable->ySize-1;
|
||||
yMin = yMax - 1;
|
||||
}
|
||||
|
||||
yMaxValue = fromTable->axisY[yMax];
|
||||
yMinValue = fromTable->axisY[yMin];
|
||||
xMaxValue = fromTable->axisX[xMax];
|
||||
xMinValue = fromTable->axisX[xMin];
|
||||
|
||||
int A = fromTable->values[yMin][xMin];
|
||||
int B = fromTable->values[yMin][xMax];
|
||||
int C = fromTable->values[yMax][xMin];
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
|
||||
p = ((long)(X - xMinValue) << 8) / (xMaxValue - xMinValue); //(RPM - RPM[1])/(RPM[2]- RPM[1])
|
||||
q = 256 - (((long)(Y - yMaxValue) << 8) / (yMinValue - yMaxValue)); //(MAP - MAP[2])/(MAP[2]- MAP[1])
|
||||
|
||||
int m = ((256-p) * (256-q)) >> 8;
|
||||
int n = (p * (256-q)) >> 8;
|
||||
int o = ((256-p) * q) >> 8;
|
||||
int r = (p * q) >> 8;
|
||||
return ( (A * m) + (B * n) + (C * o) + (D * r) ) >> 8;
|
||||
}
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue