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 pinInjector2; //Output pin injector 2
|
||||||
byte pinInjector3; //Output pin injector 3 is on
|
byte pinInjector3; //Output pin injector 3 is on
|
||||||
byte pinInjector4; //Output pin injector 4 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 pinInjector6; //Placeholder only - NOT USED
|
||||||
byte pinInjector7; //Placeholder only - NOT USED
|
byte pinInjector7; //Placeholder only - NOT USED
|
||||||
byte pinInjector8; //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 pinCoil2; //Pin for coil 2
|
||||||
byte pinCoil3; //Pin for coil 3
|
byte pinCoil3; //Pin for coil 3
|
||||||
byte pinCoil4; //Pin for coil 4
|
byte pinCoil4; //Pin for coil 4
|
||||||
byte pinCoil5; //Pin for coil 4
|
byte pinCoil5; //Pin for coil 5
|
||||||
byte pinCoil6; //Pin for coil 4
|
byte pinCoil6; //Pin for coil 6
|
||||||
byte pinCoil7; //Pin for coil 4
|
byte pinCoil7; //Pin for coil 7
|
||||||
byte pinCoil8; //Pin for coil 4
|
byte pinCoil8; //Pin for coil 8
|
||||||
byte pinTrigger; //The CAS pin
|
byte pinTrigger; //The CAS pin
|
||||||
byte pinTrigger2; //The Cam Sensor pin
|
byte pinTrigger2; //The Cam Sensor pin
|
||||||
byte pinTrigger3; //the 2nd 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_MIN 87
|
||||||
#define BARO_MAX 108
|
#define BARO_MAX 108
|
||||||
|
|
||||||
|
#define ANALOG_ISR
|
||||||
|
|
||||||
volatile byte flexCounter = 0;
|
volatile byte flexCounter = 0;
|
||||||
|
volatile int AnChannel[15];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simple low pass IIR filter macro for the analog inputs
|
* Simple low pass IIR filter macro for the analog inputs
|
||||||
|
@ -27,4 +30,38 @@ void flexPulse();
|
||||||
|
|
||||||
unsigned int tempReading;
|
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
|
#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
|
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()
|
void instanteneousMAPReading()
|
||||||
{
|
{
|
||||||
//Instantaneous MAP readings
|
//Instantaneous MAP readings
|
||||||
tempReading = analogRead(pinMAP);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = analogRead(pinMAP);
|
tempReading = AnChannel[pinMAP-A0];
|
||||||
|
#else
|
||||||
|
tempReading = analogRead(pinMAP);
|
||||||
|
tempReading = analogRead(pinMAP);
|
||||||
|
#endif
|
||||||
//Error checking
|
//Error checking
|
||||||
if(tempReading >= VALID_MAP_MAX || tempReading <= VALID_MAP_MIN) { mapErrorCount += 1; }
|
if(tempReading >= VALID_MAP_MAX || tempReading <= VALID_MAP_MIN) { mapErrorCount += 1; }
|
||||||
else { currentStatus.mapADC = tempReading; mapErrorCount = 0; }
|
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.
|
if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
|
||||||
{
|
{
|
||||||
tempReading = analogRead(pinMAP);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = analogRead(pinMAP);
|
tempReading = AnChannel[pinMAP-A0];
|
||||||
|
#else
|
||||||
|
tempReading = analogRead(pinMAP);
|
||||||
|
tempReading = analogRead(pinMAP);
|
||||||
|
#endif
|
||||||
|
|
||||||
//Error check
|
//Error check
|
||||||
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
|
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.
|
if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for.
|
||||||
{
|
{
|
||||||
tempReading = analogRead(pinMAP);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = analogRead(pinMAP);
|
tempReading = AnChannel[pinMAP-A0];
|
||||||
|
#else
|
||||||
|
tempReading = analogRead(pinMAP);
|
||||||
|
tempReading = analogRead(pinMAP);
|
||||||
|
#endif
|
||||||
//Error check
|
//Error check
|
||||||
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
|
if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN)
|
||||||
{
|
{
|
||||||
|
@ -87,8 +138,12 @@ void readTPS()
|
||||||
{
|
{
|
||||||
currentStatus.TPSlast = currentStatus.TPS;
|
currentStatus.TPSlast = currentStatus.TPS;
|
||||||
currentStatus.TPSlast_time = currentStatus.TPS_time;
|
currentStatus.TPSlast_time = currentStatus.TPS_time;
|
||||||
analogRead(pinTPS);
|
#if defined(ANALOG_ISR)
|
||||||
byte tempTPS = fastMap1023toX(analogRead(pinTPS), 255); //Get the current raw TPS ADC value and map it into a byte
|
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);
|
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).
|
//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
|
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()
|
void readCLT()
|
||||||
{
|
{
|
||||||
tempReading = analogRead(pinCLT);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = fastMap1023toX(analogRead(pinCLT), 511); //Get the current raw CLT value
|
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.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
|
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()
|
void readIAT()
|
||||||
{
|
{
|
||||||
tempReading = analogRead(pinIAT);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = fastMap1023toX(analogRead(pinIAT), 511); //Get the current raw IAT value
|
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.iatADC = ADC_FILTER(tempReading, ADCFILTER_IAT, currentStatus.iatADC);
|
||||||
currentStatus.IAT = iatCalibrationTable[currentStatus.iatADC] - CALIBRATION_TEMPERATURE_OFFSET;
|
currentStatus.IAT = iatCalibrationTable[currentStatus.iatADC] - CALIBRATION_TEMPERATURE_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readO2()
|
void readO2()
|
||||||
{
|
{
|
||||||
tempReading = analogRead(pinO2);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = fastMap1023toX(analogRead(pinO2), 511); //Get the current O2 value.
|
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.O2ADC = ADC_FILTER(tempReading, ADCFILTER_O2, currentStatus.O2ADC);
|
||||||
currentStatus.O2 = o2CalibrationTable[currentStatus.O2ADC];
|
currentStatus.O2 = o2CalibrationTable[currentStatus.O2ADC];
|
||||||
}
|
}
|
||||||
|
@ -130,8 +197,12 @@ void readO2()
|
||||||
|
|
||||||
void readBat()
|
void readBat()
|
||||||
{
|
{
|
||||||
tempReading = analogRead(pinBat);
|
#if defined(ANALOG_ISR)
|
||||||
tempReading = fastMap1023toX(analogRead(pinBat), 245); //Get the current raw Battery value. Permissible values are from 0v to 24.5v (245)
|
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);
|
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 "decoders.h"
|
||||||
#include "idle.h"
|
#include "idle.h"
|
||||||
#include "auxiliaries.h"
|
#include "auxiliaries.h"
|
||||||
#include "fastAnalog.h"
|
|
||||||
#include "sensors.h"
|
#include "sensors.h"
|
||||||
#include "src/PID_v1/PID_v1.h"
|
#include "src/PID_v1/PID_v1.h"
|
||||||
//#include "src/DigitalWriteFast/digitalWriteFast.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
|
//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; }
|
if(configPage2.IgInv == 1) { coilHIGH = LOW, coilLOW = HIGH; }
|
||||||
else { coilHIGH = HIGH, coilLOW = LOW; }
|
else { coilHIGH = HIGH, coilLOW = LOW; }
|
||||||
digitalWrite(pinCoil1, coilLOW);
|
endCoil1Charge();
|
||||||
digitalWrite(pinCoil2, coilLOW);
|
endCoil2Charge();
|
||||||
digitalWrite(pinCoil3, coilLOW);
|
endCoil3Charge();
|
||||||
digitalWrite(pinCoil4, coilLOW);
|
endCoil4Charge();
|
||||||
digitalWrite(pinCoil5, coilLOW);
|
endCoil5Charge();
|
||||||
|
|
||||||
//Similar for injectors, make sure they're turned off
|
//Similar for injectors, make sure they're turned off
|
||||||
digitalWrite(pinInjector1, LOW);
|
closeInjector1();
|
||||||
digitalWrite(pinInjector2, LOW);
|
closeInjector2();
|
||||||
digitalWrite(pinInjector3, LOW);
|
closeInjector3();
|
||||||
digitalWrite(pinInjector4, LOW);
|
closeInjector4();
|
||||||
digitalWrite(pinInjector5, LOW);
|
closeInjector5();
|
||||||
|
|
||||||
//Set the tacho output default state
|
//Set the tacho output default state
|
||||||
digitalWrite(pinTachOut, HIGH);
|
digitalWrite(pinTachOut, HIGH);
|
||||||
|
@ -254,6 +253,7 @@ void setup()
|
||||||
initialiseFan();
|
initialiseFan();
|
||||||
initialiseAuxPWM();
|
initialiseAuxPWM();
|
||||||
initialiseCorrections();
|
initialiseCorrections();
|
||||||
|
initialiseADC();
|
||||||
|
|
||||||
//Check whether the flex sensor is enabled and if so, attach an interupt for it
|
//Check whether the flex sensor is enabled and if so, attach an interupt for it
|
||||||
if(configPage1.flexEnabled)
|
if(configPage1.flexEnabled)
|
||||||
|
@ -484,20 +484,6 @@ void setup()
|
||||||
//Initial values for loop times
|
//Initial values for loop times
|
||||||
previousLoopTime = 0;
|
previousLoopTime = 0;
|
||||||
currentLoopTime = micros();
|
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;
|
mainLoopCount = 0;
|
||||||
ignitionCount = 0;
|
ignitionCount = 0;
|
||||||
|
@ -1452,6 +1438,37 @@ void loop()
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
//Interrupts
|
//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.
|
//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
|
//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;
|
int r = (p * q) >> 8;
|
||||||
return ( (A * m) + (B * n) + (C * o) + (D * r) ) >> 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