Merge branch 'master' into improved_io2

This commit is contained in:
Josh Stewart 2018-10-23 10:05:54 +11:00 committed by GitHub
commit 2057f05d47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 502 additions and 186 deletions

View File

@ -306,11 +306,11 @@ page = 4
FixAng = scalar, S08, 2, "Deg", 1, 0, -64, 64, 0 ; Allow negative values here
CrankAng = scalar, U08, 3, "Deg", 1, 0, -10, 80, 0
TrigAngMul = scalar, U08, 4, "", 1, 0, 0, 88, 0 ; Multiplier for tooth counts that don't evenly divide into 360
TrigEdge = bits, U08, 5,[0:0], "Leading", "Trailing"
TrigEdge = bits, U08, 5,[0:0], "RISING", "FALLING"
TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed"
IgInv = bits, U08, 5,[2:2], "Going Low", "Going High"
TrigPattern= bits, U08, 5,[3:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata / 3000GT", "GM 24X", "Jeep 2000", "Audi 135", "Honda D17", "Miata 99-05", "Mazda AU", "Non-360 Dual", "Nissan 360", "Subaru 6/7", "Daihatsu +1", "Harley EVO", "36-2-2-2", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
TrigEdgeSec= bits, U08, 6,[0:0], "Leading", "Trailing"
TrigEdgeSec= bits, U08, 6,[0:0], "RISING", "FALLING"
fuelPumpPin= bits , U08, 6,[1:6], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID"
useResync = bits, U08, 6,[7:7], "No", "Yes"
sparkDur = scalar, U08, 7, "ms", 0.1, 0, 0, 25.5, 1 ; Spark duration
@ -377,14 +377,14 @@ page = 4
ignBypassEnable = bits, U08, 63, [0:0], "Off", "On"
ignBypassPin = bits , U08, 63, [1:6], "INVALID", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
ignBypassHiLo = bits, U08, 63, [7:7], "LOW", "HIGH"
;Analog input filter levels
ADCFILTER_TPS = scalar, U08, 64, "%", 1.0, 0.0, 0, 255, 0
ADCFILTER_CLT = scalar, U08, 65, "%", 1.0, 0.0, 0, 255, 0
ADCFILTER_IAT = scalar, U08, 66, "%", 1.0, 0.0, 0, 255, 0
ADCFILTER_O2 = scalar, U08, 67, "%", 1.0, 0.0, 0, 255, 0
ADCFILTER_BAT = scalar, U08, 68, "%", 1.0, 0.0, 0, 255, 0
ADCFILTER_MAP = scalar, U08, 69, "%", 1.0, 0.0, 0, 255, 0
ADCFILTER_BARO = scalar, U08, 70, "%", 1.0, 0.0, 0, 255, 0
;Analog input filter levels (Note max values are 254 so that default values of 255 can be overwirtten on bootup)
ADCFILTER_TPS = scalar, U08, 64, "%", 1.0, 0.0, 0, 254, 0
ADCFILTER_CLT = scalar, U08, 65, "%", 1.0, 0.0, 0, 254, 0
ADCFILTER_IAT = scalar, U08, 66, "%", 1.0, 0.0, 0, 254, 0
ADCFILTER_O2 = scalar, U08, 67, "%", 1.0, 0.0, 0, 254, 0
ADCFILTER_BAT = scalar, U08, 68, "%", 1.0, 0.0, 0, 254, 0
ADCFILTER_MAP = scalar, U08, 69, "%", 1.0, 0.0, 0, 254, 0
ADCFILTER_BARO = scalar, U08, 70, "%", 1.0, 0.0, 0, 254, 0
unused4-64 = array, U08, 71, [56], "%", 1.0, 0.0, 0.0, 255, 0
;--------------------------------------------------
@ -1110,10 +1110,10 @@ page = 10
defaultValue = resetControlPin, 0
;Default ADC filter values
defaultValue = ADCFILTER_TPS 128
defaultValue = ADCFILTER_TPS 50
defaultValue = ADCFILTER_CLT 180
defaultValue = ADCFILTER_IAT 180
defaultValue = ADCFILTER_O2 128
defaultValue = ADCFILTER_O2 100
defaultValue = ADCFILTER_BAT 128
defaultValue = ADCFILTER_MAP 20 ;This is only used on Instantaneous MAP readings and is intentionally very weak to allow for faster response
defaultValue = ADCFILTER_BARO 64
@ -3310,10 +3310,13 @@ cmdtestspk450dc = "E\x03\x0C"
;loggerDef = uniqueName, Display Name, type
loggerDef = tooth, "Tooth Logger", tooth
;dataReadCommand = "r\\x00\\xf4\\x00\\x00\\x04\\x00" ; standard TS command format
startCommand = "H"
stopCommand = "h"
dataReadCommand = "T" ; Basic TS command format
dataReadTimeout = 15000 ; time in ms
dataReadyCondition = { toothLog1Ready }
dataLength = 256 ; in bytes, including headers, footers and data (not used)
;dataLength = 256 ; in bytes, including headers, footers and data (not used)
dataLength = 128 ; in bytes, including headers, footers and data (not used)
;recordDef = headerLen. footerLen, recordLen
recordDef = 0, 0, 2; in bytes, the recordLen is for each record, currently limited to 4 bytes
@ -3321,6 +3324,32 @@ cmdtestspk450dc = "E\x03\x0C"
;recordField = Name, HeaderName, startBit, bitCount, scale, units, updateCondition
recordField = toothTime, "ToothTime", 0, 16, 1.0, "uS"
loggerDef = compositeLogger, "Composite Logger", composite
startCommand = "J"
stopCommand = "j"
dataReadCommand = "T" ; Basic TS command format. Note that this is shared with the composite logger. Firmware detects which log is currently running
dataReadTimeout = 5000 ; time in ms
dataReadyCondition = { toothLog1Ready }
;dataLength = 256 ; in bytes, including headers, footers and data (not used)
;dataLength = 320 ; in bytes, including headers, footers and data (not used)
;recordDef = headerLen. footerLen, recordLen
recordDef = 0, 0, 5; in bytes, the recordLen is for each record, currently limited to 4 bytes
;recordField = Name, HeaderName, startBit, bitCount, scale, units, updateCondition
recordField = priLevel, "PriLevel", 0, 1, 1.0, "Flag"
recordField = secLevel, "SecLevel", 1, 1, 1.0, "Flag"
recordField = trigger, "Trigger", 2, 1, 1.0, "Flag"
recordField = sync, "Sync", 3, 1, 1.0, "Flag"
recordField = refTime, "RefTime", 8, 32, 0.001, "ms", hidden
; hidden calcField serves as intermediate variable
calcField = maxTime, "MaxTime", "ms", { maxValue(refTime) }, hidden
calcField = toothTime, "ToothTime", "ms", { refTime - pastValue(refTime, 1) }
;recordField = time, "Time", 24, 16, 1.0, "ms"
calcField = time, "Time", "ms", { refTime }
[Tools]
;addTool = toolName, PanelName

View File

@ -26,7 +26,6 @@ int valueOffset; //cannot use offset as a variable name, it is a reserved word f
byte cmdGroup = 0;
byte cmdValue = 0;
int cmdCombined = 0; //the cmdgroup as high byte and cmdvalue as low byte
byte cmdStore[8]; //array storing pre test values
byte tsCanId = 0; // current tscanid requested
const char pageTitles[] PROGMEM //This is being stored in the avr flash instead of SRAM which there is not very much of

View File

@ -10,6 +10,7 @@ A full copy of the license may be found in the projects root directory
#include "storage.h"
#include "maths.h"
#include "utils.h"
#include "decoders.h"
/*
Processes the data on the serial buffer.
@ -74,6 +75,43 @@ void command()
Serial.print("001");
break;
case 'H': //Start the tooth logger
currentStatus.toothLogEnabled = true;
currentStatus.compositeLogEnabled = false; //Safety first (Should never be required)
toothHistoryIndex = 0;
toothHistorySerialIndex = 0;
break;
case 'h': //Stop the tooth logger
currentStatus.toothLogEnabled = false;
break;
case 'J': //Start the composite logger
currentStatus.compositeLogEnabled = true;
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
toothHistoryIndex = 0;
toothHistorySerialIndex = 0;
compositeLastToothTime = 0;
//Disconnect the standard interrupt and add the logger verion
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
attachInterrupt( digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE );
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
attachInterrupt( digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE );
break;
case 'j': //Stop the composite logger
currentStatus.compositeLogEnabled = false;
//Disconnect the logger interrupts and attach the normal ones
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
attachInterrupt( digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge );
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
attachInterrupt( digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge );
break;
case 'L': // List the contents of current page in human readable form
sendPage(true);
break;
@ -139,7 +177,7 @@ void command()
break;
case 'Q': // send code version
Serial.print("speeduino 201809-dev");
Serial.print(F("speeduino 201809-dev"));
break;
case 'r': //New format for the optimised OutputChannels
@ -169,12 +207,14 @@ void command()
break;
case 'S': // send code version
Serial.print("Speeduino 2018.9-dev");
Serial.print(F("Speeduino 2018.9-dev"));
currentStatus.secl = 0; //This is required in TS3 due to its stricter timings
break;
case 'T': //Send 256 tooth log entries to Tuner Studios tooth logger
sendToothLog(false); //Sends tooth log values as ints
if(currentStatus.toothLogEnabled == true) { sendToothLog(false); } //Sends tooth log values as ints
else if (currentStatus.compositeLogEnabled == true) { sendCompositeLog(); }
break;
case 't': // receive new Calibration info. Command structure: "t", <tble_idx> <data array>. This is an MS2/Extra command, NOT part of MS1 spec
@ -1391,33 +1431,52 @@ Send 256 tooth log entries
void sendToothLog(bool useChar)
{
//We need TOOTH_LOG_SIZE number of records to send to TunerStudio. If there aren't that many in the buffer then we just return and wait for the next call
if (toothHistoryIndex >= TOOTH_LOG_SIZE) //Sanity check. Flagging system means this should always be true
if (BIT_CHECK(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY)) //Sanity check. Flagging system means this should always be true
{
unsigned int tempToothHistory[TOOTH_LOG_BUFFER]; //Create a temporary array that will contain a copy of what is in the main toothHistory array
//Copy the working history into the temporary buffer array. This is done so that, if the history loops whilst the values are being sent over serial, it doesn't affect the values
memcpy( (void*)tempToothHistory, (void*)toothHistory, sizeof(tempToothHistory) );
toothHistoryIndex = 0; //Reset the history index
//Loop only needs to go to half the buffer size
if (useChar)
{
for (int x = 0; x < TOOTH_LOG_SIZE; x++)
{
Serial.println(tempToothHistory[x]);
}
}
else
{
for (int x = 0; x < TOOTH_LOG_SIZE; x++)
{
Serial.write(highByte(tempToothHistory[x]));
Serial.write(lowByte(tempToothHistory[x]));
Serial.write(highByte(toothHistory[toothHistorySerialIndex]));
Serial.write(lowByte(toothHistory[toothHistorySerialIndex]));
if(toothHistorySerialIndex == (TOOTH_LOG_BUFFER-1)) { toothHistorySerialIndex = 0; }
else { toothHistorySerialIndex++; }
}
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
}
toothLogRead = true;
cmdPending = false;
}
else { cmdPending = true; } //Mark this request as being incomplete.
}
void sendCompositeLog()
{
if (BIT_CHECK(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY)) //Sanity check. Flagging system means this should always be true
{
uint32_t runTime = 0;
for (int x = 0; x < TOOTH_LOG_SIZE; x++)
{
runTime += toothHistory[toothHistorySerialIndex]; //This combined runtime (in us) that the log was going for by this record)
//Serial.write(highByte(runTime));
//Serial.write(lowByte(runTime));
Serial.write(runTime >> 24);
Serial.write(runTime >> 16);
Serial.write(runTime >> 8);
Serial.write(runTime);
//Serial.write(highByte(toothHistory[toothHistorySerialIndex]));
//Serial.write(lowByte(toothHistory[toothHistorySerialIndex]));
Serial.write(compositeLogHistory[toothHistorySerialIndex]); //The status byte (Indicates which)
if(toothHistorySerialIndex == (TOOTH_LOG_BUFFER-1)) { toothHistorySerialIndex = 0; }
else { toothHistorySerialIndex++; }
}
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
cmdPending = false;
}
else { cmdPending = true; } //Mark this request as being incomplete.
}
void testComm()

View File

@ -9,14 +9,16 @@
#define READ_SEC_TRIGGER() digitalRead(pinTrigger2)
#endif
static inline void addToothLogEntry(unsigned long);
static inline void addToothLogEntry(unsigned long, bool);
void loggerPrimaryISR();
void loggerSecondaryISR();
static inline uint16_t stdGetRPM(uint16_t);
static inline void setFilter(unsigned long);
static inline int crankingGetRPM(byte);
//static inline void doPerToothTiming(uint16_t);
void (*trigger)(); //Pointer for the trigger function (Gets pointed to the relevant decoder)
void (*triggerSecondary)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder)
void (*triggerHandler)(); //Pointer for the trigger function (Gets pointed to the relevant decoder)
void (*triggerSecondaryHandler)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder)
uint16_t (*getRPM)(); //Pointer to the getRPM function (Gets pointed to the relevant decoder)
int (*getCrankAngle)(); //Pointer to the getCrank Angle function (Gets pointed to the relevant decoder)
void (*triggerSetEndTeeth)(); //Pointer to the triggerSetEndTeeth function of each decoder
@ -149,6 +151,7 @@ volatile unsigned long curTime2;
volatile unsigned long curGap2;
volatile unsigned long lastGap;
volatile unsigned long targetGap;
volatile unsigned long compositeLastToothTime;
volatile int toothCurrentCount = 0; //The current number of teeth (Onec sync has been achieved, this can never actually be 0
volatile byte toothSystemCount = 0; //Used for decoders such as Audi 135 where not every tooth is used for calculating crank angle. This variable stores the actual number of teeth, not the number being used to calculate crank angle
@ -171,12 +174,14 @@ volatile unsigned long secondaryLastToothTime1 = 0; //The time (micros()) that t
volatile int triggerActualTeeth;
volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering)
volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input
volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters)
unsigned int triggerSecFilterTime_duration; // The shortest valid time (in uS) pulse DURATION
volatile uint16_t triggerToothAngle; //The number of crank degrees that elapse per tooth
volatile bool triggerToothAngleIsCorrect = false; //Whether or not the triggerToothAngle variable is currently accurate. Some patterns have times when the triggerToothAngle variable cannot be accurately set.
bool secondDerivEnabled = false; //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine
bool decoderIsSequential; //Whether or not the decoder supports sequential operation
bool decoderIsLowRes = false; //Is set true, certain extra calculations are performed for better timing accuracy
bool decoderHasSecondary = false; //Whether or not the pattern uses a secondary input
bool decoderHasFixedCrankingTiming = false; //Whether or not the decoder supports fixed cranking timing
byte checkSyncToothCount; //How many teeth must've been seen on this revolution before we try to confirm sync (Useful for missing tooth type decoders)
unsigned long elapsedTime;
@ -197,4 +202,7 @@ int16_t toothAngles[24]; //An array for storing fixed tooth angles. Currently si
#define CRANK_SPEED 0
#define CAM_SPEED 1
#define TOOTH_CRANK 0
#define TOOTH_CAM 1
#endif

View File

@ -27,21 +27,113 @@ toothLastToothTime - The time (In uS) that the last primary tooth was 'seen'
#include "scheduler.h"
#include "crankMaths.h"
static inline void addToothLogEntry(unsigned long toothTime)
/*
*
* whichTooth - 0 for Primary (Crank), 1 for Secondary (Cam)
*/
static inline void addToothLogEntry(unsigned long toothTime, bool whichTooth)
{
//High speed tooth logging history
toothHistory[toothHistoryIndex] = toothTime;
if(toothHistoryIndex == (TOOTH_LOG_BUFFER-1))
if( (currentStatus.toothLogEnabled == true) || (currentStatus.compositeLogEnabled == true) )
{
if (toothLogRead)
bool valueLogged = false;
if(currentStatus.toothLogEnabled == true)
{
toothHistoryIndex = 0;
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
toothLogRead = false; //The tooth log ready bit is cleared to ensure that we only get a set of concurrent values.
//Tooth log only works on the Crank tooth
if(whichTooth == TOOTH_CRANK)
{
toothHistory[toothHistoryIndex] = toothTime; //Set the value in the log.
valueLogged = true;
}
}
else if(currentStatus.compositeLogEnabled == true)
{
compositeLogHistory[toothHistoryIndex] = 0;
if(READ_PRI_TRIGGER() == true) { BIT_SET(compositeLogHistory[toothHistoryIndex], COMPOSITE_LOG_PRI); }
if(READ_SEC_TRIGGER() == true) { BIT_SET(compositeLogHistory[toothHistoryIndex], COMPOSITE_LOG_SEC); }
if(whichTooth == TOOTH_CAM) { BIT_SET(compositeLogHistory[toothHistoryIndex], COMPOSITE_LOG_TRIG); }
if(currentStatus.hasSync == true) { BIT_SET(compositeLogHistory[toothHistoryIndex], COMPOSITE_LOG_SYNC); }
toothHistory[toothHistoryIndex] = micros() - compositeLastToothTime;
compositeLastToothTime = micros();
valueLogged = true;
}
//If there has been a value logged above, update the indexes
if(valueLogged == true)
{
if(toothHistoryIndex == (TOOTH_LOG_BUFFER-1)) { toothHistoryIndex = 0; }
else { toothHistoryIndex++; }
uint16_t absoluteToothHistoryIndex = toothHistoryIndex;
if(toothHistoryIndex < toothHistorySerialIndex)
{
//If the main history index is lower than the serial index, it means that this has looped. To calculate the delta between the two indexes, add the buffer size back on
absoluteToothHistoryIndex += TOOTH_LOG_BUFFER;
}
//Check whether the current index is ahead of the serial index by at least the size of the log
if( (absoluteToothHistoryIndex - toothHistorySerialIndex) >= TOOTH_LOG_SIZE ) { BIT_SET(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY); }
else { BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY); } //Tooth log is not yet ahead of the serial index by enough, so mark the log as not yet ready
}
} //Tooth/Composite log enabled
}
/*
* This function is called on both the rising and falling edges of the primary trigger, when either the
* composite or tooth loggers are turned on.
*/
void loggerPrimaryISR()
{
validTrigger = false; //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
bool validEdge = false; //This is set true below if the edge
/* Two checks here:
1) If the primary trigger is RISING, then check whether the primary is currently HIGH
2) If the primary trigger is FALLING, then check whether the primary is currently LOW
If either of these are true, the primary decoder funtino is called
*/
if( ( (primaryTriggerEdge == RISING) && (READ_PRI_TRIGGER() == HIGH) ) || ( (primaryTriggerEdge == FALLING) && (READ_PRI_TRIGGER() == LOW) ) || (primaryTriggerEdge == CHANGE) )
{
triggerHandler();
validEdge = true;
}
if( (currentStatus.toothLogEnabled == true) && (validTrigger == true) )
{
//Tooth logger only logs when the edge was correct
if(validEdge == true) { addToothLogEntry(curGap, TOOTH_CRANK); }
}
//else if( (currentStatus.compositeLogEnabled == true) && (validTrigger == true) )
else if( (currentStatus.compositeLogEnabled == true) )
{
//Composite logger adds an entry regardless of which edge it was
addToothLogEntry(curGap, TOOTH_CRANK);
}
}
/*
* As above, but for the secondary
*/
void loggerSecondaryISR()
{
validTrigger = false; //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
validTrigger = true;
/* 3 checks here:
1) If the primary trigger is RISING, then check whether the primary is currently HIGH
2) If the primary trigger is FALLING, then check whether the primary is currently LOW
3) The secondary trigger is CHANGING
If either of these are true, the primary decoder funtino is called
*/
if( ( (secondaryTriggerEdge == RISING) && (READ_SEC_TRIGGER() == HIGH) ) || ( (secondaryTriggerEdge == FALLING) && (READ_SEC_TRIGGER() == LOW) ) || (secondaryTriggerEdge == CHANGE) )
{
triggerSecondaryHandler();
}
//No tooth logger for the secondary input
if( (currentStatus.compositeLogEnabled == true) && (validTrigger == true) )
{
//Composite logger adds an entry regardless of which edge it was
addToothLogEntry(curGap2, TOOTH_CAM);
}
else
{ toothHistoryIndex++; }
}
/*
@ -179,8 +271,7 @@ void triggerPri_missingTooth()
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS)
{
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
//if(toothCurrentCount > checkSyncToothCount || currentStatus.hasSync == false)
{
@ -390,7 +481,7 @@ void triggerPri_DualWheel()
if ( curGap >= triggerFilterTime )
{
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -578,7 +669,7 @@ void triggerPri_BasicDistributor()
}
setFilter(curGap); //Recalc the new filter value
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
if ( configPage4.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
{
@ -691,8 +782,7 @@ void triggerPri_GM7X()
curTime = micros();
curGap = curTime - toothLastToothTime;
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
//
if( toothCurrentCount > 7 )
@ -855,7 +945,7 @@ void triggerPri_4G63()
curGap = curTime - toothLastToothTime;
if ( (curGap >= triggerFilterTime) || (currentStatus.startRevolutions == 0) )
{
addToothLogEntry(curGap);
validTrigger = true; //Flag that this pulse was accepted as a valid trigger
triggerFilterTime = curGap >> 2; //This only applies during non-sync conditions. If there is sync then triggerFilterTime gets changed again below with a better value.
toothLastMinusOneToothTime = toothLastToothTime;
@ -1054,6 +1144,8 @@ void triggerSec_4G63()
if ( (curGap2 >= triggerSecFilterTime) )//|| (currentStatus.startRevolutions == 0) )
{
toothLastSecToothTime = curTime2;
validTrigger = true; //Flag that this pulse was accepted as a valid trigger
//addToothLogEntry(curGap, TOOTH_CAM);
triggerSecFilterTime = curGap2 >> 1; //Basic 50% filter for the secondary reading
//More aggressive options:
@ -1287,7 +1379,7 @@ void triggerPri_24X()
triggerToothAngle = toothAngles[(toothCurrentCount-1)] - toothAngles[(toothCurrentCount-2)]; //Calculate the last tooth gap in degrees
}
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastToothTime = curTime;
@ -1399,7 +1491,7 @@ void triggerPri_Jeep2000()
setFilter(curGap); //Recalc the new filter value
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -1482,7 +1574,7 @@ void triggerPri_Audi135()
{
//We only proceed for every third tooth
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothSystemLastToothTime = curTime;
toothSystemCount = 0;
toothCurrentCount++; //Increment the tooth counter
@ -1588,7 +1680,7 @@ void triggerPri_HondaD17()
curGap = curTime - toothLastToothTime;
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
//
if( (toothCurrentCount == 13) && (currentStatus.hasSync == true) )
@ -1717,6 +1809,7 @@ void triggerPri_Miata9905()
if ( (curGap >= triggerFilterTime) || (currentStatus.startRevolutions == 0) )
{
toothCurrentCount++;
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
if( (toothCurrentCount == (triggerActualTeeth + 1)) )
{
toothCurrentCount = 1; //Reset the counter
@ -1739,7 +1832,6 @@ void triggerPri_Miata9905()
if (currentStatus.hasSync == true)
{
addToothLogEntry(curGap);
//Whilst this is an uneven tooth pattern, if the specific angle between the last 2 teeth is specified, 1st deriv prediction can be used
if( (configPage4.triggerFilter == 1) || (currentStatus.RPM < 1400) )
@ -1903,7 +1995,7 @@ void triggerPri_MazdaAU()
curGap = curTime - toothLastToothTime;
if ( curGap >= triggerFilterTime )
{
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothCurrentCount++;
if( (toothCurrentCount == 1) || (toothCurrentCount == 5) ) //Trigger is on CHANGE, hence 4 pulses = 1 crank rev
@ -2120,7 +2212,7 @@ void triggerPri_Nissan360()
curGap = curTime - toothLastToothTime;
//if ( curGap < triggerFilterTime ) { return; }
toothCurrentCount++; //Increment the tooth counter
//addToothLogEntry(curGap); Disable tooth logging on this decoder due to overhead
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -2361,7 +2453,7 @@ void triggerPri_Subaru67()
//curGap = curTime - toothLastToothTime;
//if ( curGap < triggerFilterTime ) { return; }
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -2443,7 +2535,7 @@ uint16_t getRPM_Subaru67()
uint16_t tempRPM = 0;
if(currentStatus.startRevolutions > 0)
{
//As the tooth count is over 720 degrees, we need to double the RPM value and halve the revolution time
//As the tooth count is over 720 degrees
tempRPM = stdGetRPM(720);
}
return tempRPM;
@ -2525,6 +2617,7 @@ void triggerPri_Daihatsu()
//if ( curGap >= triggerFilterTime || (currentStatus.startRevolutions == 0 )
{
toothSystemCount++;
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
if (currentStatus.hasSync == true)
{
@ -2545,8 +2638,6 @@ void triggerPri_Daihatsu()
setFilter(curGap); //Recalc the new filter value
}
//addToothLogEntry(curGap);
if ( configPage4.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
{
//This locks the cranking timing to 0 degrees BTDC (All the triggers allow for)
@ -2674,7 +2765,7 @@ void triggerPri_Harley()
{
if ( READ_PRI_TRIGGER() == HIGH) // Has to be the same as in main() trigger-attach, for readability we do it this way.
{
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
targetGap = lastGap ; //Gap is the Time to next toothtrigger, so we know where we are
toothCurrentCount++;
if (curGap > targetGap)
@ -2814,8 +2905,7 @@ void triggerPri_ThirtySixMinus222()
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS)
{
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
//Begin the missing tooth detection
//If the time between the current tooth and the last is greater than 2x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after a gap

View File

@ -127,9 +127,14 @@
#define VALID_MAP_MAX 1022 //The largest ADC value that is valid for the MAP sensor
#define VALID_MAP_MIN 2 //The smallest ADC value that is valid for the MAP sensor
#define TOOTH_LOG_SIZE 128
#define TOOTH_LOG_SIZE 64
#define TOOTH_LOG_BUFFER 256
#define COMPOSITE_LOG_PRI 0
#define COMPOSITE_LOG_SEC 1
#define COMPOSITE_LOG_TRIG 2
#define COMPOSITE_LOG_SYNC 3
#define INJ_PAIRED 0
#define INJ_SEMISEQUENTIAL 1
#define INJ_BANKED 2
@ -199,11 +204,11 @@
#define FUEL_PUMP_ON() *pump_pin_port |= (pump_pin_mask)
#define FUEL_PUMP_OFF() *pump_pin_port &= ~(pump_pin_mask)
const char TSfirmwareVersion[] = "Speeduino 2016.09";
const char TSfirmwareVersion[] PROGMEM = "Speeduino";
const byte data_structure_version = 2; //This identifies the data structure when reading / writing.
//const byte page_size = 64;
const int16_t npage_size[11] = {0,288,128,288,128,288,128,240,192,192,192};
const int16_t npage_size[11] PROGMEM = {0,288,128,288,128,288,128,240,192,192,192};
//const byte page11_size = 128;
#define MAP_PAGE_SIZE 288
@ -302,9 +307,12 @@ uint16_t fixedCrankingOverride = 0;
bool clutchTrigger;
bool previousClutchTrigger;
volatile uint16_t toothHistory[TOOTH_LOG_BUFFER];
volatile uint8_t compositeLogHistory[TOOTH_LOG_BUFFER];
volatile bool fpPrimed = false; //Tracks whether or not the fuel pump priming has been completed yet
volatile unsigned int toothHistoryIndex = 0;
volatile bool toothLogRead = false; //Flag to indicate whether the current tooth log values have been read out yet
volatile byte toothHistorySerialIndex = 0;
byte primaryTriggerEdge;
byte secondaryTriggerEdge;
int CRANK_ANGLE_MAX = 720;
int CRANK_ANGLE_MAX_IGN = 360;
int CRANK_ANGLE_MAX_INJ = 360; // The number of crank degrees that the system track over. 360 for wasted / timed batch and 720 for sequential
@ -404,6 +412,8 @@ struct statuses {
byte syncLossCounter;
byte knockRetard;
bool knockActive;
bool toothLogEnabled;
bool compositeLogEnabled;
//Helpful bitwise operations:
//Useful reference: http://playground.arduino.cc/Code/BitMath
@ -520,7 +530,7 @@ struct config2 {
} __attribute__((__packed__)); //The 32 bi systems require all structs to be fully packed
#endif
//Page 2 of the config - See the ini file for further reference
//Page 4 of the config - See the ini file for further reference
//This mostly covers off variables that are required for ignition
struct config4 {

View File

@ -29,7 +29,7 @@ void initialiseIdle()
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) )
{
//FlexTimer 2 is used for idle
//FlexTimer 2, compare channel 0 is used for idle
FTM2_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
FTM2_MODE |= FTM_MODE_FTMEN; //Flex Timer module enable
FTM2_MODE |= FTM_MODE_INIT;
@ -75,7 +75,12 @@ void initialiseIdle()
//Setup the channels (See Pg 1014 of K64 DS).
FTM2_C0SC &= ~FTM_CSC_MSB; //According to Pg 965 of the K64 datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM2_C0SC |= FTM_CSC_MSA; //Enable Compare mode
FTM2_C0SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
//The below enables channel compare interrupt, but this is done in idleControl()
//FTM2_C0SC |= FTM_CSC_CHIE;
FTM2_C1SC &= ~FTM_CSC_MSB; //According to Pg 965 of the K64 datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM2_C1SC |= FTM_CSC_MSA; //Enable Compare mode
//FTM2_C1SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
// enable IRQ Interrupt
NVIC_ENABLE_IRQ(IRQ_FTM2);
@ -117,8 +122,10 @@ void initialiseIdle()
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
#if defined(CORE_STM32)
idle_pwm_max_count = 1000000L / (configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 5KHz
#else
#elif defined(CORE_AVR)
idle_pwm_max_count = 1000000L / (16 * configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
#elif defined(CORE_TEENSY)
idle_pwm_max_count = 1000000L / (32 * configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
#endif
enableIdle();
break;
@ -141,8 +148,10 @@ void initialiseIdle()
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
#if defined(CORE_STM32)
idle_pwm_max_count = 1000000L / (configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 5KHz
#else
#elif defined(CORE_AVR)
idle_pwm_max_count = 1000000L / (16 * configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
#elif defined(CORE_TEENSY)
idle_pwm_max_count = 1000000L / (32 * configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
#endif
idlePID.SetOutputLimits(percentage(configPage2.iacCLminDuty, idle_pwm_max_count), percentage(configPage2.iacCLmaxDuty, idle_pwm_max_count));
idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD);
@ -250,9 +259,10 @@ void idleControl()
if(currentStatus.idleUpActive == true) { currentStatus.idleDuty += configPage2.idleUpAdder; } //Add Idle Up amount if active
if( currentStatus.idleDuty == 0 ) { disableIdle(); break; }
idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count);
currentStatus.idleLoad = currentStatus.idleDuty >> 1;
currentStatus.idleLoad = currentStatus.idleDuty >> 1; //Idle Load is divided by 2 in order to send to TS
idleOn = true;
}
break;
case IAC_ALGORITHM_PWM_CL: //Case 3 is PWM closed loop
@ -479,3 +489,16 @@ static inline void idleInterrupt() //Most ARM chips can simply call a function
idle_pwm_state = true;
}
}
#if defined(CORE_TEENSY)
void ftm2_isr(void)
{
//FTM2 only has 2 compare channels
//Use separate variables for each test to ensure conversion to bool
bool interrupt1 = (FTM2_C0SC & FTM_CSC_CHF);
bool interrupt2 = (FTM2_C1SC & FTM_CSC_CHF); //Not currently used
if(interrupt1) { FTM2_C0SC &= ~FTM_CSC_CHF; idleInterrupt(); }
else if(interrupt2) { FTM2_C1SC &= ~FTM_CSC_CHF; } //Add a callback function here if this is ever used
}
#endif

View File

@ -457,9 +457,9 @@ struct Schedule {
#endif
};
volatile Schedule *timer3Aqueue[4];
Schedule *timer3Bqueue[4];
Schedule *timer3Cqueue[4];
//volatile Schedule *timer3Aqueue[4];
//Schedule *timer3Bqueue[4];
//Schedule *timer3Cqueue[4];
Schedule fuelSchedule1;
Schedule fuelSchedule2;

View File

@ -30,7 +30,6 @@
volatile byte flexCounter = 0;
volatile byte knockCounter = 0;
volatile uint16_t knockAngle;
volatile int AnChannel[15];
unsigned long MAPrunningValue; //Used for tracking either the total of all MAP readings in this cycle (Event average) or the lowest value detected in this cycle (event minimum)
unsigned long EMAPrunningValue; //As above but for EMAP
@ -70,6 +69,8 @@ void readBat();
void readBaro();
#if defined(ANALOG_ISR)
volatile int AnChannel[15];
//Analog ISR interrupt routine
/*
ISR(ADC_vect)

View File

@ -100,8 +100,17 @@ void initialiseADC()
}
}
}
} //For loop iterating through aux in lines
//Sanity checks to ensure none of the filter values are set to 255 (Which would be the default on a new arduino, but can prevent the sensor readings from going through correctly)
//Each sensor has it's own default value
if(configPage4.ADCFILTER_TPS == 255) { configPage4.ADCFILTER_TPS = 50; }
if(configPage4.ADCFILTER_CLT == 255) { configPage4.ADCFILTER_TPS = 180; }
if(configPage4.ADCFILTER_IAT == 255) { configPage4.ADCFILTER_TPS = 180; }
if(configPage4.ADCFILTER_O2 == 255) { configPage4.ADCFILTER_TPS = 100; }
if(configPage4.ADCFILTER_BAT == 255) { configPage4.ADCFILTER_TPS = 128; }
if(configPage4.ADCFILTER_MAP == 255) { configPage4.ADCFILTER_TPS = 20; }
if(configPage4.ADCFILTER_BARO == 255) { configPage4.ADCFILTER_TPS = 64; }
}
static inline void instanteneousMAPReading()
@ -254,6 +263,7 @@ void readTPS()
byte tempTPS = fastMap1023toX(analogRead(pinTPS), 255); //Get the current raw TPS ADC value and map it into a byte
#endif
currentStatus.tpsADC = ADC_FILTER(tempTPS, configPage4.ADCFILTER_TPS, currentStatus.tpsADC);
//currentStatus.tpsADC = ADC_FILTER(tempTPS, 128, currentStatus.tpsADC);
byte tempADC = currentStatus.tpsADC; //The tempADC value is used in order to allow TunerStudio to recover and redo the TPS calibration if this somehow gets corrupted
if(configPage2.tpsMax > configPage2.tpsMin)

View File

@ -867,6 +867,12 @@ void loop()
if ( ((mainLoopCount & 31) == 1) or (Serial.available() > SERIAL_BUFFER_THRESHOLD) )
{
if (Serial.available() > 0) { command(); }
else if(cmdPending == true)
{
//This is a special case just for the tooth and composite loggers
if (currentCommand == 'T') { command(); }
}
}
//if can or secondary serial interface is enabled then check for requests.
if (configPage9.enable_secondarySerial == 1) //secondary serial interface enabled

View File

@ -905,6 +905,9 @@ void initialiseTriggers()
//digitalWrite(pinTrigger, HIGH);
detachInterrupt(triggerInterrupt);
detachInterrupt(triggerInterrupt2);
//The default values for edges
primaryTriggerEdge = 0; //This should ALWAYS be changed below
secondaryTriggerEdge = 0; //This is optional and may not be changed below, depending on the decoder in use
//Set the trigger function based on the decoder in the config
switch (configPage4.TrigPattern)
@ -912,222 +915,300 @@ void initialiseTriggers()
case 0:
//Missing tooth decoder
triggerSetup_missingTooth();
//trigger = triggerPri_missingTooth;
//triggerSecondary = triggerSec_missingTooth;
triggerHandler = triggerPri_missingTooth;
triggerSecondaryHandler = triggerSec_missingTooth;
decoderHasSecondary = true;
getRPM = getRPM_missingTooth;
getCrankAngle = getCrankAngle_missingTooth;
triggerSetEndTeeth = triggerSetEndTeeth_missingTooth;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, triggerPri_missingTooth, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, triggerPri_missingTooth, FALLING); }
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
if(configPage4.TrigEdgeSec == 0) { secondaryTriggerEdge = RISING; }
else { secondaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
/*
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, triggerHandler, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, triggerHandler, FALLING); }
if(configPage4.TrigEdgeSec == 0) { attachInterrupt(triggerInterrupt2, triggerSec_missingTooth, RISING); }
else { attachInterrupt(triggerInterrupt2, triggerSec_missingTooth, FALLING); }
*/
break;
case 1:
// Basic distributor
triggerSetup_BasicDistributor();
trigger = triggerPri_BasicDistributor;
triggerHandler = triggerPri_BasicDistributor;
getRPM = getRPM_BasicDistributor;
getCrankAngle = getCrankAngle_BasicDistributor;
triggerSetEndTeeth = triggerSetEndTeeth_BasicDistributor;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
break;
case 2:
triggerSetup_DualWheel();
trigger = triggerPri_DualWheel;
triggerHandler = triggerPri_DualWheel;
triggerSecondaryHandler = triggerSec_DualWheel;
decoderHasSecondary = true;
getRPM = getRPM_DualWheel;
getCrankAngle = getCrankAngle_DualWheel;
triggerSetEndTeeth = triggerSetEndTeeth_DualWheel;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
if(configPage4.TrigEdgeSec == 0) { attachInterrupt(triggerInterrupt2, triggerSec_DualWheel, RISING); }
else { attachInterrupt(triggerInterrupt2, triggerSec_DualWheel, FALLING); }
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
if(configPage4.TrigEdgeSec == 0) { secondaryTriggerEdge = RISING; }
else { secondaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 3:
triggerSetup_GM7X();
trigger = triggerPri_GM7X;
triggerHandler = triggerPri_GM7X;
getRPM = getRPM_GM7X;
getCrankAngle = getCrankAngle_GM7X;
triggerSetEndTeeth = triggerSetEndTeeth_GM7X;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, triggerHandler, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, triggerHandler, FALLING); }
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
break;
case 4:
triggerSetup_4G63();
trigger = triggerPri_4G63;
triggerHandler = triggerPri_4G63;
triggerSecondaryHandler = triggerSec_4G63;
decoderHasSecondary = true;
getRPM = getRPM_4G63;
getCrankAngle = getCrankAngle_4G63;
triggerSetEndTeeth = triggerSetEndTeeth_4G63;
attachInterrupt(triggerInterrupt, trigger, CHANGE); // Primary trigger connects to
attachInterrupt(triggerInterrupt2, triggerSec_4G63, FALLING);
primaryTriggerEdge = CHANGE;
secondaryTriggerEdge = FALLING;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 5:
triggerSetup_24X();
trigger = triggerPri_24X;
triggerHandler = triggerPri_24X;
triggerSecondaryHandler = triggerSec_24X;
decoderHasSecondary = true;
getRPM = getRPM_24X;
getCrankAngle = getCrankAngle_24X;
triggerSetEndTeeth = triggerSetEndTeeth_24X;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); } // Primary trigger connects to
attachInterrupt(triggerInterrupt2, triggerSec_24X, CHANGE);
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = CHANGE; //Secondary is always on every change
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 6:
triggerSetup_Jeep2000();
trigger = triggerPri_Jeep2000;
triggerHandler = triggerPri_Jeep2000;
triggerSecondaryHandler = triggerSec_Jeep2000;
decoderHasSecondary = true;
getRPM = getRPM_Jeep2000;
getCrankAngle = getCrankAngle_Jeep2000;
triggerSetEndTeeth = triggerSetEndTeeth_Jeep2000;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); } // Primary trigger connects to
attachInterrupt(triggerInterrupt2, triggerSec_Jeep2000, CHANGE);
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = CHANGE;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 7:
triggerSetup_Audi135();
trigger = triggerPri_Audi135;
triggerHandler = triggerPri_Audi135;
triggerSecondaryHandler = triggerSec_Audi135;
decoderHasSecondary = true;
getRPM = getRPM_Audi135;
getCrankAngle = getCrankAngle_Audi135;
triggerSetEndTeeth = triggerSetEndTeeth_Audi135;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
attachInterrupt(triggerInterrupt2, triggerSec_Audi135, RISING);
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = RISING; //always rising for this trigger
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 8:
triggerSetup_HondaD17();
trigger = triggerPri_HondaD17;
triggerHandler = triggerPri_HondaD17;
triggerSecondaryHandler = triggerSec_HondaD17;
decoderHasSecondary = true;
getRPM = getRPM_HondaD17;
getCrankAngle = getCrankAngle_HondaD17;
triggerSetEndTeeth = triggerSetEndTeeth_HondaD17;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); } // Primary trigger connects to
attachInterrupt(triggerInterrupt2, triggerSec_HondaD17, CHANGE);
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = CHANGE;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 9:
triggerSetup_Miata9905();
trigger = triggerPri_Miata9905;
triggerHandler = triggerPri_Miata9905;
triggerSecondaryHandler = triggerSec_Miata9905;
decoderHasSecondary = true;
getRPM = getRPM_Miata9905;
getCrankAngle = getCrankAngle_Miata9905;
triggerSetEndTeeth = triggerSetEndTeeth_Miata9905;
//These may both need to change, not sure
// Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); }
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
if(configPage4.TrigEdgeSec == 0) { secondaryTriggerEdge = RISING; }
else { secondaryTriggerEdge = FALLING; }
if(configPage4.TrigEdgeSec == 0) { attachInterrupt(triggerInterrupt2, triggerSec_Miata9905, RISING); }
else { attachInterrupt(triggerInterrupt2, triggerSec_Miata9905, FALLING); }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 10:
triggerSetup_MazdaAU();
trigger = triggerPri_MazdaAU;
triggerHandler = triggerPri_MazdaAU;
triggerSecondaryHandler = triggerSec_MazdaAU;
decoderHasSecondary = true;
getRPM = getRPM_MazdaAU;
getCrankAngle = getCrankAngle_MazdaAU;
triggerSetEndTeeth = triggerSetEndTeeth_MazdaAU;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); } // Primary trigger connects to
attachInterrupt(triggerInterrupt2, triggerSec_MazdaAU, FALLING);
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = FALLING;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 11:
triggerSetup_non360();
trigger = triggerPri_DualWheel; //Is identical to the dual wheel decoder, so that is used. Same goes for the secondary below
triggerHandler = triggerPri_DualWheel; //Is identical to the dual wheel decoder, so that is used. Same goes for the secondary below
triggerSecondaryHandler = triggerSec_DualWheel; //Note the use of the Dual Wheel trigger function here. No point in having the same code in twice.
decoderHasSecondary = true;
getRPM = getRPM_non360;
getCrankAngle = getCrankAngle_non360;
triggerSetEndTeeth = triggerSetEndTeeth_non360;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
attachInterrupt(triggerInterrupt2, triggerSec_DualWheel, FALLING); //Note the use of the Dual Wheel trigger function here. No point in having the same code in twice.
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = FALLING;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 12:
triggerSetup_Nissan360();
trigger = triggerPri_Nissan360;
getRPM = getRPM_Nissan360;
getCrankAngle = getCrankAngle_Nissan360;
triggerSetEndTeeth = triggerSetEndTeeth_Nissan360;
triggerSetup_Nissan360();
triggerHandler = triggerPri_Nissan360;
triggerSecondaryHandler = triggerSec_Nissan360;
decoderHasSecondary = true;
getRPM = getRPM_Nissan360;
getCrankAngle = getCrankAngle_Nissan360;
triggerSetEndTeeth = triggerSetEndTeeth_Nissan360;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
attachInterrupt(triggerInterrupt2, triggerSec_Nissan360, CHANGE);
break;
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = CHANGE;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 13:
triggerSetup_Subaru67();
trigger = triggerPri_Subaru67;
getRPM = getRPM_Subaru67;
getCrankAngle = getCrankAngle_Subaru67;
triggerSetEndTeeth = triggerSetEndTeeth_Subaru67;
triggerSetup_Subaru67();
triggerHandler = triggerPri_Subaru67;
triggerSecondaryHandler = triggerSec_Subaru67;
decoderHasSecondary = true;
getRPM = getRPM_Subaru67;
getCrankAngle = getCrankAngle_Subaru67;
triggerSetEndTeeth = triggerSetEndTeeth_Subaru67;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
attachInterrupt(triggerInterrupt2, triggerSec_Subaru67, FALLING);
break;
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
secondaryTriggerEdge = FALLING;
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
case 14:
triggerSetup_Daihatsu();
trigger = triggerPri_Daihatsu;
getRPM = getRPM_Daihatsu;
getCrankAngle = getCrankAngle_Daihatsu;
triggerSetEndTeeth = triggerSetEndTeeth_Daihatsu;
triggerSetup_Daihatsu();
triggerHandler = triggerPri_Daihatsu;
getRPM = getRPM_Daihatsu;
getCrankAngle = getCrankAngle_Daihatsu;
triggerSetEndTeeth = triggerSetEndTeeth_Daihatsu;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
//No secondary input required for this pattern
break;
//No secondary input required for this pattern
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
break;
case 15:
triggerSetup_Harley();
trigger = triggerPri_Harley;
//triggerSecondary = triggerSec_Harley;
getRPM = getRPM_Harley;
getCrankAngle = getCrankAngle_Harley;
triggerSetEndTeeth = triggerSetEndTeeth_Harley;
attachInterrupt(triggerInterrupt, trigger, RISING);
// attachInterrupt(triggerInterrupt2, triggerSec_Harley, FALLING);
break;
triggerSetup_Harley();
triggerHandler = triggerPri_Harley;
//triggerSecondaryHandler = triggerSec_Harley;
getRPM = getRPM_Harley;
getCrankAngle = getCrankAngle_Harley;
triggerSetEndTeeth = triggerSetEndTeeth_Harley;
primaryTriggerEdge = RISING; //Always rising
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
break;
case 16:
//36-2-2-2
triggerSetup_ThirtySixMinus222();
trigger = triggerPri_ThirtySixMinus222;
triggerSecondary = triggerSec_ThirtySixMinus222;
getRPM = getRPM_missingTooth; //This uses the same function as the missing tooth decoder, so no need to duplicate code
getCrankAngle = getCrankAngle_missingTooth; //This uses the same function as the missing tooth decoder, so no need to duplicate code
triggerSetEndTeeth = triggerSetEndTeeth_ThirtySixMinus222;
//36-2-2-2
triggerSetup_ThirtySixMinus222();
triggerHandler = triggerPri_ThirtySixMinus222;
triggerSecondaryHandler = triggerSec_ThirtySixMinus222;
decoderHasSecondary = true;
getRPM = getRPM_missingTooth; //This uses the same function as the missing tooth decoder, so no need to duplicate code
getCrankAngle = getCrankAngle_missingTooth; //This uses the same function as the missing tooth decoder, so no need to duplicate code
triggerSetEndTeeth = triggerSetEndTeeth_ThirtySixMinus222;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
if(configPage4.TrigEdgeSec == 0) { attachInterrupt(triggerInterrupt2, triggerSecondary, RISING); }
else { attachInterrupt(triggerInterrupt2, triggerSecondary, FALLING); }
break;
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
if(configPage4.TrigEdgeSec == 0) { secondaryTriggerEdge = RISING; }
else { secondaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
default:
trigger = triggerPri_missingTooth;
triggerHandler = triggerPri_missingTooth;
getRPM = getRPM_missingTooth;
getCrankAngle = getCrankAngle_missingTooth;
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, trigger, FALLING); }
if(configPage4.TrigEdge == 0) { attachInterrupt(triggerInterrupt, triggerHandler, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { attachInterrupt(triggerInterrupt, triggerHandler, FALLING); }
break;
}
}