Various minor optimisations - Replace custom divide operation with div

This commit is contained in:
Josh Stewart 2014-05-08 23:01:36 +10:00
parent 781c6b72dc
commit 5870a47558
7 changed files with 27 additions and 177 deletions

View File

@ -89,15 +89,15 @@ void sendValues(int length)
response[3] = 0x00; //baro
response[4] = currentStatus.MAP; //map
response[5] = 0x00; //mat
response[6] = 0x00; //Coolant
response[6] = 0x00; //Coolant ADC
response[7] = currentStatus.tpsADC; //TPS (Raw 0-255)
response[8] = 0x00; //battery voltage
response[9] = 0x00; //O2
response[10] = 0x00; //Exhaust gas correction (%)
response[11] = 0x00; //Air Correction (%)
response[12] = 0x00; //Warmup enrichment (%)
response[13] = (currentStatus.RPM / 100); //rpm / 100
response[14] = (currentStatus.PW / 100); //Pulsewidth 1 divided by 10 (in ms)
response[13] = div(currentStatus.RPM, 100).quot; //rpm / 100
response[14] = div(currentStatus.PW, 100).quot; //Pulsewidth 1 divided by 10 (in ms)
response[15] = 0x00; //acceleration enrichment (ms)
response[16] = 0x00; //Barometer correction (%)
response[17] = 0x00; //Total GammaE (%)

View File

@ -12,8 +12,8 @@ byte correctionsTotal()
byte correctionWUE()
{
//Not yet implemented
return 100;
//Possibly reduce the frequency this runs at (Costs about 50 loops per second)
return 100 + table2D_getValue(WUETable, currentStatus.coolant);
}
byte correctionASE()
@ -38,8 +38,9 @@ Calculates the % change of the throttle over time (%/second) and performs a look
byte correctionAccel()
{
int rateOfChange = (1000000 / (currentLoopTime - previousLoopTime)) * (currentStatus.TPS - currentStatus.TPSlast); //This is the % per second that the TPS has moved
currentStatus.tpsDOT = rateOfChange / 10;
int rateOfChange = div(1000000, (currentLoopTime - previousLoopTime)).quot * (currentStatus.TPS - currentStatus.TPSlast); //This is the % per second that the TPS has moved
//int rateOfChange = div( (1000000 * (currentStatus.TPS - currentStatus.TPSlast)), (currentLoopTime - previousLoopTime)).quot; //This is the % per second that the TPS has moved
currentStatus.tpsDOT = div(rateOfChange, 10).quot;
if (rateOfChange > configPage1.tpsThresh)
{

View File

@ -41,6 +41,10 @@ struct statuses {
byte tpsDOT;
byte VE;
byte O2;
byte coolant;
byte coolantADC;
byte IAT;
byte iatADC;
byte advance;
volatile byte squirt;
byte engine;

160
math.h
View File

@ -1,163 +1,7 @@
/*
* Copyright (c) 2013 Ambroz Bizjak
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AMBRO_AVR_ASM_DIV_32_32_LARGE
#define AMBRO_AVR_ASM_DIV_32_32_LARGE
#include <stdint.h>
#define DIVIDE_32_32_ITER_0_7(i) \
" lsl %D[n]\n" \
" rol __tmp_reg__\n" \
" cp __tmp_reg__,%A[d]\n" \
" cpc __zero_reg__,%B[d]\n" \
" cpc __zero_reg__,%C[d]\n" \
" cpc __zero_reg__,%D[d]\n" \
" brcs zero_bit_" #i "__%=\n" \
" sub __tmp_reg__,%A[d]\n" \
" ori %D[q],1<<(7-" #i ")\n" \
"zero_bit_" #i "__%=:\n"
#define DIVIDE_32_32_ITER_8_15(i) \
" lsl %C[n]\n" \
" rol __tmp_reg__\n" \
" rol %D[n]\n" \
" cp __tmp_reg__,%A[d]\n" \
" cpc %D[n],%B[d]\n" \
" cpc __zero_reg__,%C[d]\n" \
" cpc __zero_reg__,%D[d]\n" \
" brcs zero_bit_" #i "__%=\n" \
" sub __tmp_reg__,%A[d]\n" \
" sbc %D[n],%B[d]\n" \
" ori %C[q],1<<(15-" #i ")\n" \
"zero_bit_" #i "__%=:\n"
#define DIVIDE_32_32_ITER_16_23(i) \
" lsl %B[n]\n" \
" rol __tmp_reg__\n" \
" rol %D[n]\n" \
" rol %C[n]\n" \
" cp __tmp_reg__,%A[d]\n" \
" cpc %D[n],%B[d]\n" \
" cpc %C[n],%C[d]\n" \
" cpc __zero_reg__,%D[d]\n" \
" brcs zero_bit_" #i "__%=\n" \
" sub __tmp_reg__,%A[d]\n" \
" sbc %D[n],%B[d]\n" \
" sbc %C[n],%C[d]\n" \
" ori %B[q],1<<(23-" #i ")\n" \
"zero_bit_" #i "__%=:\n"
#define DIVIDE_32_32_ITER_24_30(i) \
" lsl %A[n]\n" \
" rol __tmp_reg__\n" \
" rol %D[n]\n" \
" rol %C[n]\n" \
" rol %B[n]\n" \
" cp __tmp_reg__,%A[d]\n" \
" cpc %D[n],%B[d]\n" \
" cpc %C[n],%C[d]\n" \
" cpc %B[n],%D[d]\n" \
" brcs zero_bit_" #i "__%=\n" \
" sub __tmp_reg__,%A[d]\n" \
" sbc %D[n],%B[d]\n" \
" sbc %C[n],%C[d]\n" \
" sbc %B[n],%D[d]\n" \
" ori %A[q],1<<(31-" #i ")\n" \
"zero_bit_" #i "__%=:\n"
/**
* Division uint32_t/uint32_t.
*
* Cycles in worst case: 384
* = 5 + (8 * 9) + (8 * 11) + (8 * 13) + (7 * 15) + 10
*/
static inline uint32_t fastDivide32(uint32_t n, uint32_t d)
{
uint32_t q;
asm(
" clr %A[q]\n"
" clr %B[q]\n"
" clr %C[q]\n"
" clr %D[q]\n"
" clr __tmp_reg__\n"
DIVIDE_32_32_ITER_0_7(0)
DIVIDE_32_32_ITER_0_7(1)
DIVIDE_32_32_ITER_0_7(2)
DIVIDE_32_32_ITER_0_7(3)
DIVIDE_32_32_ITER_0_7(4)
DIVIDE_32_32_ITER_0_7(5)
DIVIDE_32_32_ITER_0_7(6)
DIVIDE_32_32_ITER_0_7(7)
DIVIDE_32_32_ITER_8_15(8)
DIVIDE_32_32_ITER_8_15(9)
DIVIDE_32_32_ITER_8_15(10)
DIVIDE_32_32_ITER_8_15(11)
DIVIDE_32_32_ITER_8_15(12)
DIVIDE_32_32_ITER_8_15(13)
DIVIDE_32_32_ITER_8_15(14)
DIVIDE_32_32_ITER_8_15(15)
DIVIDE_32_32_ITER_16_23(16)
DIVIDE_32_32_ITER_16_23(17)
DIVIDE_32_32_ITER_16_23(18)
DIVIDE_32_32_ITER_16_23(19)
DIVIDE_32_32_ITER_16_23(20)
DIVIDE_32_32_ITER_16_23(21)
DIVIDE_32_32_ITER_16_23(22)
DIVIDE_32_32_ITER_16_23(23)
DIVIDE_32_32_ITER_24_30(24)
DIVIDE_32_32_ITER_24_30(25)
DIVIDE_32_32_ITER_24_30(26)
DIVIDE_32_32_ITER_24_30(27)
DIVIDE_32_32_ITER_24_30(28)
DIVIDE_32_32_ITER_24_30(29)
DIVIDE_32_32_ITER_24_30(30)
" lsl %A[n]\n"
" rol __tmp_reg__\n"
" rol %D[n]\n"
" rol %C[n]\n"
" rol %B[n]\n"
" cp __tmp_reg__,%A[d]\n"
" cpc %D[n],%B[d]\n"
" cpc %C[n],%C[d]\n"
" cpc %B[n],%D[d]\n"
" sbci %A[q],-1\n"
: [q] "=&a" (q),
[n] "=&r" (n)
: "[n]" (n),
[d] "r" (d)
);
return q;
}
//Replace the standard arduino map() function to use the above
//Replace the standard arduino map() function to use the div function instead
long fastMap(long x, long in_min, long in_max, long out_min, long out_max)
{
return fastDivide32( ((x - in_min) * (out_max - out_min)) , ((in_max - in_min) + out_min) );
return div( ((x - in_min) * (out_max - out_min)) , ((in_max - in_min) + out_min) ).quot;
}
#endif

View File

@ -208,7 +208,7 @@ void loop()
noInterrupts();
unsigned long revolutionTime = (toothOneTime - toothOneMinusOneTime); //The time in uS that one revolution would take at current speed (The time tooth 1 was last seen, minus the time it was seen prior to that)
interrupts();
currentStatus.RPM = fastDivide32(US_IN_MINUTE, revolutionTime); //Calc RPM based on last full revolution time
currentStatus.RPM = div(US_IN_MINUTE, revolutionTime).quot; //Calc RPM based on last full revolution time
}
else
{
@ -222,17 +222,18 @@ void loop()
//Uncomment the following for testing
/*
currentStatus.hasSync = true;
currentStatus.TPS = 100;
currentStatus.RPM = 5500;
*/
//***SET STATUSES***
//-----------------------------------------------------------------------------------------------------
currentStatus.TPSlast = currentStatus.TPS;
currentStatus.MAP = map(analogRead(pinMAP), 0, 1023, 0, 100); //Get the current MAP value
currentStatus.tpsADC = map(analogRead(pinTPS), 0, 1023, 0, 255); //Get the current raw TPS ADC value and map it into a byte
currentStatus.TPS = map(currentStatus.tpsADC, configPage1.tpsMin, configPage1.tpsMax, 0, 100); //Take the raw TPS ADC value and convert it into a TPS% based on the calibrated values
currentStatus.O2 = map(analogRead(pinO2), 0, 1023, 117, 358); //Get the current O2 value. Calibration is from AFR values 7.35 to 22.4, then multiplied by 16 (<< 4). This is the correct calibration for an Innovate Wideband 0v - 5V unit
currentStatus.MAP = fastMap(analogRead(pinMAP), 0, 1023, 0, 100); //Get the current MAP value
currentStatus.coolant = fastMap(analogRead(pinCLT), 0, 1023, 0, 255); //Get the current raw CLT value
currentStatus.iatADC = fastMap(analogRead(pinIAT), 0, 1023, 0, 255); //Get the current raw IAT value
currentStatus.tpsADC = fastMap(analogRead(pinTPS), 0, 1023, 0, 255); //Get the current raw TPS ADC value and map it into a byte
currentStatus.TPS = fastMap(currentStatus.tpsADC, configPage1.tpsMin, configPage1.tpsMax, 0, 100); //Take the raw TPS ADC value and convert it into a TPS% based on the calibrated values
currentStatus.O2 = fastMap(analogRead(pinO2), 0, 1023, 117, 358); //Get the current O2 value. Calibration is from AFR values 7.35 to 22.4, then multiplied by 16 (<< 4). This is the correct calibration for an Innovate Wideband 0v - 5V unit
//Always check for sync
//Main loop runs within this clause
@ -282,14 +283,14 @@ void loop()
if (crankAngle > 360) { crankAngle -= 360; }
//How fast are we going? Need to know how long (uS) it will take to get from one tooth to the next. We then use that to estimate how far we are between the last tooth and the next one
unsigned long timePerDegree = fastDivide32( (toothOneTime - toothOneMinusOneTime), (triggerToothAngle * configPage2.triggerTeeth)); //The time (uS) it is currently taking to move 1 degree (fastDivide version)
crankAngle += fastDivide32( (micros() - toothLastToothTime), timePerDegree); //Estimate the number of degrees travelled since the last tooth (fastDivide version)
unsigned long timePerDegree = div( (toothOneTime - toothOneMinusOneTime), (triggerToothAngle * configPage2.triggerTeeth)).quot; //The time (uS) it is currently taking to move 1 degree (fastDivide version)
crankAngle += div( (micros() - toothLastToothTime), timePerDegree).quot; //Estimate the number of degrees travelled since the last tooth
//Determine next firing angles
int injector1StartAngle = 355 - ( fastDivide32(currentStatus.PW, timePerDegree) ); //This is a little primitive, but is based on the idea that all fuel needs to be delivered before the inlet valve opens. I am using 355 as the point at which the injector MUST be closed by. See http://www.extraefi.co.uk/sequential_fuel.html for more detail
int injector1StartAngle = 355 - ( div(currentStatus.PW, timePerDegree).quot ); //This is a little primitive, but is based on the idea that all fuel needs to be delivered before the inlet valve opens. I am using 355 as the point at which the injector MUST be closed by. See http://www.extraefi.co.uk/sequential_fuel.html for more detail
if (currentStatus.RPM > ((int)(configPage2.SoftRevLim * 100)) ) { currentStatus.advance -= configPage2.SoftLimRetard; } //Softcut RPM limit (If we're above softcut limit, delay timing by configured number of degrees)
int ignition1StartAngle = 360 - currentStatus.advance - (fastDivide32((configPage2.dwellRun*100), timePerDegree) ); // 360 - desired advance angle - number of degrees the dwell will take
int ignition1StartAngle = 360 - currentStatus.advance - (div((configPage2.dwellRun*100), timePerDegree).quot ); // 360 - desired advance angle - number of degrees the dwell will take
//Finally calculate the time (uS) until we reach the firing angles and set the schedules

View File

@ -182,7 +182,8 @@ int get3DTableValue(struct table3D fromTable, int Y, int X)
{ p = ((long)(X - xMinValue) << 8); } //This only occurs if the requested X value was equal to one of the X axis bins
else
{
p = ((long)(X - xMinValue) << 8) / (xMaxValue - xMinValue); } //This is the standard case
p = ((long)(X - xMinValue) << 8) / (xMaxValue - xMinValue); //This is the standard case
}
long q;
if (yMaxValue == yMinValue)

View File

@ -31,7 +31,6 @@ int PW(int REQ_FUEL, byte VE, byte MAP, int corrections, int injOpen, byte TPS)
//return (REQ_FUEL * (float)(VE/100.0) * (float)(MAP/100.0) * (float)(corrections/100.0) + injOpen);
//100% float free version, does sacrifice a little bit of accuracy. Accuracy loss is in the order of 0.1ms (100uS)
int iVE = ((int)VE << 7) / 100;
int iMAP = ((int)MAP << 7) / 100;
int iCorrections = (corrections << 7) / 100;