Merge branch 'master' into dev/injOpen

This commit is contained in:
Josh Stewart 2019-11-06 17:00:45 +11:00 committed by GitHub
commit 71add256fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 528 additions and 276 deletions

View File

@ -10,7 +10,7 @@ if [ -f ./results.txt ]; then
fi
for i in speeduino/speeduino/*.ino; do
$cppcheck_bin --dump --max-configs=1 --inline-suppr --suppressions-list=speeduino/misra/suppressions.txt --suppress=syntaxError:speeduino/speeduino/src/PID_v1/PID_v1.h --include=${i%.*}.h -DCORE_AVR=1 -D__AVR_ATmega2560__=1 $i > /dev/null
$cppcheck_bin --dump --max-configs=1 --inline-suppr --suppressions-list=speeduino/misra/suppressions.txt --language=c++ --include=${i%.*}.h -DCORE_AVR=1 -D__AVR_ATmega2560__=1 $i > /dev/null
done
mv speeduino/speeduino/*.dump ./
@ -19,10 +19,10 @@ rm ./utils.*.dump
python $cppcheck_misra --rule-texts=speeduino/misra/misra_2012_text.txt *.dump 2> results.txt
#rm *.dump
cat results.txt
sort results.txt | uniq
# wc -l results.txt
errors=`wc -l < results.txt | tr -d ' '`
errors=`sort results.txt | uniq | wc -l`
echo $errors MISRA violations
if [ $errors -gt 0 ]; then

View File

@ -114,7 +114,7 @@ No text specified
Rule 11.2
No text specified
Rule 11.3
No text specified
A cast shall not be performed between a pointer to object type and a pointer to a different object type
Rule 11.4
Advisory - Object pointers should not be treated as or converted to integers
Rule 11.5
@ -186,7 +186,7 @@ No text specified
Rule 17.1
No text specified
Rule 17.2
No text specified
Functions shall not call themselves, either directly or indirectly
Rule 17.3
No text specified
Rule 17.4
@ -196,7 +196,7 @@ No text specified
Rule 17.6
No text specified
Rule 17.7
No text specified
The value returned by a function having non-void return type shall be used
Rule 17.8
Advisory - An argument to a function should be treated as read-only
Rule 18.1
@ -206,7 +206,7 @@ No text specified
Rule 18.3
No text specified
Rule 18.4
No text specified
Advisory - The +, -, += and -= operators should not be applied to an expression of pointer type
Rule 18.5
No text specified
Rule 18.6

View File

@ -95,6 +95,7 @@ upload_protocol = sam-ba
src_dir=speeduino
default_envs = megaatmega2560
;The following lines are for testing / experimentation only. Comment the line above to try them out
;default_envs = black_F407VE
;env_default = teensy35
;env_default = LaunchPad_tm4c1294ncpdt
;env_default = genericSTM32F103RB

View File

@ -303,7 +303,7 @@ page = 1
fanWhenOff = bits, U08, 70, [0:0], "No", "Yes"
unused_fan_bits = bits, U08, 70,[1:7]
asePct = array, U08, 71, [4], "%", 1.0, 0.0, 0, 255, 0
asePct = array, U08, 71, [4], "%", 1.0, 0.0, 0, 155, 0
aseCount = array, U08, 75, [4], "s", 1.0, 0.0, 0.0, 255, 0 ; Values for the afterstart enrichment curve
#if CELSIUS
aseBins = array, U08, 79, [4], "C", 1.0, -40, -40, 215, 0
@ -432,14 +432,19 @@ page = 4
#else
cltAdvBins = array, U08, 71, [ 6], "F", 1.8, -22.23, -40, 215.0, 0 ; No -40 degree offset here
#endif
cltAdvValues = array, S08, 77, [ 6], "deg", 1.0, -15, -15, 15, 0
cltAdvValues = array, S08, 77, [ 6], "deg", 1.0, -15, -15, 15, 0
;MAP based acceleration enrichment
maeBins = array, U08, 83, [ 4], "kpa/s", 10.0, 0.0, 0.00, 2550.0, 0
maeRates = array, U08, 87, [ 4], "%", 1.0, 0.0, 0.00, 255.0, 0 ; 4 bytes
batVoltCorrect = scalar, S08, 91, "v", 0.1, 0.0, -2, 2, 1 ;Battery reading calibration value. Note: Signed value
unused4-92 = array, U08, 92, [36], "%", 1.0, 0.0, 0.0, 255, 0
;Baro fuel correction
baroFuelBins = array, U08, 92, [8], "kPa", 1.0, 0, 80, 120, 0 ; Bins for the Baro correction curve
baroFuelValues = array, U08, 100, [8], "%", 1.0, 0, 0, 255, 0 ; % Values for same
unused4-92 = array, U08, 108,[20], "%", 1.0, 0.0, 0.0, 255, 0
;--------------------------------------------------
;Start AFR page
@ -1208,6 +1213,7 @@ menuDialog = main
subMenu = triggerSettings, "Trigger Setup"
;subMenu = OLED, "OLED Setup"
subMenu = airdensity_curve, "IAT Density"
subMenu = baroFuel_curve, "Barometric Correction"
subMenu = reset_control, "Reset Control"
@ -2805,6 +2811,14 @@ cmdtestspk450dc = "E\x03\x0C"
xBins = airDenBins, iat
yBins = airDenRates
; Correction curve for Barometric pressure fuel adjustment
curve = baroFuel_curve, "Baro fuel correction"
columnLabel = "Baro Pressure", "Fuel Amount"
xAxis = 70, 130, 6
yAxis = 0, 255, 6
xBins = baroFuelBins, baro
yBins = baroFuelValues
; IAT based ignition timing retard
curve = iat_retard_curve, "IAT timing retard"
columnLabel = "Inlet Air Temp", "Retard"

View File

@ -18,7 +18,7 @@
uint16_t freeRam();
#if defined(TIMER5_MICROS)
//#define micros() (((timer5_overflow_count << 16) + TCNT5) * 4) //Fast version of micros() that uses the 4uS tick of timer5. See timers.ino for the overflow ISR of timer5
/*#define micros() (((timer5_overflow_count << 16) + TCNT5) * 4) */ //Fast version of micros() that uses the 4uS tick of timer5. See timers.ino for the overflow ISR of timer5
#define millis() (ms_counter) //Replaces the standard millis() function with this macro. It is both faster and more accurate. See timers.ino for its counter increment.
static inline unsigned long micros_safe(); //A version of micros() that is interrupt safe
#else
@ -34,7 +34,7 @@
***********************************************************************************************************
* Schedules
*/
//Refer to http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/avr/iomxx0_1.h?root=avr-libc&view=markup
//Refer to svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/avr/iomxx0_1.h?root=avr-libc&view=markup
#define FUEL1_COUNTER TCNT3
#define FUEL2_COUNTER TCNT3
#define FUEL3_COUNTER TCNT3
@ -94,9 +94,9 @@
#define IGN1_TIMER_ENABLE() TIFR5 |= (1<<OCF5A); TIMSK5 |= (1 << OCIE5A) //Turn on the A compare unit (ie turn on the interrupt)
#define IGN2_TIMER_ENABLE() TIFR5 |= (1<<OCF5B); TIMSK5 |= (1 << OCIE5B) //Turn on the B compare unit (ie turn on the interrupt)
#define IGN3_TIMER_ENABLE() TIFR5 |= (1<<OCF5C); TIMSK5 |= (1 << OCIE5C) //Turn on the C compare unit (ie turn on the interrupt)
//#define IGN1_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5A) //Turn on the B compare unit (ie turn on the interrupt)
//#define IGN2_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5B) //Turn on the B compare unit (ie turn on the interrupt)
//#define IGN3_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5C) //Turn on the C compare unit (ie turn on the interrupt)
/*#define IGN1_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5A) */ //Turn on the B compare unit (ie turn on the interrupt)
/*#define IGN2_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5B) */ //Turn on the B compare unit (ie turn on the interrupt)
/*#define IGN3_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5C) */ //Turn on the C compare unit (ie turn on the interrupt)
#define IGN4_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4A) //Turn on the A compare unit (ie turn on the interrupt)
#define IGN5_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4C) //Turn on the A compare unit (ie turn on the interrupt)
#define IGN6_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4B) //Replaces injector 4

View File

@ -130,7 +130,7 @@
#define IGN7_COMPARE (TIM4)->CCR3
#define IGN8_COMPARE (TIM4)->CCR4
#endif
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
//github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
#define FUEL1_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC1E
#define FUEL2_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC2E
#define FUEL3_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC3E
@ -214,7 +214,7 @@
#define IGN7_COMPARE (TIMER4->regs).gen->CCR3
#define IGN8_COMPARE (TIMER4->regs).gen->CCR4
#endif
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
//github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
#define FUEL1_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC1E
#define FUEL2_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC2E
#define FUEL3_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC3E

View File

@ -23,7 +23,7 @@
***********************************************************************************************************
* Schedules
*/
//http://shawnhymel.com/661/learning-the-teensy-lc-interrupt-service-routines/
//shawnhymel.com/661/learning-the-teensy-lc-interrupt-service-routines/
#define FUEL1_COUNTER FTM0_CNT
#define FUEL2_COUNTER FTM0_CNT
#define FUEL3_COUNTER FTM0_CNT

View File

@ -23,7 +23,7 @@
***********************************************************************************************************
* Schedules
*/
//http://shawnhymel.com/661/learning-the-teensy-lc-interrupt-service-routines/
//shawnhymel.com/661/learning-the-teensy-lc-interrupt-service-routines/
#define FUEL1_COUNTER TMR1_CNTR0
#define FUEL2_COUNTER TMR1_CNTR0
#define FUEL3_COUNTER TMR1_CNTR1

View File

@ -1126,7 +1126,7 @@ void sendPageASCII()
Serial.println((const __FlashStringHelper *)&pageTitles[27]);//27 is the index to the first char in the second sting in pageTitles
// The following loop displays in human readable form of all byte values in config page 1 up to but not including the first array.
// incrementing void pointers is cumbersome. Thus we have "pnt_configPage = (byte *)pnt_configPage + 1"
for (pnt_configPage = &configPage2; pnt_configPage < &configPage2.wueValues[0]; pnt_configPage = (byte *)pnt_configPage + 1) { Serial.println(*((byte *)pnt_configPage)); }
for (pnt_configPage = (byte *)&configPage2; pnt_configPage < &configPage2.wueValues[0]; pnt_configPage = (byte *)pnt_configPage + 1) { Serial.println(*((byte *)pnt_configPage)); }
for (byte x = 10; x; x--)// The x between the ';' has the same representation as the "x != 0" test or comparision
{
Serial.print(configPage2.wueValues[10 - x]);// This displays the values horizantially on the screen
@ -1204,7 +1204,7 @@ void sendPageASCII()
//currentTitleIndex = 91;
//To Display Values from Config Page 3
Serial.println((const __FlashStringHelper *)&pageTitles[91]);//special typecasting to enable suroutine that the F macro uses
for (pnt_configPage = &configPage6; pnt_configPage < &configPage6.voltageCorrectionBins[0]; pnt_configPage = (byte *)pnt_configPage + 1)
for (pnt_configPage = (byte *)&configPage6; pnt_configPage < &configPage6.voltageCorrectionBins[0]; pnt_configPage = (byte *)pnt_configPage + 1)
{
Serial.println(*((byte *)pnt_configPage));// Displaying byte values of config page 3 up to but not including the first array
}
@ -1641,10 +1641,14 @@ void receiveCalibration(byte tableID)
bool every2nd = true;
int x;
int counter = 0;
// stm32 board has buildin led used as fuel pump
// pinMode(LED_BUILTIN, OUTPUT); //pinMode(13, OUTPUT);
bool useLEDIndicator = false;
if (pinIsOutput(LED_BUILTIN) == false)
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
useLEDIndicator = true;
}
// digitalWrite(LED_BUILTIN, LOW); //digitalWrite(13, LOW);
for (x = 0; x < 1024; x++)
{
//UNlike what is listed in the protocol documentation, the O2 sensor values are sent as bytes rather than ints
@ -1681,13 +1685,14 @@ void receiveCalibration(byte tableID)
storeCalibrationValue(y, (byte)tempValue);
every2nd = false;
#if defined(CORE_STM32)
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
#elif defined(CORE_STM32_OFFICIAL)
//Of core offical do nothing. led is reserved for fuel pump
#else
analogWrite(LED_BUILTIN, (counter % 50) ); //analogWrite(13, (counter % 50) );
#endif
if(useLEDIndicator == true)
{
#if defined(CORE_STM32)
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
#else
analogWrite(LED_BUILTIN, (counter % 50) );
#endif
}
counter++;
}
else {

View File

@ -17,6 +17,7 @@ static inline byte correctionAFRClosedLoop() __attribute__((always_inline)); //C
static inline byte correctionFlex() __attribute__((always_inline)); //Flex fuel adjustment
static inline byte correctionBatVoltage() __attribute__((always_inline)); //Battery voltage correction
static inline byte correctionIATDensity() __attribute__((always_inline)); //Inlet temp density correction
static inline byte correctionBaro() __attribute__((always_inline)); //Inlet temp density correction
static inline byte correctionLaunch() __attribute__((always_inline)); //Launch control correction
static inline bool correctionDFCO() __attribute__((always_inline)); //Decelleration fuel cutoff
@ -25,6 +26,7 @@ static inline int8_t correctionFixedTiming(int8_t);
static inline int8_t correctionCrankingFixedTiming(int8_t);
static inline int8_t correctionFlexTiming(int8_t);
static inline int8_t correctionIATretard(int8_t);
static inline int8_t correctionBaro(int8_t);
static inline int8_t correctionCLTadvance(int8_t);
static inline int8_t correctionSoftRevLimit(int8_t);
static inline int8_t correctionNitrous(int8_t);

View File

@ -38,7 +38,8 @@ This is the only function that should be called from anywhere outside the file
*/
static inline byte correctionsFuel()
{
unsigned long sumCorrections = 100;
#define MAX_CORRECTIONS 3 //The maximum number of corrections allowed before the sum is reprocessed
uint32_t sumCorrections = 100;
byte activeCorrections = 0;
byte result; //temporary variable to store the result of each corrections function
@ -51,31 +52,35 @@ static inline byte correctionsFuel()
result = correctionCranking();
if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } // Need to check this to ensure that sumCorrections doesn't overflow. Can occur when the number of corrections is greater than 3 (Which is 100^4) as 100^5 can overflow
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } // Need to check this to ensure that sumCorrections doesn't overflow. Can occur when the number of corrections is greater than 3 (Which is 100^4) as 100^5 can overflow
currentStatus.AEamount = correctionAccel();
if (currentStatus.AEamount != 100) { sumCorrections = (sumCorrections * currentStatus.AEamount); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
result = correctionFloodClear();
if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
currentStatus.egoCorrection = correctionAFRClosedLoop();
if (currentStatus.egoCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.egoCorrection); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
currentStatus.batCorrection = correctionBatVoltage();
if (currentStatus.batCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.batCorrection); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
currentStatus.iatCorrection = correctionIATDensity();
if (currentStatus.iatCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.iatCorrection); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
currentStatus.baroCorrection = correctionBaro();
if (currentStatus.baroCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.baroCorrection); activeCorrections++; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
currentStatus.flexCorrection = correctionFlex();
if (currentStatus.flexCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.flexCorrection); activeCorrections++; }
if (activeCorrections == 3) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; }
currentStatus.launchCorrection = correctionLaunch();
if (currentStatus.launchCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.launchCorrection); activeCorrections++; }
@ -97,11 +102,13 @@ static inline byte correctionWUE()
{
byte WUEValue;
//Possibly reduce the frequency this runs at (Costs about 50 loops per second)
if (currentStatus.coolant > (WUETable.axisX[9] - CALIBRATION_TEMPERATURE_OFFSET))
//if (currentStatus.coolant > (WUETable.axisX[9] - CALIBRATION_TEMPERATURE_OFFSET))
if (currentStatus.coolant > (table2D_getAxisValue(&WUETable, 9) - CALIBRATION_TEMPERATURE_OFFSET))
{
//This prevents us doing the 2D lookup if we're already up to temp
BIT_CLEAR(currentStatus.engine, BIT_ENGINE_WARMUP);
WUEValue = WUETable.values[9]; //Set the current value to be whatever the final value on the curve is.
//WUEValue = WUETable.values[9]; //Set the current value to be whatever the final value on the curve is.
WUEValue = table2D_getAxisValue(&WUETable, 9);
}
else
{
@ -134,9 +141,9 @@ where an additional amount of fuel is added (Over and above the WUE amount)
*/
static inline byte correctionASE()
{
byte ASEValue;
int16_t ASEValue;
//Two checks are requiredL:
//1) Is the negine run time less than the configured ase time
//1) Is the engine run time less than the configured ase time
//2) Make sure we're not still cranking
if ( (currentStatus.runSecs < (table2D_getValue(&ASECountTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET))) && !(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) )
{
@ -148,7 +155,12 @@ static inline byte correctionASE()
BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive.
ASEValue = 100;
}
return ASEValue;
//Safety checks
if(ASEValue > 255) { ASEValue = 255; }
if(ASEValue < 0) { ASEValue = 0; }
return (byte)ASEValue;
}
/**
@ -303,6 +315,7 @@ static inline byte correctionBatVoltage()
if (currentStatus.battery10 > (injectorVCorrectionTable.axisX[5])) { batValue = injectorVCorrectionTable.values[injectorVCorrectionTable.xSize-1]; } //This prevents us doing the 2D lookup if the voltage is above maximum
else { batValue = table2D_getValue(&injectorVCorrectionTable, currentStatus.battery10); }
}
return batValue;
}
@ -313,12 +326,23 @@ This corrects for changes in air density from movement of the temperature
static inline byte correctionIATDensity()
{
byte IATValue = 100;
if ( (currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET) > (IATDensityCorrectionTable.axisX[8])) { IATValue = IATDensityCorrectionTable.values[IATDensityCorrectionTable.xSize-1]; } //This prevents us doing the 2D lookup if the intake temp is above maximum
else { IATValue = table2D_getValue(&IATDensityCorrectionTable, currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); }//currentStatus.IAT is the actual temperature, values in IATDensityCorrectionTable.axisX are temp+offset
IATValue = table2D_getValue(&IATDensityCorrectionTable, currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //currentStatus.IAT is the actual temperature, values in IATDensityCorrectionTable.axisX are temp+offset
return IATValue;
}
/**
* @brief
*
*/
static inline byte correctionBaro()
{
byte baroValue = 100;
baroValue = table2D_getValue(&baroFuelTable, currentStatus.baro);
return baroValue;
}
/*
Launch control has a setting to increase the fuel load to assist in bringing up boost
This simple check applies the extra fuel if we're currently launching

View File

@ -9,7 +9,7 @@
//#define fastDegreesToUS(targetDegrees) ((targetDegrees) * (unsigned long)timePerDegree)
#define fastDegreesToUS(targetDegrees) (((targetDegrees) * (unsigned long)timePerDegreex16) >> 4)
//#define fastTimeToAngle(time) (((unsigned long)time * degreesPeruSx2048) / 2048) //Divide by 2048 will be converted at compile time to bitshift
/*#define fastTimeToAngle(time) (((unsigned long)time * degreesPeruSx2048) / 2048) */ //Divide by 2048 will be converted at compile time to bitshift
#define fastTimeToAngle(time) (((unsigned long)(time) * degreesPeruSx32768) / 32768) //Divide by 32768 will be converted at compile time to bitshift
#define ignitionLimits(angle) ( (((int16_t)(angle)) >= CRANK_ANGLE_MAX_IGN) ? ((angle) - CRANK_ANGLE_MAX_IGN) : ( ((int16_t)(angle) < 0) ? ((angle) + CRANK_ANGLE_MAX_IGN) : (angle)) )

View File

@ -262,6 +262,7 @@ void triggerSetup_missingTooth()
checkSyncToothCount = (configPage4.triggerTeeth) >> 1; //50% of the total teeth.
toothLastMinusOneToothTime = 0;
toothCurrentCount = 0;
secondaryToothCount = 0;
toothOneTime = 0;
toothOneMinusOneTime = 0;
MAX_STALL_TIME = (3333UL * triggerToothAngle * (configPage4.triggerMissingTeeth + 1)); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
@ -299,23 +300,34 @@ void triggerPri_missingTooth()
//else if (currentStatus.hasSync == false && toothCurrentCount < checkSyncToothCount ) { triggerFilterTime = 0; }
else
{
if(currentStatus.hasSync == true)
{
currentStatus.startRevolutions++; //Counter
if ( configPage4.TrigSpeed == CAM_SPEED ) { currentStatus.startRevolutions++; } //Add an extra revolution count if we're running at cam speed
}
else { currentStatus.startRevolutions = 0; }
toothCurrentCount = 1;
revolutionOne = !revolutionOne; //Flip sequential revolution tracker
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
currentStatus.hasSync = true;
if(currentStatus.hasSync == true)
{
currentStatus.startRevolutions++; //Counter
if ( configPage4.TrigSpeed == CAM_SPEED ) { currentStatus.startRevolutions++; } //Add an extra revolution count if we're running at cam speed
}
else { currentStatus.startRevolutions = 0; }
toothCurrentCount = 1;
revolutionOne = !revolutionOne; //Flip sequential revolution tracker
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
triggerFilterTime = 0; //This is used to prevent a condition where serious intermitent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
triggerToothAngleIsCorrect = false; //The tooth angle is double at this point
//if Sequential fuel or ignition is in use, further checks are needed before determining sync
if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) || (configPage2.injLayout == INJ_SEQUENTIAL) )
{
//If either fuel or ignition is sequential, only declare sync if the cam tooth has been seen OR if the missing wheel is on the cam
if( (secondaryToothCount > 0) || (configPage4.TrigSpeed == CAM_SPEED) )
{
currentStatus.hasSync = true;
if(configPage4.trigPatternSec == SEC_TRIGGER_SINGLE) { secondaryToothCount = 0; } //Reset the secondary tooth counter to prevent it overflowing
}
}
else { currentStatus.hasSync = true; } //If nothing is using sequential, we have sync
triggerFilterTime = 0; //This is used to prevent a condition where serious intermitent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
triggerToothAngleIsCorrect = false; //The tooth angle is double at this point
}
}
else
@ -389,6 +401,7 @@ void triggerSec_missingTooth()
//Standard single tooth cam trigger
revolutionOne = 1; //Sequential revolution reset
triggerSecFilterTime = curGap2 >> 1; //Next secondary filter is half the current gap
secondaryToothCount++;
}
toothLastSecToothTime = curTime2;
} //Trigger filter

View File

@ -281,6 +281,7 @@ struct table2D crankingEnrichTable; //4 bin cranking Enrichment map (2D)
struct table2D dwellVCorrectionTable; //6 bin dwell voltage correction (2D)
struct table2D injectorVCorrectionTable; //6 bin injector voltage correction (2D)
struct table2D IATDensityCorrectionTable; //9 bin inlet air temperature density correction (2D)
struct table2D baroFuelTable; //8 bin baro correction curve (2D)
struct table2D IATRetardTable; //6 bin ignition adjustment based on inlet air temperature (2D)
struct table2D IDLEAdvanceTable; //6 bin idle advance adjustment table based on RPM difference (2D)
struct table2D CLTAdvanceTable; //6 bin ignition adjustment based on coolant temperature (2D)
@ -382,6 +383,13 @@ byte resetControl = RESET_CONTROL_DISABLED;
volatile byte TIMER_mask;
volatile byte LOOP_TIMER;
//These functions all do checks on a pin to determine if it is already in use by another (higher importance) function
#define pinIsInjector(pin) ( ((pin) == pinInjector1) || ((pin) == pinInjector2) || ((pin) == pinInjector3) || ((pin) == pinInjector4) )
#define pinIsIgnition(pin) ( ((pin) == pinCoil1) || ((pin) == pinCoil2) || ((pin) == pinCoil3) || ((pin) == pinCoil4) )
#define pinIsSensor(pin) ( ((pin) == pinCLT) || ((pin) == pinIAT) || ((pin) == pinMAP) || ((pin) == pinTPS) || ((pin) == pinO2) || ((pin) == pinBat) )
#define pinIsUsed(pin) ( pinIsInjector((pin)) || pinIsIgnition((pin)) || pinIsSensor((pin)) )
#define pinIsOutput(pin) ( ((pin) == pinFuelPump) || ((pin) == pinFan) || ((pin) == pinVVT_1) || ((pin) == pinVVT_2) || ((pin) == pinBoost) || ((pin) == pinIdle1) || ((pin) == pinIdle2) || ((pin) == pinTachOut) )
//The status struct contains the current values for all 'live' variables
//In current version this is 64 bytes
struct statuses {
@ -421,6 +429,7 @@ struct statuses {
byte wueCorrection; /**< The amount of warmup enrichment currently being applied */
byte batCorrection; /**< The amount of battery voltage enrichment currently being applied */
byte iatCorrection; /**< The amount of inlet air temperature adjustment currently being applied */
byte baroCorrection; /**< The amount of correction being applied for the current baro reading */
byte launchCorrection; /**< The amount of correction being applied if launch control is active */
byte flexCorrection; /**< Amount of correction being applied to compensate for ethanol content */
int8_t flexIgnCorrection; /**< Amount of additional advance being applied based on flex. Note the type as this allows for negative values */
@ -675,7 +684,11 @@ struct config4 {
byte maeRates[4]; /**< MAP based AE values */
int8_t batVoltCorrect; /**< Battery voltage calibration offset */
byte unused2_91[36];
byte baroFuelBins[8];
byte baroFuelValues[8];
byte unused2_91[20];
#if defined(CORE_AVR)
};
@ -1026,7 +1039,7 @@ byte pinSpareLOut4;
byte pinSpareLOut5;
byte pinBoost;
byte pinVVT_1; // vvt output 1
byte pinVVt_2; // vvt output 2
byte pinVVT_2; // vvt output 2
byte pinFan; // Cooling fan output
byte pinStepperDir; //Direction pin for the stepper motor driver
byte pinStepperStep; //Step pin for the stepper motor driver
@ -1037,7 +1050,7 @@ byte pinFlex; //Pin with the flex sensor attached
byte pinBaro; //Pin that an external barometric pressure sensor is attached to (If used)
byte pinResetControl; // Output pin used control resetting the Arduino
// global variables // from speeduino.ino
/* global variables */ // from speeduino.ino
extern struct statuses currentStatus; // from speeduino.ino
extern struct table3D fuelTable; //16x16 fuel map
extern struct table3D fuelTable2; //16x16 fuel map

View File

@ -43,12 +43,14 @@ void initialiseIdle()
//Case 2 is PWM open loop
iacPWMTable.xSize = 10;
iacPWMTable.valueSize = SIZE_BYTE;
iacPWMTable.axisSize = SIZE_BYTE;
iacPWMTable.values = configPage6.iacOLPWMVal;
iacPWMTable.axisX = configPage6.iacBins;
iacCrankDutyTable.xSize = 4;
iacCrankDutyTable.valueSize = SIZE_BYTE;
iacCrankDutyTable.axisSize = SIZE_BYTE;
iacCrankDutyTable.values = configPage6.iacCrankDuty;
iacCrankDutyTable.axisX = configPage6.iacCrankBins;
@ -68,11 +70,13 @@ void initialiseIdle()
//Case 3 is PWM closed loop
iacClosedLoopTable.xSize = 10;
iacClosedLoopTable.valueSize = SIZE_BYTE;
iacClosedLoopTable.axisSize = SIZE_BYTE;
iacClosedLoopTable.values = configPage6.iacCLValues;
iacClosedLoopTable.axisX = configPage6.iacBins;
iacCrankDutyTable.xSize = 4;
iacCrankDutyTable.valueSize = SIZE_BYTE;
iacCrankDutyTable.axisSize = SIZE_BYTE;
iacCrankDutyTable.values = configPage6.iacCrankDuty;
iacCrankDutyTable.axisX = configPage6.iacCrankBins;
@ -96,11 +100,13 @@ void initialiseIdle()
//Case 2 is Stepper open loop
iacStepTable.xSize = 10;
iacStepTable.valueSize = SIZE_BYTE;
iacStepTable.axisSize = SIZE_BYTE;
iacStepTable.values = configPage6.iacOLStepVal;
iacStepTable.axisX = configPage6.iacBins;
iacCrankStepsTable.xSize = 4;
iacCrankStepsTable.valueSize = SIZE_BYTE;
iacCrankStepsTable.axisSize = SIZE_BYTE;
iacCrankStepsTable.values = configPage6.iacCrankSteps;
iacCrankStepsTable.axisX = configPage6.iacCrankBins;
iacStepTime = configPage6.iacStepTime * 1000;
@ -126,11 +132,13 @@ void initialiseIdle()
//Case 5 is Stepper closed loop
iacClosedLoopTable.xSize = 10;
iacClosedLoopTable.valueSize = SIZE_BYTE;
iacClosedLoopTable.axisSize = SIZE_BYTE;
iacClosedLoopTable.values = configPage6.iacCLValues;
iacClosedLoopTable.axisX = configPage6.iacBins;
iacCrankStepsTable.xSize = 4;
iacCrankStepsTable.valueSize = SIZE_BYTE;
iacCrankStepsTable.axisSize = SIZE_BYTE;
iacCrankStepsTable.values = configPage6.iacCrankSteps;
iacCrankStepsTable.axisX = configPage6.iacCrankBins;
iacStepTime = configPage6.iacStepTime * 1000;
@ -259,11 +267,13 @@ void idleControl()
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > configPage9.iacMaxSteps * 3)
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
doStep();
}
else if( (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < iacStepTable.axisX[IDLE_TABLE_SIZE-1])
else if( (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) < table2D_getAxisValue(&iacStepTable, (IDLE_TABLE_SIZE-1)) )
{
//Standard running
//We must also have more than zero RPM for the running state
@ -275,9 +285,11 @@ void idleControl()
iacStepTime = configPage6.iacStepTime * 1000;
iacCoolTime = configPage9.iacCoolTime * 1000;
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > configPage9.iacMaxSteps * 3)
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > configPage9.iacMaxSteps * 3)
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
}
doStep();
}
@ -308,7 +320,9 @@ void idleControl()
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > configPage9.iacMaxSteps * 3)
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
doStep();
currentStatus.idleLoad = idleStepper.curIdleStep >> 1; //Current step count (Divided by 2 for byte)
@ -458,7 +472,9 @@ static inline void disableIdle()
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > configPage9.iacMaxSteps * 3)
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
}
}
BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag off

View File

@ -57,78 +57,100 @@ void initialiseAll()
//Repoint the 2D table structs to the config pages that were just loaded
taeTable.valueSize = SIZE_BYTE; //Set this table to use byte values
taeTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
taeTable.xSize = 4;
taeTable.values = configPage4.taeValues;
taeTable.axisX = configPage4.taeBins;
maeTable.valueSize = SIZE_BYTE; //Set this table to use byte values
maeTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
maeTable.xSize = 4;
maeTable.values = configPage4.maeRates;
maeTable.axisX = configPage4.maeBins;
WUETable.valueSize = SIZE_BYTE; //Set this table to use byte values
WUETable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
WUETable.xSize = 10;
WUETable.values = configPage2.wueValues;
WUETable.axisX = configPage4.wueBins;
ASETable.valueSize = SIZE_BYTE;
ASETable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
ASETable.xSize = 4;
ASETable.values = configPage2.asePct;
ASETable.axisX = configPage2.aseBins;
ASECountTable.valueSize = SIZE_BYTE;
ASECountTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
ASECountTable.xSize = 4;
ASECountTable.values = configPage2.aseCount;
ASECountTable.axisX = configPage2.aseBins;
PrimingPulseTable.valueSize = SIZE_BYTE;
PrimingPulseTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
PrimingPulseTable.xSize = 4;
PrimingPulseTable.values = configPage2.primePulse;
PrimingPulseTable.axisX = configPage2.primeBins;
crankingEnrichTable.valueSize = SIZE_BYTE;
crankingEnrichTable.valueSize = SIZE_BYTE;
crankingEnrichTable.axisSize = SIZE_BYTE;
crankingEnrichTable.xSize = 4;
crankingEnrichTable.values = configPage10.crankingEnrichValues;
crankingEnrichTable.axisX = configPage10.crankingEnrichBins;
dwellVCorrectionTable.valueSize = SIZE_BYTE;
dwellVCorrectionTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
dwellVCorrectionTable.xSize = 6;
dwellVCorrectionTable.values = configPage4.dwellCorrectionValues;
dwellVCorrectionTable.axisX = configPage6.voltageCorrectionBins;
injectorVCorrectionTable.valueSize = SIZE_BYTE;
injectorVCorrectionTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
injectorVCorrectionTable.xSize = 6;
injectorVCorrectionTable.values = configPage6.injVoltageCorrectionValues;
injectorVCorrectionTable.axisX = configPage6.voltageCorrectionBins;
IATDensityCorrectionTable.valueSize = SIZE_BYTE;
IATDensityCorrectionTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
IATDensityCorrectionTable.xSize = 9;
IATDensityCorrectionTable.values = configPage6.airDenRates;
IATDensityCorrectionTable.axisX = configPage6.airDenBins;
baroFuelTable.valueSize = SIZE_BYTE;
baroFuelTable.axisSize = SIZE_BYTE;
baroFuelTable.xSize = 8;
baroFuelTable.values = configPage4.baroFuelValues;
baroFuelTable.axisX = configPage4.baroFuelBins;
IATRetardTable.valueSize = SIZE_BYTE;
IATRetardTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
IATRetardTable.xSize = 6;
IATRetardTable.values = configPage4.iatRetValues;
IATRetardTable.axisX = configPage4.iatRetBins;
CLTAdvanceTable.valueSize = SIZE_BYTE;
CLTAdvanceTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
CLTAdvanceTable.xSize = 6;
CLTAdvanceTable.values = (byte*)configPage4.cltAdvValues;
CLTAdvanceTable.axisX = configPage4.cltAdvBins;
rotarySplitTable.valueSize = SIZE_BYTE;
rotarySplitTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
rotarySplitTable.xSize = 8;
rotarySplitTable.values = configPage10.rotarySplitValues;
rotarySplitTable.axisX = configPage10.rotarySplitBins;
flexFuelTable.valueSize = SIZE_BYTE;
flexFuelTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
flexFuelTable.xSize = 6;
flexFuelTable.values = configPage10.flexFuelAdj;
flexFuelTable.axisX = configPage10.flexFuelBins;
flexAdvTable.valueSize = SIZE_BYTE;
flexAdvTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
flexAdvTable.xSize = 6;
flexAdvTable.values = configPage10.flexAdvAdj;
flexAdvTable.axisX = configPage10.flexAdvBins;
flexBoostTable.valueSize = SIZE_INT;
flexBoostTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins (NOTE THIS IS DIFFERENT TO THE VALUES!!)
flexBoostTable.xSize = 6;
flexBoostTable.values16 = configPage10.flexBoostAdj;
flexBoostTable.values = configPage10.flexBoostAdj;
flexBoostTable.axisX = configPage10.flexBoostBins;
knockWindowStartTable.valueSize = SIZE_BYTE;
knockWindowStartTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
knockWindowStartTable.xSize = 6;
knockWindowStartTable.values = configPage10.knock_window_angle;
knockWindowStartTable.axisX = configPage10.knock_window_rpms;
knockWindowDurationTable.valueSize = SIZE_BYTE;
knockWindowDurationTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
knockWindowDurationTable.xSize = 6;
knockWindowDurationTable.values = configPage10.knock_window_dur;
knockWindowDurationTable.axisX = configPage10.knock_window_rpms;
@ -153,13 +175,13 @@ void initialiseAll()
endCoil3Charge();
endCoil4Charge();
endCoil5Charge();
#if (INJ_CHANNELS >= 6)
#if (IGN_CHANNELS >= 6)
endCoil6Charge();
#endif
#if (INJ_CHANNELS >= 7)
#if (IGN_CHANNELS >= 7)
endCoil7Charge();
#endif
#if (INJ_CHANNELS >= 8)
#if (IGN_CHANNELS >= 8)
endCoil8Charge();
#endif
@ -169,13 +191,13 @@ void initialiseAll()
closeInjector3();
closeInjector4();
closeInjector5();
#if (IGN_CHANNELS >= 6)
#if (INJ_CHANNELS >= 6)
closeInjector6();
#endif
#if (IGN_CHANNELS >= 7)
#if (INJ_CHANNELS >= 7)
closeInjector7();
#endif
#if (IGN_CHANNELS >= 8)
#if (INJ_CHANNELS >= 8)
closeInjector8();
#endif
@ -1026,82 +1048,82 @@ void setPinMapping(byte boardID)
//******************************************
//******** PORTA CONNECTIONS ***************
//******************************************
// = PA0 //Wakeup ADC123
/* = PA0 */ //Wakeup ADC123
pinTPS = PA1; //ADC123
pinMAP = PA2; //ADC123
pinIAT = PA3; //ADC123
pinCLT = PA4; //ADC12
pinO2 = PA5; //ADC12
// = PA6; //ADC12 LED_BUILTIN_1
/* = PA6; */ //ADC12 LED_BUILTIN_1
pinFuelPump = PA7; //ADC12 LED_BUILTIN_2
pinIdle1 = PA8; //
// = PA9 //TXD1
// = PA10 //RXD1
// = PA11 //(DO NOT USE FOR SPEEDUINO) USB
// = PA12 //(DO NOT USE FOR SPEEDUINO) USB
// = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
// = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
// = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
/* = PA9 */ //TXD1
/* = PA10 */ //RXD1
/* = PA11 */ //(DO NOT USE FOR SPEEDUINO) USB
/* = PA12 */ //(DO NOT USE FOR SPEEDUINO) USB
/* = PA13 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
/* = PA14 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
/* = PA15 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
//******************************************
//******** PORTB CONNECTIONS ***************
//******************************************
// = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin
/* = PB0; */ //(DO NOT USE FOR SPEEDUINO) ADC123 - SPI FLASH CHIP CS pin
pinBaro = PB1; //ADC12
// = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1
// = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
// = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
// = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
// = PB6; //NRF_CE
// = PB7; //NRF_CS
// = PB8; //NRF_IRQ
/* = PB2; */ //(DO NOT USE FOR SPEEDUINO) BOOT1
/* = PB3; */ //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
/* = PB4; */ //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
/* = PB5; */ //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
/* = PB6; */ //NRF_CE
/* = PB7; */ //NRF_CS
/* = PB8; */ //NRF_IRQ
pinIdle2 = PB9; //
// = PB10; //TXD3
// = PB11; //RXD3
/* = PB10; */ //TXD3
/* = PB11; */ //RXD3
pinBoost = PB12; //
// = PB13; //SPI2_SCK
// = PB14; //SPI2_MISO
// = PB15; //SPI2_MOSI
/* = PB13; */ //SPI2_SCK
/* = PB14; */ //SPI2_MISO
/* = PB15; */ //SPI2_MOSI
//******************************************
//******** PORTC CONNECTIONS ***************
//******************************************
// = PC0; //ADC123
/* = PC0; */ //ADC123
pinBat = PC1; //ADC123
// = PC2; //ADC123
// = PC3; //ADC123
// = PC4; //ADC12
// = PC5; //ADC12
/* = PC2; */ //ADC123
/* = PC3; */ //ADC123
/* = PC4; */ //ADC12
/* = PC5; */ //ADC12
pinVVT_1 = PC6; //
pinDisplayReset = PC7; //
// = PC8; //(DO NOT USE FOR SPEEDUINO) //SDIO_D0
// = PC9; //(DO NOT USE FOR SPEEDUINO) //SDIO_D1
// = PC10; //(DO NOT USE FOR SPEEDUINO) //SDIO_D2
// = PC11; //(DO NOT USE FOR SPEEDUINO) //SDIO_D3
// = PC12; //(DO NOT USE FOR SPEEDUINO) //SDIO_SCK
/* = PC8; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D0
/* = PC9; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D1
/* = PC10; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D2
/* = PC11; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D3
/* = PC12; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_SCK
pinTachOut = PC13; //
// = PC14; //(DO NOT USE FOR SPEEDUINO) //OSC32_IN
// = PC15; //(DO NOT USE FOR SPEEDUINO) //OSC32_OUT
/* = PC14; */ //(DO NOT USE FOR SPEEDUINO) - OSC32_IN
/* = PC15; */ //(DO NOT USE FOR SPEEDUINO) - OSC32_OUT
//******************************************
//******** PORTD CONNECTIONS ***************
//******************************************
// = PD0; //CANRX
// = PD1; //CANTX
// = PD2; //(DO NOT USE FOR SPEEDUINO) //SDIO_CMD
/* = PD0; */ //CANRX
/* = PD1; */ //CANTX
/* = PD2; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_CMD
pinCoil1 = PD3; //
pinCoil2 = PD4; //
// = PD5;//TXD2
// = PD6; //RXD2
/* = PD5;*/ //TXD2
/* = PD6; */ //RXD2
pinCoil3 = PD7; //
pinCoil4 = PD8; //
pinCoil5 = PD9;//
pinFan = PD10; //
// = PD11; //
// = PD12; //
// = PD13; //
// = PD14; //
// = PD15; //
/* = PD11; */ //
/* = PD12; */ //
/* = PD13; */ //
/* = PD14; */ //
/* = PD15; */ //
//******************************************
//******** PORTE CONNECTIONS ***************
@ -1109,8 +1131,8 @@ void setPinMapping(byte boardID)
pinStepperDir = PE0; //
pinStepperStep = PE1; //
pinStepperEnable = PE2; //
// = PE3; //ONBOARD KEY1
// = PE4; //ONBOARD KEY2
/* = PE3; */ //ONBOARD KEY1
/* = PE4; */ //ONBOARD KEY2
pinFlex = PE5; //
pinTrigger = PE6; //
pinInjector1 = PE7; //
@ -1120,8 +1142,8 @@ void setPinMapping(byte boardID)
pinInjector5 = PE11; //
pinInjector6 = PE12; //
pinTrigger2 = PE13; //
// = PE14; //
// = PE15; //
/* = PE14; */ //
/* = PE15; */ //
#elif defined(CORE_STM32)
//blue pill wiki.stm32duino.com/index.php?title=Blue_Pill
//Maple mini wiki.stm32duino.com/index.php?title=Maple_Mini
@ -1637,45 +1659,45 @@ void setPinMapping(byte boardID)
//******************************************
//******** PORTA CONNECTIONS ***************
//******************************************
// = PA0 //Wakeup ADC123
/* = PA0 */ //Wakeup ADC123
pinInjector1 = PA1;
pinInjector2 = PA2;
pinInjector3 = PA3;
pinInjector4 = PA4;
// = PA5; //ADC12
/* = PA5; */ //ADC12
pinFuelPump = PA6; //ADC12 LED_BUILTIN_1
// = PA7; //ADC12 LED_BUILTIN_2
/* = PA7; */ //ADC12 LED_BUILTIN_2
pinCoil3 = PA8;
// = PA9 //TXD1
// = PA10 //RXD1
// = PA11 //(DO NOT USE FOR SPEEDUINO) USB
// = PA12 //(DO NOT USE FOR SPEEDUINO) USB
// = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
// = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
// = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
/* = PA9 */ //TXD1
/* = PA10 */ //RXD1
/* = PA11 */ //(DO NOT USE FOR SPEEDUINO) USB
/* = PA12 */ //(DO NOT USE FOR SPEEDUINO) USB
/* = PA13 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
/* = PA14 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
/* = PA15 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
//******************************************
//******** PORTB CONNECTIONS ***************
//******************************************
// = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin
/* = PB0; */ //(DO NOT USE FOR SPEEDUINO) ADC123 - SPI FLASH CHIP CS pin
pinBaro = PB1; //ADC12
// = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1
// = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
// = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
// = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
// = PB6; //NRF_CE
// = PB7; //NRF_CS
// = PB8; //NRF_IRQ
/* = PB2; */ //(DO NOT USE FOR SPEEDUINO) BOOT1
/* = PB3; */ //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
/* = PB4; */ //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
/* = PB5; */ //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
/* = PB6; */ //NRF_CE
/* = PB7; */ //NRF_CS
/* = PB8; */ //NRF_IRQ
pinCoil2 = PB9; //
// = PB9; //
/* = PB9; */ //
pinCoil4 = PB10; //TXD3
pinIdle1 = PB11; //RXD3
pinIdle2 = PB12; //
// pinBoost = PB12; //
// = PB13; //SPI2_SCK
// = PB14; //SPI2_MISO
// = PB15; //SPI2_MOSI
/* pinBoost = PB12; */ //
/* = PB13; */ //SPI2_SCK
/* = PB14; */ //SPI2_MISO
/* = PB15; */ //SPI2_MOSI
//******************************************
//******** PORTC CONNECTIONS ***************
@ -1685,60 +1707,60 @@ void setPinMapping(byte boardID)
pinIAT = PC2; //ADC123
pinCLT = PC3; //ADC123
pinO2 = PC4; //ADC12
// = PC5; //ADC12
//pinVVT_1 = PC6; //
/* = PC5; */ //ADC12
/*pinVVT_1 = PC6; */ //
pinBat = PC6; //
pinDisplayReset = PC7; //
// = PC8; //(DO NOT USE FOR SPEEDUINO) //SDIO_D0
// = PC9; //(DO NOT USE FOR SPEEDUINO) //SDIO_D1
// = PC10; //(DO NOT USE FOR SPEEDUINO) //SDIO_D2
// = PC11; //(DO NOT USE FOR SPEEDUINO) //SDIO_D3
// = PC12; //(DO NOT USE FOR SPEEDUINO) //SDIO_SCK
/* = PC8; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D0
/* = PC9; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D1
/* = PC10; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D2
/* = PC11; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D3
/* = PC12; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_SCK
pinTachOut = PC13; //
// = PC14; //(DO NOT USE FOR SPEEDUINO) //OSC32_IN
// = PC15; //(DO NOT USE FOR SPEEDUINO) //OSC32_OUT
/* = PC14; */ //(DO NOT USE FOR SPEEDUINO) - OSC32_IN
/* = PC15; */ //(DO NOT USE FOR SPEEDUINO) - OSC32_OUT
//******************************************
//******** PORTD CONNECTIONS ***************
//******************************************
// = PD0; //CANRX
// = PD1; //CANTX
// = PD2; //(DO NOT USE FOR SPEEDUINO) //SDIO_CMD
// = PD3; //
// = PD4; //
/* = PD0; */ //CANRX
/* = PD1; */ //CANTX
/* = PD2; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_CMD
/* = PD3; */ //
/* = PD4; */ //
pinFlex = PD4;
// = PD5;//TXD2
// = PD6; //RXD2
/* = PD5;*/ //TXD2
/* = PD6; */ //RXD2
pinCoil1 = PD7; //
// = PD7; //
// = PD8; //
/* = PD7; */ //
/* = PD8; */ //
pinCoil5 = PD9;//
// = PD10; //
// = PD11; //
// = PD12; //
/* = PD10; */ //
/* = PD11; */ //
/* = PD12; */ //
pinTrigger = PD13; //
pinTrigger2 = PD14; //
// = PD15; //
/* = PD15; */ //
//******************************************
//******** PORTE CONNECTIONS ***************
//******************************************
// = PE0; //
// = PE1; //
/* = PE0; */ //
/* = PE1; */ //
pinStepperEnable = PE2; //
// = PE3; //ONBOARD KEY1
// = PE4; //ONBOARD KEY2
/* = PE3; */ //ONBOARD KEY1
/* = PE4; */ //ONBOARD KEY2
pinStepperStep = PE5; //
pinFan = PE6; //
pinStepperDir = PE7; //
// = PE8; //
// = PE9; //
// = PE10; //
/* = PE8; */ //
/* = PE9; */ //
/* = PE10; */ //
pinInjector5 = PE11; //
pinInjector6 = PE12; //
// = PE13; //
// = PE14; //
// = PE15; //
/* = PE13; */ //
/* = PE14; */ //
/* = PE15; */ //
#elif defined(CORE_STM32)
//blue pill wiki.stm32duino.com/index.php?title=Blue_Pill
@ -1786,45 +1808,45 @@ void setPinMapping(byte boardID)
//******************************************
//******** PORTA CONNECTIONS ***************
//******************************************
// = PA0 //Wakeup ADC123
/* = PA0 */ //Wakeup ADC123
pinInjector1 = PA1;
pinInjector2 = PA2;
pinInjector3 = PA3;
pinInjector4 = PA4;
pinFuelPump = PA5; //ADC12
// = PA6; //ADC12 LED_BUILTIN_1
// = PA7; //ADC12 LED_BUILTIN_2
/* = PA6; */ //ADC12 LED_BUILTIN_1
/* = PA7; */ //ADC12 LED_BUILTIN_2
pinCoil3 = PA8;
// = PA9 //TXD1
// = PA10 //RXD1
// = PA11 //(DO NOT USE FOR SPEEDUINO) USB
// = PA12 //(DO NOT USE FOR SPEEDUINO) USB
// = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
// = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
// = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
/* = PA9 */ //TXD1
/* = PA10 */ //RXD1
/* = PA11 */ //(DO NOT USE FOR SPEEDUINO) USB
/* = PA12 */ //(DO NOT USE FOR SPEEDUINO) USB
/* = PA13 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
/* = PA14 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
/* = PA15 */ //(DO NOT USE FOR SPEEDUINO) NOT ON GPIO - DEBUG ST-LINK
//******************************************
//******** PORTB CONNECTIONS ***************
//******************************************
// = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin
/* = PB0; */ //(DO NOT USE FOR SPEEDUINO) ADC123 - SPI FLASH CHIP CS pin
pinBaro = PB1; //ADC12
// = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1
// = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
// = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
// = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
// = PB6; //NRF_CE
// = PB7; //NRF_CS
// = PB8; //NRF_IRQ
/* = PB2; */ //(DO NOT USE FOR SPEEDUINO) BOOT1
/* = PB3; */ //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
/* = PB4; */ //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
/* = PB5; */ //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
/* = PB6; */ //NRF_CE
/* = PB7; */ //NRF_CS
/* = PB8; */ //NRF_IRQ
pinCoil2 = PB9; //
// = PB9; //
/* = PB9; */ //
pinCoil4 = PB10; //TXD3
pinIdle1 = PB11; //RXD3
pinIdle2 = PB12; //
// pinBoost = PB12; //
// = PB13; //SPI2_SCK
// = PB14; //SPI2_MISO
// = PB15; //SPI2_MOSI
/* pinBoost = PB12; */ //
/* = PB13; */ //SPI2_SCK
/* = PB14; */ //SPI2_MISO
/* = PB15; */ //SPI2_MOSI
//******************************************
//******** PORTC CONNECTIONS ***************
@ -1834,60 +1856,60 @@ void setPinMapping(byte boardID)
pinIAT = PC2; //ADC123
pinCLT = PC3; //ADC123
pinO2 = PC4; //ADC12
// = PC5; //ADC12
//pinVVT_1 = PC6; //
/* = PC5; */ //ADC12
/*pinVVT_1 = PC6; */ //
pinBat = PC6; //
pinDisplayReset = PC7; //
// = PC8; //(DO NOT USE FOR SPEEDUINO) //SDIO_D0
// = PC9; //(DO NOT USE FOR SPEEDUINO) //SDIO_D1
// = PC10; //(DO NOT USE FOR SPEEDUINO) //SDIO_D2
// = PC11; //(DO NOT USE FOR SPEEDUINO) //SDIO_D3
// = PC12; //(DO NOT USE FOR SPEEDUINO) //SDIO_SCK
/* = PC8; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D0
/* = PC9; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D1
/* = PC10; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D2
/* = PC11; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_D3
/* = PC12; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_SCK
pinTachOut = PC13; //
// = PC14; //(DO NOT USE FOR SPEEDUINO) //OSC32_IN
// = PC15; //(DO NOT USE FOR SPEEDUINO) //OSC32_OUT
/* = PC14; */ //(DO NOT USE FOR SPEEDUINO) - OSC32_IN
/* = PC15; */ //(DO NOT USE FOR SPEEDUINO) - OSC32_OUT
//******************************************
//******** PORTD CONNECTIONS ***************
//******************************************
// = PD0; //CANRX
// = PD1; //CANTX
// = PD2; //(DO NOT USE FOR SPEEDUINO) //SDIO_CMD
// = PD3; //
// = PD4; //
/* = PD0; */ //CANRX
/* = PD1; */ //CANTX
/* = PD2; */ //(DO NOT USE FOR SPEEDUINO) - SDIO_CMD
/* = PD3; */ //
/* = PD4; */ //
pinFlex = PD4;
// = PD5;//TXD2
// = PD6; //RXD2
/* = PD5;*/ //TXD2
/* = PD6; */ //RXD2
pinCoil1 = PD7; //
// = PD7; //
// = PD8; //
/* = PD7; */ //
/* = PD8; */ //
pinCoil5 = PD9;//
// = PD10; //
// = PD11; //
// = PD12; //
/* = PD10; */ //
/* = PD11; */ //
/* = PD12; */ //
pinTrigger = PD13; //
pinTrigger2 = PD14; //
// = PD15; //
/* = PD15; */ //
//******************************************
//******** PORTE CONNECTIONS ***************
//******************************************
// = PE0; //
// = PE1; //
/* = PE0; */ //
/* = PE1; */ //
pinStepperEnable = PE2; //
// = PE3; //ONBOARD KEY1
// = PE4; //ONBOARD KEY2
/* = PE3; */ //ONBOARD KEY1
/* = PE4; */ //ONBOARD KEY2
pinStepperStep = PE5; //
pinFan = PE6; //
pinStepperDir = PE7; //
// = PE8; //
// = PE9; //
// = PE10; //
/* = PE8; */ //
/* = PE9; */ //
/* = PE10; */ //
pinInjector5 = PE11; //
pinInjector6 = PE12; //
// = PE13; //
// = PE14; //
// = PE15; //
/* = PE13; */ //
/* = PE14; */ //
/* = PE15; */ //
#else
#ifndef SMALL_FLASH_MODE //No support for bluepill here anyway
//Pin mappings as per the v0.2 shield

View File

@ -11,7 +11,7 @@ unsigned long divu100(unsigned long);
//This is a dedicated function that specifically handles the case of mapping 0-1023 values into a 0 to X range
//This is a common case because it means converting from a standard 10-bit analog input to a byte or 10-bit analog into 0-511 (Eg the temperature readings)
#if defined(_VARIANT_ARDUINO_STM32_) //libmaple //ST stm32duino core returns 0 - 1023 for analog read first use analogReadResolution(12); to make it 12 bit
#if defined(_VARIANT_ARDUINO_STM32_) /*libmaple */ //ST stm32duino core returns 0 - 1023 for analog read first use analogReadResolution(12); to make it 12 bit
#define fastMap1023toX(x, out_max) ( ((unsigned long)x * out_max) >> 12)
//This is a new version that allows for out_min
#define fastMap10Bit(x, out_min, out_max) ( ( ((unsigned long)x * (out_max-out_min)) >> 12 ) + out_min)

View File

@ -2,10 +2,10 @@
This scheduler is designed to maintain 2 schedules for use by the fuel and ignition systems.
It functions by waiting for the overflow vectors from each of the timers in use to overflow, which triggers an interrupt
//Technical
/Technical
Currently I am prescaling the 16-bit timers to 256 for injection and 64 for ignition. This means that the counter increments every 16us (injection) / 4uS (ignition) and will overflow every 1048576uS
Max Period = (Prescale)*(1/Frequency)*(2^17)
(See http://playground.arduino.cc/code/timer1)
(See playground.arduino.cc/code/timer1)
This means that the precision of the scheduler is 16uS (+/- 8uS of target) for fuel and 4uS (+/- 2uS) for ignition
/Features
@ -16,7 +16,7 @@ Timer identification
The Arduino timer3 is used for schedule 1
The Arduino timer4 is used for schedule 2
Both of these are 16-bit timers (ie count to 65536)
See page 136 of the processors datasheet: http://www.atmel.com/Images/doc2549.pdf
See page 136 of the processors datasheet: www.atmel.com/Images/doc2549.pdf
256 prescale gives tick every 16uS
256 prescale gives overflow every 1048576uS (This means maximum wait time is 1.0485 seconds)
@ -181,10 +181,10 @@ static inline unsigned int setQueue(volatile Schedule *queue[], Schedule *schedu
//Sort the queues. Both queues are kept in sync.
//This implementes a sorting networking based on the Bose-Nelson sorting network
//See: http://pages.ripco.net/~jgamble/nw.html
//See: pages.ripco.net/~jgamble/nw.html
#define SWAP(x,y) if(tmpQueue[y] < tmpQueue[x]) { unsigned int tmp = tmpQueue[x]; tmpQueue[x] = tmpQueue[y]; tmpQueue[y] = tmp; volatile Schedule *tmpS = queue[x]; queue[x] = queue[y]; queue[y] = tmpS; }
//SWAP(0, 1); //Likely not needed
//SWAP(2, 3); //Likely not needed
/*SWAP(0, 1); */ //Likely not needed
/*SWAP(2, 3); */ //Likely not needed
SWAP(0, 2);
SWAP(1, 3);
SWAP(1, 2);

View File

@ -87,19 +87,19 @@ void initialiseSchedulers()
ignitionSchedule3.compare = &IGN3_COMPARE;
ignitionSchedule4.counter = &IGN4_COUNTER;
ignitionSchedule4.compare = &IGN4_COMPARE;
#if (INJ_CHANNELS >= 5)
#if (IGN_CHANNELS >= 5)
ignitionSchedule5.counter = &IGN5_COUNTER;
ignitionSchedule5.compare = &IGN5_COMPARE;
#endif
#if (INJ_CHANNELS >= 6)
#if (IGN_CHANNELS >= 6)
ignitionSchedule6.counter = &IGN6_COUNTER;
ignitionSchedule6.compare = &IGN6_COMPARE;
#endif
#if (INJ_CHANNELS >= 7)
#if (IGN_CHANNELS >= 7)
ignitionSchedule7.counter = &IGN7_COUNTER;
ignitionSchedule7.compare = &IGN7_COMPARE;
#endif
#if (INJ_CHANNELS >= 8)
#if (IGN_CHANNELS >= 8)
ignitionSchedule8.counter = &IGN8_COUNTER;
ignitionSchedule8.compare = &IGN8_COMPARE;
#endif

View File

@ -50,15 +50,10 @@ byte cltErrorCount = 0;
/**
* @brief Simple low pass IIR filter macro for the analog inputs
* This is effectively implementing the smooth filter from http://playground.arduino.cc/Main/Smooth
* This is effectively implementing the smooth filter from playground.arduino.cc/Main/Smooth
* But removes the use of floats and uses 8 bits of fixed precision.
*/
#define ADC_FILTER(input, alpha, prior) (((long)input * (256 - alpha) + ((long)prior * alpha))) >> 8
//These functions all do checks on a pin to determine if it is already in use by another (higher importance) function
#define pinIsInjector(pin) ( ((pin) == pinInjector1) || ((pin) == pinInjector2) || ((pin) == pinInjector3) || ((pin) == pinInjector4) )
#define pinIsIgnition(pin) ( ((pin) == pinCoil1) || ((pin) == pinCoil2) || ((pin) == pinCoil3) || ((pin) == pinCoil4) )
#define pinIsSensor(pin) ( ((pin) == pinCLT) || ((pin) == pinIAT) || ((pin) == pinMAP) || ((pin) == pinTPS) || ((pin) == pinO2) || ((pin) == pinBat) )
#define pinIsUsed(pin) ( pinIsInjector((pin)) || pinIsIgnition((pin)) || pinIsSensor((pin)) )
static inline void instanteneousMAPReading() __attribute__((always_inline));
static inline void readMAP() __attribute__((always_inline));
@ -84,7 +79,7 @@ ISR(ADC_vect)
byte nChannel;
int result = ADCL | (ADCH << 8);
//ADCSRA = 0x6E; // ADC disabled by clearing bit 7(ADEN)
//ADCSRA = 0x6E; - ADC disabled by clearing bit 7(ADEN)
//BIT_CLEAR(ADCSRA, ADIE);
nChannel = ADMUX & 0x07;
@ -107,7 +102,7 @@ ISR(ADC_vect)
AnChannel[nChannel-1] = result;
//BIT_SET(ADCSRA, ADIE);
//ADCSRA = 0xEE; // ADC Interrupt Flag enabled
//ADCSRA = 0xEE; - ADC Interrupt Flag enabled
}
*/
ISR(ADC_vect)

View File

@ -466,20 +466,25 @@ void loop()
//Calculate staging pulsewidths if used
//To run staged injection, the number of cylinders must be less than or equal to the injector channels (ie Assuming you're running paired injection, you need at least as many injector channels as you have cylinders, half for the primaries and half for the secondaries)
if( (configPage10.stagingEnabled == true) && (configPage2.nCylinders <= INJ_CHANNELS) )
if( (configPage10.stagingEnabled == true) && (configPage2.nCylinders <= INJ_CHANNELS) && (currentStatus.PW1 > inj_opentime_uS) ) //Final check is to ensure that DFCO isn't active, which would cause an overflow below (See #267)
{
//Scale the 'full' pulsewidth by each of the injector capacities
currentStatus.PW1 -= inj_opentime_uS; //Subtract the opening time from PW1 as it needs to be multiplied out again by the pri/sec req_fuel values below. It is added on again after that calculation.
uint32_t tempPW1 = (((unsigned long)currentStatus.PW1 * staged_req_fuel_mult_pri) / 100) + inj_opentime_uS; //Opening time has to be added back on here (See above where it is subtracted)
uint32_t tempPW1 = (((unsigned long)currentStatus.PW1 * staged_req_fuel_mult_pri) / 100);
if(configPage10.stagingMode == STAGING_MODE_TABLE)
{
uint32_t tempPW3 = (((unsigned long)currentStatus.PW1 * staged_req_fuel_mult_sec) / 100) + inj_opentime_uS; //This is ONLY needed in in table mode. Auto mode only calculates the difference. As above, opening time must be readded.
uint32_t tempPW3 = (((unsigned long)currentStatus.PW1 * staged_req_fuel_mult_sec) / 100); //This is ONLY needed in in table mode. Auto mode only calculates the difference.
byte stagingSplit = get3DTableValue(&stagingTable, currentStatus.MAP, currentStatus.RPM);
currentStatus.PW1 = ((100 - stagingSplit) * tempPW1) / 100;
currentStatus.PW1 += inj_opentime_uS;
if(stagingSplit > 0) { currentStatus.PW3 = (stagingSplit * tempPW3) / 100; }
if(stagingSplit > 0)
{
currentStatus.PW3 = (stagingSplit * tempPW3) / 100;
currentStatus.PW3 += inj_opentime_uS;
}
else { currentStatus.PW3 = 0; }
}
else if(configPage10.stagingMode == STAGING_MODE_AUTO)
@ -489,9 +494,10 @@ void loop()
//If they exceed their limit, the extra duty is passed to the secondaries
if(tempPW1 > pwLimit)
{
uint32_t extraPW = tempPW1 - pwLimit;
uint32_t extraPW = tempPW1 - pwLimit + inj_opentime_uS; //The open time must be added here AND below because tempPW1 does not include an open time. The addition of it here takes into account the fact that pwLlimit does not contain an allowance for an open time.
currentStatus.PW1 = pwLimit;
currentStatus.PW3 = ((extraPW * staged_req_fuel_mult_sec) / staged_req_fuel_mult_pri) + inj_opentime_uS; //Convert the 'left over' fuel amount from primary injector scaling to secondary
currentStatus.PW3 = ((extraPW * staged_req_fuel_mult_sec) / staged_req_fuel_mult_pri); //Convert the 'left over' fuel amount from primary injector scaling to secondary
currentStatus.PW3 += inj_opentime_uS;
}
else { currentStatus.PW3 = 0; } //If tempPW1 < pwLImit it means that the entire fuel load can be handled by the primaries. Simply set the secondaries to 0
}
@ -1242,7 +1248,7 @@ uint16_t PW(int REQ_FUEL, byte VE, long MAP, int corrections, int injOpen)
if ( configPage2.multiplyMAP == true ) {
iMAP = ((unsigned int)MAP << 7) / currentStatus.baro; //Include multiply MAP (vs baro) if enabled
}
if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2)) {
if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) && (currentStatus.runSecs > configPage6.ego_sdelay) ) {
iAFR = ((unsigned int)currentStatus.O2 << 7) / currentStatus.afrTarget; //Include AFR (vs target) if enabled
}
iCorrections = (corrections << 7) / 100;
@ -1252,8 +1258,9 @@ uint16_t PW(int REQ_FUEL, byte VE, long MAP, int corrections, int injOpen)
if ( configPage2.multiplyMAP == true ) {
intermediate = (intermediate * (unsigned long)iMAP) >> 7;
}
if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) ) {
intermediate = (intermediate * (unsigned long)iAFR) >> 7; //EGO type must be set to wideband for this to be used
if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) && (currentStatus.runSecs > configPage6.ego_sdelay) ) {
//EGO type must be set to wideband and the AFR warmup time must've elapsed for this to be used
intermediate = (intermediate * (unsigned long)iAFR) >> 7;
}
intermediate = (intermediate * (unsigned long)iCorrections) >> 7;
if (intermediate != 0)

View File

@ -12,14 +12,16 @@ The 2D table can contain either 8-bit (byte) or 16-bit (int) values
The valueSize variable should be set to either 8 or 16 to indicate this BEFORE the table is used
*/
struct table2D {
//Used 5414 RAM with original version
byte valueSize;
byte axisSize;
byte xSize;
byte *values;
byte *axisX;
void *values;
void *axisX;
int16_t *values16;
int16_t *axisX16;
//int16_t *values16;
//int16_t *axisX16;
//Store the last X and Y coordinates in the table. This is used to make the next check faster
int16_t lastXMax;
@ -33,6 +35,8 @@ struct table2D {
//void table2D_setSize(struct table2D targetTable, byte newSize);
void table2D_setSize(struct table2D, byte);
int16_t table2D_getAxisValue(struct table2D, byte);
int16_t table2D_getRawValue(struct table2D, byte);
struct table3D {

View File

@ -11,6 +11,7 @@ Note that this may clear some of the existing values of the table
#include "table.h"
#include "globals.h"
/*
void table2D_setSize(struct table2D* targetTable, byte newSize)
{
//Table resize is ONLY permitted during system initialisation.
@ -33,6 +34,7 @@ void table2D_setSize(struct table2D* targetTable, byte newSize)
} //Byte or int
} //initialisationComplete
}
*/
void table3D_setSize(struct table3D *targetTable, byte newSize)
@ -56,7 +58,8 @@ ie: Given a value on the X axis, it returns a Y value that coresponds to the poi
This function must take into account whether a table contains 8-bit or 16-bit values.
Unfortunately this means many of the lines are duplicated depending on this
*/
int table2D_getValue(struct table2D *fromTable, int X_in)
/*
int table2D_getValue_orig(struct table2D *fromTable, int X_in)
{
int returnValue = 0;
bool valueFound = false;
@ -184,9 +187,7 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
unsigned int n = xMaxValue - xMinValue;
//Float version
/*
int yVal = (m / n) * (abs(fromTable.values[xMax] - fromTable.values[xMin]));
*/
//int yVal = (m / n) * (abs(fromTable.values[xMax] - fromTable.values[xMin]));
//Non-Float version
uint16_t yVal;
@ -216,6 +217,141 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
return returnValue;
}
*/
int table2D_getValue(struct table2D *fromTable, int X_in)
{
//Orig memory usage = 5414
int returnValue = 0;
bool valueFound = false;
int X = X_in;
int xMinValue, xMaxValue;
int xMin = 0;
int xMax = fromTable->xSize-1;
//Check whether the X input is the same as last time this ran
if( (X_in == fromTable->lastInput) && (fromTable->cacheTime == currentStatus.secl) )
{
returnValue = fromTable->lastOutput;
valueFound = true;
}
//If the requested X value is greater/small than the maximum/minimum bin, simply return that value
else if(X >= table2D_getAxisValue(fromTable, xMax))
{
returnValue = table2D_getRawValue(fromTable, xMax);
valueFound = true;
}
else if(X <= table2D_getAxisValue(fromTable, xMin))
{
returnValue = table2D_getRawValue(fromTable, xMin);
valueFound = true;
}
//Finally if none of that is found
else
{
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
xMaxValue = table2D_getAxisValue(fromTable, fromTable->lastXMax);
xMinValue = table2D_getAxisValue(fromTable, fromTable->lastXMin);
if ( (X <= xMaxValue) && (X > xMinValue) )
{
xMax = fromTable->lastXMax;
xMin = fromTable->lastXMin;
}
else
{
//If we're not in the same bin, loop through to find where we are
xMaxValue = table2D_getAxisValue(fromTable, fromTable->xSize-1); // init xMaxValue in preparation for loop.
for (int x = fromTable->xSize-1; x > 0; x--)
{
xMinValue = table2D_getAxisValue(fromTable, x-1); // fetch next Min
//Checks the case where the X value is exactly what was requested
if (X == xMaxValue)
{
returnValue = table2D_getRawValue(fromTable, x); //Simply return the coresponding value
valueFound = true;
break;
}
else if (X > xMinValue)
{
// Value is in the current bin
xMax = x;
fromTable->lastXMax = xMax;
xMin = x-1;
fromTable->lastXMin = xMin;
break;
}
// Otherwise, continue to next bin
xMaxValue = xMinValue; // for the next bin, our Min is their Max
}
}
} //X_in same as last time
if (valueFound == false)
{
int16_t m = X - xMinValue;
int16_t n = xMaxValue - xMinValue;
int16_t yMax = table2D_getRawValue(fromTable, xMax);
int16_t yMin = table2D_getRawValue(fromTable, xMin);
//Float version
/*
int yVal = (m / n) * (abs(yMax - yMin));
*/
//Non-Float version
int16_t yVal = ((long)(m << 6) / n) * (abs(yMax - yMin));
yVal = (yVal >> 6);
if (yMax > yMin) { yVal = yMin + yVal; }
else { yVal = yMin - yVal; }
returnValue = yVal;
}
fromTable->lastInput = X_in;
fromTable->lastOutput = returnValue;
return returnValue;
}
/**
* @brief Returns an axis (bin) value from the 2D table. This works regardless of whether that axis is bytes or int16_ts
*
* @param fromTable
* @param X_in
* @return int16_t
*/
int16_t table2D_getAxisValue(struct table2D *fromTable, byte X_in)
{
int returnValue = 0;
if(fromTable->axisSize == SIZE_INT) { returnValue = ((int16_t*)fromTable->axisX)[X_in]; }
else if(fromTable->axisSize == SIZE_BYTE) { returnValue = ((uint8_t*)fromTable->axisX)[X_in]; }
return returnValue;
}
/**
* @brief Returns an value from the 2D table given an index value. No interpolation is performed
*
* @param fromTable
* @param X_in
* @return int16_t
*/
int16_t table2D_getRawValue(struct table2D *fromTable, byte X_index)
{
int returnValue = 0;
if(fromTable->valueSize == SIZE_INT) { returnValue = ((int16_t*)fromTable->values)[X_index]; }
else if(fromTable->valueSize == SIZE_BYTE) { returnValue = ((uint8_t*)fromTable->values)[X_index]; }
return returnValue;
}
//This function pulls a value from a 3D table given a target for X and Y coordinates.

View File

@ -10,7 +10,7 @@ We're implementing a lower frequency interrupt loop to perform calculations that
//Technical
Timer2 is only 8bit so we are setting the prescaler to 128 to get the most out of it. This means that the counter increments every 0.008ms and the overflow at 256 will be after 2.048ms
Max Period = (Prescale)*(1/Frequency)*(2^8)
(See http://arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html)
(See arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html)
We're after a 1ms interval so we'll need 131 intervals to reach this ( 1ms / 0.008ms per tick = 125).
Hence we will preload the timer with 131 cycles to leave 125 until overflow (1ms).