Merge pull request #17 from noisymime/master

Get latest fixes from Josh
This commit is contained in:
Vitor Moreno B. Sales 2018-02-09 13:06:05 -02:00 committed by GitHub
commit e510c0e909
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 308 additions and 251 deletions

View File

@ -1,4 +1,4 @@
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
#unset CAN_COMMANDS
#unset enablehardware_test
@ -2393,6 +2393,7 @@ cmdtestspk450dc = "E\x03\x0C"
boostCutOut = { boostCutFuel || boostCutSpark }
lambda = { afr / stoich }
MAPxRPM = { rpm * map }
loopsPerRev = { loopsPerSecond / (rpm / 60) }
;Manifold pressure in weirdo units
map_bar = { (map - baro) / 101.33 }

View File

@ -377,7 +377,8 @@ void triggerSec_DualWheel()
{
toothLastToothTime = micros();
//CONFIRM THE BELOW! IT DOESN'T LOOK RIGHT (toothOneTime??)
toothLastMinusOneToothTime = (toothOneTime - 6000000) / configPage4.triggerTeeth; //Fixes RPM at 10rpm until a full revolution has taken place
//toothLastMinusOneToothTime = (toothOneTime - 6000000) / configPage4.triggerTeeth; //Fixes RPM at 10rpm until a full revolution has taken place
toothLastMinusOneToothTime = micros() - (6000000 / configPage4.triggerTeeth); //Fixes RPM at 10rpm until a full revolution has taken place
toothCurrentCount = configPage4.triggerTeeth;
currentStatus.hasSync = true;
@ -1025,7 +1026,8 @@ void triggerSetup_24X()
toothAngles[23] = 357;
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
toothCurrentCount = 25; //We set the initial tooth value to be something that should never be reached. This indicates no sync
if(initialisationComplete == false) { toothCurrentCount = 25; toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initi check to prevent the fuel pump just staying on all the time
//We set the initial tooth value to be something that should never be reached. This indicates no sync
secondDerivEnabled = false;
decoderIsSequential = true;
}
@ -1043,24 +1045,29 @@ void triggerPri_24X()
toothCurrentCount = 1; //Reset the counter
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
revolutionOne = !revolutionOne; //Sequential revolution flip
currentStatus.hasSync = true;
currentStatus.startRevolutions++; //Counter
triggerToothAngle = 15; //Always 15 degrees for tooth #15
}
else
{
toothCurrentCount++; //Increment the tooth counter
triggerToothAngle = toothAngles[(toothCurrentCount-1)] - toothAngles[(toothCurrentCount-2)]; //Calculate the last tooth gap in degrees
}
addToothLogEntry(curGap);
toothLastToothTime = curTime;
}
}
void triggerSec_24X()
{
toothCurrentCount = 0; //All we need to do is reset the tooth count back to zero, indicating that we're at the beginning of a new revolution
return;
revolutionOne = 1; //Sequential revolution reset
}
uint16_t getRPM_24X()
@ -1071,11 +1078,12 @@ int getCrankAngle_24X(int timePerDegree)
{
//This is the current angle ATDC the engine is at. This is the last known position based on what tooth was last 'seen'. It is only accurate to the resolution of the trigger wheel (Eg 36-1 is 10 degrees)
unsigned long tempToothLastToothTime;
int tempToothCurrentCount;
int tempToothCurrentCount, tempRevolutionOne;
//Grab some variables that are used in the trigger code and assign them to temp variables.
noInterrupts();
tempToothCurrentCount = toothCurrentCount;
tempToothLastToothTime = toothLastToothTime;
tempRevolutionOne = revolutionOne;
interrupts();
int crankAngle;
@ -1087,6 +1095,9 @@ int getCrankAngle_24X(int timePerDegree)
if(elapsedTime < SHRT_MAX ) { crankAngle += div((int)elapsedTime, timePerDegree).quot; } //This option is much faster, but only available for smaller values of elapsedTime
else { crankAngle += ldiv(elapsedTime, timePerDegree).quot; }
//Sequential check (simply sets whether we're on the first or 2nd revoltuion of the cycle)
if (tempRevolutionOne) { crankAngle += 360; }
if (crankAngle >= 720) { crankAngle -= 720; }
if (crankAngle > CRANK_ANGLE_MAX) { crankAngle -= CRANK_ANGLE_MAX; }
if (crankAngle < 0) { crankAngle += 360; }

View File

@ -412,8 +412,8 @@ struct Schedule {
void (*StartCallback)(); //Start Callback function for schedule
void (*EndCallback)(); //Start Callback function for schedule
volatile unsigned long startTime; //The system time (in uS) that the schedule started
volatile unsigned int startCompare; //The counter value of the timer when this will start
volatile unsigned int endCompare;
volatile uint16_t startCompare; //The counter value of the timer when this will start
volatile uint16_t endCompare;
unsigned int nextStartCompare;
unsigned int nextEndCompare;

View File

@ -288,13 +288,13 @@ void setFuelSchedule(struct Schedule *targetSchedule, unsigned long timeout, uns
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD_SLOW - 1) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
if (timeout > MAX_TIMER_PERIOD) { timeout_timer_compare = uS_TO_TIMER_COMPARE( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
targetSchedule->startCompare = *targetSchedule->counter + timeout_timer_compare;
targetSchedule->endCompare = targetSchedule->startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
targetSchedule->endCompare = targetSchedule->startCompare + uS_TO_TIMER_COMPARE(duration);
targetSchedule->Status = PENDING; //Turn this schedule on
targetSchedule->schedulesSet++; //Increment the number of times this schedule has been set
@ -306,8 +306,8 @@ void setFuelSchedule(struct Schedule *targetSchedule, unsigned long timeout, uns
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
targetSchedule->nextStartCompare = *targetSchedule->counter + uS_TO_TIMER_COMPARE_SLOW(timeout);
targetSchedule->nextEndCompare = targetSchedule->nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
targetSchedule->nextStartCompare = *targetSchedule->counter + uS_TO_TIMER_COMPARE(timeout);
targetSchedule->nextEndCompare = targetSchedule->nextStartCompare + uS_TO_TIMER_COMPARE(duration);
targetSchedule->hasNextSchedule = true;
}
}
@ -316,141 +316,160 @@ void setFuelSchedule(struct Schedule *targetSchedule, unsigned long timeout, uns
//void setFuelSchedule1(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
void setFuelSchedule1(unsigned long timeout, unsigned long duration)
{
if(fuelSchedule1.Status != RUNNING) //Check that we're not already part way through a schedule
//Check whether timeout exceeds the maximum future time. This can potentially occur on sequential setups when below ~115rpm
if(timeout < MAX_TIMER_PERIOD_SLOW)
{
//Callbacks no longer used, but retained for now:
//fuelSchedule1.StartCallback = startCallback;
//fuelSchedule1.EndCallback = endCallback;
fuelSchedule1.duration = duration;
if(fuelSchedule1.Status != RUNNING) //Check that we're not already part way through a schedule
{
//Callbacks no longer used, but retained for now:
//fuelSchedule1.StartCallback = startCallback;
//fuelSchedule1.EndCallback = endCallback;
fuelSchedule1.duration = duration;
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD_SLOW - 1) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if ((timeout+duration) > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD_SLOW - 1 - duration) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule1.startCompare = FUEL1_COUNTER + timeout_timer_compare;
fuelSchedule1.endCompare = fuelSchedule1.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule1.Status = PENDING; //Turn this schedule on
fuelSchedule1.schedulesSet++; //Increment the number of times this schedule has been set
//Schedule 1 shares a timer with schedule 5
//if(channel5InjEnabled) { FUEL1_COMPARE = setQueue(timer3Aqueue, &fuelSchedule1, &fuelSchedule5, FUEL1_COUNTER); }
//else { timer3Aqueue[0] = &fuelSchedule1; timer3Aqueue[1] = &fuelSchedule1; timer3Aqueue[2] = &fuelSchedule1; timer3Aqueue[3] = &fuelSchedule1; FUEL1_COMPARE = fuelSchedule1.startCompare; }
//timer3Aqueue[0] = &fuelSchedule1; timer3Aqueue[1] = &fuelSchedule1; timer3Aqueue[2] = &fuelSchedule1; timer3Aqueue[3] = &fuelSchedule1;
FUEL1_COMPARE = fuelSchedule1.startCompare;
interrupts();
FUEL1_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule1.nextStartCompare = FUEL1_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule1.nextEndCompare = fuelSchedule1.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule1.hasNextSchedule = true;
}
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule1.startCompare = FUEL1_COUNTER + timeout_timer_compare;
fuelSchedule1.endCompare = fuelSchedule1.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule1.Status = PENDING; //Turn this schedule on
fuelSchedule1.schedulesSet++; //Increment the number of times this schedule has been set
//Schedule 1 shares a timer with schedule 5
//if(channel5InjEnabled) { FUEL1_COMPARE = setQueue(timer3Aqueue, &fuelSchedule1, &fuelSchedule5, FUEL1_COUNTER); }
//else { timer3Aqueue[0] = &fuelSchedule1; timer3Aqueue[1] = &fuelSchedule1; timer3Aqueue[2] = &fuelSchedule1; timer3Aqueue[3] = &fuelSchedule1; FUEL1_COMPARE = fuelSchedule1.startCompare; }
//timer3Aqueue[0] = &fuelSchedule1; timer3Aqueue[1] = &fuelSchedule1; timer3Aqueue[2] = &fuelSchedule1; timer3Aqueue[3] = &fuelSchedule1;
FUEL1_COMPARE = fuelSchedule1.startCompare;
interrupts();
FUEL1_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
noInterrupts();
fuelSchedule1.nextStartCompare = FUEL1_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule1.nextEndCompare = fuelSchedule1.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule1.duration = duration;
fuelSchedule1.hasNextSchedule = true;
interrupts();
} //Schedule is RUNNING
} //Timeout less than threshold
}
void setFuelSchedule2(unsigned long timeout, unsigned long duration)
{
if(fuelSchedule2.Status != RUNNING) //Check that we're not already part way through a schedule
//Check whether timeout exceeds the maximum future time. This can potentially occur on sequential setups when below ~115rpm
if(timeout < MAX_TIMER_PERIOD_SLOW)
{
//Callbacks no longer used, but retained for now:
//fuelSchedule2.StartCallback = startCallback;
//fuelSchedule2.EndCallback = endCallback;
fuelSchedule2.duration = duration;
if(fuelSchedule2.Status != RUNNING) //Check that we're not already part way through a schedule
{
//Callbacks no longer used, but retained for now:
//fuelSchedule2.StartCallback = startCallback;
//fuelSchedule2.EndCallback = endCallback;
fuelSchedule2.duration = duration;
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule2.startCompare = FUEL2_COUNTER + timeout_timer_compare;
fuelSchedule2.endCompare = fuelSchedule2.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
FUEL2_COMPARE = fuelSchedule2.startCompare; //Use the B compare unit of timer 3
fuelSchedule2.Status = PENDING; //Turn this schedule on
fuelSchedule2.schedulesSet++; //Increment the number of times this schedule has been set
interrupts();
FUEL2_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule2.nextStartCompare = FUEL2_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule2.nextEndCompare = fuelSchedule2.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule2.hasNextSchedule = true;
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule2.startCompare = FUEL2_COUNTER + timeout_timer_compare;
fuelSchedule2.endCompare = fuelSchedule2.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
FUEL2_COMPARE = fuelSchedule2.startCompare; //Use the B compare unit of timer 3
fuelSchedule2.Status = PENDING; //Turn this schedule on
fuelSchedule2.schedulesSet++; //Increment the number of times this schedule has been set
interrupts();
FUEL2_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule2.nextStartCompare = FUEL2_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule2.nextEndCompare = fuelSchedule2.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule2.hasNextSchedule = true;
}
}
}
//void setFuelSchedule3(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
void setFuelSchedule3(unsigned long timeout, unsigned long duration)
{
if(fuelSchedule3.Status != RUNNING)//Check that we're not already part way through a schedule
//Check whether timeout exceeds the maximum future time. This can potentially occur on sequential setups when below ~115rpm
if(timeout < MAX_TIMER_PERIOD_SLOW)
{
//Callbacks no longer used, but retained for now:
//fuelSchedule3.StartCallback = startCallback;
//fuelSchedule3.EndCallback = endCallback;
fuelSchedule3.duration = duration;
if(fuelSchedule3.Status != RUNNING)//Check that we're not already part way through a schedule
{
//Callbacks no longer used, but retained for now:
//fuelSchedule3.StartCallback = startCallback;
//fuelSchedule3.EndCallback = endCallback;
fuelSchedule3.duration = duration;
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule3.startCompare = FUEL3_COUNTER + timeout_timer_compare;
fuelSchedule3.endCompare = fuelSchedule3.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
FUEL3_COMPARE = fuelSchedule3.startCompare; //Use the C copmare unit of timer 3
fuelSchedule3.Status = PENDING; //Turn this schedule on
fuelSchedule3.schedulesSet++; //Increment the number of times this schedule has been set
interrupts();
FUEL3_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule3.nextStartCompare = FUEL3_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule3.nextEndCompare = fuelSchedule3.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule3.hasNextSchedule = true;
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule3.startCompare = FUEL3_COUNTER + timeout_timer_compare;
fuelSchedule3.endCompare = fuelSchedule3.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
FUEL3_COMPARE = fuelSchedule3.startCompare; //Use the C copmare unit of timer 3
fuelSchedule3.Status = PENDING; //Turn this schedule on
fuelSchedule3.schedulesSet++; //Increment the number of times this schedule has been set
interrupts();
FUEL3_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule3.nextStartCompare = FUEL3_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule3.nextEndCompare = fuelSchedule3.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule3.hasNextSchedule = true;
}
}
}
//void setFuelSchedule4(void (*startCallback)(), unsigned long timeout, unsigned long duration, void(*endCallback)())
void setFuelSchedule4(unsigned long timeout, unsigned long duration) //Uses timer 4 compare B
{
if(fuelSchedule4.Status != RUNNING) //Check that we're not already part way through a schedule
//Check whether timeout exceeds the maximum future time. This can potentially occur on sequential setups when below ~115rpm
if(timeout < MAX_TIMER_PERIOD_SLOW)
{
//Callbacks no longer used, but retained for now:
//fuelSchedule4.StartCallback = startCallback;
//fuelSchedule4.EndCallback = endCallback;
fuelSchedule4.duration = duration;
if(fuelSchedule4.Status != RUNNING) //Check that we're not already part way through a schedule
{
//Callbacks no longer used, but retained for now:
//fuelSchedule4.StartCallback = startCallback;
//fuelSchedule4.EndCallback = endCallback;
fuelSchedule4.duration = duration;
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule4.startCompare = FUEL4_COUNTER + timeout_timer_compare;
fuelSchedule4.endCompare = fuelSchedule4.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
FUEL4_COMPARE = fuelSchedule4.startCompare; //Use the C copmare unit of timer 3
fuelSchedule4.Status = PENDING; //Turn this schedule on
fuelSchedule4.schedulesSet++; //Increment the number of times this schedule has been set
interrupts();
FUEL4_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule4.nextStartCompare = FUEL4_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule4.nextEndCompare = fuelSchedule4.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule4.hasNextSchedule = true;
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
fuelSchedule4.startCompare = FUEL4_COUNTER + timeout_timer_compare;
fuelSchedule4.endCompare = fuelSchedule4.startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
FUEL4_COMPARE = fuelSchedule4.startCompare; //Use the C copmare unit of timer 3
fuelSchedule4.Status = PENDING; //Turn this schedule on
fuelSchedule4.schedulesSet++; //Increment the number of times this schedule has been set
interrupts();
FUEL4_TIMER_ENABLE();
}
else
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule4.nextStartCompare = FUEL4_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule4.nextEndCompare = fuelSchedule4.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule4.hasNextSchedule = true;
}
}
}
@ -764,7 +783,7 @@ static inline void fuelSchedule1Interrupt() //Most ARM chips can simply call a f
if (configPage2.injLayout == INJ_SEMISEQUENTIAL) { openInjector1and4(); }
else { openInjector1(); }
fuelSchedule1.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL1_COMPARE = fuelSchedule1.endCompare;
FUEL1_COMPARE = FUEL1_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule1.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule1.Status == RUNNING)
{
@ -801,7 +820,7 @@ static inline void fuelSchedule2Interrupt() //Most ARM chips can simply call a f
if (configPage2.injLayout == INJ_SEMISEQUENTIAL) { openInjector2and3(); }
else { openInjector2(); }
fuelSchedule2.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL2_COMPARE = fuelSchedule2.endCompare;
FUEL2_COMPARE = FUEL2_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule2.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule2.Status == RUNNING)
{
@ -837,7 +856,7 @@ static inline void fuelSchedule3Interrupt() //Most ARM chips can simply call a f
if(channel5InjEnabled) { openInjector3and5(); }
else { openInjector3(); }
fuelSchedule3.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL3_COMPARE = fuelSchedule3.endCompare;
FUEL3_COMPARE = FUEL3_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule3.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule3.Status == RUNNING)
{
@ -872,7 +891,7 @@ static inline void fuelSchedule4Interrupt() //Most ARM chips can simply call a f
//fuelSchedule4.StartCallback();
openInjector4();
fuelSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL4_COMPARE = fuelSchedule4.endCompare;
FUEL4_COMPARE = FUEL4_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule4.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule4.Status == RUNNING)
{
@ -940,11 +959,12 @@ static inline void ignitionSchedule1Interrupt() //Most ARM chips can simply call
ignitionSchedule1.StartCallback();
ignitionSchedule1.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule1.startTime = micros();
IGN1_COMPARE = ignitionSchedule1.endCompare;
//IGN1_COMPARE = ignitionSchedule1.endCompare;
IGN1_COMPARE = IGN1_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule1.duration); //Doing this here prevents a potential overflow on restarts
//This code is all to do with the staged ignition timing testing. That is, calling this interrupt slightly before the true ignition point and recalculating the end time for more accuracy
//IGN1_COMPARE = ignitionSchedule1.endCompare - 50;
//ignitionSchedule1.Status = STAGED;
}
}
else if (ignitionSchedule1.Status == STAGED)
{
int16_t crankAngle = getCrankAngle(timePerDegree);
@ -978,7 +998,7 @@ static inline void ignitionSchedule2Interrupt() //Most ARM chips can simply call
ignitionSchedule2.StartCallback();
ignitionSchedule2.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule2.startTime = micros();
IGN2_COMPARE = ignitionSchedule2.endCompare; //OCR5B = TCNT5 + (ignitionSchedule2.duration >> 2);
IGN2_COMPARE = IGN2_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule2.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule2.Status == RUNNING)
{
@ -1001,7 +1021,7 @@ static inline void ignitionSchedule3Interrupt() //Most ARM chips can simply call
ignitionSchedule3.StartCallback();
ignitionSchedule3.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule3.startTime = micros();
IGN3_COMPARE = ignitionSchedule3.endCompare; //OCR5C = TCNT5 + (ignitionSchedule3.duration >> 2);
IGN3_COMPARE = IGN3_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule3.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule3.Status == RUNNING)
{
@ -1034,7 +1054,7 @@ static inline void ignitionSchedule4Interrupt() //Most ARM chips can simply call
ignitionSchedule4.StartCallback();
ignitionSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule4.startTime = micros();
IGN4_COMPARE = ignitionSchedule4.endCompare;
IGN4_COMPARE = IGN4_COUNTER + uS_TO_TIMER_COMPARE_SLOW(ignitionSchedule4.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule4.Status == RUNNING)
{
@ -1067,7 +1087,7 @@ static inline void ignitionSchedule5Interrupt() //Most ARM chips can simply call
ignitionSchedule5.StartCallback();
ignitionSchedule5.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule5.startTime = micros();
IGN5_COMPARE = ignitionSchedule5.endCompare;
IGN5_COMPARE = IGN5_COUNTER + uS_TO_TIMER_COMPARE_SLOW(ignitionSchedule5.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule5.Status == RUNNING)
{

View File

@ -1227,6 +1227,7 @@ void loop()
//Calculate start angle for each channel
//1 cylinder (Everyone gets this)
ignition1EndAngle = CRANK_ANGLE_MAX_IGN - currentStatus.advance;
if(ignition1EndAngle > CRANK_ANGLE_MAX_IGN) {ignition1EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition1StartAngle = ignition1EndAngle - dwellAngle; // 360 - desired advance angle - number of degrees the dwell will take
if(ignition1StartAngle < 0) {ignition1StartAngle += CRANK_ANGLE_MAX_IGN;}
@ -1235,35 +1236,41 @@ void loop()
{
//2 cylinders
case 2:
ignition2EndAngle = channel2IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition2EndAngle = channel2IgnDegrees - currentStatus.advance;
if(ignition2EndAngle > CRANK_ANGLE_MAX_IGN) {ignition2EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition2StartAngle = ignition2EndAngle - dwellAngle;
if(ignition2StartAngle > CRANK_ANGLE_MAX_IGN) {ignition2StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition2StartAngle < 0) {ignition2StartAngle += CRANK_ANGLE_MAX_IGN;}
break;
//3 cylinders
case 3:
ignition2EndAngle = channel2IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition2EndAngle = channel2IgnDegrees - currentStatus.advance;
if(ignition2EndAngle > CRANK_ANGLE_MAX_IGN) {ignition2EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition2StartAngle = ignition2EndAngle - dwellAngle;
if(ignition2StartAngle > CRANK_ANGLE_MAX_IGN) {ignition2StartAngle -= CRANK_ANGLE_MAX_IGN;}
ignition3EndAngle = channel3IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
if(ignition2StartAngle < 0) {ignition2StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition3EndAngle = channel3IgnDegrees - currentStatus.advance;
if(ignition3EndAngle > CRANK_ANGLE_MAX_IGN) {ignition3EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition3StartAngle = channel3IgnDegrees + 360 - currentStatus.advance - dwellAngle;
if(ignition3StartAngle > CRANK_ANGLE_MAX_IGN) {ignition3StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition3StartAngle < 0) {ignition3StartAngle += CRANK_ANGLE_MAX_IGN;}
break;
//4 cylinders
case 4:
ignition2EndAngle = channel2IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition2EndAngle = channel2IgnDegrees - currentStatus.advance;
if(ignition2EndAngle > CRANK_ANGLE_MAX_IGN) {ignition2EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition2StartAngle = ignition2EndAngle - dwellAngle;
if(ignition2StartAngle > CRANK_ANGLE_MAX_IGN) {ignition2StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition2StartAngle < 0) {ignition2StartAngle += CRANK_ANGLE_MAX_IGN;}
if(configPage4.sparkMode == IGN_MODE_SEQUENTIAL)
{
ignition3EndAngle = channel3IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition3EndAngle = channel3IgnDegrees - currentStatus.advance;
if(ignition3EndAngle > CRANK_ANGLE_MAX_IGN) {ignition3EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition3StartAngle = ignition3EndAngle - dwellAngle;
if(ignition3StartAngle > CRANK_ANGLE_MAX_IGN) {ignition3StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition3StartAngle < 0) {ignition3StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition4EndAngle = channel4IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition4EndAngle = channel4IgnDegrees - currentStatus.advance;
if(ignition4EndAngle > CRANK_ANGLE_MAX_IGN) {ignition4EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition4StartAngle = ignition4EndAngle - dwellAngle;
if(ignition4StartAngle > CRANK_ANGLE_MAX_IGN) {ignition4StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition4StartAngle < 0) {ignition4StartAngle += CRANK_ANGLE_MAX_IGN;}
}
else if(configPage4.sparkMode == IGN_MODE_ROTARY)
{
@ -1288,18 +1295,20 @@ void loop()
break;
//5 cylinders
case 5:
ignition2EndAngle = channel2IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition2EndAngle = channel2IgnDegrees - currentStatus.advance;
if(ignition2EndAngle > CRANK_ANGLE_MAX_IGN) {ignition2EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition2StartAngle = ignition2EndAngle - dwellAngle;
if(ignition2StartAngle > CRANK_ANGLE_MAX_IGN) {ignition2StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition2StartAngle < 0) {ignition2StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition3EndAngle = channel3IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition3EndAngle = channel3IgnDegrees - currentStatus.advance;
if(ignition3EndAngle > CRANK_ANGLE_MAX_IGN) {ignition3EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition3StartAngle = ignition3EndAngle - dwellAngle;
if(ignition3StartAngle > CRANK_ANGLE_MAX_IGN) {ignition3StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition3StartAngle < 0) {ignition3StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition4EndAngle = channel4IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
if(ignition4EndAngle > CRANK_ANGLE_MAX_IGN) {ignition4EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition4StartAngle = ignition4EndAngle - dwellAngle;
if(ignition4StartAngle > CRANK_ANGLE_MAX_IGN) {ignition4StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition4StartAngle < 0) {ignition4StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition5StartAngle = channel5IgnDegrees + CRANK_ANGLE_MAX - currentStatus.advance - dwellAngle;
if(ignition5StartAngle > CRANK_ANGLE_MAX_IGN) {ignition5StartAngle -= CRANK_ANGLE_MAX_IGN;}
@ -1307,27 +1316,32 @@ void loop()
break;
//6 cylinders
case 6:
ignition2EndAngle = channel2IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition2EndAngle = channel2IgnDegrees - currentStatus.advance;
if(ignition2EndAngle > CRANK_ANGLE_MAX_IGN) {ignition2EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition2StartAngle = ignition2EndAngle - dwellAngle;
if(ignition2StartAngle > CRANK_ANGLE_MAX_IGN) {ignition2StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition2StartAngle < 0) {ignition2StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition3EndAngle = channel3IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition3EndAngle = channel3IgnDegrees - currentStatus.advance;
if(ignition3EndAngle > CRANK_ANGLE_MAX_IGN) {ignition3EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition3StartAngle = ignition3EndAngle - dwellAngle;
if(ignition3StartAngle > CRANK_ANGLE_MAX_IGN) {ignition3StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition3StartAngle < 0) {ignition3StartAngle += CRANK_ANGLE_MAX_IGN;}
break;
//8 cylinders
case 8:
ignition2EndAngle = channel2IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition2EndAngle = channel2IgnDegrees - currentStatus.advance;
if(ignition2EndAngle > CRANK_ANGLE_MAX_IGN) {ignition2EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition2StartAngle = ignition2EndAngle - dwellAngle;
if(ignition2StartAngle > CRANK_ANGLE_MAX_IGN) {ignition2StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition2StartAngle < 0) {ignition2StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition3EndAngle = channel3IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition3EndAngle = channel3IgnDegrees - currentStatus.advance;
if(ignition3EndAngle > CRANK_ANGLE_MAX_IGN) {ignition3EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition3StartAngle = ignition3EndAngle - dwellAngle;
if(ignition3StartAngle > CRANK_ANGLE_MAX_IGN) {ignition3StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition3StartAngle < 0) {ignition3StartAngle += CRANK_ANGLE_MAX_IGN;}
ignition4EndAngle = channel4IgnDegrees + CRANK_ANGLE_MAX_IGN - currentStatus.advance;
ignition4EndAngle = channel4IgnDegrees - currentStatus.advance;
if(ignition4EndAngle > CRANK_ANGLE_MAX_IGN) {ignition4EndAngle -= CRANK_ANGLE_MAX_IGN;}
ignition4StartAngle = ignition4EndAngle - dwellAngle;
if(ignition4StartAngle > CRANK_ANGLE_MAX_IGN) {ignition4StartAngle -= CRANK_ANGLE_MAX_IGN;}
if(ignition4StartAngle < 0) {ignition4StartAngle += CRANK_ANGLE_MAX_IGN;}
break;
//Will hit the default case on 1 cylinder or >8 cylinders. Do nothing in these cases

View File

@ -29,6 +29,7 @@ struct table2D {
//Store the last input and output for caching
int16_t lastInput;
int16_t lastOutput;
byte cacheTime; //TRacks when the last cache value was set so it can expire after x seconds. A timeout is required to pickup when a tuning value is changed, otherwise the old cached value will continue to be returned as the X value isn't changing.
};
void table2D_setSize(struct table2D targetTable, byte newSize);

View File

@ -59,111 +59,121 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
bool valueFound = false;
int X = X_in;
int xMinValue, xMaxValue;
if (fromTable->valueSize == SIZE_BYTE)
{
//Byte version
xMinValue = fromTable->axisX[0];
xMaxValue = fromTable->axisX[fromTable->xSize-1];
}
else
{
//int version
xMinValue = fromTable->axisX16[0];
xMaxValue = fromTable->axisX16[fromTable->xSize-1];
}
int xMin = 0;
int xMax = 0;
//If the requested X value is greater/small than the maximum/minimum bin, reset X to be that value
if(X > xMaxValue) { X = xMaxValue; }
if(X < xMinValue) { X = xMinValue; }
if (fromTable->valueSize == SIZE_BYTE)
//Check whether the X input is the same as last time this ran
if(X_in == fromTable->lastInput && fromTable->cacheTime == currentStatus.secl)
{
//**** Byte version ****
//1st check is whether we're still in the same X bin as last time
if ( (X <= fromTable->axisX[fromTable->lastXMax]) && (X > fromTable->axisX[fromTable->lastXMin]) )
{
xMaxValue = fromTable->axisX[fromTable->lastXMax];
xMinValue = fromTable->axisX[fromTable->lastXMin];
xMax = fromTable->lastXMax;
xMin = fromTable->lastXMin;
}
else
{
//If we're not in the same bin, loop through to find where we are
for (int x = fromTable->xSize-1; x >= 0; x--)
{
//Checks the case where the X value is exactly what was requested
if ( (X == fromTable->axisX[x]) || (x == 0) )
{
returnValue = fromTable->values[x]; //Simply return the coresponding value
valueFound = true;
break;
}
else
{
//Normal case
if ( (X <= fromTable->axisX[x]) && (X > fromTable->axisX[x-1]) )
{
xMaxValue = fromTable->axisX[x];
xMinValue = fromTable->axisX[x-1];
xMax = x;
fromTable->lastXMax = xMax;
xMin = x-1;
fromTable->lastXMin = xMin;
break;
}
}
}
}
returnValue = fromTable->lastOutput;
valueFound = true;
}
else
{
// **** INT VERSION ****
fromTable->cacheTime = currentStatus.secl; //As we're not using the cache value, set the current secl value to track when this new value was calc'd
//1st check is whether we're still in the same X bin as last time
if ( (X <= fromTable->axisX16[fromTable->lastXMax]) && (X > fromTable->axisX16[fromTable->lastXMin]) )
{
xMaxValue = fromTable->axisX16[fromTable->lastXMax];
xMinValue = fromTable->axisX16[fromTable->lastXMin];
xMax = fromTable->lastXMax;
xMin = fromTable->lastXMin;
}
else
{
//If we're not in the same bin, loop through to find where we are
for (int x = fromTable->xSize-1; x >= 0; x--)
{
//Checks the case where the X value is exactly what was requested
if ( (X == fromTable->axisX16[x]) || (x == 0) )
{
returnValue = fromTable->values16[x]; //Simply return the coresponding value
valueFound = true;
break;
}
else
{
//Normal case
if ( (X <= fromTable->axisX16[x]) && (X > fromTable->axisX16[x-1]) )
if (fromTable->valueSize == SIZE_BYTE)
{
//Byte version
xMinValue = fromTable->axisX[0];
xMaxValue = fromTable->axisX[fromTable->xSize-1];
}
else
{
//int version
xMinValue = fromTable->axisX16[0];
xMaxValue = fromTable->axisX16[fromTable->xSize-1];
}
//If the requested X value is greater/small than the maximum/minimum bin, reset X to be that value
if(X > xMaxValue) { X = xMaxValue; }
if(X < xMinValue) { X = xMinValue; }
if (fromTable->valueSize == SIZE_BYTE)
{
//**** Byte version ****
//1st check is whether we're still in the same X bin as last time
if ( (X <= fromTable->axisX[fromTable->lastXMax]) && (X > fromTable->axisX[fromTable->lastXMin]) )
{
xMaxValue = fromTable->axisX[fromTable->lastXMax];
xMinValue = fromTable->axisX[fromTable->lastXMin];
xMax = fromTable->lastXMax;
xMin = fromTable->lastXMin;
}
else
{
//If we're not in the same bin, loop through to find where we are
for (int x = fromTable->xSize-1; x >= 0; x--)
{
//Checks the case where the X value is exactly what was requested
if ( (X == fromTable->axisX[x]) || (x == 0) )
{
xMaxValue = fromTable->axisX16[x];
xMinValue = fromTable->axisX16[x-1];
xMax = x;
fromTable->lastXMax = xMax;
xMin = x-1;
fromTable->lastXMin = xMin;
returnValue = fromTable->values[x]; //Simply return the coresponding value
valueFound = true;
break;
} //Found in loop
} //Exact hit
} //For loop
}
}
else
{
//Normal case
if ( (X <= fromTable->axisX[x]) && (X > fromTable->axisX[x-1]) )
{
xMaxValue = fromTable->axisX[x];
xMinValue = fromTable->axisX[x-1];
xMax = x;
fromTable->lastXMax = xMax;
xMin = x-1;
fromTable->lastXMin = xMin;
break;
}
}
}
}
}
else
{
// **** INT VERSION ****
}
//1st check is whether we're still in the same X bin as last time
if ( (X <= fromTable->axisX16[fromTable->lastXMax]) && (X > fromTable->axisX16[fromTable->lastXMin]) )
{
xMaxValue = fromTable->axisX16[fromTable->lastXMax];
xMinValue = fromTable->axisX16[fromTable->lastXMin];
xMax = fromTable->lastXMax;
xMin = fromTable->lastXMin;
}
else
{
//If we're not in the same bin, loop through to find where we are
for (int x = fromTable->xSize-1; x >= 0; x--)
{
//Checks the case where the X value is exactly what was requested
if ( (X == fromTable->axisX16[x]) || (x == 0) )
{
returnValue = fromTable->values16[x]; //Simply return the coresponding value
valueFound = true;
break;
}
else
{
//Normal case
if ( (X <= fromTable->axisX16[x]) && (X > fromTable->axisX16[x-1]) )
{
xMaxValue = fromTable->axisX16[x];
xMinValue = fromTable->axisX16[x-1];
xMax = x;
fromTable->lastXMax = xMax;
xMin = x-1;
fromTable->lastXMin = xMin;
break;
} //Found in loop
} //Exact hit
} //For loop
} //In cache or not
} //byte or int values
} //X_in same as last time
if (valueFound == false)
{