Initial proposed clang-format
This commit is contained in:
parent
a92ca8d191
commit
0e49e268f4
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: "true"
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: "false"
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAfterAttributes: Never
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 300
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: ^"(llvm|llvm-c|clang|clang-c)/
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: ^(<|"(gtest|gmock|isl|json)/)
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: .*
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: (Test)?$
|
||||
IncludeIsMainSourceRegex: ""
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: true
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
LambdaBodyIndentation: Signature
|
||||
Language: Cpp
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ""
|
||||
MacroBlockEnd: ""
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PPIndentWidth: -1
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: false
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: "false"
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: "true"
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: Never
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: "false"
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: "false"
|
||||
SpacesInCStyleCastParentheses: "false"
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: "2"
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
|
@ -2,52 +2,52 @@
|
|||
#include BOARD_H
|
||||
|
||||
#ifdef SD_LOGGING
|
||||
#include <SPI.h>
|
||||
#ifdef __SD_H__
|
||||
#include <SD.h>
|
||||
#else
|
||||
#include "SdFat.h"
|
||||
#endif
|
||||
#include "SD_logger.h"
|
||||
#include "logger.h"
|
||||
#include "rtc_common.h"
|
||||
#include "maths.h"
|
||||
#include <SPI.h>
|
||||
#ifdef __SD_H__
|
||||
#include <SD.h>
|
||||
#else
|
||||
#include "SdFat.h"
|
||||
#endif
|
||||
#include "SD_logger.h"
|
||||
#include "logger.h"
|
||||
#include "rtc_common.h"
|
||||
#include "maths.h"
|
||||
|
||||
SdExFat sd;
|
||||
ExFile logFile;
|
||||
SdExFat sd;
|
||||
ExFile logFile;
|
||||
RingBuf<ExFile, RING_BUF_CAPACITY> rb;
|
||||
uint8_t SD_status = SD_STATUS_OFF;
|
||||
uint16_t currentLogFileNumber;
|
||||
bool manualLogActive = false;
|
||||
uint32_t logStartTime = 0; //In ms
|
||||
uint8_t SD_status = SD_STATUS_OFF;
|
||||
uint16_t currentLogFileNumber;
|
||||
bool manualLogActive = false;
|
||||
uint32_t logStartTime = 0; // In ms
|
||||
|
||||
void initSD()
|
||||
{
|
||||
//Set default state to ready. If any stage of the init fails, this will be changed
|
||||
SD_status = SD_STATUS_READY;
|
||||
// Set default state to ready. If any stage of the init fails, this will be changed
|
||||
SD_status = SD_STATUS_READY;
|
||||
|
||||
//Set the RTC callback. This is used to set the correct timestamp on file creation and sync operations
|
||||
// Set the RTC callback. This is used to set the correct timestamp on file creation and sync operations
|
||||
FsDateTime::setCallback(dateTime);
|
||||
|
||||
// Initialise the SD.
|
||||
if (!sd.begin(SD_CONFIG))
|
||||
if(!sd.begin(SD_CONFIG))
|
||||
{
|
||||
//sd.initErrorHalt(&Serial);
|
||||
//if (sdErrorCode() == SD_CARD_ERROR_CMD0) { SD_status = SD_STATUS_ERROR_NO_CARD;
|
||||
// sd.initErrorHalt(&Serial);
|
||||
// if (sdErrorCode() == SD_CARD_ERROR_CMD0) { SD_status = SD_STATUS_ERROR_NO_CARD;
|
||||
SD_status = SD_STATUS_ERROR_NO_CARD;
|
||||
}
|
||||
|
||||
//Set the TunerStudio status variable
|
||||
|
||||
// Set the TunerStudio status variable
|
||||
setTS_SD_status();
|
||||
}
|
||||
|
||||
bool createLogFile()
|
||||
{
|
||||
//TunerStudio only supports 8.3 filename format.
|
||||
char filenameBuffer[13]; //8 + 1 + 3 + 1
|
||||
// TunerStudio only supports 8.3 filename format.
|
||||
char filenameBuffer[13]; // 8 + 1 + 3 + 1
|
||||
bool returnValue = false;
|
||||
|
||||
//Saving this in case we ever go back to the datestamped filename
|
||||
// Saving this in case we ever go back to the datestamped filename
|
||||
/*
|
||||
//Filename format is: YYYY-MM-DD_HH.MM.SS.csv
|
||||
char intBuffer[5];
|
||||
|
@ -71,17 +71,14 @@ bool createLogFile()
|
|||
strcat(filenameBuffer, ".csv");
|
||||
*/
|
||||
|
||||
//Lookup the next available file number
|
||||
// Lookup the next available file number
|
||||
currentLogFileNumber = getNextSDLogFileNumber();
|
||||
|
||||
//Create the filename
|
||||
// Create the filename
|
||||
sprintf(filenameBuffer, "%s%04d.%s", LOG_FILE_PREFIX, currentLogFileNumber, LOG_FILE_EXTENSION);
|
||||
|
||||
logFile.close();
|
||||
if (logFile.open(filenameBuffer, O_RDWR | O_CREAT | O_TRUNC))
|
||||
{
|
||||
returnValue = true;
|
||||
}
|
||||
if(logFile.open(filenameBuffer, O_RDWR | O_CREAT | O_TRUNC)) { returnValue = true; }
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
@ -89,11 +86,11 @@ bool createLogFile()
|
|||
uint16_t getNextSDLogFileNumber()
|
||||
{
|
||||
uint16_t nextFileNumber = 1;
|
||||
char filenameBuffer[13]; //8 + 1 + 3 + 1
|
||||
char filenameBuffer[13]; // 8 + 1 + 3 + 1
|
||||
sprintf(filenameBuffer, "%s%04d.%s", LOG_FILE_PREFIX, nextFileNumber, LOG_FILE_EXTENSION);
|
||||
|
||||
//Lookup the next available file number
|
||||
while( (nextFileNumber < MAX_LOG_FILES) && (sd.exists(filenameBuffer)) )
|
||||
// Lookup the next available file number
|
||||
while((nextFileNumber < MAX_LOG_FILES) && (sd.exists(filenameBuffer)))
|
||||
{
|
||||
nextFileNumber++;
|
||||
sprintf(filenameBuffer, "%s%04d.%s", LOG_FILE_PREFIX, nextFileNumber, LOG_FILE_EXTENSION);
|
||||
|
@ -102,57 +99,57 @@ uint16_t getNextSDLogFileNumber()
|
|||
return nextFileNumber;
|
||||
}
|
||||
|
||||
bool getSDLogFileDetails(uint8_t* buffer, uint16_t logNumber)
|
||||
bool getSDLogFileDetails(uint8_t *buffer, uint16_t logNumber)
|
||||
{
|
||||
bool fileFound = false;
|
||||
|
||||
if(logFile.isOpen()) { endSDLogging(); }
|
||||
|
||||
char filenameBuffer[13]; //8 + 1 + 3 + 1
|
||||
char filenameBuffer[13]; // 8 + 1 + 3 + 1
|
||||
sprintf(filenameBuffer, "%s%04d.%s", LOG_FILE_PREFIX, logNumber, LOG_FILE_EXTENSION);
|
||||
|
||||
|
||||
if(sd.exists(filenameBuffer))
|
||||
{
|
||||
fileFound = true;
|
||||
|
||||
logFile = sd.open(filenameBuffer, O_RDONLY);
|
||||
//Copy the filename into the buffer. Note we do not copy the termination character or the fullstop
|
||||
for(byte i=0; i<12; i++)
|
||||
// Copy the filename into the buffer. Note we do not copy the termination character or the fullstop
|
||||
for(byte i = 0; i < 12; i++)
|
||||
{
|
||||
//We don't copy the fullstop to the buffer
|
||||
//As TS requires 8.3 filenames, it's always in the same spot
|
||||
if(i < 8) { buffer[i] = filenameBuffer[i]; } //Everything before the fullstop
|
||||
else if(i > 8) { buffer[i-1] = filenameBuffer[i]; } //Everything after the fullstop
|
||||
// We don't copy the fullstop to the buffer
|
||||
// As TS requires 8.3 filenames, it's always in the same spot
|
||||
if(i < 8) { buffer[i] = filenameBuffer[i]; } // Everything before the fullstop
|
||||
else if(i > 8) { buffer[i - 1] = filenameBuffer[i]; } // Everything after the fullstop
|
||||
}
|
||||
|
||||
//Maintenance check, truncate the file. This will usually do nothing, but in the case where a prior log was interrupted, this will truncate the file
|
||||
//Due to overhead, only bother doing this if the engine isn't running
|
||||
// Maintenance check, truncate the file. This will usually do nothing, but in the case where a prior log was interrupted, this will truncate the file
|
||||
// Due to overhead, only bother doing this if the engine isn't running
|
||||
if(currentStatus.RPM == 0) { logFile.truncate(); }
|
||||
|
||||
//Is File or ignore
|
||||
// Is File or ignore
|
||||
buffer[11] = 1;
|
||||
|
||||
//No idea
|
||||
// No idea
|
||||
buffer[12] = 0;
|
||||
|
||||
//5 bytes for FAT creation date/time
|
||||
// 5 bytes for FAT creation date/time
|
||||
uint16_t pDate = 0;
|
||||
uint16_t pTime = 0;
|
||||
logFile.getCreateDateTime(&pDate, &pTime);
|
||||
buffer[13] = 0; //Not sure what this byte is for yet
|
||||
buffer[13] = 0; // Not sure what this byte is for yet
|
||||
buffer[14] = lowByte(pTime);
|
||||
buffer[15] = highByte(pTime);
|
||||
buffer[16] = lowByte(pDate);
|
||||
buffer[17] = highByte(pDate);
|
||||
|
||||
//Sector number (4 bytes) - This byte order might be backwards
|
||||
// Sector number (4 bytes) - This byte order might be backwards
|
||||
uint32_t sector = logFile.firstSector();
|
||||
buffer[18] = ((sector) & 255);
|
||||
buffer[19] = ((sector >> 8) & 255);
|
||||
buffer[20] = ((sector >> 16) & 255);
|
||||
buffer[21] = ((sector >> 24) & 255);
|
||||
buffer[18] = ((sector)&255);
|
||||
buffer[19] = ((sector >> 8) & 255);
|
||||
buffer[20] = ((sector >> 16) & 255);
|
||||
buffer[21] = ((sector >> 24) & 255);
|
||||
|
||||
//Unsure on the below 6 bytes, possibly last accessed or modified date/time?
|
||||
// Unsure on the below 6 bytes, possibly last accessed or modified date/time?
|
||||
buffer[22] = 0;
|
||||
buffer[23] = 0;
|
||||
buffer[24] = 0;
|
||||
|
@ -160,22 +157,18 @@ bool getSDLogFileDetails(uint8_t* buffer, uint16_t logNumber)
|
|||
buffer[26] = 0;
|
||||
buffer[27] = 0;
|
||||
|
||||
//File size (4 bytes). Little endian
|
||||
// File size (4 bytes). Little endian
|
||||
uint32_t size = logFile.fileSize();
|
||||
buffer[28] = ((size) & 255);
|
||||
buffer[29] = ((size >> 8) & 255);
|
||||
buffer[30] = ((size >> 16) & 255);
|
||||
buffer[31] = ((size >> 24) & 255);
|
||||
|
||||
buffer[28] = ((size)&255);
|
||||
buffer[29] = ((size >> 8) & 255);
|
||||
buffer[30] = ((size >> 16) & 255);
|
||||
buffer[31] = ((size >> 24) & 255);
|
||||
}
|
||||
|
||||
return fileFound;
|
||||
}
|
||||
|
||||
void readSDSectors(uint8_t* buffer, uint32_t sectorNumber, uint16_t sectorCount)
|
||||
{
|
||||
sd.card()->readSectors(sectorNumber, buffer, sectorCount);
|
||||
}
|
||||
void readSDSectors(uint8_t *buffer, uint32_t sectorNumber, uint16_t sectorCount) { sd.card()->readSectors(sectorNumber, buffer, sectorCount); }
|
||||
|
||||
// Forward declare
|
||||
void writeSDLogHeader();
|
||||
|
@ -184,31 +177,31 @@ void beginSDLogging()
|
|||
{
|
||||
if(SD_status == SD_STATUS_READY)
|
||||
{
|
||||
SD_status = SD_STATUS_ACTIVE; //Set the status as being active so that entries will begin to be written. This will be updated below if there is an error
|
||||
SD_status = SD_STATUS_ACTIVE; // Set the status as being active so that entries will begin to be written. This will be updated below if there is an error
|
||||
|
||||
// Open or create file - truncate existing file.
|
||||
if (!createLogFile())
|
||||
if(!createLogFile())
|
||||
{
|
||||
SD_status = SD_STATUS_ERROR_NO_WRITE;
|
||||
setTS_SD_status();
|
||||
return;
|
||||
}
|
||||
|
||||
//Perform pre-allocation on card. This dramatically improves write speed
|
||||
if (!logFile.preAllocate(SD_LOG_FILE_SIZE))
|
||||
// Perform pre-allocation on card. This dramatically improves write speed
|
||||
if(!logFile.preAllocate(SD_LOG_FILE_SIZE))
|
||||
{
|
||||
SD_status = SD_STATUS_ERROR_NO_SPACE;
|
||||
setTS_SD_status();
|
||||
return;
|
||||
}
|
||||
|
||||
//initialise the RingBuf.
|
||||
// initialise the RingBuf.
|
||||
rb.begin(&logFile);
|
||||
|
||||
//Write a header row
|
||||
// Write a header row
|
||||
writeSDLogHeader();
|
||||
|
||||
//Note the start time
|
||||
// Note the start time
|
||||
logStartTime = millis();
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +215,7 @@ void endSDLogging()
|
|||
logFile.truncate();
|
||||
logFile.rewind();
|
||||
logFile.close();
|
||||
logFile.sync(); //This is required to update the sd object. Without this any subsequent logfiles will overwrite this one
|
||||
logFile.sync(); // This is required to update the sd object. Without this any subsequent logfiles will overwrite this one
|
||||
|
||||
SD_status = SD_STATUS_READY;
|
||||
setTS_SD_status();
|
||||
|
@ -235,59 +228,56 @@ void checkForSDStop();
|
|||
|
||||
void writeSDLogEntry()
|
||||
{
|
||||
//Check if we're already running a log
|
||||
// Check if we're already running a log
|
||||
if(SD_status == SD_STATUS_READY)
|
||||
{
|
||||
//Log not currently running, check if it should be
|
||||
// Log not currently running, check if it should be
|
||||
checkForSDStart();
|
||||
}
|
||||
|
||||
if(SD_status == SD_STATUS_ACTIVE)
|
||||
{
|
||||
//Write the timestamp (x.yyy seconds format)
|
||||
uint32_t duration = millis() - logStartTime;
|
||||
uint32_t seconds = duration / 1000;
|
||||
// Write the timestamp (x.yyy seconds format)
|
||||
uint32_t duration = millis() - logStartTime;
|
||||
uint32_t seconds = duration / 1000;
|
||||
uint32_t milliseconds = duration % 1000;
|
||||
rb.print(seconds);
|
||||
rb.print('.');
|
||||
if (milliseconds < 100) { rb.print("0"); }
|
||||
if (milliseconds < 10) { rb.print("0"); }
|
||||
if(milliseconds < 100) { rb.print("0"); }
|
||||
if(milliseconds < 10) { rb.print("0"); }
|
||||
rb.print(milliseconds);
|
||||
rb.print(',');
|
||||
|
||||
//Write the line to the ring buffer
|
||||
for(byte x=0; x<SD_LOG_NUM_FIELDS; x++)
|
||||
// Write the line to the ring buffer
|
||||
for(byte x = 0; x < SD_LOG_NUM_FIELDS; x++)
|
||||
{
|
||||
#if FPU_MAX_SIZE >= 32
|
||||
float entryValue = getReadableFloatLogEntry(x);
|
||||
if(IS_INTEGER(entryValue)) { rb.print((uint16_t)entryValue); }
|
||||
else { rb.print(entryValue); }
|
||||
#else
|
||||
rb.print(getReadableLogEntry(x));
|
||||
#endif
|
||||
#if FPU_MAX_SIZE >= 32
|
||||
float entryValue = getReadableFloatLogEntry(x);
|
||||
if(IS_INTEGER(entryValue)) { rb.print((uint16_t)entryValue); }
|
||||
else { rb.print(entryValue); }
|
||||
#else
|
||||
rb.print(getReadableLogEntry(x));
|
||||
#endif
|
||||
if(x < (SD_LOG_NUM_FIELDS - 1)) { rb.print(","); }
|
||||
}
|
||||
rb.println("");
|
||||
|
||||
//Check if write to SD from ringbuffer is needed
|
||||
//We write to SD when there is more than 1 sector worth of data in the ringbuffer and there is not already a write being performed
|
||||
if( (rb.bytesUsed() >= SD_SECTOR_SIZE) && !logFile.isBusy() )
|
||||
// Check if write to SD from ringbuffer is needed
|
||||
// We write to SD when there is more than 1 sector worth of data in the ringbuffer and there is not already a write being performed
|
||||
if((rb.bytesUsed() >= SD_SECTOR_SIZE) && !logFile.isBusy())
|
||||
{
|
||||
uint16_t bytesWritten = rb.writeOut(SD_SECTOR_SIZE);
|
||||
//Make sure that the entire sector was written successfully
|
||||
if (SD_SECTOR_SIZE != bytesWritten)
|
||||
{
|
||||
SD_status = SD_STATUS_ERROR_WRITE_FAIL;
|
||||
}
|
||||
uint16_t bytesWritten = rb.writeOut(SD_SECTOR_SIZE);
|
||||
// Make sure that the entire sector was written successfully
|
||||
if(SD_SECTOR_SIZE != bytesWritten) { SD_status = SD_STATUS_ERROR_WRITE_FAIL; }
|
||||
}
|
||||
|
||||
//Check whether we should stop logging
|
||||
// Check whether we should stop logging
|
||||
checkForSDStop();
|
||||
|
||||
//Check whether the file is full (IE When there is not enough room to write 1 more sector)
|
||||
if( (logFile.dataLength() - logFile.curPosition()) < SD_SECTOR_SIZE)
|
||||
// Check whether the file is full (IE When there is not enough room to write 1 more sector)
|
||||
if((logFile.dataLength() - logFile.curPosition()) < SD_SECTOR_SIZE)
|
||||
{
|
||||
//Provided the conditions for logging are still met, a new file will be created the next time writeSDLogEntry is called
|
||||
// Provided the conditions for logging are still met, a new file will be created the next time writeSDLogEntry is called
|
||||
endSDLogging();
|
||||
beginSDLogging();
|
||||
}
|
||||
|
@ -297,172 +287,146 @@ void writeSDLogEntry()
|
|||
|
||||
void writeSDLogHeader()
|
||||
{
|
||||
//Write header for Time field
|
||||
// Write header for Time field
|
||||
rb.print("Time,");
|
||||
|
||||
//WRite remaining fields based on log definitions
|
||||
for(byte x=0; x<SD_LOG_NUM_FIELDS; x++)
|
||||
// WRite remaining fields based on log definitions
|
||||
for(byte x = 0; x < SD_LOG_NUM_FIELDS; x++)
|
||||
{
|
||||
#ifdef CORE_AVR
|
||||
//This will probably never be used
|
||||
char buffer[30];
|
||||
strcpy_P(buffer, (char *)pgm_read_word(&(header_table[x])));
|
||||
rb.print(buffer);
|
||||
#else
|
||||
rb.print(header_table[x]);
|
||||
#endif
|
||||
#ifdef CORE_AVR
|
||||
// This will probably never be used
|
||||
char buffer[30];
|
||||
strcpy_P(buffer, (char *)pgm_read_word(&(header_table[x])));
|
||||
rb.print(buffer);
|
||||
#else
|
||||
rb.print(header_table[x]);
|
||||
#endif
|
||||
if(x < (SD_LOG_NUM_FIELDS - 1)) { rb.print(","); }
|
||||
}
|
||||
rb.println("");
|
||||
}
|
||||
|
||||
//Sets the status variable for TunerStudio
|
||||
// Sets the status variable for TunerStudio
|
||||
void setTS_SD_status()
|
||||
{
|
||||
if( SD_status == SD_STATUS_ERROR_NO_CARD ) { BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_PRESENT); } // CARD is not present
|
||||
else { BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_PRESENT); } // CARD present
|
||||
if(SD_status == SD_STATUS_ERROR_NO_CARD) { BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_PRESENT); } // CARD is not present
|
||||
else { BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_PRESENT); } // CARD present
|
||||
|
||||
BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_TYPE); // CARD is SDHC
|
||||
|
||||
|
||||
BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_READY); // CARD is ready
|
||||
|
||||
if( SD_status == SD_STATUS_ACTIVE ) { BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_LOGGING); }// CARD is logging
|
||||
else { BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_LOGGING); }// CARD is not logging
|
||||
|
||||
if( (SD_status >= SD_STATUS_ERROR_NO_FS) ) { BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_ERROR); }// CARD has an error
|
||||
else { BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_ERROR); }// CARD has no error
|
||||
if(SD_status == SD_STATUS_ACTIVE) { BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_LOGGING); } // CARD is logging
|
||||
else { BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_LOGGING); } // CARD is not logging
|
||||
|
||||
BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_FS); // CARD has a FAT32 filesystem (Though this will be exFAT)
|
||||
BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_UNUSED); //Unused bit is always 0
|
||||
if((SD_status >= SD_STATUS_ERROR_NO_FS)) { BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_ERROR); } // CARD has an error
|
||||
else { BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_ERROR); } // CARD has no error
|
||||
|
||||
BIT_SET(currentStatus.TS_SD_Status, SD_STATUS_CARD_FS); // CARD has a FAT32 filesystem (Though this will be exFAT)
|
||||
BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_UNUSED); // Unused bit is always 0
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Checks whether the SD logging should be started based on the logging trigger conditions
|
||||
*/
|
||||
void checkForSDStart()
|
||||
{
|
||||
//Logging can only start if we're in the ready state
|
||||
//We must check the SD_status each time to prevent trying to init a new log file multiple times
|
||||
// Logging can only start if we're in the ready state
|
||||
// We must check the SD_status each time to prevent trying to init a new log file multiple times
|
||||
|
||||
if(configPage13.onboard_log_file_style > 0)
|
||||
{
|
||||
//Check for enable at boot
|
||||
if( (configPage13.onboard_log_trigger_boot) && (SD_status == SD_STATUS_READY) )
|
||||
// Check for enable at boot
|
||||
if((configPage13.onboard_log_trigger_boot) && (SD_status == SD_STATUS_READY))
|
||||
{
|
||||
//Check that we're not already finished the logging
|
||||
// Check that we're not already finished the logging
|
||||
if((millis() / 1000) <= configPage13.onboard_log_tr1_duration)
|
||||
{
|
||||
beginSDLogging(); //Setup the log file, preallocation, header row
|
||||
}
|
||||
}
|
||||
|
||||
//Check for RPM based Enable
|
||||
if( (configPage13.onboard_log_trigger_RPM) && (SD_status == SD_STATUS_READY) )
|
||||
{
|
||||
if( (currentStatus.RPMdiv100 >= configPage13.onboard_log_tr2_thr_on) && (currentStatus.RPMdiv100 <= configPage13.onboard_log_tr2_thr_off) ) //Need to check both on and off conditions to prevent logging starting and stopping continually
|
||||
{
|
||||
beginSDLogging(); //Setup the log file, preallocation, header row
|
||||
beginSDLogging(); // Setup the log file, preallocation, header row
|
||||
}
|
||||
}
|
||||
|
||||
//Check for engine protection based enable
|
||||
if((configPage13.onboard_log_trigger_prot) && (SD_status == SD_STATUS_READY) )
|
||||
// Check for RPM based Enable
|
||||
if((configPage13.onboard_log_trigger_RPM) && (SD_status == SD_STATUS_READY))
|
||||
{
|
||||
if((currentStatus.RPMdiv100 >= configPage13.onboard_log_tr2_thr_on) && (currentStatus.RPMdiv100 <= configPage13.onboard_log_tr2_thr_off)) // Need to check both on and off conditions to prevent logging starting and stopping continually
|
||||
{
|
||||
beginSDLogging(); // Setup the log file, preallocation, header row
|
||||
}
|
||||
}
|
||||
|
||||
// Check for engine protection based enable
|
||||
if((configPage13.onboard_log_trigger_prot) && (SD_status == SD_STATUS_READY))
|
||||
{
|
||||
if(currentStatus.engineProtectStatus > 0)
|
||||
{
|
||||
beginSDLogging(); //Setup the log file, preallocation, header row
|
||||
beginSDLogging(); // Setup the log file, preallocation, header row
|
||||
}
|
||||
}
|
||||
|
||||
if( (configPage13.onboard_log_trigger_Vbat) && (SD_status == SD_STATUS_READY) )
|
||||
{
|
||||
if((configPage13.onboard_log_trigger_Vbat) && (SD_status == SD_STATUS_READY)) {}
|
||||
|
||||
}
|
||||
|
||||
if((configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY) )
|
||||
if((configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY))
|
||||
{
|
||||
if(digitalRead(pinSDEnable) == LOW)
|
||||
{
|
||||
beginSDLogging(); //Setup the log file, preallocation, header row
|
||||
beginSDLogging(); // Setup the log file, preallocation, header row
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Checks whether the SD logging should be stopped, based on the logging trigger conditions
|
||||
*/
|
||||
void checkForSDStop()
|
||||
{
|
||||
//Check the various conditions to see if we should stop logging
|
||||
// Check the various conditions to see if we should stop logging
|
||||
bool log_boot = false;
|
||||
bool log_RPM = false;
|
||||
bool log_RPM = false;
|
||||
bool log_prot = false;
|
||||
bool log_Vbat = false;
|
||||
bool log_Epin = false;
|
||||
|
||||
//Logging only needs to be stopped if already active
|
||||
// Logging only needs to be stopped if already active
|
||||
if(SD_status == SD_STATUS_ACTIVE)
|
||||
{
|
||||
//Check for enable at boot
|
||||
// Check for enable at boot
|
||||
if(configPage13.onboard_log_trigger_boot)
|
||||
{
|
||||
//Check if we're past the logging duration
|
||||
if((millis() / 1000) <= configPage13.onboard_log_tr1_duration)
|
||||
{
|
||||
log_boot = true;
|
||||
}
|
||||
// Check if we're past the logging duration
|
||||
if((millis() / 1000) <= configPage13.onboard_log_tr1_duration) { log_boot = true; }
|
||||
}
|
||||
if(configPage13.onboard_log_trigger_RPM)
|
||||
{
|
||||
if( (currentStatus.RPMdiv100 >= configPage13.onboard_log_tr2_thr_on) && (currentStatus.RPMdiv100 <= configPage13.onboard_log_tr2_thr_off) )
|
||||
{
|
||||
log_RPM = true;
|
||||
}
|
||||
if((currentStatus.RPMdiv100 >= configPage13.onboard_log_tr2_thr_on) && (currentStatus.RPMdiv100 <= configPage13.onboard_log_tr2_thr_off)) { log_RPM = true; }
|
||||
}
|
||||
if(configPage13.onboard_log_trigger_prot)
|
||||
{
|
||||
if(currentStatus.engineProtectStatus > 0)
|
||||
{
|
||||
log_prot = true;
|
||||
}
|
||||
if(currentStatus.engineProtectStatus > 0) { log_prot = true; }
|
||||
}
|
||||
if(configPage13.onboard_log_trigger_Vbat)
|
||||
{
|
||||
if(configPage13.onboard_log_trigger_Vbat) {}
|
||||
|
||||
}
|
||||
|
||||
//External Pin
|
||||
// External Pin
|
||||
if(configPage13.onboard_log_trigger_Epin)
|
||||
{
|
||||
if(digitalRead(pinSDEnable) == LOW)
|
||||
{
|
||||
log_Epin = true;
|
||||
}
|
||||
if(digitalRead(pinSDEnable) == LOW) { log_Epin = true; }
|
||||
}
|
||||
|
||||
//Check all conditions to see if we should stop logging
|
||||
if( (log_boot == false) && (log_RPM == false) && (log_prot == false) && (log_Vbat == false) && (log_Epin == false) && (manualLogActive == false) )
|
||||
{
|
||||
endSDLogging();
|
||||
}
|
||||
//ALso check whether logging has been disabled entirely
|
||||
// Check all conditions to see if we should stop logging
|
||||
if((log_boot == false) && (log_RPM == false) && (log_prot == false) && (log_Vbat == false) && (log_Epin == false) && (manualLogActive == false)) { endSDLogging(); }
|
||||
// ALso check whether logging has been disabled entirely
|
||||
if(configPage13.onboard_log_file_style == 0) { endSDLogging(); }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void syncSDLog()
|
||||
{
|
||||
if( (SD_status == SD_STATUS_ACTIVE) && (!logFile.isBusy()) && (!sd.isBusy()) )
|
||||
{
|
||||
logFile.sync();
|
||||
}
|
||||
{
|
||||
if((SD_status == SD_STATUS_ACTIVE) && (!logFile.isBusy()) && (!sd.isBusy())) { logFile.sync(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Will perform a complete format of the SD card to ExFAT.
|
||||
/**
|
||||
* Will perform a complete format of the SD card to ExFAT.
|
||||
* This will delete all files and create a new empty file system.
|
||||
* The SD status will be set to busy when this happens to prevent any other operations
|
||||
*/
|
||||
|
@ -470,19 +434,16 @@ void formatExFat()
|
|||
{
|
||||
bool result = false;
|
||||
|
||||
//Set the SD status to busy
|
||||
// Set the SD status to busy
|
||||
BIT_CLEAR(currentStatus.TS_SD_Status, SD_STATUS_CARD_READY);
|
||||
|
||||
logFile.close();
|
||||
|
||||
if (sd.cardBegin(SD_CONFIG))
|
||||
if(sd.cardBegin(SD_CONFIG))
|
||||
{
|
||||
if(sd.format())
|
||||
if(sd.format())
|
||||
{
|
||||
if (sd.volumeBegin())
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
if(sd.volumeBegin()) { result = true; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,13 +453,13 @@ void formatExFat()
|
|||
|
||||
/**
|
||||
* @brief Deletes a log file from the SD card
|
||||
*
|
||||
*
|
||||
* Log files all have the same name with a 4 digit number at the end (Eg SPD_0001.csv). TS sends the 4 digits as ASCII characters and they are combined here with the logfile prefix
|
||||
*
|
||||
* @param log1
|
||||
* @param log2
|
||||
* @param log3
|
||||
* @param log4
|
||||
*
|
||||
* @param log1
|
||||
* @param log2
|
||||
* @param log3
|
||||
* @param log4
|
||||
*/
|
||||
void deleteLogFile(char log1, char log2, char log3, char log4)
|
||||
{
|
||||
|
@ -510,31 +471,26 @@ void deleteLogFile(char log1, char log2, char log3, char log4)
|
|||
logFileName[7] = log4;
|
||||
logFileName[8] = '.';
|
||||
strcpy(logFileName + 9, LOG_FILE_EXTENSION);
|
||||
//logFileName[8] = '\0';
|
||||
// logFileName[8] = '\0';
|
||||
|
||||
if(sd.exists(logFileName))
|
||||
{
|
||||
sd.remove(logFileName);
|
||||
}
|
||||
if(sd.exists(logFileName)) { sd.remove(logFileName); }
|
||||
}
|
||||
|
||||
// Call back for file timestamps. Only called for file create and sync().
|
||||
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {
|
||||
|
||||
void dateTime(uint16_t *date, uint16_t *time, uint8_t *ms10)
|
||||
{
|
||||
|
||||
// Return date using FS_DATE macro to format fields.
|
||||
//*date = FS_DATE(year(), month(), day());
|
||||
*date = FS_DATE(rtc_getYear(), rtc_getMonth(), rtc_getDay());
|
||||
|
||||
// Return time using FS_TIME macro to format fields.
|
||||
*time = FS_TIME(rtc_getHour(), rtc_getMinute(), rtc_getSecond());
|
||||
|
||||
|
||||
// Return low time bits in units of 10 ms.
|
||||
*ms10 = rtc_getSecond() & 1 ? 100 : 0;
|
||||
}
|
||||
|
||||
uint32_t sectorCount()
|
||||
{
|
||||
return sd.card()->sectorCount();
|
||||
}
|
||||
uint32_t sectorCount() { return sd.card()->sectorCount(); }
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,25 +15,18 @@
|
|||
#include "acc_mc33810.h"
|
||||
#endif
|
||||
|
||||
static bool commandRequiresStoppedEngine(uint16_t buttonCommand)
|
||||
{
|
||||
return ((buttonCommand >= TS_CMD_INJ1_ON) && (buttonCommand <= TS_CMD_IGN8_50PC))
|
||||
|| ((buttonCommand == TS_CMD_TEST_ENBL) || (buttonCommand == TS_CMD_TEST_DSBL));
|
||||
}
|
||||
static bool commandRequiresStoppedEngine(uint16_t buttonCommand) { return ((buttonCommand >= TS_CMD_INJ1_ON) && (buttonCommand <= TS_CMD_IGN8_50PC)) || ((buttonCommand == TS_CMD_TEST_ENBL) || (buttonCommand == TS_CMD_TEST_DSBL)); }
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @param buttonCommand The command number of the button that was clicked. See TS_CommendButtonHandler.h for a list of button IDs
|
||||
*/
|
||||
bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
||||
{
|
||||
if (commandRequiresStoppedEngine(buttonCommand) && currentStatus.RPM != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (buttonCommand)
|
||||
if(commandRequiresStoppedEngine(buttonCommand) && currentStatus.RPM != 0) { return false; }
|
||||
|
||||
switch(buttonCommand)
|
||||
{
|
||||
case TS_CMD_TEST_DSBL: // cmd is stop
|
||||
BIT_CLEAR(currentStatus.testOutputs, 1);
|
||||
|
@ -41,36 +34,35 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
endCoil2Charge();
|
||||
endCoil3Charge();
|
||||
endCoil4Charge();
|
||||
#if IGN_CHANNELS >= 5
|
||||
#if IGN_CHANNELS >= 5
|
||||
endCoil5Charge();
|
||||
#endif
|
||||
#if IGN_CHANNELS >= 6
|
||||
#endif
|
||||
#if IGN_CHANNELS >= 6
|
||||
endCoil6Charge();
|
||||
#endif
|
||||
#if IGN_CHANNELS >= 7
|
||||
#endif
|
||||
#if IGN_CHANNELS >= 7
|
||||
endCoil7Charge();
|
||||
#endif
|
||||
#if IGN_CHANNELS >= 8
|
||||
#endif
|
||||
#if IGN_CHANNELS >= 8
|
||||
endCoil8Charge();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
closeInjector1();
|
||||
closeInjector2();
|
||||
closeInjector3();
|
||||
closeInjector4();
|
||||
#if INJ_CHANNELS >= 5
|
||||
#if INJ_CHANNELS >= 5
|
||||
closeInjector5();
|
||||
#endif
|
||||
#if INJ_CHANNELS >= 6
|
||||
#endif
|
||||
#if INJ_CHANNELS >= 6
|
||||
closeInjector6();
|
||||
#endif
|
||||
#if INJ_CHANNELS >= 7
|
||||
#endif
|
||||
#if INJ_CHANNELS >= 7
|
||||
closeInjector7();
|
||||
#endif
|
||||
#if INJ_CHANNELS >= 8
|
||||
#endif
|
||||
#if INJ_CHANNELS >= 8
|
||||
closeInjector8();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
HWTest_INJ_50pc = 0;
|
||||
HWTest_IGN_50pc = 0;
|
||||
|
@ -82,244 +74,307 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
break;
|
||||
|
||||
case TS_CMD_INJ1_ON: // cmd group is for injector1 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector1(); }
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector1(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ1_OFF: // cmd group is for injector1 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector1(); BIT_CLEAR(HWTest_INJ_50pc, INJ1_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ1_50PC: // cmd group is for injector1 50% dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ1_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ1_CMD_BIT)) { closeInjector1(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ2_ON: // cmd group is for injector2 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector2(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ2_OFF: // cmd group is for injector2 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector2(); BIT_CLEAR(HWTest_INJ_50pc, INJ2_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ2_50PC: // cmd group is for injector2 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ2_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ2_CMD_BIT)) { closeInjector2(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ3_ON: // cmd group is for injector3 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector3(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ3_OFF: // cmd group is for injector3 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector3(); BIT_CLEAR(HWTest_INJ_50pc, INJ3_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ3_50PC: // cmd group is for injector3 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ3_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ3_CMD_BIT)) { closeInjector3(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ4_ON: // cmd group is for injector4 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector4(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ4_OFF: // cmd group is for injector4 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector4(); BIT_CLEAR(HWTest_INJ_50pc, INJ4_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ4_50PC: // cmd group is for injector4 50% dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ4_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ4_CMD_BIT)) { closeInjector4(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ5_ON: // cmd group is for injector5 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector5(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ5_OFF: // cmd group is for injector5 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector5(); BIT_CLEAR(HWTest_INJ_50pc, INJ5_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ5_50PC: // cmd group is for injector5 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ5_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ5_CMD_BIT)) { closeInjector5(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ6_ON: // cmd group is for injector6 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector6(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ6_OFF: // cmd group is for injector6 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector6(); BIT_CLEAR(HWTest_INJ_50pc, INJ6_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ6_50PC: // cmd group is for injector6 50% dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ6_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ6_CMD_BIT)) { closeInjector6(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ7_ON: // cmd group is for injector7 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector7(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ7_OFF: // cmd group is for injector7 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector7(); BIT_CLEAR(HWTest_INJ_50pc, INJ7_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ7_50PC: // cmd group is for injector7 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ7_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ7_CMD_BIT)) { closeInjector7(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ8_ON: // cmd group is for injector8 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector8(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ8_OFF: // cmd group is for injector8 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector8(); BIT_CLEAR(HWTest_INJ_50pc, INJ8_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ8_50PC: // cmd group is for injector8 50% dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, INJ8_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ8_CMD_BIT)) { closeInjector8(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN1_ON: // cmd group is for spark1 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ beginCoil1Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN1_OFF: // cmd group is for spark1 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil1Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN1_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN1_50PC: // cmd group is for spark1 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN1_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN1_CMD_BIT)) { endCoil1Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN2_ON: // cmd group is for spark2 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil2Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN2_OFF: // cmd group is for spark2 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil2Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN2_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN2_50PC: // cmd group is for spark2 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN2_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN2_CMD_BIT)) { endCoil2Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN3_ON: // cmd group is for spark3 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil3Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN3_OFF: // cmd group is for spark3 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil3Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN3_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN3_50PC: // cmd group is for spark3 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN3_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN3_CMD_BIT)) { endCoil3Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN4_ON: // cmd group is for spark4 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil4Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN4_OFF: // cmd group is for spark4 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil4Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN4_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN4_50PC: // cmd group is for spark4 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN4_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN4_CMD_BIT)) { endCoil4Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN5_ON: // cmd group is for spark5 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil5Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN5_OFF: // cmd group is for spark5 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil5Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN5_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN5_50PC: // cmd group is for spark4 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN5_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN5_CMD_BIT)) { endCoil5Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN6_ON: // cmd group is for spark6 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil6Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN6_OFF: // cmd group is for spark6 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil6Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN6_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN6_50PC: // cmd group is for spark6 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN6_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN6_CMD_BIT)) { endCoil6Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN7_ON: // cmd group is for spark7 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil7Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN7_OFF: // cmd group is for spark7 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil7Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN7_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN7_50PC: // cmd group is for spark7 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN7_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN7_CMD_BIT)) { endCoil7Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN8_ON: // cmd group is for spark8 on actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil8Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN8_OFF: // cmd group is for spark8 off actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil8Charge(); BIT_CLEAR(HWTest_IGN_50pc, IGN8_CMD_BIT); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN8_50PC: // cmd group is for spark8 50%dc actions
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, IGN8_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN8_CMD_BIT)) { endCoil8Charge(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
//VSS Calibration routines
|
||||
case TS_CMD_VSS_60KMH:
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
if(configPage2.vssMode == 1)
|
||||
{
|
||||
//Calculate the ratio of VSS reading from Aux input and actual VSS (assuming that actual VSS is really 60km/h).
|
||||
configPage2.vssPulsesPerKm = (currentStatus.canin[configPage2.vssAuxCh] / 60);
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
}
|
||||
else
|
||||
{
|
||||
//Calibrate the actual pulses per distance
|
||||
uint32_t calibrationGap = vssGetPulseGap(0);
|
||||
if( calibrationGap > 0 )
|
||||
{
|
||||
configPage2.vssPulsesPerKm = 60000000UL / calibrationGap;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
}
|
||||
}
|
||||
closeInjector1();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ1_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
//Calculate the RPM to speed ratio for each gear
|
||||
case TS_CMD_INJ1_50PC: // cmd group is for injector1 50% dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ1_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ1_CMD_BIT)) { closeInjector1(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ2_ON: // cmd group is for injector2 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector2(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ2_OFF: // cmd group is for injector2 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector2();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ2_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ2_50PC: // cmd group is for injector2 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ2_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ2_CMD_BIT)) { closeInjector2(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ3_ON: // cmd group is for injector3 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector3(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ3_OFF: // cmd group is for injector3 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector3();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ3_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ3_50PC: // cmd group is for injector3 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ3_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ3_CMD_BIT)) { closeInjector3(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ4_ON: // cmd group is for injector4 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector4(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ4_OFF: // cmd group is for injector4 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector4();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ4_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ4_50PC: // cmd group is for injector4 50% dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ4_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ4_CMD_BIT)) { closeInjector4(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ5_ON: // cmd group is for injector5 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector5(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ5_OFF: // cmd group is for injector5 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector5();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ5_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ5_50PC: // cmd group is for injector5 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ5_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ5_CMD_BIT)) { closeInjector5(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ6_ON: // cmd group is for injector6 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector6(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ6_OFF: // cmd group is for injector6 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector6();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ6_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ6_50PC: // cmd group is for injector6 50% dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ6_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ6_CMD_BIT)) { closeInjector6(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ7_ON: // cmd group is for injector7 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector7(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ7_OFF: // cmd group is for injector7 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector7();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ7_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ7_50PC: // cmd group is for injector7 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ7_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ7_CMD_BIT)) { closeInjector7(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ8_ON: // cmd group is for injector8 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { openInjector8(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ8_OFF: // cmd group is for injector8 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
closeInjector8();
|
||||
BIT_CLEAR(HWTest_INJ_50pc, INJ8_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_INJ8_50PC: // cmd group is for injector8 50% dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_INJ_50pc, INJ8_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_INJ_50pc, INJ8_CMD_BIT)) { closeInjector8(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN1_ON: // cmd group is for spark1 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil1Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN1_OFF: // cmd group is for spark1 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil1Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN1_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN1_50PC: // cmd group is for spark1 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN1_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN1_CMD_BIT)) { endCoil1Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN2_ON: // cmd group is for spark2 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil2Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN2_OFF: // cmd group is for spark2 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil2Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN2_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN2_50PC: // cmd group is for spark2 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN2_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN2_CMD_BIT)) { endCoil2Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN3_ON: // cmd group is for spark3 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil3Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN3_OFF: // cmd group is for spark3 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil3Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN3_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN3_50PC: // cmd group is for spark3 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN3_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN3_CMD_BIT)) { endCoil3Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN4_ON: // cmd group is for spark4 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil4Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN4_OFF: // cmd group is for spark4 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil4Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN4_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN4_50PC: // cmd group is for spark4 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN4_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN4_CMD_BIT)) { endCoil4Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN5_ON: // cmd group is for spark5 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil5Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN5_OFF: // cmd group is for spark5 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil5Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN5_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN5_50PC: // cmd group is for spark4 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN5_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN5_CMD_BIT)) { endCoil5Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN6_ON: // cmd group is for spark6 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil6Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN6_OFF: // cmd group is for spark6 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil6Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN6_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN6_50PC: // cmd group is for spark6 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN6_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN6_CMD_BIT)) { endCoil6Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN7_ON: // cmd group is for spark7 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil7Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN7_OFF: // cmd group is for spark7 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil7Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN7_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN7_50PC: // cmd group is for spark7 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN7_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN7_CMD_BIT)) { endCoil7Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN8_ON: // cmd group is for spark8 on actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { beginCoil8Charge(); }
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN8_OFF: // cmd group is for spark8 off actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
endCoil8Charge();
|
||||
BIT_CLEAR(HWTest_IGN_50pc, IGN8_CMD_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_IGN8_50PC: // cmd group is for spark8 50%dc actions
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1)) { BIT_TOGGLE(HWTest_IGN_50pc, IGN8_CMD_BIT); }
|
||||
if(!BIT_CHECK(HWTest_IGN_50pc, IGN8_CMD_BIT)) { endCoil8Charge(); } // Ensure this output is turned off (Otherwise the output may stay on permanently)
|
||||
break;
|
||||
|
||||
// VSS Calibration routines
|
||||
case TS_CMD_VSS_60KMH: {
|
||||
if(configPage2.vssMode == 1)
|
||||
{
|
||||
// Calculate the ratio of VSS reading from Aux input and actual VSS (assuming that actual VSS is really 60km/h).
|
||||
configPage2.vssPulsesPerKm = (currentStatus.canin[configPage2.vssAuxCh] / 60);
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calibrate the actual pulses per distance
|
||||
uint32_t calibrationGap = vssGetPulseGap(0);
|
||||
if(calibrationGap > 0)
|
||||
{
|
||||
configPage2.vssPulsesPerKm = 60000000UL / calibrationGap;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Calculate the RPM to speed ratio for each gear
|
||||
case TS_CMD_VSS_RATIO1:
|
||||
if(currentStatus.vss > 0)
|
||||
{
|
||||
configPage2.vssRatio1 = (currentStatus.vss * 10000UL) / currentStatus.RPM;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -327,8 +382,8 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
if(currentStatus.vss > 0)
|
||||
{
|
||||
configPage2.vssRatio2 = (currentStatus.vss * 10000UL) / currentStatus.RPM;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -336,17 +391,17 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
if(currentStatus.vss > 0)
|
||||
{
|
||||
configPage2.vssRatio3 = (currentStatus.vss * 10000UL) / currentStatus.RPM;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_CMD_VSS_RATIO4:
|
||||
case TS_CMD_VSS_RATIO4:
|
||||
if(currentStatus.vss > 0)
|
||||
{
|
||||
configPage2.vssRatio4 = (currentStatus.vss * 10000UL) / currentStatus.RPM;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -354,8 +409,8 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
if(currentStatus.vss > 0)
|
||||
{
|
||||
configPage2.vssRatio5 = (currentStatus.vss * 10000UL) / currentStatus.RPM;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -363,12 +418,12 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
if(currentStatus.vss > 0)
|
||||
{
|
||||
configPage2.vssRatio6 = (currentStatus.vss * 10000UL) / currentStatus.RPM;
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); //Set the flag to trigger the UI reset
|
||||
writeConfig(1); // Need to manually save the new config value as it will not trigger a burn in tunerStudio due to use of ControllerPriority
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); // Set the flag to trigger the UI reset
|
||||
}
|
||||
break;
|
||||
|
||||
//STM32 Commands
|
||||
// STM32 Commands
|
||||
case TS_CMD_STM32_REBOOT: //
|
||||
doSystemReset();
|
||||
break;
|
||||
|
@ -378,14 +433,12 @@ bool TS_CommandButtonsHandler(uint16_t buttonCommand)
|
|||
break;
|
||||
|
||||
#ifdef SD_LOGGING
|
||||
case TS_CMD_SD_FORMAT: //Format SD card
|
||||
case TS_CMD_SD_FORMAT: // Format SD card
|
||||
formatExFat();
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
default: return false; break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -4,34 +4,33 @@
|
|||
|
||||
void initMC33810(void)
|
||||
{
|
||||
//Set the output states of both ICs to be off to fuel and ignition
|
||||
mc33810_1_requestedState = 0;
|
||||
mc33810_2_requestedState = 0;
|
||||
mc33810_1_returnState = 0;
|
||||
mc33810_2_returnState = 0;
|
||||
// Set the output states of both ICs to be off to fuel and ignition
|
||||
mc33810_1_requestedState = 0;
|
||||
mc33810_2_requestedState = 0;
|
||||
mc33810_1_returnState = 0;
|
||||
mc33810_2_returnState = 0;
|
||||
|
||||
pinMode(pinMC33810_1_CS, OUTPUT);
|
||||
pinMode(pinMC33810_2_CS, OUTPUT);
|
||||
pinMode(pinMC33810_1_CS, OUTPUT);
|
||||
pinMode(pinMC33810_2_CS, OUTPUT);
|
||||
|
||||
SPI.begin();
|
||||
//These are the SPI settings per the datasheet
|
||||
SPI.beginTransaction(SPISettings(6000000, MSBFIRST, SPI_MODE0));
|
||||
SPI.begin();
|
||||
// These are the SPI settings per the datasheet
|
||||
SPI.beginTransaction(SPISettings(6000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
//Set the ignition outputs to GPGD mode
|
||||
/*
|
||||
0001 = Mode select command
|
||||
1111 = Set all 1 GD[0...3] outputs to use GPGD mode
|
||||
00000000 = All remaining values are unused (For us)
|
||||
*/
|
||||
//uint16_t cmd = 0b000111110000;
|
||||
uint16_t cmd = 0b0001111100000000;
|
||||
//IC1
|
||||
MC33810_1_ACTIVE();
|
||||
SPI.transfer16(cmd);
|
||||
MC33810_1_INACTIVE();
|
||||
//IC2
|
||||
MC33810_2_ACTIVE();
|
||||
SPI.transfer16(cmd);
|
||||
MC33810_2_INACTIVE();
|
||||
|
||||
// Set the ignition outputs to GPGD mode
|
||||
/*
|
||||
0001 = Mode select command
|
||||
1111 = Set all 1 GD[0...3] outputs to use GPGD mode
|
||||
00000000 = All remaining values are unused (For us)
|
||||
*/
|
||||
// uint16_t cmd = 0b000111110000;
|
||||
uint16_t cmd = 0b0001111100000000;
|
||||
// IC1
|
||||
MC33810_1_ACTIVE();
|
||||
SPI.transfer16(cmd);
|
||||
MC33810_1_INACTIVE();
|
||||
// IC2
|
||||
MC33810_2_ACTIVE();
|
||||
SPI.transfer16(cmd);
|
||||
MC33810_2_INACTIVE();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,92 +1,91 @@
|
|||
|
||||
#if defined(CORE_AVR)
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
|
||||
// Prescaler values for timers 1-3-4-5. Refer to www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||
#define TIMER_PRESCALER_OFF ((0<<CS12)|(0<<CS11)|(0<<CS10))
|
||||
#define TIMER_PRESCALER_1 ((0<<CS12)|(0<<CS11)|(1<<CS10))
|
||||
#define TIMER_PRESCALER_8 ((0<<CS12)|(1<<CS11)|(0<<CS10))
|
||||
#define TIMER_PRESCALER_64 ((0<<CS12)|(1<<CS11)|(1<<CS10))
|
||||
#define TIMER_PRESCALER_256 ((1<<CS12)|(0<<CS11)|(0<<CS10))
|
||||
#define TIMER_PRESCALER_1024 ((1<<CS12)|(0<<CS11)|(1<<CS10))
|
||||
// Prescaler values for timers 1-3-4-5. Refer to www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||
#define TIMER_PRESCALER_OFF ((0 << CS12) | (0 << CS11) | (0 << CS10))
|
||||
#define TIMER_PRESCALER_1 ((0 << CS12) | (0 << CS11) | (1 << CS10))
|
||||
#define TIMER_PRESCALER_8 ((0 << CS12) | (1 << CS11) | (0 << CS10))
|
||||
#define TIMER_PRESCALER_64 ((0 << CS12) | (1 << CS11) | (1 << CS10))
|
||||
#define TIMER_PRESCALER_256 ((1 << CS12) | (0 << CS11) | (0 << CS10))
|
||||
#define TIMER_PRESCALER_1024 ((1 << CS12) | (0 << CS11) | (1 << CS10))
|
||||
|
||||
#define TIMER_MODE_NORMAL ((0<<WGM01)|(0<<WGM00))
|
||||
#define TIMER_MODE_PWM ((0<<WGM01)|(1<<WGM00))
|
||||
#define TIMER_MODE_CTC ((1<<WGM01)|(0<<WGM00))
|
||||
#define TIMER_MODE_FASTPWM ((1<<WGM01)|(1<<WGM00))
|
||||
#define TIMER_MODE_NORMAL ((0 << WGM01) | (0 << WGM00))
|
||||
#define TIMER_MODE_PWM ((0 << WGM01) | (1 << WGM00))
|
||||
#define TIMER_MODE_CTC ((1 << WGM01) | (0 << WGM00))
|
||||
#define TIMER_MODE_FASTPWM ((1 << WGM01) | (1 << WGM00))
|
||||
|
||||
void initBoard(void)
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
configPage9.intcan_available = 0; // AVR devices do NOT have internal canbus
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
configPage9.intcan_available = 0; // AVR devices do NOT have internal canbus
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
//PWM used by the Boost and VVT outputs. C Channel is used by ign5
|
||||
TCCR1B = TIMER_PRESCALER_OFF; //Disable Timer1 while we set it up
|
||||
TCNT1 = 0; //Reset Timer Count
|
||||
TCCR1A = TIMER_MODE_NORMAL; //Timer1 Control Reg A: Wave Gen Mode normal (Simply counts up from 0 to 65535 (16-bit int)
|
||||
TCCR1B = TIMER_PRESCALER_256; //Timer1 Control Reg B: Timer Prescaler set to 256. 1 tick = 16uS.
|
||||
TIFR1 = (1 << OCF1A) | (1<<OCF1B) | (1<<OCF1C) | (1<<TOV1) | (1<<ICF1); //Clear the compare flags, overflow flag and external input flag bits
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
// PWM used by the Boost and VVT outputs. C Channel is used by ign5
|
||||
TCCR1B = TIMER_PRESCALER_OFF; // Disable Timer1 while we set it up
|
||||
TCNT1 = 0; // Reset Timer Count
|
||||
TCCR1A = TIMER_MODE_NORMAL; // Timer1 Control Reg A: Wave Gen Mode normal (Simply counts up from 0 to 65535 (16-bit int)
|
||||
TCCR1B = TIMER_PRESCALER_256; // Timer1 Control Reg B: Timer Prescaler set to 256. 1 tick = 16uS.
|
||||
TIFR1 = (1 << OCF1A) | (1 << OCF1B) | (1 << OCF1C) | (1 << TOV1) | (1 << ICF1); // Clear the compare flags, overflow flag and external input flag bits
|
||||
|
||||
boost_pwm_max_count = 1000000L / (16 * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (16 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
|
||||
// put idle_pwm_max_count calculation here?
|
||||
boost_pwm_max_count = 1000000L / (16 * configPage6.boostFreq * 2); // Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (16 * configPage6.vvtFreq * 2); // Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
|
||||
// put idle_pwm_max_count calculation here?
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
//Configure Timer2 for our low-freq interrupt code.
|
||||
TCCR2B = TIMER_PRESCALER_OFF; //Disable Timer2 while we set it up
|
||||
TCNT2 = 131; //Preload timer2 with 131 cycles, leaving 125 till overflow. As the timer runs at 125Khz, this causes overflow to occur at 1Khz = 1ms
|
||||
TIMSK2 = (1<<TOIE2); //Timer2 Set Overflow Interrupt enabled.
|
||||
TCCR2A = TIMER_MODE_NORMAL; //Timer2 Control Reg A: Wave Gen Mode normal
|
||||
/* Now configure the prescaler to CPU clock divided by 128 = 125Khz */
|
||||
TCCR2B = (1<<CS22) | (1<<CS20); // Set bits. This timer uses different prescaler values, thus we cannot use the defines above.
|
||||
TIFR2 = (1 << OCF2A) | (1<<OCF2B) | (1<<TOV2); //Clear the compare flag bits and overflow flag bit
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
// Configure Timer2 for our low-freq interrupt code.
|
||||
TCCR2B = TIMER_PRESCALER_OFF; // Disable Timer2 while we set it up
|
||||
TCNT2 = 131; // Preload timer2 with 131 cycles, leaving 125 till overflow. As the timer runs at 125Khz, this causes overflow to occur at 1Khz = 1ms
|
||||
TIMSK2 = (1 << TOIE2); // Timer2 Set Overflow Interrupt enabled.
|
||||
TCCR2A = TIMER_MODE_NORMAL; // Timer2 Control Reg A: Wave Gen Mode normal
|
||||
/* Now configure the prescaler to CPU clock divided by 128 = 125Khz */
|
||||
TCCR2B = (1 << CS22) | (1 << CS20); // Set bits. This timer uses different prescaler values, thus we cannot use the defines above.
|
||||
TIFR2 = (1 << OCF2A) | (1 << OCF2B) | (1 << TOV2); // Clear the compare flag bits and overflow flag bit
|
||||
|
||||
//Enable the watchdog timer for 2 second resets (Good reference: www.tushev.org/articles/arduino/5/arduino-and-watchdog-timer)
|
||||
//Boooooooooo WDT is currently broken on Mega 2560 bootloaders :(
|
||||
//wdt_enable(WDTO_2S);
|
||||
// Enable the watchdog timer for 2 second resets (Good reference: www.tushev.org/articles/arduino/5/arduino-and-watchdog-timer)
|
||||
// Boooooooooo WDT is currently broken on Mega 2560 bootloaders :(
|
||||
// wdt_enable(WDTO_2S);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
* */
|
||||
//Much help in this from www.arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html
|
||||
//Fuel Schedules, which uses timer 3
|
||||
TCCR3B = TIMER_PRESCALER_OFF; //Disable Timer3 while we set it up
|
||||
TCNT3 = 0; //Reset Timer Count
|
||||
TCCR3A = TIMER_MODE_NORMAL; //Timer3 Control Reg A: Wave Gen Mode normal
|
||||
TCCR3B = TIMER_PRESCALER_64; //Timer3 Control Reg B: Timer Prescaler set to 64.
|
||||
TIFR3 = (1 << OCF3A) | (1<<OCF3B) | (1<<OCF3C) | (1<<TOV3) | (1<<ICF3); //Clear the compare flags, overflow flag and external input flag bits
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
* */
|
||||
// Much help in this from www.arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html
|
||||
// Fuel Schedules, which uses timer 3
|
||||
TCCR3B = TIMER_PRESCALER_OFF; // Disable Timer3 while we set it up
|
||||
TCNT3 = 0; // Reset Timer Count
|
||||
TCCR3A = TIMER_MODE_NORMAL; // Timer3 Control Reg A: Wave Gen Mode normal
|
||||
TCCR3B = TIMER_PRESCALER_64; // Timer3 Control Reg B: Timer Prescaler set to 64.
|
||||
TIFR3 = (1 << OCF3A) | (1 << OCF3B) | (1 << OCF3C) | (1 << TOV3) | (1 << ICF3); // Clear the compare flags, overflow flag and external input flag bits
|
||||
|
||||
//Ignition Schedules, which uses timer 5. This is also used by the fast version of micros(). If the speed of this timer is changed from 4uS ticks, that MUST be changed as well. See globals.h and timers.ino
|
||||
TCCR5B = TIMER_PRESCALER_OFF; //Disable Timer5 while we set it up
|
||||
TCNT5 = 0; //Reset Timer Count
|
||||
TCCR5A = TIMER_MODE_NORMAL; //Timer5 Control Reg A: Wave Gen Mode normal
|
||||
TCCR5B = TIMER_PRESCALER_64; //Timer5 Control Reg B: Timer Prescaler set to 64.
|
||||
TIFR5 = (1 << OCF5A) | (1<<OCF5B) | (1<<OCF5C) | (1<<TOV5) | (1<<ICF5); //Clear the compare flags, overflow flag and external input flag bits
|
||||
|
||||
#if defined(TIMER5_MICROS)
|
||||
TIMSK5 |= (1 << TOIE5); //Enable the timer5 overflow interrupt (See timers.ino for ISR)
|
||||
TIMSK0 &= ~_BV(TOIE0); // disable timer0 overflow interrupt
|
||||
#endif
|
||||
// Ignition Schedules, which uses timer 5. This is also used by the fast version of micros(). If the speed of this timer is changed from 4uS ticks, that MUST be changed as well. See globals.h and timers.ino
|
||||
TCCR5B = TIMER_PRESCALER_OFF; // Disable Timer5 while we set it up
|
||||
TCNT5 = 0; // Reset Timer Count
|
||||
TCCR5A = TIMER_MODE_NORMAL; // Timer5 Control Reg A: Wave Gen Mode normal
|
||||
TCCR5B = TIMER_PRESCALER_64; // Timer5 Control Reg B: Timer Prescaler set to 64.
|
||||
TIFR5 = (1 << OCF5A) | (1 << OCF5B) | (1 << OCF5C) | (1 << TOV5) | (1 << ICF5); // Clear the compare flags, overflow flag and external input flag bits
|
||||
|
||||
//The remaining Schedules (Fuel schedule 4 and ignition schedules 4 and 5) use Timer4
|
||||
TCCR4B = TIMER_PRESCALER_OFF; //Disable Timer4 while we set it up
|
||||
TCNT4 = 0; //Reset Timer Count
|
||||
TCCR4A = TIMER_MODE_NORMAL; //Timer4 Control Reg A: Wave Gen Mode normal
|
||||
TCCR4B = TIMER_PRESCALER_64; //Timer4 Control Reg B: Timer Prescaler set to 64.
|
||||
TIFR4 = (1 << OCF4A) | (1<<OCF4B) | (1<<OCF4C) | (1<<TOV4) | (1<<ICF4); //Clear the compare flags, overflow flag and external input flag bits
|
||||
#if defined(TIMER5_MICROS)
|
||||
TIMSK5 |= (1 << TOIE5); // Enable the timer5 overflow interrupt (See timers.ino for ISR)
|
||||
TIMSK0 &= ~_BV(TOIE0); // disable timer0 overflow interrupt
|
||||
#endif
|
||||
|
||||
// The remaining Schedules (Fuel schedule 4 and ignition schedules 4 and 5) use Timer4
|
||||
TCCR4B = TIMER_PRESCALER_OFF; // Disable Timer4 while we set it up
|
||||
TCNT4 = 0; // Reset Timer Count
|
||||
TCCR4A = TIMER_MODE_NORMAL; // Timer4 Control Reg A: Wave Gen Mode normal
|
||||
TCCR4B = TIMER_PRESCALER_64; // Timer4 Control Reg B: Timer Prescaler set to 64.
|
||||
TIFR4 = (1 << OCF4A) | (1 << OCF4B) | (1 << OCF4C) | (1 << TOV4) | (1 << ICF4); // Clear the compare flags, overflow flag and external input flag bits
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -95,27 +94,24 @@ void initBoard(void)
|
|||
*/
|
||||
uint16_t freeRam(void)
|
||||
{
|
||||
extern int __heap_start, *__brkval;
|
||||
int currentVal;
|
||||
uint16_t v;
|
||||
extern int __heap_start, *__brkval;
|
||||
int currentVal;
|
||||
uint16_t v;
|
||||
|
||||
if(__brkval == 0) { currentVal = (int) &__heap_start; }
|
||||
else { currentVal = (int) __brkval; }
|
||||
if(__brkval == 0) { currentVal = (int)&__heap_start; }
|
||||
else { currentVal = (int)__brkval; }
|
||||
|
||||
//Old version:
|
||||
//return (uint16_t) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
||||
/* cppcheck-suppress misra-c2012-11.4 ; DEVIATION(D3) */
|
||||
return (uint16_t) &v - currentVal; //cppcheck-suppress misra-c2012-11.4
|
||||
// Old version:
|
||||
// return (uint16_t) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
||||
/* cppcheck-suppress misra-c2012-11.4 ; DEVIATION(D3) */
|
||||
return (uint16_t)&v - currentVal; // cppcheck-suppress misra-c2012-11.4
|
||||
}
|
||||
|
||||
void doSystemReset(void) { return; }
|
||||
void jumpToBootloader(void) { return; }
|
||||
#if defined(TIMER5_MICROS)
|
||||
//This is used by the fast version of micros(). We just need to increment the timer overflow counter
|
||||
ISR(TIMER5_OVF_vect)
|
||||
{
|
||||
++timer5_overflow_count;
|
||||
}
|
||||
#if defined(TIMER5_MICROS)
|
||||
// This is used by the fast version of micros(). We just need to increment the timer overflow counter
|
||||
ISR(TIMER5_OVF_vect) { ++timer5_overflow_count; }
|
||||
|
||||
static inline unsigned long micros_safe(void)
|
||||
{
|
||||
|
@ -125,7 +121,7 @@ static inline unsigned long micros_safe(void)
|
|||
interrupts();
|
||||
|
||||
return newMicros;
|
||||
}
|
||||
#endif //TIMER5_MICROS
|
||||
}
|
||||
#endif // TIMER5_MICROS
|
||||
|
||||
#endif //CORE_AVR
|
||||
#endif // CORE_AVR
|
||||
|
|
|
@ -1,39 +1,36 @@
|
|||
#if defined(CORE_SAME51)
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint16_t freeRam() { return 0; }
|
||||
|
||||
void doSystemReset() { return; }
|
||||
void jumpToBootloader() { return; }
|
||||
|
|
|
@ -1,205 +1,204 @@
|
|||
#if defined(CORE_STM32_GENERIC)
|
||||
#include "board_stm32_generic.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
#include "HardwareTimer.h"
|
||||
#include "board_stm32_generic.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
#include "HardwareTimer.h"
|
||||
|
||||
#if defined(FRAM_AS_EEPROM)
|
||||
#if defined(STM32F407xx)
|
||||
FramClass EEPROM(PB5, PB4, PB3, PB0); /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
FramClass EEPROM(PB5, PB4, PB3, PB0); /*(mosi, miso, sclk, ssel, clockspeed) 31/01/2020*/
|
||||
#else
|
||||
FramClass EEPROM(PB15, PB14, PB13, PB12); //Blue/Black Pills
|
||||
FramClass EEPROM(PB15, PB14, PB13, PB12); // Blue/Black Pills
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
#ifndef FLASH_LENGTH
|
||||
#define FLASH_LENGTH 8192
|
||||
#endif
|
||||
delay(10);
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) )
|
||||
{
|
||||
idle_pwm_max_count = 1000000L / (TIMER_RESOLUTION * 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
|
||||
}
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
#ifndef FLASH_LENGTH
|
||||
#define FLASH_LENGTH 8192
|
||||
#endif
|
||||
delay(10);
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL))
|
||||
{
|
||||
idle_pwm_max_count = 1000000L / (TIMER_RESOLUTION * 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
|
||||
}
|
||||
|
||||
//This must happen at the end of the idle init
|
||||
Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.attachInterrupt(4, idleInterrupt); //on first flash the configPage4.iacAlgorithm is invalid
|
||||
// This must happen at the end of the idle init
|
||||
Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.attachInterrupt(4, idleInterrupt); // on first flash the configPage4.iacAlgorithm is invalid
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
#if defined(ARDUINO_BLUEPILL_F103C8) || defined(ARDUINO_BLUEPILL_F103CB)
|
||||
Timer4.setPeriod(1000); // Set up period
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, oneMSInterval);
|
||||
Timer4.resume(); // Start Timer
|
||||
#else
|
||||
Timer11.setPeriod(1000); // Set up period
|
||||
Timer11.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer11.attachInterrupt(1, oneMSInterval);
|
||||
Timer11.resume(); // Start Timer
|
||||
#endif
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Visual WDT
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
#if defined(ARDUINO_BLUEPILL_F103C8) || defined(ARDUINO_BLUEPILL_F103CB)
|
||||
Timer4.setPeriod(1000); // Set up period
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, oneMSInterval);
|
||||
Timer4.resume(); //Start Timer
|
||||
#else
|
||||
Timer11.setPeriod(1000); // Set up period
|
||||
Timer11.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer11.attachInterrupt(1, oneMSInterval);
|
||||
Timer11.resume(); //Start Timer
|
||||
#endif
|
||||
pinMode(LED_BUILTIN, OUTPUT); //Visual WDT
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
// 2uS resolution Min 8Hz, Max 5KHz
|
||||
boost_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.boostFreq * 2); // Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.vvtFreq * 2); // Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
|
||||
fan_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.fanFreq * 2); // Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
//2uS resolution Min 8Hz, Max 5KHz
|
||||
boost_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
|
||||
fan_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.fanFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle
|
||||
// Need to be initialised last due to instant interrupt
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.attachInterrupt(1, fanInterrupt);
|
||||
Timer1.attachInterrupt(2, boostInterrupt);
|
||||
Timer1.attachInterrupt(3, vvtInterrupt);
|
||||
|
||||
//Need to be initialised last due to instant interrupt
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.attachInterrupt(1, fanInterrupt);
|
||||
Timer1.attachInterrupt(2, boostInterrupt);
|
||||
Timer1.attachInterrupt(3, vvtInterrupt);
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
#if defined(ARDUINO_BLUEPILL_F103C8) || defined(ARDUINO_BLUEPILL_F103CB)
|
||||
//(CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz).
|
||||
// Timer2 to 4 is on APB1, Timer1 on APB2. www.st.com/resource/en/datasheet/stm32f103cb.pdf sheet 12
|
||||
Timer1.setPrescaleFactor(((Timer1.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
Timer2.setPrescaleFactor(((Timer2.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
Timer3.setPrescaleFactor(((Timer3.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
#else
|
||||
//(CYCLES_PER_MICROSECOND == 168, APB2 at 84MHz, APB1 at 42MHz).
|
||||
// Timer2 to 14 is on APB1, Timers 1, 8, 9 and 10 on APB2. www.st.com/resource/en/datasheet/stm32f407vg.pdf sheet 120
|
||||
Timer1.setPrescaleFactor(((Timer1.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
Timer2.setPrescaleFactor(((Timer2.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
Timer3.setPrescaleFactor(((Timer3.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
Timer4.setPrescaleFactor(((Timer4.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
Timer5.setPrescaleFactor(((Timer5.getBaseFrequency() / 1000000) * TIMER_RESOLUTION) - 1); // 2us resolution
|
||||
#endif
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
#if defined(ARDUINO_BLUEPILL_F103C8) || defined(ARDUINO_BLUEPILL_F103CB)
|
||||
//(CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz).
|
||||
//Timer2 to 4 is on APB1, Timer1 on APB2. www.st.com/resource/en/datasheet/stm32f103cb.pdf sheet 12
|
||||
Timer1.setPrescaleFactor(((Timer1.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
Timer2.setPrescaleFactor(((Timer2.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
Timer3.setPrescaleFactor(((Timer3.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
#else
|
||||
//(CYCLES_PER_MICROSECOND == 168, APB2 at 84MHz, APB1 at 42MHz).
|
||||
//Timer2 to 14 is on APB1, Timers 1, 8, 9 and 10 on APB2. www.st.com/resource/en/datasheet/stm32f407vg.pdf sheet 120
|
||||
Timer1.setPrescaleFactor(((Timer1.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
Timer2.setPrescaleFactor(((Timer2.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
Timer3.setPrescaleFactor(((Timer3.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
Timer4.setPrescaleFactor(((Timer4.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
Timer5.setPrescaleFactor(((Timer5.getBaseFrequency()/1000000) * TIMER_RESOLUTION)-1); //2us resolution
|
||||
#endif
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
// Attach interrupt functions
|
||||
// Injection
|
||||
Timer2.attachInterrupt(1, fuelSchedule1Interrupt);
|
||||
Timer2.attachInterrupt(2, fuelSchedule2Interrupt);
|
||||
Timer2.attachInterrupt(3, fuelSchedule3Interrupt);
|
||||
Timer2.attachInterrupt(4, fuelSchedule4Interrupt);
|
||||
#if(INJ_CHANNELS >= 5)
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 6)
|
||||
Timer5.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(2, fuelSchedule6Interrupt);
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 7)
|
||||
Timer5.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(3, fuelSchedule7Interrupt);
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 8)
|
||||
Timer5.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(4, fuelSchedule8Interrupt);
|
||||
#endif
|
||||
|
||||
//Attach interrupt functions
|
||||
//Injection
|
||||
Timer2.attachInterrupt(1, fuelSchedule1Interrupt);
|
||||
Timer2.attachInterrupt(2, fuelSchedule2Interrupt);
|
||||
Timer2.attachInterrupt(3, fuelSchedule3Interrupt);
|
||||
Timer2.attachInterrupt(4, fuelSchedule4Interrupt);
|
||||
#if (INJ_CHANNELS >= 5)
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 6)
|
||||
Timer5.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(2, fuelSchedule6Interrupt);
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 7)
|
||||
Timer5.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(3, fuelSchedule7Interrupt);
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 8)
|
||||
Timer5.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer5.attachInterrupt(4, fuelSchedule8Interrupt);
|
||||
#endif
|
||||
// Ignition
|
||||
Timer3.attachInterrupt(1, ignitionSchedule1Interrupt);
|
||||
Timer3.attachInterrupt(2, ignitionSchedule2Interrupt);
|
||||
Timer3.attachInterrupt(3, ignitionSchedule3Interrupt);
|
||||
Timer3.attachInterrupt(4, ignitionSchedule4Interrupt);
|
||||
#if(IGN_CHANNELS >= 5)
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 6)
|
||||
Timer4.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(2, ignitionSchedule6Interrupt);
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 7)
|
||||
Timer4.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(3, ignitionSchedule7Interrupt);
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 8)
|
||||
Timer4.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(4, ignitionSchedule8Interrupt);
|
||||
#endif
|
||||
|
||||
//Ignition
|
||||
Timer3.attachInterrupt(1, ignitionSchedule1Interrupt);
|
||||
Timer3.attachInterrupt(2, ignitionSchedule2Interrupt);
|
||||
Timer3.attachInterrupt(3, ignitionSchedule3Interrupt);
|
||||
Timer3.attachInterrupt(4, ignitionSchedule4Interrupt);
|
||||
#if (IGN_CHANNELS >= 5)
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 6)
|
||||
Timer4.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(2, ignitionSchedule6Interrupt);
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 7)
|
||||
Timer4.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(3, ignitionSchedule7Interrupt);
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 8)
|
||||
Timer4.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(4, ignitionSchedule8Interrupt);
|
||||
#endif
|
||||
|
||||
Timer1.setOverflow(0xFFFF);
|
||||
Timer1.resume();
|
||||
Timer2.setOverflow(0xFFFF);
|
||||
Timer2.resume();
|
||||
Timer3.setOverflow(0xFFFF);
|
||||
Timer3.resume();
|
||||
#if (IGN_CHANNELS >= 5)
|
||||
Timer4.setOverflow(0xFFFF);
|
||||
Timer4.resume();
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 5)
|
||||
Timer5.setOverflow(0xFFFF);
|
||||
Timer5.resume();
|
||||
#endif
|
||||
Timer1.setOverflow(0xFFFF);
|
||||
Timer1.resume();
|
||||
Timer2.setOverflow(0xFFFF);
|
||||
Timer2.resume();
|
||||
Timer3.setOverflow(0xFFFF);
|
||||
Timer3.resume();
|
||||
#if(IGN_CHANNELS >= 5)
|
||||
Timer4.setOverflow(0xFFFF);
|
||||
Timer4.resume();
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 5)
|
||||
Timer5.setOverflow(0xFFFF);
|
||||
Timer5.resume();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
char top = 't';
|
||||
return &top - reinterpret_cast<char*>(sbrk(0));
|
||||
char top = 't';
|
||||
return &top - reinterpret_cast<char *>(sbrk(0));
|
||||
}
|
||||
|
||||
void doSystemReset( void )
|
||||
void doSystemReset(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_SystemReset();
|
||||
__disable_irq();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void jumpToBootloader( void ) // https://github.com/3devo/Arduino_Core_STM32/blob/jumpSysBL/libraries/SrcWrapper/src/stm32/bootloader.c
|
||||
{ // https://github.com/markusgritsch/SilF4ware/blob/master/SilF4ware/drv_reset.c
|
||||
HAL_RCC_DeInit();
|
||||
HAL_DeInit();
|
||||
SysTick->VAL = SysTick->LOAD = SysTick->CTRL = 0;
|
||||
SYSCFG->MEMRMP = 0x01;
|
||||
void jumpToBootloader(void) // https://github.com/3devo/Arduino_Core_STM32/blob/jumpSysBL/libraries/SrcWrapper/src/stm32/bootloader.c
|
||||
{ // https://github.com/markusgritsch/SilF4ware/blob/master/SilF4ware/drv_reset.c
|
||||
HAL_RCC_DeInit();
|
||||
HAL_DeInit();
|
||||
SysTick->VAL = SysTick->LOAD = SysTick->CTRL = 0;
|
||||
SYSCFG->MEMRMP = 0x01;
|
||||
|
||||
#if defined(STM32F7xx) || defined(STM32H7xx)
|
||||
const uint32_t DFU_addr = 0x1FF00000; // From AN2606
|
||||
#else
|
||||
const uint32_t DFU_addr = 0x1FFF0000; // Default for STM32F10xxx and STM32F40xxx/STM32F41xxx from AN2606
|
||||
#endif
|
||||
// This is assembly to prevent modifying the stack pointer after
|
||||
// loading it, and to ensure a jump (not call) to the bootloader.
|
||||
// Not sure if the barriers are really needed, they were taken from
|
||||
// https://github.com/GrumpyOldPizza/arduino-STM32L4/blob/ac659033eadd50cfe001ba1590a1362b2d87bb76/system/STM32L4xx/Source/boot_stm32l4xx.c#L159-L165
|
||||
asm volatile (
|
||||
"ldr r0, [%[DFU_addr], #0] \n\t" // get address of stack pointer
|
||||
"msr msp, r0 \n\t" // set stack pointer
|
||||
"ldr r0, [%[DFU_addr], #4] \n\t" // get address of reset handler
|
||||
"dsb \n\t" // data sync barrier
|
||||
"isb \n\t" // instruction sync barrier
|
||||
"bx r0 \n\t" // branch to bootloader
|
||||
: : [DFU_addr] "l" (DFU_addr) : "r0"
|
||||
);
|
||||
__builtin_unreachable();
|
||||
#if defined(STM32F7xx) || defined(STM32H7xx)
|
||||
const uint32_t DFU_addr = 0x1FF00000; // From AN2606
|
||||
#else
|
||||
const uint32_t DFU_addr = 0x1FFF0000; // Default for STM32F10xxx and STM32F40xxx/STM32F41xxx from AN2606
|
||||
#endif
|
||||
// This is assembly to prevent modifying the stack pointer after
|
||||
// loading it, and to ensure a jump (not call) to the bootloader.
|
||||
// Not sure if the barriers are really needed, they were taken from
|
||||
// https://github.com/GrumpyOldPizza/arduino-STM32L4/blob/ac659033eadd50cfe001ba1590a1362b2d87bb76/system/STM32L4xx/Source/boot_stm32l4xx.c#L159-L165
|
||||
asm volatile("ldr r0, [%[DFU_addr], #0] \n\t" // get address of stack pointer
|
||||
"msr msp, r0 \n\t" // set stack pointer
|
||||
"ldr r0, [%[DFU_addr], #4] \n\t" // get address of reset handler
|
||||
"dsb \n\t" // data sync barrier
|
||||
"isb \n\t" // instruction sync barrier
|
||||
"bx r0 \n\t" // branch to bootloader
|
||||
:
|
||||
: [DFU_addr] "l"(DFU_addr)
|
||||
: "r0");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
#include "board_stm32_official.h"
|
||||
#if defined(STM32_CORE_VERSION_MAJOR)
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
#include "HardwareTimer.h"
|
||||
|
||||
#if HAL_CAN_MODULE_ENABLED
|
||||
// This activates CAN1 interface on STM32, but it's named as Can0, because that's how Teensy implementation is done
|
||||
STM32_CAN Can0(CAN1, ALT_2, RX_SIZE_256, TX_SIZE_16);
|
||||
/*
|
||||
These CAN interfaces and pins are available for use, depending on the chip/package:
|
||||
Default CAN1 pins are PA11 and PA12. Alternative (ALT) pins are PB8 & PB9 and ALT_2 pins are PD0 & PD1.
|
||||
Default CAN2 pins are PB12 & PB13. Alternative (ALT) pins are PB5 & PB6.
|
||||
Default CAN3 pins are PA8 & PA15. Alternative (ALT) pins are PB3 & PB4.
|
||||
*/
|
||||
#endif
|
||||
|
||||
#if defined SD_LOGGING
|
||||
SPIClass SD_SPI(PC12, PC11, PC10); // SPI3_MOSI, SPI3_MISO, SPI3_SCK
|
||||
#endif
|
||||
|
||||
#if defined(SRAM_AS_EEPROM)
|
||||
BackupSramAsEEPROM EEPROM;
|
||||
#elif defined(USE_SPI_EEPROM)
|
||||
#if defined(STM32F407xx)
|
||||
SPIClass SPI_for_flash(PB5, PB4, PB3); // SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
#else // Blue/Black Pills
|
||||
SPIClass SPI_for_flash(PB15, PB14, PB13);
|
||||
#endif
|
||||
|
||||
// winbond W25Q16 SPI flash EEPROM emulation
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{255UL, 4096UL, 31, 0x00100000UL};
|
||||
Flash_SPI_Config SPIconfig{USE_SPI_EEPROM, SPI_for_flash};
|
||||
SPI_EEPROM_Class EEPROM(EmulatedEEPROMMconfig, SPIconfig);
|
||||
#elif defined(FRAM_AS_EEPROM) // https://github.com/VitorBoss/FRAM
|
||||
#if defined(STM32F407xx)
|
||||
SPIClass SPI_for_FRAM(PB5, PB4, PB3); // SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
FramClass EEPROM(PB0, SPI_for_FRAM);
|
||||
#else // Blue/Black Pills
|
||||
SPIClass SPI_for_FRAM(PB15, PB14, PB13);
|
||||
FramClass EEPROM(PB12, SPI_for_FRAM);
|
||||
#endif
|
||||
#elif defined(STM32F7xx)
|
||||
#if defined(DUAL_BANK)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08120000UL};
|
||||
#else
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 262144UL, 4095UL, 0x08180000UL};
|
||||
#endif
|
||||
InternalSTM32F7_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#elif defined(STM32F401xC)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{1UL, 131072UL, 4095UL, 0x08020000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#elif defined(STM32F411xE)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 131072UL, 4095UL, 0x08040000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#else // default case, internal flash as EEPROM for STM32F4
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08080000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#endif
|
||||
|
||||
HardwareTimer Timer1(TIM1);
|
||||
HardwareTimer Timer2(TIM2);
|
||||
HardwareTimer Timer3(TIM3);
|
||||
HardwareTimer Timer4(TIM4);
|
||||
#if !defined(ARDUINO_BLUEPILL_F103C8) && !defined(ARDUINO_BLUEPILL_F103CB) // F103 just have 4 timers
|
||||
HardwareTimer Timer5(TIM5);
|
||||
#if defined(TIM11)
|
||||
HardwareTimer Timer11(TIM11);
|
||||
#elif defined(TIM7)
|
||||
HardwareTimer Timer11(TIM7);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RTC_ENABLED
|
||||
STM32RTC &rtc = STM32RTC::getInstance();
|
||||
#endif
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
#ifndef FLASH_LENGTH
|
||||
#define FLASH_LENGTH 8192
|
||||
#endif
|
||||
delay(10);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Real Time clock for datalogging/time stamping
|
||||
*/
|
||||
#ifdef RTC_ENABLED
|
||||
// Check if RTC time has been set earlier. If yes, RTC will use LSE_CLOCK. If not, default LSI_CLOCK is used, to prevent hanging on boot.
|
||||
if(rtc.isTimeSet())
|
||||
{
|
||||
rtc.setClockSource(STM32RTC::LSE_CLOCK); // Initialise external clock for RTC if clock is set. That is the only clock running of VBAT
|
||||
}
|
||||
rtc.begin(); // initialise RTC 24H format
|
||||
#endif
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL))
|
||||
{
|
||||
idle_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.idleFreq * 2); // Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 5KHz
|
||||
}
|
||||
|
||||
// This must happen at the end of the idle init
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else
|
||||
Timer1.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer1.attachInterrupt(4, idleInterrupt); // on first flash the configPage4.iacAlgorithm is invalid
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
#if defined(ARDUINO_BLUEPILL_F103C8) || defined(ARDUINO_BLUEPILL_F103CB)
|
||||
Timer4.setOverflow(1000, MICROSEC_FORMAT); // Set up period
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, oneMSInterval);
|
||||
#else // 2.0 forward
|
||||
Timer4.attachInterrupt(oneMSInterval);
|
||||
#endif
|
||||
Timer4.resume(); // Start Timer
|
||||
#else
|
||||
Timer11.setOverflow(1000, MICROSEC_FORMAT); // Set up period
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer11.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer11.attachInterrupt(1, oneMSInterval);
|
||||
#else
|
||||
Timer11.attachInterrupt(oneMSInterval);
|
||||
#endif
|
||||
Timer11.resume(); // Start Timer
|
||||
#endif
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Visual WDT
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
// 2uS resolution Min 8Hz, Max 5KHz
|
||||
|
||||
boost_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.boostFreq * 2); // Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.vvtFreq * 2); // Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle
|
||||
fan_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.fanFreq * 2); // Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle
|
||||
|
||||
// Need to be initialised last due to instant interrupt
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer1.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer1.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer1.attachInterrupt(1, fanInterrupt);
|
||||
Timer1.attachInterrupt(2, boostInterrupt);
|
||||
Timer1.attachInterrupt(3, vvtInterrupt);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
Timer1.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer2.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer3.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
|
||||
Timer1.setPrescaleFactor(((Timer1.getTimerClkFreq() / 1000000) * TIMER_RESOLUTION) - 1); // 4us resolution
|
||||
Timer2.setPrescaleFactor(((Timer2.getTimerClkFreq() / 1000000) * TIMER_RESOLUTION) - 1); // 4us resolution
|
||||
Timer3.setPrescaleFactor(((Timer3.getTimerClkFreq() / 1000000) * TIMER_RESOLUTION) - 1); // 4us resolution
|
||||
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
// Attach interrupt functions
|
||||
// Injection
|
||||
Timer3.attachInterrupt(1, fuelSchedule1Interrupt);
|
||||
Timer3.attachInterrupt(2, fuelSchedule2Interrupt);
|
||||
Timer3.attachInterrupt(3, fuelSchedule3Interrupt);
|
||||
Timer3.attachInterrupt(4, fuelSchedule4Interrupt);
|
||||
#if(INJ_CHANNELS >= 5)
|
||||
Timer5.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer5.setPrescaleFactor(((Timer5.getTimerClkFreq() / 1000000) * TIMER_RESOLUTION) - 1); // 4us resolution
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 6)
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer5.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(2, fuelSchedule6Interrupt);
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 7)
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer5.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer5.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(3, fuelSchedule7Interrupt);
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 8)
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer5.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer5.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(4, fuelSchedule8Interrupt);
|
||||
#endif
|
||||
|
||||
// Ignition
|
||||
Timer2.attachInterrupt(1, ignitionSchedule1Interrupt);
|
||||
Timer2.attachInterrupt(2, ignitionSchedule2Interrupt);
|
||||
Timer2.attachInterrupt(3, ignitionSchedule3Interrupt);
|
||||
Timer2.attachInterrupt(4, ignitionSchedule4Interrupt);
|
||||
#if(IGN_CHANNELS >= 5)
|
||||
Timer4.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer4.setPrescaleFactor(((Timer4.getTimerClkFreq() / 1000000) * TIMER_RESOLUTION) - 1); // 4us resolution
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 6)
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer4.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer4.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(2, ignitionSchedule6Interrupt);
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 7)
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer4.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer4.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(3, ignitionSchedule7Interrupt);
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 8)
|
||||
#if(STM32_CORE_VERSION_MAJOR < 2)
|
||||
Timer4.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else // 2.0 forward
|
||||
Timer4.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(4, ignitionSchedule8Interrupt);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
uint32_t freeRam;
|
||||
uint32_t stackTop;
|
||||
uint32_t heapTop;
|
||||
|
||||
// current position of the stack.
|
||||
stackTop = (uint32_t)&stackTop;
|
||||
|
||||
// current position of heap.
|
||||
void *hTop = malloc(1);
|
||||
heapTop = (uint32_t)hTop;
|
||||
free(hTop);
|
||||
freeRam = stackTop - heapTop;
|
||||
|
||||
if(freeRam > 0xFFFF) { return 0xFFFF; }
|
||||
else { return freeRam; }
|
||||
}
|
||||
|
||||
void doSystemReset(void)
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void jumpToBootloader(void) // https://github.com/3devo/Arduino_Core_STM32/blob/jumpSysBL/libraries/SrcWrapper/src/stm32/bootloader.c
|
||||
{ // https://github.com/markusgritsch/SilF4ware/blob/master/SilF4ware/drv_reset.c
|
||||
#if !defined(STM32F103xB)
|
||||
HAL_RCC_DeInit();
|
||||
HAL_DeInit();
|
||||
SysTick->VAL = SysTick->LOAD = SysTick->CTRL = 0;
|
||||
SYSCFG->MEMRMP = 0x01;
|
||||
|
||||
#if defined(STM32F7xx) || defined(STM32H7xx)
|
||||
const uint32_t DFU_addr = 0x1FF00000; // From AN2606
|
||||
#else
|
||||
const uint32_t DFU_addr = 0x1FFF0000; // Default for STM32F10xxx and STM32F40xxx/STM32F41xxx from AN2606
|
||||
#endif
|
||||
// This is assembly to prevent modifying the stack pointer after
|
||||
// loading it, and to ensure a jump (not call) to the bootloader.
|
||||
// Not sure if the barriers are really needed, they were taken from
|
||||
// https://github.com/GrumpyOldPizza/arduino-STM32L4/blob/ac659033eadd50cfe001ba1590a1362b2d87bb76/system/STM32L4xx/Source/boot_stm32l4xx.c#L159-L165
|
||||
asm volatile("ldr r0, [%[DFU_addr], #0] \n\t" // get address of stack pointer
|
||||
"msr msp, r0 \n\t" // set stack pointer
|
||||
"ldr r0, [%[DFU_addr], #4] \n\t" // get address of reset handler
|
||||
"dsb \n\t" // data sync barrier
|
||||
"isb \n\t" // instruction sync barrier
|
||||
"bx r0 \n\t" // branch to bootloader
|
||||
:
|
||||
: [DFU_addr] "l"(DFU_addr)
|
||||
: "r0");
|
||||
__builtin_unreachable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Interrupt callback functions
|
||||
*/
|
||||
#if((STM32_CORE_VERSION_MINOR <= 8) & (STM32_CORE_VERSION_MAJOR == 1))
|
||||
void oneMSInterval(HardwareTimer *) { oneMSInterval(); }
|
||||
void boostInterrupt(HardwareTimer *) { boostInterrupt(); }
|
||||
void fuelSchedule1Interrupt(HardwareTimer *) { fuelSchedule1Interrupt(); }
|
||||
void fuelSchedule2Interrupt(HardwareTimer *) { fuelSchedule2Interrupt(); }
|
||||
void fuelSchedule3Interrupt(HardwareTimer *) { fuelSchedule3Interrupt(); }
|
||||
void fuelSchedule4Interrupt(HardwareTimer *) { fuelSchedule4Interrupt(); }
|
||||
#if(INJ_CHANNELS >= 5)
|
||||
void fuelSchedule5Interrupt(HardwareTimer *) { fuelSchedule5Interrupt(); }
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 6)
|
||||
void fuelSchedule6Interrupt(HardwareTimer *) { fuelSchedule6Interrupt(); }
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 7)
|
||||
void fuelSchedule7Interrupt(HardwareTimer *) { fuelSchedule7Interrupt(); }
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 8)
|
||||
void fuelSchedule8Interrupt(HardwareTimer *) { fuelSchedule8Interrupt(); }
|
||||
#endif
|
||||
void idleInterrupt(HardwareTimer *) { idleInterrupt(); }
|
||||
void vvtInterrupt(HardwareTimer *) { vvtInterrupt(); }
|
||||
void fanInterrupt(HardwareTimer *) { fanInterrupt(); }
|
||||
void ignitionSchedule1Interrupt(HardwareTimer *) { ignitionSchedule1Interrupt(); }
|
||||
void ignitionSchedule2Interrupt(HardwareTimer *) { ignitionSchedule2Interrupt(); }
|
||||
void ignitionSchedule3Interrupt(HardwareTimer *) { ignitionSchedule3Interrupt(); }
|
||||
void ignitionSchedule4Interrupt(HardwareTimer *) { ignitionSchedule4Interrupt(); }
|
||||
#if(IGN_CHANNELS >= 5)
|
||||
void ignitionSchedule5Interrupt(HardwareTimer *) { ignitionSchedule5Interrupt(); }
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 6)
|
||||
void ignitionSchedule6Interrupt(HardwareTimer *) { ignitionSchedule6Interrupt(); }
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 7)
|
||||
void ignitionSchedule7Interrupt(HardwareTimer *) { ignitionSchedule7Interrupt(); }
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 8)
|
||||
void ignitionSchedule8Interrupt(HardwareTimer *) { ignitionSchedule8Interrupt(); }
|
||||
#endif
|
||||
#endif // End core<=1.8
|
||||
#endif
|
|
@ -288,7 +288,7 @@ extern HardwareTimer Timer11;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if ((STM32_CORE_VERSION_MINOR<=8) & (STM32_CORE_VERSION_MAJOR==1))
|
||||
#if ((STM32_CORE_VERSION_MINOR<=8) && (STM32_CORE_VERSION_MAJOR==1))
|
||||
void oneMSInterval(HardwareTimer*);
|
||||
void boostInterrupt(HardwareTimer*);
|
||||
void fuelSchedule1Interrupt(HardwareTimer*);
|
||||
|
|
|
@ -1,385 +0,0 @@
|
|||
#include "board_stm32_official.h"
|
||||
#if defined(STM32_CORE_VERSION_MAJOR)
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
#include "HardwareTimer.h"
|
||||
|
||||
#if HAL_CAN_MODULE_ENABLED
|
||||
//This activates CAN1 interface on STM32, but it's named as Can0, because that's how Teensy implementation is done
|
||||
STM32_CAN Can0 (CAN1, ALT_2, RX_SIZE_256, TX_SIZE_16);
|
||||
/*
|
||||
These CAN interfaces and pins are available for use, depending on the chip/package:
|
||||
Default CAN1 pins are PA11 and PA12. Alternative (ALT) pins are PB8 & PB9 and ALT_2 pins are PD0 & PD1.
|
||||
Default CAN2 pins are PB12 & PB13. Alternative (ALT) pins are PB5 & PB6.
|
||||
Default CAN3 pins are PA8 & PA15. Alternative (ALT) pins are PB3 & PB4.
|
||||
*/
|
||||
#endif
|
||||
|
||||
#if defined SD_LOGGING
|
||||
SPIClass SD_SPI(PC12, PC11, PC10); //SPI3_MOSI, SPI3_MISO, SPI3_SCK
|
||||
#endif
|
||||
|
||||
#if defined(SRAM_AS_EEPROM)
|
||||
BackupSramAsEEPROM EEPROM;
|
||||
#elif defined(USE_SPI_EEPROM)
|
||||
#if defined(STM32F407xx)
|
||||
SPIClass SPI_for_flash(PB5, PB4, PB3); //SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
#else //Blue/Black Pills
|
||||
SPIClass SPI_for_flash(PB15, PB14, PB13);
|
||||
#endif
|
||||
|
||||
//winbond W25Q16 SPI flash EEPROM emulation
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{255UL, 4096UL, 31, 0x00100000UL};
|
||||
Flash_SPI_Config SPIconfig{USE_SPI_EEPROM, SPI_for_flash};
|
||||
SPI_EEPROM_Class EEPROM(EmulatedEEPROMMconfig, SPIconfig);
|
||||
#elif defined(FRAM_AS_EEPROM) //https://github.com/VitorBoss/FRAM
|
||||
#if defined(STM32F407xx)
|
||||
SPIClass SPI_for_FRAM(PB5, PB4, PB3); //SPI1_MOSI, SPI1_MISO, SPI1_SCK
|
||||
FramClass EEPROM(PB0, SPI_for_FRAM);
|
||||
#else //Blue/Black Pills
|
||||
SPIClass SPI_for_FRAM(PB15, PB14, PB13);
|
||||
FramClass EEPROM(PB12, SPI_for_FRAM);
|
||||
#endif
|
||||
#elif defined(STM32F7xx)
|
||||
#if defined(DUAL_BANK)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08120000UL};
|
||||
#else
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 262144UL, 4095UL, 0x08180000UL};
|
||||
#endif
|
||||
InternalSTM32F7_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#elif defined(STM32F401xC)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{1UL, 131072UL, 4095UL, 0x08020000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#elif defined(STM32F411xE)
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{2UL, 131072UL, 4095UL, 0x08040000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#else //default case, internal flash as EEPROM for STM32F4
|
||||
EEPROM_Emulation_Config EmulatedEEPROMMconfig{4UL, 131072UL, 2047UL, 0x08080000UL};
|
||||
InternalSTM32F4_EEPROM_Class EEPROM(EmulatedEEPROMMconfig);
|
||||
#endif
|
||||
|
||||
|
||||
HardwareTimer Timer1(TIM1);
|
||||
HardwareTimer Timer2(TIM2);
|
||||
HardwareTimer Timer3(TIM3);
|
||||
HardwareTimer Timer4(TIM4);
|
||||
#if !defined(ARDUINO_BLUEPILL_F103C8) && !defined(ARDUINO_BLUEPILL_F103CB) //F103 just have 4 timers
|
||||
HardwareTimer Timer5(TIM5);
|
||||
#if defined(TIM11)
|
||||
HardwareTimer Timer11(TIM11);
|
||||
#elif defined(TIM7)
|
||||
HardwareTimer Timer11(TIM7);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RTC_ENABLED
|
||||
STM32RTC& rtc = STM32RTC::getInstance();
|
||||
#endif
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
#ifndef FLASH_LENGTH
|
||||
#define FLASH_LENGTH 8192
|
||||
#endif
|
||||
delay(10);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Real Time clock for datalogging/time stamping
|
||||
*/
|
||||
#ifdef RTC_ENABLED
|
||||
//Check if RTC time has been set earlier. If yes, RTC will use LSE_CLOCK. If not, default LSI_CLOCK is used, to prevent hanging on boot.
|
||||
if (rtc.isTimeSet()) {
|
||||
rtc.setClockSource(STM32RTC::LSE_CLOCK); //Initialise external clock for RTC if clock is set. That is the only clock running of VBAT
|
||||
}
|
||||
rtc.begin(); // initialise RTC 24H format
|
||||
#endif
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL))
|
||||
{
|
||||
idle_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 5KHz
|
||||
}
|
||||
|
||||
//This must happen at the end of the idle init
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else
|
||||
Timer1.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer1.attachInterrupt(4, idleInterrupt); //on first flash the configPage4.iacAlgorithm is invalid
|
||||
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
#if defined(ARDUINO_BLUEPILL_F103C8) || defined(ARDUINO_BLUEPILL_F103CB)
|
||||
Timer4.setOverflow(1000, MICROSEC_FORMAT); // Set up period
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, oneMSInterval);
|
||||
#else //2.0 forward
|
||||
Timer4.attachInterrupt(oneMSInterval);
|
||||
#endif
|
||||
Timer4.resume(); //Start Timer
|
||||
#else
|
||||
Timer11.setOverflow(1000, MICROSEC_FORMAT); // Set up period
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer11.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer11.attachInterrupt(1, oneMSInterval);
|
||||
#else
|
||||
Timer11.attachInterrupt(oneMSInterval);
|
||||
#endif
|
||||
Timer11.resume(); //Start Timer
|
||||
#endif
|
||||
pinMode(LED_BUILTIN, OUTPUT); //Visual WDT
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
//2uS resolution Min 8Hz, Max 5KHz
|
||||
|
||||
boost_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle
|
||||
fan_pwm_max_count = 1000000L / (TIMER_RESOLUTION * configPage6.fanFreq * 2); //Converts the frequency in Hz to the number of ticks (at 4uS) it takes to complete 1 cycle
|
||||
|
||||
//Need to be initialised last due to instant interrupt
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer1.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer1.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer1.attachInterrupt(1, fanInterrupt);
|
||||
Timer1.attachInterrupt(2, boostInterrupt);
|
||||
Timer1.attachInterrupt(3, vvtInterrupt);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
Timer1.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer2.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer3.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
|
||||
Timer1.setPrescaleFactor(((Timer1.getTimerClkFreq()/1000000) * TIMER_RESOLUTION)-1); //4us resolution
|
||||
Timer2.setPrescaleFactor(((Timer2.getTimerClkFreq()/1000000) * TIMER_RESOLUTION)-1); //4us resolution
|
||||
Timer3.setPrescaleFactor(((Timer3.getTimerClkFreq()/1000000) * TIMER_RESOLUTION)-1); //4us resolution
|
||||
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
//Attach interrupt functions
|
||||
//Injection
|
||||
Timer3.attachInterrupt(1, fuelSchedule1Interrupt);
|
||||
Timer3.attachInterrupt(2, fuelSchedule2Interrupt);
|
||||
Timer3.attachInterrupt(3, fuelSchedule3Interrupt);
|
||||
Timer3.attachInterrupt(4, fuelSchedule4Interrupt);
|
||||
#if (INJ_CHANNELS >= 5)
|
||||
Timer5.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer5.setPrescaleFactor(((Timer5.getTimerClkFreq()/1000000) * TIMER_RESOLUTION)-1); //4us resolution
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 6)
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer5.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer5.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(2, fuelSchedule6Interrupt);
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 7)
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer5.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer5.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(3, fuelSchedule7Interrupt);
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 8)
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer5.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer5.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer5.attachInterrupt(4, fuelSchedule8Interrupt);
|
||||
#endif
|
||||
|
||||
//Ignition
|
||||
Timer2.attachInterrupt(1, ignitionSchedule1Interrupt);
|
||||
Timer2.attachInterrupt(2, ignitionSchedule2Interrupt);
|
||||
Timer2.attachInterrupt(3, ignitionSchedule3Interrupt);
|
||||
Timer2.attachInterrupt(4, ignitionSchedule4Interrupt);
|
||||
#if (IGN_CHANNELS >= 5)
|
||||
Timer4.setOverflow(0xFFFF, TICK_FORMAT);
|
||||
Timer4.setPrescaleFactor(((Timer4.getTimerClkFreq()/1000000) * TIMER_RESOLUTION)-1); //4us resolution
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 6)
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer4.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer4.setMode(2, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(2, ignitionSchedule6Interrupt);
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 7)
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer4.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer4.setMode(3, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(3, ignitionSchedule7Interrupt);
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 8)
|
||||
#if ( STM32_CORE_VERSION_MAJOR < 2 )
|
||||
Timer4.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
#else //2.0 forward
|
||||
Timer4.setMode(4, TIMER_OUTPUT_COMPARE_TOGGLE);
|
||||
#endif
|
||||
Timer4.attachInterrupt(4, ignitionSchedule8Interrupt);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
uint32_t freeRam;
|
||||
uint32_t stackTop;
|
||||
uint32_t heapTop;
|
||||
|
||||
// current position of the stack.
|
||||
stackTop = (uint32_t)&stackTop;
|
||||
|
||||
// current position of heap.
|
||||
void *hTop = malloc(1);
|
||||
heapTop = (uint32_t)hTop;
|
||||
free(hTop);
|
||||
freeRam = stackTop - heapTop;
|
||||
|
||||
if(freeRam>0xFFFF){return 0xFFFF;}
|
||||
else{return freeRam;}
|
||||
}
|
||||
|
||||
void doSystemReset( void )
|
||||
{
|
||||
__disable_irq();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void jumpToBootloader( void ) // https://github.com/3devo/Arduino_Core_STM32/blob/jumpSysBL/libraries/SrcWrapper/src/stm32/bootloader.c
|
||||
{ // https://github.com/markusgritsch/SilF4ware/blob/master/SilF4ware/drv_reset.c
|
||||
#if !defined(STM32F103xB)
|
||||
HAL_RCC_DeInit();
|
||||
HAL_DeInit();
|
||||
SysTick->VAL = SysTick->LOAD = SysTick->CTRL = 0;
|
||||
SYSCFG->MEMRMP = 0x01;
|
||||
|
||||
#if defined(STM32F7xx) || defined(STM32H7xx)
|
||||
const uint32_t DFU_addr = 0x1FF00000; // From AN2606
|
||||
#else
|
||||
const uint32_t DFU_addr = 0x1FFF0000; // Default for STM32F10xxx and STM32F40xxx/STM32F41xxx from AN2606
|
||||
#endif
|
||||
// This is assembly to prevent modifying the stack pointer after
|
||||
// loading it, and to ensure a jump (not call) to the bootloader.
|
||||
// Not sure if the barriers are really needed, they were taken from
|
||||
// https://github.com/GrumpyOldPizza/arduino-STM32L4/blob/ac659033eadd50cfe001ba1590a1362b2d87bb76/system/STM32L4xx/Source/boot_stm32l4xx.c#L159-L165
|
||||
asm volatile (
|
||||
"ldr r0, [%[DFU_addr], #0] \n\t" // get address of stack pointer
|
||||
"msr msp, r0 \n\t" // set stack pointer
|
||||
"ldr r0, [%[DFU_addr], #4] \n\t" // get address of reset handler
|
||||
"dsb \n\t" // data sync barrier
|
||||
"isb \n\t" // instruction sync barrier
|
||||
"bx r0 \n\t" // branch to bootloader
|
||||
: : [DFU_addr] "l" (DFU_addr) : "r0"
|
||||
);
|
||||
__builtin_unreachable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Interrupt callback functions
|
||||
*/
|
||||
#if ((STM32_CORE_VERSION_MINOR<=8) & (STM32_CORE_VERSION_MAJOR==1))
|
||||
void oneMSInterval(HardwareTimer*){oneMSInterval();}
|
||||
void boostInterrupt(HardwareTimer*){boostInterrupt();}
|
||||
void fuelSchedule1Interrupt(HardwareTimer*){fuelSchedule1Interrupt();}
|
||||
void fuelSchedule2Interrupt(HardwareTimer*){fuelSchedule2Interrupt();}
|
||||
void fuelSchedule3Interrupt(HardwareTimer*){fuelSchedule3Interrupt();}
|
||||
void fuelSchedule4Interrupt(HardwareTimer*){fuelSchedule4Interrupt();}
|
||||
#if (INJ_CHANNELS >= 5)
|
||||
void fuelSchedule5Interrupt(HardwareTimer*){fuelSchedule5Interrupt();}
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 6)
|
||||
void fuelSchedule6Interrupt(HardwareTimer*){fuelSchedule6Interrupt();}
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 7)
|
||||
void fuelSchedule7Interrupt(HardwareTimer*){fuelSchedule7Interrupt();}
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 8)
|
||||
void fuelSchedule8Interrupt(HardwareTimer*){fuelSchedule8Interrupt();}
|
||||
#endif
|
||||
void idleInterrupt(HardwareTimer*){idleInterrupt();}
|
||||
void vvtInterrupt(HardwareTimer*){vvtInterrupt();}
|
||||
void fanInterrupt(HardwareTimer*){fanInterrupt();}
|
||||
void ignitionSchedule1Interrupt(HardwareTimer*){ignitionSchedule1Interrupt();}
|
||||
void ignitionSchedule2Interrupt(HardwareTimer*){ignitionSchedule2Interrupt();}
|
||||
void ignitionSchedule3Interrupt(HardwareTimer*){ignitionSchedule3Interrupt();}
|
||||
void ignitionSchedule4Interrupt(HardwareTimer*){ignitionSchedule4Interrupt();}
|
||||
#if (IGN_CHANNELS >= 5)
|
||||
void ignitionSchedule5Interrupt(HardwareTimer*){ignitionSchedule5Interrupt();}
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 6)
|
||||
void ignitionSchedule6Interrupt(HardwareTimer*){ignitionSchedule6Interrupt();}
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 7)
|
||||
void ignitionSchedule7Interrupt(HardwareTimer*){ignitionSchedule7Interrupt();}
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 8)
|
||||
void ignitionSchedule8Interrupt(HardwareTimer*){ignitionSchedule8Interrupt();}
|
||||
#endif
|
||||
#endif //End core<=1.8
|
||||
#endif
|
|
@ -1,306 +1,304 @@
|
|||
#if defined(CORE_TEENSY) && defined(CORE_TEENSY35)
|
||||
#include "board_teensy35.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
#include "board_teensy35.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
#if defined(__MK64FX512__) // use for Teensy 3.5 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
#elif defined(__MK66FX1M0__) // use for Teensy 3.6 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
#endif
|
||||
#if defined(__MK64FX512__) // use for Teensy 3.5 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
#elif defined(__MK66FX1M0__) // use for Teensy 3.6 only
|
||||
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
#endif
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL))
|
||||
{
|
||||
// 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;
|
||||
|
||||
FTM2_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM2_CNTIN = 0x0000; // Shouldn't be needed, but just in case
|
||||
FTM2_CNT = 0x0000; // Reset the count to zero
|
||||
FTM2_MOD = 0xFFFF; // max modulus = 65535
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if ((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL))
|
||||
{
|
||||
//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;
|
||||
|
||||
FTM2_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM2_CNTIN = 0x0000; //Shouldn't be needed, but just in case
|
||||
FTM2_CNT = 0x0000; // Reset the count to zero
|
||||
FTM2_MOD = 0xFFFF; // max modulus = 65535
|
||||
|
||||
/*
|
||||
* Enable the clock for FTM0/1
|
||||
* 00 No clock selected. Disables the FTM counter.
|
||||
* 01 System clock
|
||||
* 10 Fixed frequency clock (32kHz)
|
||||
* 11 External clock
|
||||
*/
|
||||
FTM2_SC |= FTM_SC_CLKS(0b10);
|
||||
|
||||
/*
|
||||
* Trim the slow clock from 32kHz down to 31.25kHz (The slowest it will go)
|
||||
* This is somewhat imprecise and documentation is not good.
|
||||
* I poked the chip until I figured out the values associated with 31.25kHz
|
||||
*/
|
||||
MCG_C3 = 0x9B;
|
||||
|
||||
/*
|
||||
* Set Prescaler
|
||||
* This is the slowest that the timer can be clocked . It results in ticks of 32uS on the teensy 3.5:
|
||||
* 31250 Hz = Slow_clock
|
||||
* 1 * 1000000uS / Slow_clock = 32uS
|
||||
*
|
||||
* 000 = Divide by 1
|
||||
* 001 Divide by 2
|
||||
* 010 Divide by 4
|
||||
* 011 Divide by 8
|
||||
* 100 Divide by 16
|
||||
* 101 Divide by 32
|
||||
* 110 Divide by 64
|
||||
* 111 Divide by 128
|
||||
*/
|
||||
FTM2_SC |= FTM_SC_PS(0b0); //No prescaler
|
||||
|
||||
//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
|
||||
//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
|
||||
//Enable channel compare interrupt (This is currently disabled as not in use)
|
||||
//FTM2_C1SC |= FTM_CSC_CHIE;
|
||||
|
||||
//Enable IRQ Interrupt
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM2);
|
||||
}
|
||||
* Enable the clock for FTM0/1
|
||||
* 00 No clock selected. Disables the FTM counter.
|
||||
* 01 System clock
|
||||
* 10 Fixed frequency clock (32kHz)
|
||||
* 11 External clock
|
||||
*/
|
||||
FTM2_SC |= FTM_SC_CLKS(0b10);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
* Trim the slow clock from 32kHz down to 31.25kHz (The slowest it will go)
|
||||
* This is somewhat imprecise and documentation is not good.
|
||||
* I poked the chip until I figured out the values associated with 31.25kHz
|
||||
*/
|
||||
MCG_C3 = 0x9B;
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* BOOST and VVT
|
||||
*/
|
||||
if (configPage6.boostEnabled == 1 || configPage6.vvtEnabled == 1)
|
||||
{
|
||||
//FlexTimer 2, compare channel 0 is used for idle
|
||||
FTM1_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
|
||||
FTM1_MODE |= FTM_MODE_FTMEN; //Flex Timer module enable
|
||||
FTM1_MODE |= FTM_MODE_INIT;
|
||||
* Set Prescaler
|
||||
* This is the slowest that the timer can be clocked . It results in ticks of 32uS on the teensy 3.5:
|
||||
* 31250 Hz = Slow_clock
|
||||
* 1 * 1000000uS / Slow_clock = 32uS
|
||||
*
|
||||
* 000 = Divide by 1
|
||||
* 001 Divide by 2
|
||||
* 010 Divide by 4
|
||||
* 011 Divide by 8
|
||||
* 100 Divide by 16
|
||||
* 101 Divide by 32
|
||||
* 110 Divide by 64
|
||||
* 111 Divide by 128
|
||||
*/
|
||||
FTM2_SC |= FTM_SC_PS(0b0); // No prescaler
|
||||
|
||||
FTM1_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM1_CNTIN = 0x0000; //Shouldn't be needed, but just in case
|
||||
FTM1_CNT = 0x0000; // Reset the count to zero
|
||||
FTM1_MOD = 0xFFFF; // max modulus = 65535
|
||||
// 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
|
||||
// The below enables channel compare interrupt, but this is done in idleControl()
|
||||
// FTM2_C0SC |= FTM_CSC_CHIE;
|
||||
|
||||
/*
|
||||
* Enable the clock for FTM0/1
|
||||
* 00 No clock selected. Disables the FTM counter.
|
||||
* 01 System clock
|
||||
* 10 Fixed frequency clock (32kHz)
|
||||
* 11 External clock
|
||||
*/
|
||||
FTM1_SC |= FTM_SC_CLKS(0b10);
|
||||
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
|
||||
// Enable channel compare interrupt (This is currently disabled as not in use)
|
||||
// FTM2_C1SC |= FTM_CSC_CHIE;
|
||||
|
||||
/*
|
||||
* Trim the slow clock from 32kHz down to 31.25kHz (The slowest it will go)
|
||||
* This is somewhat imprecise and documentation is not good.
|
||||
* I poked the chip until I figured out the values associated with 31.25kHz
|
||||
*/
|
||||
MCG_C3 = 0x9B;
|
||||
// Enable IRQ Interrupt
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set Prescaler
|
||||
* This is the slowest that the timer can be clocked . It results in ticks of 32uS on the teensy 3.5:
|
||||
* 31250 Hz = Slow_clock
|
||||
* 1 * 1000000uS / Slow_clock = 32uS
|
||||
*
|
||||
* 000 = Divide by 1
|
||||
* 001 Divide by 2
|
||||
* 010 Divide by 4
|
||||
* 011 Divide by 8
|
||||
* 100 Divide by 16
|
||||
* 101 Divide by 32
|
||||
* 110 Divide by 64
|
||||
* 111 Divide by 128
|
||||
*/
|
||||
FTM1_SC |= FTM_SC_PS(0b0); //No prescaler
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
|
||||
//Setup the channels (See Pg 1014 of K64 DS).
|
||||
FTM1_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
|
||||
FTM1_C0SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
//The below enables channel compare interrupt, but this is done in idleControl()
|
||||
//FTM1_C0SC |= FTM_CSC_CHIE;
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* BOOST and VVT
|
||||
*/
|
||||
if(configPage6.boostEnabled == 1 || configPage6.vvtEnabled == 1)
|
||||
{
|
||||
// FlexTimer 2, compare channel 0 is used for idle
|
||||
FTM1_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
|
||||
FTM1_MODE |= FTM_MODE_FTMEN; // Flex Timer module enable
|
||||
FTM1_MODE |= FTM_MODE_INIT;
|
||||
|
||||
FTM1_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
|
||||
FTM1_C1SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
//Enable channel compare interrupt (This is currently disabled as not in use)
|
||||
//FTM1_C1SC |= 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
|
||||
//Enable channel compare interrupt (This is currently disabled as not in use)
|
||||
//FTM1_C2SC |= FTM_CSC_CHIE;
|
||||
|
||||
//Enable IRQ Interrupt
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM1);
|
||||
|
||||
boost_pwm_max_count = 1000000L / (32 * configPage6.boostFreq * 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
|
||||
vvt_pwm_max_count = 1000000L / (32 * configPage6.vvtFreq * 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
|
||||
fan_pwm_max_count = 1000000L / (32 * configPage6.fanFreq * 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
|
||||
|
||||
|
||||
}
|
||||
FTM1_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM1_CNTIN = 0x0000; // Shouldn't be needed, but just in case
|
||||
FTM1_CNT = 0x0000; // Reset the count to zero
|
||||
FTM1_MOD = 0xFFFF; // max modulus = 65535
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
//Uses the PIT timer on Teensy.
|
||||
lowResTimer.begin(oneMSInterval, 1000);
|
||||
* Enable the clock for FTM0/1
|
||||
* 00 No clock selected. Disables the FTM counter.
|
||||
* 01 System clock
|
||||
* 10 Fixed frequency clock (32kHz)
|
||||
* 11 External clock
|
||||
*/
|
||||
FTM1_SC |= FTM_SC_CLKS(0b10);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
|
||||
//FlexTimer 0 is used for 4 ignition and 4 injection schedules. There are 8 channels on this module, so no other timers are needed
|
||||
FTM0_MODE |= FTM_MODE_WPDIS; //Write Protection Disable
|
||||
FTM0_MODE |= FTM_MODE_FTMEN; //Flex Timer module enable
|
||||
FTM0_MODE |= FTM_MODE_INIT;
|
||||
|
||||
FTM0_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM0_CNTIN = 0x0000; //Shouldn't be needed, but just in case
|
||||
FTM0_CNT = 0x0000; //Reset the count to zero
|
||||
FTM0_MOD = 0xFFFF; //max modulus = 65535
|
||||
|
||||
//FlexTimer 3 is used for schedules on channel 5+. Currently only channel 5 is used, but will likely be expanded later
|
||||
FTM3_MODE |= FTM_MODE_WPDIS; //Write Protection Disable
|
||||
FTM3_MODE |= FTM_MODE_FTMEN; //Flex Timer module enable
|
||||
FTM3_MODE |= FTM_MODE_INIT;
|
||||
|
||||
FTM3_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM3_CNTIN = 0x0000; //Shouldn't be needed, but just in case
|
||||
FTM3_CNT = 0x0000; //Reset the count to zero
|
||||
FTM3_MOD = 0xFFFF; //max modulus = 65535
|
||||
* Trim the slow clock from 32kHz down to 31.25kHz (The slowest it will go)
|
||||
* This is somewhat imprecise and documentation is not good.
|
||||
* I poked the chip until I figured out the values associated with 31.25kHz
|
||||
*/
|
||||
MCG_C3 = 0x9B;
|
||||
|
||||
/*
|
||||
* Enable the clock for FTM0/1
|
||||
* 00 No clock selected. Disables the FTM counter.
|
||||
* 01 System clock
|
||||
* 10 Fixed frequency clock
|
||||
* 11 External clock
|
||||
*/
|
||||
FTM0_SC |= FTM_SC_CLKS(0b1);
|
||||
FTM3_SC |= FTM_SC_CLKS(0b1);
|
||||
* Set Prescaler
|
||||
* This is the slowest that the timer can be clocked . It results in ticks of 32uS on the teensy 3.5:
|
||||
* 31250 Hz = Slow_clock
|
||||
* 1 * 1000000uS / Slow_clock = 32uS
|
||||
*
|
||||
* 000 = Divide by 1
|
||||
* 001 Divide by 2
|
||||
* 010 Divide by 4
|
||||
* 011 Divide by 8
|
||||
* 100 Divide by 16
|
||||
* 101 Divide by 32
|
||||
* 110 Divide by 64
|
||||
* 111 Divide by 128
|
||||
*/
|
||||
FTM1_SC |= FTM_SC_PS(0b0); // No prescaler
|
||||
|
||||
/*
|
||||
* Set Prescaler
|
||||
* This is the slowest that the timer can be clocked (Without used the slow timer, which is too slow). It results in ticks of 2.13333uS on the teensy 3.5:
|
||||
* 60000000 Hz = F_BUS
|
||||
* 128 * 1000000uS / F_BUS = 2.133uS
|
||||
*
|
||||
* 000 = Divide by 1
|
||||
* 001 Divide by 2
|
||||
* 010 Divide by 4
|
||||
* 011 Divide by 8
|
||||
* 100 Divide by 16
|
||||
* 101 Divide by 32
|
||||
* 110 Divide by 64
|
||||
* 111 Divide by 128
|
||||
*/
|
||||
FTM0_SC |= FTM_SC_PS(0b111);
|
||||
FTM3_SC |= FTM_SC_PS(0b111);
|
||||
// Setup the channels (See Pg 1014 of K64 DS).
|
||||
FTM1_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
|
||||
FTM1_C0SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
// The below enables channel compare interrupt, but this is done in idleControl()
|
||||
// FTM1_C0SC |= FTM_CSC_CHIE;
|
||||
|
||||
//Setup the channels (See Pg 1014 of K64 DS).
|
||||
//The are probably not needed as power on state should be 0
|
||||
//FTM0_C0SC &= ~FTM_CSC_ELSB;
|
||||
//FTM0_C0SC &= ~FTM_CSC_ELSA;
|
||||
//FTM0_C0SC &= ~FTM_CSC_DMA;
|
||||
FTM0_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
|
||||
FTM0_C0SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C0SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
FTM1_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
|
||||
FTM1_C1SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
// Enable channel compare interrupt (This is currently disabled as not in use)
|
||||
// FTM1_C1SC |= FTM_CSC_CHIE;
|
||||
|
||||
FTM0_C1SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C1SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C1SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
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
|
||||
// Enable channel compare interrupt (This is currently disabled as not in use)
|
||||
// FTM1_C2SC |= FTM_CSC_CHIE;
|
||||
|
||||
FTM0_C2SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C2SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C2SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
// Enable IRQ Interrupt
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM1);
|
||||
|
||||
FTM0_C3SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C3SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C3SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
boost_pwm_max_count = 1000000L / (32 * configPage6.boostFreq * 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
|
||||
vvt_pwm_max_count = 1000000L / (32 * configPage6.vvtFreq * 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
|
||||
fan_pwm_max_count = 1000000L / (32 * configPage6.fanFreq * 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
|
||||
}
|
||||
|
||||
FTM0_C4SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C4SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C4SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
// Uses the PIT timer on Teensy.
|
||||
lowResTimer.begin(oneMSInterval, 1000);
|
||||
|
||||
FTM0_C5SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C5SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C5SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
|
||||
FTM0_C6SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C6SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C6SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
// FlexTimer 0 is used for 4 ignition and 4 injection schedules. There are 8 channels on this module, so no other timers are needed
|
||||
FTM0_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
|
||||
FTM0_MODE |= FTM_MODE_FTMEN; // Flex Timer module enable
|
||||
FTM0_MODE |= FTM_MODE_INIT;
|
||||
|
||||
FTM0_C7SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C7SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM0_C7SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
FTM0_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM0_CNTIN = 0x0000; // Shouldn't be needed, but just in case
|
||||
FTM0_CNT = 0x0000; // Reset the count to zero
|
||||
FTM0_MOD = 0xFFFF; // max modulus = 65535
|
||||
|
||||
//Do the same, but on flex timer 3 (Used for channels 5-8)
|
||||
FTM3_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
|
||||
FTM3_C0SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C0SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
// FlexTimer 3 is used for schedules on channel 5+. Currently only channel 5 is used, but will likely be expanded later
|
||||
FTM3_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
|
||||
FTM3_MODE |= FTM_MODE_FTMEN; // Flex Timer module enable
|
||||
FTM3_MODE |= FTM_MODE_INIT;
|
||||
|
||||
FTM3_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
|
||||
FTM3_C1SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C1SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
FTM3_SC = 0x00; // Set this to zero before changing the modulus
|
||||
FTM3_CNTIN = 0x0000; // Shouldn't be needed, but just in case
|
||||
FTM3_CNT = 0x0000; // Reset the count to zero
|
||||
FTM3_MOD = 0xFFFF; // max modulus = 65535
|
||||
|
||||
FTM3_C2SC &= ~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
|
||||
FTM3_C2SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C2SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
/*
|
||||
* Enable the clock for FTM0/1
|
||||
* 00 No clock selected. Disables the FTM counter.
|
||||
* 01 System clock
|
||||
* 10 Fixed frequency clock
|
||||
* 11 External clock
|
||||
*/
|
||||
FTM0_SC |= FTM_SC_CLKS(0b1);
|
||||
FTM3_SC |= FTM_SC_CLKS(0b1);
|
||||
|
||||
FTM3_C3SC &= ~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
|
||||
FTM3_C3SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C3SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
/*
|
||||
* Set Prescaler
|
||||
* This is the slowest that the timer can be clocked (Without used the slow timer, which is too slow). It results in ticks of 2.13333uS on the teensy 3.5:
|
||||
* 60000000 Hz = F_BUS
|
||||
* 128 * 1000000uS / F_BUS = 2.133uS
|
||||
*
|
||||
* 000 = Divide by 1
|
||||
* 001 Divide by 2
|
||||
* 010 Divide by 4
|
||||
* 011 Divide by 8
|
||||
* 100 Divide by 16
|
||||
* 101 Divide by 32
|
||||
* 110 Divide by 64
|
||||
* 111 Divide by 128
|
||||
*/
|
||||
FTM0_SC |= FTM_SC_PS(0b111);
|
||||
FTM3_SC |= FTM_SC_PS(0b111);
|
||||
|
||||
FTM3_C4SC &= ~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
|
||||
FTM3_C4SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C4SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
// Setup the channels (See Pg 1014 of K64 DS).
|
||||
// The are probably not needed as power on state should be 0
|
||||
// FTM0_C0SC &= ~FTM_CSC_ELSB;
|
||||
// FTM0_C0SC &= ~FTM_CSC_ELSA;
|
||||
// FTM0_C0SC &= ~FTM_CSC_DMA;
|
||||
FTM0_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
|
||||
FTM0_C0SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C0SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C5SC &= ~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
|
||||
FTM3_C5SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C5SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
FTM0_C1SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C1SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C1SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C6SC &= ~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
|
||||
FTM3_C6SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C6SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
FTM0_C2SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C2SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C2SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C7SC &= ~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
|
||||
FTM3_C7SC |= FTM_CSC_MSA; //Enable Compare mode
|
||||
FTM3_C7SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
|
||||
FTM0_C3SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C3SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C3SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
// enable IRQ Interrupt
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM0);
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM3);
|
||||
FTM0_C4SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C4SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C4SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM0_C5SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C5SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C5SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM0_C6SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C6SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C6SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM0_C7SC &= ~FTM_CSC_MSB; // According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
|
||||
FTM0_C7SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM0_C7SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
// Do the same, but on flex timer 3 (Used for channels 5-8)
|
||||
FTM3_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
|
||||
FTM3_C0SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C0SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_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
|
||||
FTM3_C1SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C1SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C2SC &= ~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
|
||||
FTM3_C2SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C2SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C3SC &= ~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
|
||||
FTM3_C3SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C3SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C4SC &= ~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
|
||||
FTM3_C4SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C4SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C5SC &= ~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
|
||||
FTM3_C5SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C5SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C6SC &= ~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
|
||||
FTM3_C6SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C6SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
FTM3_C7SC &= ~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
|
||||
FTM3_C7SC |= FTM_CSC_MSA; // Enable Compare mode
|
||||
FTM3_C7SC |= FTM_CSC_CHIE; // Enable channel compare interrupt
|
||||
|
||||
// enable IRQ Interrupt
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM0);
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM3);
|
||||
}
|
||||
|
||||
void ftm0_isr(void)
|
||||
{
|
||||
//Use separate variables for each test to ensure conversion to bool
|
||||
// Use separate variables for each test to ensure conversion to bool
|
||||
bool interrupt1 = (FTM0_C0SC & FTM_CSC_CHF);
|
||||
bool interrupt2 = (FTM0_C1SC & FTM_CSC_CHF);
|
||||
bool interrupt3 = (FTM0_C2SC & FTM_CSC_CHF);
|
||||
|
@ -310,103 +308,177 @@ void ftm0_isr(void)
|
|||
bool interrupt7 = (FTM0_C6SC & FTM_CSC_CHF);
|
||||
bool interrupt8 = (FTM0_C7SC & FTM_CSC_CHF);
|
||||
|
||||
if(interrupt1) { FTM0_C0SC &= ~FTM_CSC_CHF; fuelSchedule1Interrupt(); }
|
||||
else if(interrupt2) { FTM0_C1SC &= ~FTM_CSC_CHF; fuelSchedule2Interrupt(); }
|
||||
else if(interrupt3) { FTM0_C2SC &= ~FTM_CSC_CHF; fuelSchedule3Interrupt(); }
|
||||
else if(interrupt4) { FTM0_C3SC &= ~FTM_CSC_CHF; fuelSchedule4Interrupt(); }
|
||||
else if(interrupt5) { FTM0_C4SC &= ~FTM_CSC_CHF; ignitionSchedule1Interrupt(); }
|
||||
else if(interrupt6) { FTM0_C5SC &= ~FTM_CSC_CHF; ignitionSchedule2Interrupt(); }
|
||||
else if(interrupt7) { FTM0_C6SC &= ~FTM_CSC_CHF; ignitionSchedule3Interrupt(); }
|
||||
else if(interrupt8) { FTM0_C7SC &= ~FTM_CSC_CHF; ignitionSchedule4Interrupt(); }
|
||||
|
||||
if(interrupt1)
|
||||
{
|
||||
FTM0_C0SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule1Interrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
FTM0_C1SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule2Interrupt();
|
||||
}
|
||||
else if(interrupt3)
|
||||
{
|
||||
FTM0_C2SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule3Interrupt();
|
||||
}
|
||||
else if(interrupt4)
|
||||
{
|
||||
FTM0_C3SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule4Interrupt();
|
||||
}
|
||||
else if(interrupt5)
|
||||
{
|
||||
FTM0_C4SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule1Interrupt();
|
||||
}
|
||||
else if(interrupt6)
|
||||
{
|
||||
FTM0_C5SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule2Interrupt();
|
||||
}
|
||||
else if(interrupt7)
|
||||
{
|
||||
FTM0_C6SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule3Interrupt();
|
||||
}
|
||||
else if(interrupt8)
|
||||
{
|
||||
FTM0_C7SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule4Interrupt();
|
||||
}
|
||||
}
|
||||
void ftm3_isr(void)
|
||||
{
|
||||
|
||||
#if (INJ_CHANNELS >= 5)
|
||||
#if(INJ_CHANNELS >= 5)
|
||||
bool interrupt1 = (FTM3_C0SC & FTM_CSC_CHF);
|
||||
if(interrupt1) { FTM3_C0SC &= ~FTM_CSC_CHF; fuelSchedule5Interrupt(); }
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 6)
|
||||
if(interrupt1)
|
||||
{
|
||||
FTM3_C0SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule5Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 6)
|
||||
bool interrupt2 = (FTM3_C1SC & FTM_CSC_CHF);
|
||||
if(interrupt2) { FTM3_C1SC &= ~FTM_CSC_CHF; fuelSchedule6Interrupt(); }
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 7)
|
||||
if(interrupt2)
|
||||
{
|
||||
FTM3_C1SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule6Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 7)
|
||||
bool interrupt3 = (FTM3_C2SC & FTM_CSC_CHF);
|
||||
if(interrupt3) { FTM3_C2SC &= ~FTM_CSC_CHF; fuelSchedule7Interrupt(); }
|
||||
#endif
|
||||
#if (INJ_CHANNELS >= 8)
|
||||
if(interrupt3)
|
||||
{
|
||||
FTM3_C2SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule7Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(INJ_CHANNELS >= 8)
|
||||
bool interrupt4 = (FTM3_C3SC & FTM_CSC_CHF);
|
||||
if(interrupt4) { FTM3_C3SC &= ~FTM_CSC_CHF; fuelSchedule8Interrupt(); }
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 5)
|
||||
if(interrupt4)
|
||||
{
|
||||
FTM3_C3SC &= ~FTM_CSC_CHF;
|
||||
fuelSchedule8Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 5)
|
||||
bool interrupt5 = (FTM3_C4SC & FTM_CSC_CHF);
|
||||
if(interrupt5) { FTM3_C4SC &= ~FTM_CSC_CHF; ignitionSchedule5Interrupt(); }
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 6)
|
||||
if(interrupt5)
|
||||
{
|
||||
FTM3_C4SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule5Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 6)
|
||||
bool interrupt6 = (FTM3_C5SC & FTM_CSC_CHF);
|
||||
if(interrupt6) { FTM3_C5SC &= ~FTM_CSC_CHF; ignitionSchedule6Interrupt(); }
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 7)
|
||||
if(interrupt6)
|
||||
{
|
||||
FTM3_C5SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule6Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 7)
|
||||
bool interrupt7 = (FTM3_C6SC & FTM_CSC_CHF);
|
||||
if(interrupt7) { FTM3_C6SC &= ~FTM_CSC_CHF; ignitionSchedule7Interrupt(); }
|
||||
#endif
|
||||
#if (IGN_CHANNELS >= 8)
|
||||
if(interrupt7)
|
||||
{
|
||||
FTM3_C6SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule7Interrupt();
|
||||
}
|
||||
#endif
|
||||
#if(IGN_CHANNELS >= 8)
|
||||
bool interrupt8 = (FTM3_C7SC & FTM_CSC_CHF);
|
||||
if(interrupt8) { FTM3_C7SC &= ~FTM_CSC_CHF; ignitionSchedule8Interrupt(); }
|
||||
#endif
|
||||
|
||||
if(interrupt8)
|
||||
{
|
||||
FTM3_C7SC &= ~FTM_CSC_CHF;
|
||||
ignitionSchedule8Interrupt();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//Boost and VVT handler
|
||||
// Boost and VVT handler
|
||||
void ftm1_isr(void)
|
||||
{
|
||||
//FTM1 only has 2 compare channels (Is this correct?)
|
||||
//Use separate variables for each test to ensure conversion to bool
|
||||
// FTM1 only has 2 compare channels (Is this correct?)
|
||||
// Use separate variables for each test to ensure conversion to bool
|
||||
bool interrupt1 = (FTM1_C0SC & FTM_CSC_CHF);
|
||||
bool interrupt2 = (FTM1_C1SC & FTM_CSC_CHF);
|
||||
|
||||
if(interrupt1) { FTM1_C0SC &= ~FTM_CSC_CHF; boostInterrupt(); }
|
||||
else if(interrupt2) { FTM1_C1SC &= ~FTM_CSC_CHF; vvtInterrupt(); }
|
||||
|
||||
if(interrupt1)
|
||||
{
|
||||
FTM1_C0SC &= ~FTM_CSC_CHF;
|
||||
boostInterrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
FTM1_C1SC &= ~FTM_CSC_CHF;
|
||||
vvtInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
//Idle and spare handler
|
||||
// Idle and spare handler
|
||||
void ftm2_isr(void)
|
||||
{
|
||||
//FTM2 only has 2 compare channels
|
||||
//Use separate variables for each test to ensure conversion to bool
|
||||
{
|
||||
// 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); //For PWM Fan
|
||||
bool interrupt2 = (FTM2_C1SC & FTM_CSC_CHF); // For PWM Fan
|
||||
|
||||
if(interrupt1) { FTM2_C0SC &= ~FTM_CSC_CHF; idleInterrupt(); }
|
||||
else if(interrupt2) { FTM2_C1SC &= ~FTM_CSC_CHF; fanInterrupt(); } //For PWM Fan
|
||||
if(interrupt1)
|
||||
{
|
||||
FTM2_C0SC &= ~FTM_CSC_CHF;
|
||||
idleInterrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
FTM2_C1SC &= ~FTM_CSC_CHF;
|
||||
fanInterrupt();
|
||||
} // For PWM Fan
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
uint32_t freeRam;
|
||||
uint32_t stackTop;
|
||||
uint32_t heapTop;
|
||||
uint32_t freeRam;
|
||||
uint32_t stackTop;
|
||||
uint32_t heapTop;
|
||||
|
||||
// current position of the stack.
|
||||
stackTop = (uint32_t)&stackTop;
|
||||
// current position of the stack.
|
||||
stackTop = (uint32_t)&stackTop;
|
||||
|
||||
// current position of heap.
|
||||
void *hTop = malloc(1);
|
||||
heapTop = (uint32_t)hTop;
|
||||
free(hTop);
|
||||
freeRam = stackTop - heapTop;
|
||||
// current position of heap.
|
||||
void *hTop = malloc(1);
|
||||
heapTop = (uint32_t)hTop;
|
||||
free(hTop);
|
||||
freeRam = stackTop - heapTop;
|
||||
|
||||
if(freeRam>0xFFFF){return 0xFFFF;}
|
||||
else{return freeRam;}
|
||||
if(freeRam > 0xFFFF) { return 0xFFFF; }
|
||||
else { return freeRam; }
|
||||
}
|
||||
|
||||
//This function is used for attempting to set the RTC time during compile
|
||||
time_t getTeensy3Time()
|
||||
{
|
||||
return Teensy3Clock.get();
|
||||
}
|
||||
// This function is used for attempting to set the RTC time during compile
|
||||
time_t getTeensy3Time() { return Teensy3Clock.get(); }
|
||||
|
||||
void doSystemReset() { return; }
|
||||
void jumpToBootloader() { return; }
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#if defined(CORE_TEENSY) && defined(__IMXRT1062__)
|
||||
#include "board_teensy41.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
#include "board_teensy41.h"
|
||||
#include "globals.h"
|
||||
#include "auxiliaries.h"
|
||||
#include "idle.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;
|
||||
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can1;
|
||||
|
@ -11,194 +11,194 @@ FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can2;
|
|||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
|
||||
/*
|
||||
Idle + Boost + VVT use the PIT timer. THIS IS ALSO USED BY THE INTERVAL TIMER THAT CALLS THE 1MS LOW RES TIMER!
|
||||
This has 4 channels that don't have compare registers, but will run for a period of time and then fire an interrupt
|
||||
The clock for these is set to 24Mhz and a prescale of 48 is used to give a 2uS tick time
|
||||
Set Prescaler
|
||||
* This is ideally too fast, but appears to be the slowest that the PIT can be set
|
||||
* 24Mhz = PER_clock
|
||||
* 48 * 1000000uS / PER_clock = 2uS
|
||||
*/
|
||||
CCM_CSCMR1 |= CCM_CSCMR1_PERCLK_CLK_SEL; // 24MHz
|
||||
CCM_CSCMR1 |= CCM_CSCMR1_PERCLK_PODF(0b101111); //Prescale to 48
|
||||
/*
|
||||
Idle + Boost + VVT use the PIT timer. THIS IS ALSO USED BY THE INTERVAL TIMER THAT CALLS THE 1MS LOW RES TIMER!
|
||||
This has 4 channels that don't have compare registers, but will run for a period of time and then fire an interrupt
|
||||
The clock for these is set to 24Mhz and a prescale of 48 is used to give a 2uS tick time
|
||||
Set Prescaler
|
||||
* This is ideally too fast, but appears to be the slowest that the PIT can be set
|
||||
* 24Mhz = PER_clock
|
||||
* 48 * 1000000uS / PER_clock = 2uS
|
||||
*/
|
||||
CCM_CSCMR1 |= CCM_CSCMR1_PERCLK_CLK_SEL; // 24MHz
|
||||
CCM_CSCMR1 |= CCM_CSCMR1_PERCLK_PODF(0b101111); // Prescale to 48
|
||||
|
||||
attachInterruptVector(IRQ_PIT, PIT_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_PIT);
|
||||
attachInterruptVector(IRQ_PIT, PIT_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_PIT);
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL))
|
||||
{
|
||||
PIT_TCTRL0 = 0;
|
||||
PIT_TCTRL0 |= PIT_TCTRL_TIE; // enable Timer 1 interrupts
|
||||
PIT_TCTRL0 |= PIT_TCTRL_TEN; // start Timer 1
|
||||
PIT_LDVAL0 = 1; //1 * 2uS = 2uS
|
||||
}
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
if((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL))
|
||||
{
|
||||
PIT_TCTRL0 = 0;
|
||||
PIT_TCTRL0 |= PIT_TCTRL_TIE; // enable Timer 1 interrupts
|
||||
PIT_TCTRL0 |= PIT_TCTRL_TEN; // start Timer 1
|
||||
PIT_LDVAL0 = 1; // 1 * 2uS = 2uS
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
//Uses the PIT timer channel 4 on Teensy 4.1.
|
||||
//lowResTimer.begin(oneMSInterval, 1000);
|
||||
PIT_TCTRL3 = 0;
|
||||
PIT_TCTRL3 |= PIT_TCTRL_TIE; // enable Timer 2 interrupts
|
||||
PIT_TCTRL3 |= PIT_TCTRL_TEN; // start Timer 2
|
||||
PIT_LDVAL3 = 500; //500 * 2uS = 1ms
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
// Uses the PIT timer channel 4 on Teensy 4.1.
|
||||
// lowResTimer.begin(oneMSInterval, 1000);
|
||||
PIT_TCTRL3 = 0;
|
||||
PIT_TCTRL3 |= PIT_TCTRL_TIE; // enable Timer 2 interrupts
|
||||
PIT_TCTRL3 |= PIT_TCTRL_TEN; // start Timer 2
|
||||
PIT_LDVAL3 = 500; // 500 * 2uS = 1ms
|
||||
|
||||
//TODO: Configure timers here
|
||||
// TODO: Configure timers here
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
if (configPage6.boostEnabled == 1)
|
||||
{
|
||||
PIT_TCTRL1 = 0;
|
||||
PIT_TCTRL1 |= PIT_TCTRL_TIE; // enable Timer 2 interrupts
|
||||
PIT_TCTRL1 |= PIT_TCTRL_TEN; // start Timer 2
|
||||
PIT_LDVAL1 = 1; //1 * 2uS = 2uS
|
||||
}
|
||||
if (configPage6.vvtEnabled == 1)
|
||||
{
|
||||
PIT_TCTRL2 = 0;
|
||||
PIT_TCTRL2 |= PIT_TCTRL_TIE; // enable Timer 3 interrupts
|
||||
PIT_TCTRL2 |= PIT_TCTRL_TEN; // start Timer 3
|
||||
PIT_LDVAL2 = 1; //1 * 2uS = 2uS
|
||||
}
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
if(configPage6.boostEnabled == 1)
|
||||
{
|
||||
PIT_TCTRL1 = 0;
|
||||
PIT_TCTRL1 |= PIT_TCTRL_TIE; // enable Timer 2 interrupts
|
||||
PIT_TCTRL1 |= PIT_TCTRL_TEN; // start Timer 2
|
||||
PIT_LDVAL1 = 1; // 1 * 2uS = 2uS
|
||||
}
|
||||
if(configPage6.vvtEnabled == 1)
|
||||
{
|
||||
PIT_TCTRL2 = 0;
|
||||
PIT_TCTRL2 |= PIT_TCTRL_TIE; // enable Timer 3 interrupts
|
||||
PIT_TCTRL2 |= PIT_TCTRL_TEN; // start Timer 3
|
||||
PIT_LDVAL2 = 1; // 1 * 2uS = 2uS
|
||||
}
|
||||
|
||||
//2uS resolution Min 8Hz, Max 5KHz
|
||||
boost_pwm_max_count = 1000000L / (2 * configPage6.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
|
||||
#if defined(PWM_FAN_AVAILABLE)
|
||||
fan_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
|
||||
#endif
|
||||
// 2uS resolution Min 8Hz, Max 5KHz
|
||||
boost_pwm_max_count = 1000000L / (2 * configPage6.boostFreq * 2); // Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow frequencies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); // Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
|
||||
#if defined(PWM_FAN_AVAILABLE)
|
||||
fan_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); // Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
|
||||
#endif
|
||||
|
||||
//TODO: Configure timers here
|
||||
// TODO: Configure timers here
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
//Use the Quad timer
|
||||
//Uses the BUS clock speed, which is 1/4 of the CPU clock. Maximum prescaler of 128 is used to give a 0.853333uS tick time @ 600Mhz
|
||||
//TMR1 - Fuel 1-4
|
||||
//0
|
||||
TMR1_CTRL0 = 0;
|
||||
TMR1_CSCTRL0 = 0;
|
||||
TMR1_LOAD0 = 0; /* Reset load register */
|
||||
TMR1_CTRL0 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR1_CTRL0 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//1
|
||||
TMR1_CTRL1 = 0;
|
||||
TMR1_CSCTRL1 = 0;
|
||||
TMR1_LOAD1 = 0; /* Reset load register */
|
||||
TMR1_CTRL1 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR1_CTRL1 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//2
|
||||
TMR1_CTRL2 = 0;
|
||||
TMR1_CSCTRL2 = 0;
|
||||
TMR1_LOAD2 = 0; /* Reset load register */
|
||||
TMR1_CTRL2 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR1_CTRL2 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//3
|
||||
TMR1_CTRL3 = 0;
|
||||
TMR1_CSCTRL3 = 0;
|
||||
TMR1_LOAD3 = 0; /* Reset load register */
|
||||
TMR1_CTRL3 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR1_CTRL3 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//TMR2 - Ign 1-4
|
||||
//0
|
||||
TMR2_CTRL0 = 0;
|
||||
TMR2_CSCTRL0 = 0;
|
||||
TMR2_LOAD0 = 0; /* Reset load register */
|
||||
TMR2_CTRL0 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR2_CTRL0 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//1
|
||||
TMR2_CTRL1 = 0;
|
||||
TMR2_CSCTRL1 = 0;
|
||||
TMR2_LOAD1 = 0; /* Reset load register */
|
||||
TMR2_CTRL1 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR2_CTRL1 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//2
|
||||
TMR2_CTRL2 = 0;
|
||||
TMR2_CSCTRL2 = 0;
|
||||
TMR2_LOAD2 = 0; /* Reset load register */
|
||||
TMR2_CTRL2 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR2_CTRL2 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//3
|
||||
TMR2_CTRL3 = 0;
|
||||
TMR2_CSCTRL3 = 0;
|
||||
TMR2_LOAD3 = 0; /* Reset load register */
|
||||
TMR2_CTRL3 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR2_CTRL3 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//TMR3 - Fuel 5-8
|
||||
//0
|
||||
TMR3_CTRL0 = 0;
|
||||
TMR3_CSCTRL0 = 0;
|
||||
TMR3_LOAD0 = 0; /* Reset load register */
|
||||
TMR3_CTRL0 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR3_CTRL0 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//1
|
||||
TMR3_CTRL1 = 0;
|
||||
TMR3_CSCTRL1 = 0;
|
||||
TMR3_LOAD1 = 0; /* Reset load register */
|
||||
TMR3_CTRL1 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR3_CTRL1 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//2
|
||||
TMR3_CTRL2 = 0;
|
||||
TMR3_CSCTRL2 = 0;
|
||||
TMR3_LOAD2 = 0; /* Reset load register */
|
||||
TMR3_CTRL2 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR3_CTRL2 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//3
|
||||
TMR3_CTRL3 = 0;
|
||||
TMR3_CSCTRL3 = 0;
|
||||
TMR3_LOAD3 = 0; /* Reset load register */
|
||||
TMR3_CTRL3 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR3_CTRL3 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//TMR4 - IGN 5-8
|
||||
//0
|
||||
TMR4_CTRL0 = 0;
|
||||
TMR4_CSCTRL0 = 0;
|
||||
TMR4_LOAD0 = 0; /* Reset load register */
|
||||
TMR4_CTRL0 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR4_CTRL0 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//1
|
||||
TMR4_CTRL1 = 0;
|
||||
TMR4_CSCTRL1 = 0;
|
||||
TMR4_LOAD1 = 0; /* Reset load register */
|
||||
TMR4_CTRL1 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR4_CTRL1 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//2
|
||||
TMR4_CTRL2 = 0;
|
||||
TMR4_CSCTRL2 = 0;
|
||||
TMR4_LOAD2 = 0; /* Reset load register */
|
||||
TMR4_CTRL2 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR4_CTRL2 |= TMR_CTRL_CM(1); //Start the timer
|
||||
//3
|
||||
TMR4_CTRL3 = 0;
|
||||
TMR4_CSCTRL3 = 0;
|
||||
TMR4_LOAD3 = 0; /* Reset load register */
|
||||
TMR4_CTRL3 |= TMR_CTRL_PCS(0b1111); //Set the prescaler to 128
|
||||
TMR4_CTRL3 |= TMR_CTRL_CM(1); //Start the timer
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
// Use the Quad timer
|
||||
// Uses the BUS clock speed, which is 1/4 of the CPU clock. Maximum prescaler of 128 is used to give a 0.853333uS tick time @ 600Mhz
|
||||
// TMR1 - Fuel 1-4
|
||||
// 0
|
||||
TMR1_CTRL0 = 0;
|
||||
TMR1_CSCTRL0 = 0;
|
||||
TMR1_LOAD0 = 0; /* Reset load register */
|
||||
TMR1_CTRL0 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR1_CTRL0 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 1
|
||||
TMR1_CTRL1 = 0;
|
||||
TMR1_CSCTRL1 = 0;
|
||||
TMR1_LOAD1 = 0; /* Reset load register */
|
||||
TMR1_CTRL1 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR1_CTRL1 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 2
|
||||
TMR1_CTRL2 = 0;
|
||||
TMR1_CSCTRL2 = 0;
|
||||
TMR1_LOAD2 = 0; /* Reset load register */
|
||||
TMR1_CTRL2 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR1_CTRL2 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 3
|
||||
TMR1_CTRL3 = 0;
|
||||
TMR1_CSCTRL3 = 0;
|
||||
TMR1_LOAD3 = 0; /* Reset load register */
|
||||
TMR1_CTRL3 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR1_CTRL3 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// TMR2 - Ign 1-4
|
||||
// 0
|
||||
TMR2_CTRL0 = 0;
|
||||
TMR2_CSCTRL0 = 0;
|
||||
TMR2_LOAD0 = 0; /* Reset load register */
|
||||
TMR2_CTRL0 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR2_CTRL0 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 1
|
||||
TMR2_CTRL1 = 0;
|
||||
TMR2_CSCTRL1 = 0;
|
||||
TMR2_LOAD1 = 0; /* Reset load register */
|
||||
TMR2_CTRL1 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR2_CTRL1 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 2
|
||||
TMR2_CTRL2 = 0;
|
||||
TMR2_CSCTRL2 = 0;
|
||||
TMR2_LOAD2 = 0; /* Reset load register */
|
||||
TMR2_CTRL2 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR2_CTRL2 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 3
|
||||
TMR2_CTRL3 = 0;
|
||||
TMR2_CSCTRL3 = 0;
|
||||
TMR2_LOAD3 = 0; /* Reset load register */
|
||||
TMR2_CTRL3 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR2_CTRL3 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// TMR3 - Fuel 5-8
|
||||
// 0
|
||||
TMR3_CTRL0 = 0;
|
||||
TMR3_CSCTRL0 = 0;
|
||||
TMR3_LOAD0 = 0; /* Reset load register */
|
||||
TMR3_CTRL0 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR3_CTRL0 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 1
|
||||
TMR3_CTRL1 = 0;
|
||||
TMR3_CSCTRL1 = 0;
|
||||
TMR3_LOAD1 = 0; /* Reset load register */
|
||||
TMR3_CTRL1 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR3_CTRL1 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 2
|
||||
TMR3_CTRL2 = 0;
|
||||
TMR3_CSCTRL2 = 0;
|
||||
TMR3_LOAD2 = 0; /* Reset load register */
|
||||
TMR3_CTRL2 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR3_CTRL2 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 3
|
||||
TMR3_CTRL3 = 0;
|
||||
TMR3_CSCTRL3 = 0;
|
||||
TMR3_LOAD3 = 0; /* Reset load register */
|
||||
TMR3_CTRL3 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR3_CTRL3 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// TMR4 - IGN 5-8
|
||||
// 0
|
||||
TMR4_CTRL0 = 0;
|
||||
TMR4_CSCTRL0 = 0;
|
||||
TMR4_LOAD0 = 0; /* Reset load register */
|
||||
TMR4_CTRL0 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR4_CTRL0 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 1
|
||||
TMR4_CTRL1 = 0;
|
||||
TMR4_CSCTRL1 = 0;
|
||||
TMR4_LOAD1 = 0; /* Reset load register */
|
||||
TMR4_CTRL1 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR4_CTRL1 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 2
|
||||
TMR4_CTRL2 = 0;
|
||||
TMR4_CSCTRL2 = 0;
|
||||
TMR4_LOAD2 = 0; /* Reset load register */
|
||||
TMR4_CTRL2 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR4_CTRL2 |= TMR_CTRL_CM(1); // Start the timer
|
||||
// 3
|
||||
TMR4_CTRL3 = 0;
|
||||
TMR4_CSCTRL3 = 0;
|
||||
TMR4_LOAD3 = 0; /* Reset load register */
|
||||
TMR4_CTRL3 |= TMR_CTRL_PCS(0b1111); // Set the prescaler to 128
|
||||
TMR4_CTRL3 |= TMR_CTRL_CM(1); // Start the timer
|
||||
|
||||
attachInterruptVector(IRQ_QTIMER1, TMR1_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER1);
|
||||
attachInterruptVector(IRQ_QTIMER2, TMR2_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER2);
|
||||
attachInterruptVector(IRQ_QTIMER3, TMR3_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER3);
|
||||
attachInterruptVector(IRQ_QTIMER4, TMR4_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER4);
|
||||
attachInterruptVector(IRQ_QTIMER1, TMR1_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER1);
|
||||
attachInterruptVector(IRQ_QTIMER2, TMR2_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER2);
|
||||
attachInterruptVector(IRQ_QTIMER3, TMR3_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER3);
|
||||
attachInterruptVector(IRQ_QTIMER4, TMR4_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_QTIMER4);
|
||||
}
|
||||
|
||||
void PIT_isr()
|
||||
|
@ -208,105 +208,182 @@ void PIT_isr()
|
|||
bool interrupt3 = (PIT_TFLG2 & PIT_TFLG_TIF);
|
||||
bool interrupt4 = (PIT_TFLG3 & PIT_TFLG_TIF);
|
||||
|
||||
if(interrupt1) { PIT_TFLG0 = 1; idleInterrupt(); }
|
||||
else if(interrupt2) { PIT_TFLG1 = 1; boostInterrupt(); }
|
||||
else if(interrupt3) { PIT_TFLG2 = 1; vvtInterrupt(); }
|
||||
else if(interrupt4) { PIT_TFLG3 = 1; oneMSInterval(); }
|
||||
if(interrupt1)
|
||||
{
|
||||
PIT_TFLG0 = 1;
|
||||
idleInterrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
PIT_TFLG1 = 1;
|
||||
boostInterrupt();
|
||||
}
|
||||
else if(interrupt3)
|
||||
{
|
||||
PIT_TFLG2 = 1;
|
||||
vvtInterrupt();
|
||||
}
|
||||
else if(interrupt4)
|
||||
{
|
||||
PIT_TFLG3 = 1;
|
||||
oneMSInterval();
|
||||
}
|
||||
}
|
||||
|
||||
void TMR1_isr(void)
|
||||
{
|
||||
//TMR1 is fuel channels 1-4
|
||||
// TMR1 is fuel channels 1-4
|
||||
bool interrupt1 = (TMR1_CSCTRL0 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt2 = (TMR1_CSCTRL1 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt3 = (TMR1_CSCTRL2 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt4 = (TMR1_CSCTRL3 & TMR_CSCTRL_TCF1);
|
||||
|
||||
if(interrupt1) { TMR1_CSCTRL0 &= ~TMR_CSCTRL_TCF1; fuelSchedule1Interrupt(); }
|
||||
else if(interrupt2) { TMR1_CSCTRL1 &= ~TMR_CSCTRL_TCF1; fuelSchedule2Interrupt(); }
|
||||
else if(interrupt3) { TMR1_CSCTRL2 &= ~TMR_CSCTRL_TCF1; fuelSchedule3Interrupt(); }
|
||||
else if(interrupt4) { TMR1_CSCTRL3 &= ~TMR_CSCTRL_TCF1; fuelSchedule4Interrupt(); }
|
||||
if(interrupt1)
|
||||
{
|
||||
TMR1_CSCTRL0 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule1Interrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
TMR1_CSCTRL1 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule2Interrupt();
|
||||
}
|
||||
else if(interrupt3)
|
||||
{
|
||||
TMR1_CSCTRL2 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule3Interrupt();
|
||||
}
|
||||
else if(interrupt4)
|
||||
{
|
||||
TMR1_CSCTRL3 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule4Interrupt();
|
||||
}
|
||||
}
|
||||
void TMR2_isr(void)
|
||||
{
|
||||
//TMR2 is IGN channels 1-4
|
||||
// TMR2 is IGN channels 1-4
|
||||
bool interrupt1 = (TMR2_CSCTRL0 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt2 = (TMR2_CSCTRL1 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt3 = (TMR2_CSCTRL2 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt4 = (TMR2_CSCTRL3 & TMR_CSCTRL_TCF1);
|
||||
|
||||
if(interrupt1) { TMR2_CSCTRL0 &= ~TMR_CSCTRL_TCF1; ignitionSchedule1Interrupt(); }
|
||||
else if(interrupt2) { TMR2_CSCTRL1 &= ~TMR_CSCTRL_TCF1; ignitionSchedule2Interrupt(); }
|
||||
else if(interrupt3) { TMR2_CSCTRL2 &= ~TMR_CSCTRL_TCF1; ignitionSchedule3Interrupt(); }
|
||||
else if(interrupt4) { TMR2_CSCTRL3 &= ~TMR_CSCTRL_TCF1; ignitionSchedule4Interrupt(); }
|
||||
if(interrupt1)
|
||||
{
|
||||
TMR2_CSCTRL0 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule1Interrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
TMR2_CSCTRL1 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule2Interrupt();
|
||||
}
|
||||
else if(interrupt3)
|
||||
{
|
||||
TMR2_CSCTRL2 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule3Interrupt();
|
||||
}
|
||||
else if(interrupt4)
|
||||
{
|
||||
TMR2_CSCTRL3 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule4Interrupt();
|
||||
}
|
||||
}
|
||||
void TMR3_isr(void)
|
||||
{
|
||||
//TMR3 is Fuel channels 5-8
|
||||
// TMR3 is Fuel channels 5-8
|
||||
bool interrupt1 = (TMR3_CSCTRL0 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt2 = (TMR3_CSCTRL1 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt3 = (TMR3_CSCTRL2 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt4 = (TMR3_CSCTRL3 & TMR_CSCTRL_TCF1);
|
||||
|
||||
if(interrupt1) { TMR3_CSCTRL0 &= ~TMR_CSCTRL_TCF1; fuelSchedule5Interrupt(); }
|
||||
else if(interrupt2) { TMR3_CSCTRL1 &= ~TMR_CSCTRL_TCF1; fuelSchedule6Interrupt(); }
|
||||
else if(interrupt3) { TMR3_CSCTRL2 &= ~TMR_CSCTRL_TCF1; fuelSchedule7Interrupt(); }
|
||||
else if(interrupt4) { TMR3_CSCTRL3 &= ~TMR_CSCTRL_TCF1; fuelSchedule8Interrupt(); }
|
||||
if(interrupt1)
|
||||
{
|
||||
TMR3_CSCTRL0 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule5Interrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
TMR3_CSCTRL1 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule6Interrupt();
|
||||
}
|
||||
else if(interrupt3)
|
||||
{
|
||||
TMR3_CSCTRL2 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule7Interrupt();
|
||||
}
|
||||
else if(interrupt4)
|
||||
{
|
||||
TMR3_CSCTRL3 &= ~TMR_CSCTRL_TCF1;
|
||||
fuelSchedule8Interrupt();
|
||||
}
|
||||
}
|
||||
void TMR4_isr(void)
|
||||
{
|
||||
//TMR4 is IGN channels 5-8
|
||||
// TMR4 is IGN channels 5-8
|
||||
bool interrupt1 = (TMR4_CSCTRL0 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt2 = (TMR4_CSCTRL1 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt3 = (TMR4_CSCTRL2 & TMR_CSCTRL_TCF1);
|
||||
bool interrupt4 = (TMR4_CSCTRL3 & TMR_CSCTRL_TCF1);
|
||||
|
||||
if(interrupt1) { TMR4_CSCTRL0 &= ~TMR_CSCTRL_TCF1; ignitionSchedule5Interrupt(); }
|
||||
else if(interrupt2) { TMR4_CSCTRL1 &= ~TMR_CSCTRL_TCF1; ignitionSchedule6Interrupt(); }
|
||||
else if(interrupt3) { TMR4_CSCTRL2 &= ~TMR_CSCTRL_TCF1; ignitionSchedule7Interrupt(); }
|
||||
else if(interrupt4) { TMR4_CSCTRL3 &= ~TMR_CSCTRL_TCF1; ignitionSchedule8Interrupt(); }
|
||||
if(interrupt1)
|
||||
{
|
||||
TMR4_CSCTRL0 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule5Interrupt();
|
||||
}
|
||||
else if(interrupt2)
|
||||
{
|
||||
TMR4_CSCTRL1 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule6Interrupt();
|
||||
}
|
||||
else if(interrupt3)
|
||||
{
|
||||
TMR4_CSCTRL2 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule7Interrupt();
|
||||
}
|
||||
else if(interrupt4)
|
||||
{
|
||||
TMR4_CSCTRL3 &= ~TMR_CSCTRL_TCF1;
|
||||
ignitionSchedule8Interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
uint32_t stackTop;
|
||||
uint32_t heapTop;
|
||||
uint32_t stackTop;
|
||||
uint32_t heapTop;
|
||||
|
||||
// current position of the stack.
|
||||
stackTop = (uint32_t) &stackTop;
|
||||
// current position of the stack.
|
||||
stackTop = (uint32_t)&stackTop;
|
||||
|
||||
// current position of heap.
|
||||
void* hTop = malloc(1);
|
||||
heapTop = (uint32_t) hTop;
|
||||
free(hTop);
|
||||
// current position of heap.
|
||||
void *hTop = malloc(1);
|
||||
heapTop = (uint32_t)hTop;
|
||||
free(hTop);
|
||||
|
||||
// The difference is the free, available ram.
|
||||
return (uint16_t)stackTop - heapTop;
|
||||
// The difference is the free, available ram.
|
||||
return (uint16_t)stackTop - heapTop;
|
||||
}
|
||||
|
||||
//This function is used for attempting to set the RTC time during compile
|
||||
time_t getTeensy3Time()
|
||||
{
|
||||
return Teensy3Clock.get();
|
||||
}
|
||||
// This function is used for attempting to set the RTC time during compile
|
||||
time_t getTeensy3Time() { return Teensy3Clock.get(); }
|
||||
|
||||
void doSystemReset() { return; }
|
||||
void jumpToBootloader() { return; }
|
||||
|
||||
void setTriggerHysteresis()
|
||||
{
|
||||
//Refer to digital.c in the Teensyduino core for the following code
|
||||
//Refer also to Pgs 382 and 950 of the iMXRT1060 Reference Manual
|
||||
// Refer to digital.c in the Teensyduino core for the following code
|
||||
// Refer also to Pgs 382 and 950 of the iMXRT1060 Reference Manual
|
||||
const struct digital_pin_bitband_and_config_table_struct *p;
|
||||
const uint32_t padConfig = IOMUXC_PAD_DSE(1) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_SPEED(0) | IOMUXC_PAD_HYS;
|
||||
const uint32_t padConfig = IOMUXC_PAD_DSE(1) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_SPEED(0) | IOMUXC_PAD_HYS;
|
||||
|
||||
//Primary trigger
|
||||
// Primary trigger
|
||||
p = digital_pin_to_info_PGM + pinTrigger;
|
||||
*(p->reg + 1) &= ~(p->mask); // TODO: atomic
|
||||
*(p->pad) = padConfig;
|
||||
*(p->mux) = 5 | 0x10;
|
||||
|
||||
//Secondary trigger
|
||||
// Secondary trigger
|
||||
p = digital_pin_to_info_PGM + pinTrigger2;
|
||||
*(p->reg + 1) &= ~(p->mask); // TODO: atomic
|
||||
*(p->pad) = padConfig;
|
||||
|
|
|
@ -1,38 +1,35 @@
|
|||
#if defined(CORE_TEMPLATE)
|
||||
#include "globals.h"
|
||||
#include "globals.h"
|
||||
|
||||
void initBoard()
|
||||
{
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* General
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Timers
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Auxiliaries
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Idle
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************
|
||||
* Schedules
|
||||
*/
|
||||
}
|
||||
|
||||
uint16_t freeRam()
|
||||
{
|
||||
|
||||
}
|
||||
uint16_t freeRam() {}
|
||||
|
||||
void doSystemReset() { return; }
|
||||
void jumpToBootloader() { return; }
|
||||
|
|
|
@ -8,7 +8,7 @@ A full copy of the license may be found in the projects root directory
|
|||
This is for handling the data broadcasted to various CAN dashes and instrument clusters.
|
||||
*/
|
||||
#if defined(NATIVE_CAN_AVAILABLE)
|
||||
#include "globals.h"
|
||||
#include "globals.h"
|
||||
|
||||
// Forward declare
|
||||
void DashMessage(uint16_t DashMessageID);
|
||||
|
@ -34,76 +34,76 @@ void sendVAGCluster()
|
|||
// switch case for gathering all data to message based on CAN Id.
|
||||
void DashMessage(uint16_t DashMessageID)
|
||||
{
|
||||
switch (DashMessageID)
|
||||
switch(DashMessageID)
|
||||
{
|
||||
case CAN_BMW_DME1:
|
||||
uint32_t temp_RPM;
|
||||
temp_RPM = currentStatus.RPM * 64; //RPM conversion is currentStatus.RPM * 6.4, but this does it without floats.
|
||||
temp_RPM = temp_RPM / 10;
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 8;
|
||||
outMsg.buf[0] = 0x05; //bitfield, Bit0 = 1 = terminal 15 on detected, Bit2 = 1 = the ASC message ASC1 was received within the last 500 ms and contains no plausibility errors
|
||||
outMsg.buf[1] = 0x0C; //Indexed Engine Torque in % of C_TQ_STND TBD do torque calculation.
|
||||
outMsg.buf[2] = lowByte(uint16_t(temp_RPM)); //lsb RPM
|
||||
outMsg.buf[3] = highByte(uint16_t(temp_RPM)); //msb RPM
|
||||
outMsg.buf[4] = 0x0C; //Indicated Engine Torque in % of C_TQ_STND TBD do torque calculation!! Use same as for byte 1
|
||||
outMsg.buf[5] = 0x15; //Engine Torque Loss (due to engine friction, AC compressor and electrical power consumption)
|
||||
outMsg.buf[6] = 0x00; //not used
|
||||
outMsg.buf[7] = 0x35; //Theorethical Engine Torque in % of C_TQ_STND after charge intervention
|
||||
break;
|
||||
temp_RPM = currentStatus.RPM * 64; // RPM conversion is currentStatus.RPM * 6.4, but this does it without floats.
|
||||
temp_RPM = temp_RPM / 10;
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 8;
|
||||
outMsg.buf[0] = 0x05; // bitfield, Bit0 = 1 = terminal 15 on detected, Bit2 = 1 = the ASC message ASC1 was received within the last 500 ms and contains no plausibility errors
|
||||
outMsg.buf[1] = 0x0C; // Indexed Engine Torque in % of C_TQ_STND TBD do torque calculation.
|
||||
outMsg.buf[2] = lowByte(uint16_t(temp_RPM)); // lsb RPM
|
||||
outMsg.buf[3] = highByte(uint16_t(temp_RPM)); // msb RPM
|
||||
outMsg.buf[4] = 0x0C; // Indicated Engine Torque in % of C_TQ_STND TBD do torque calculation!! Use same as for byte 1
|
||||
outMsg.buf[5] = 0x15; // Engine Torque Loss (due to engine friction, AC compressor and electrical power consumption)
|
||||
outMsg.buf[6] = 0x00; // not used
|
||||
outMsg.buf[7] = 0x35; // Theorethical Engine Torque in % of C_TQ_STND after charge intervention
|
||||
break;
|
||||
|
||||
case CAN_BMW_DME2:
|
||||
uint8_t temp_TPS;
|
||||
uint8_t temp_BARO;
|
||||
uint8_t temp_TPS;
|
||||
uint8_t temp_BARO;
|
||||
uint16_t temp_CLT;
|
||||
temp_TPS = map(currentStatus.TPS, 0, 100, 0, 254);//TPS value conversion (from 0x00 to 0xFE)
|
||||
temp_CLT = (((currentStatus.coolant - CALIBRATION_TEMPERATURE_OFFSET) + 48)*4/3); //CLT conversion (actual value to add is 48.373, but close enough)
|
||||
if (temp_CLT > 255) { temp_CLT = 255; } //CLT conversion can yield to higher values than what fits to byte, so limit the maximum value to 255.
|
||||
temp_TPS = map(currentStatus.TPS, 0, 100, 0, 254); // TPS value conversion (from 0x00 to 0xFE)
|
||||
temp_CLT = (((currentStatus.coolant - CALIBRATION_TEMPERATURE_OFFSET) + 48) * 4 / 3); // CLT conversion (actual value to add is 48.373, but close enough)
|
||||
if(temp_CLT > 255) { temp_CLT = 255; } // CLT conversion can yield to higher values than what fits to byte, so limit the maximum value to 255.
|
||||
temp_BARO = currentStatus.baro;
|
||||
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 7;
|
||||
outMsg.buf[0] = 0x11; //Multiplexed Information
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 7;
|
||||
outMsg.buf[0] = 0x11; // Multiplexed Information
|
||||
outMsg.buf[1] = temp_CLT;
|
||||
outMsg.buf[2] = temp_BARO;
|
||||
outMsg.buf[3] = 0x08; //bitfield, Bit0 = 0 = Clutch released, Bit 3 = 1 = engine running
|
||||
outMsg.buf[4] = 0x00; //TPS_VIRT_CRU_CAN (Not used)
|
||||
outMsg.buf[3] = 0x08; // bitfield, Bit0 = 0 = Clutch released, Bit 3 = 1 = engine running
|
||||
outMsg.buf[4] = 0x00; // TPS_VIRT_CRU_CAN (Not used)
|
||||
outMsg.buf[5] = temp_TPS;
|
||||
outMsg.buf[6] = 0x00; //bitfield, Bit0 = 0 = brake not actuated, Bit1 = 0 = brake switch system OK etc...
|
||||
outMsg.buf[7] = 0x00; //not used, but set to zero just in case.
|
||||
break;
|
||||
outMsg.buf[6] = 0x00; // bitfield, Bit0 = 0 = brake not actuated, Bit1 = 0 = brake switch system OK etc...
|
||||
outMsg.buf[7] = 0x00; // not used, but set to zero just in case.
|
||||
break;
|
||||
|
||||
case 0x545: //fuel consumption and CEl light for BMW e46/e39/e38 instrument cluster
|
||||
//fuel consumption calculation not implemented yet. But this still needs to be sent to get rid of the CEL and EML fault lights on the dash.
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 5;
|
||||
outMsg.buf[0] = 0x00; //Check engine light (binary 10), Cruise light (binary 1000), EML (binary 10000).
|
||||
outMsg.buf[1] = 0x00; //LSB Fuel consumption
|
||||
outMsg.buf[2] = 0x00; //MSB Fuel Consumption
|
||||
if (currentStatus.coolant > 159) { outMsg.buf[3] = 0x08; } //Turn on overheat light if coolant temp hits 120 degrees celsius.
|
||||
else { outMsg.buf[3] = 0x00; } //Overheat light off at normal engine temps.
|
||||
outMsg.buf[4] = 0x7E; //this is oil temp
|
||||
break;
|
||||
case 0x545: // fuel consumption and CEl light for BMW e46/e39/e38 instrument cluster
|
||||
// fuel consumption calculation not implemented yet. But this still needs to be sent to get rid of the CEL and EML fault lights on the dash.
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 5;
|
||||
outMsg.buf[0] = 0x00; // Check engine light (binary 10), Cruise light (binary 1000), EML (binary 10000).
|
||||
outMsg.buf[1] = 0x00; // LSB Fuel consumption
|
||||
outMsg.buf[2] = 0x00; // MSB Fuel Consumption
|
||||
if(currentStatus.coolant > 159) { outMsg.buf[3] = 0x08; } // Turn on overheat light if coolant temp hits 120 degrees celsius.
|
||||
else { outMsg.buf[3] = 0x00; } // Overheat light off at normal engine temps.
|
||||
outMsg.buf[4] = 0x7E; // this is oil temp
|
||||
break;
|
||||
|
||||
case 0x280: //RPM for VW instrument cluster
|
||||
temp_RPM = currentStatus.RPM * 4; //RPM conversion
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 8;
|
||||
case 0x280: // RPM for VW instrument cluster
|
||||
temp_RPM = currentStatus.RPM * 4; // RPM conversion
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 8;
|
||||
outMsg.buf[0] = 0x49;
|
||||
outMsg.buf[1] = 0x0E;
|
||||
outMsg.buf[2] = lowByte(uint16_t(temp_RPM)); //lsb RPM
|
||||
outMsg.buf[3] = highByte(uint16_t(temp_RPM)); //msb RPM
|
||||
outMsg.buf[2] = lowByte(uint16_t(temp_RPM)); // lsb RPM
|
||||
outMsg.buf[3] = highByte(uint16_t(temp_RPM)); // msb RPM
|
||||
outMsg.buf[4] = 0x0E;
|
||||
outMsg.buf[5] = 0x00;
|
||||
outMsg.buf[6] = 0x1B;
|
||||
outMsg.buf[7] = 0x0E;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x5A0: //VSS for VW instrument cluster
|
||||
case 0x5A0: // VSS for VW instrument cluster
|
||||
uint16_t temp_VSS;
|
||||
temp_VSS = currentStatus.vss * 133; //VSS conversion
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 8;
|
||||
temp_VSS = currentStatus.vss * 133; // VSS conversion
|
||||
outMsg.id = DashMessageID;
|
||||
outMsg.len = 8;
|
||||
outMsg.buf[0] = 0xFF;
|
||||
outMsg.buf[1] = lowByte(temp_VSS);
|
||||
outMsg.buf[2] = highByte(temp_VSS);
|
||||
|
@ -112,10 +112,9 @@ void DashMessage(uint16_t DashMessageID)
|
|||
outMsg.buf[5] = 0x00;
|
||||
outMsg.buf[6] = 0x00;
|
||||
outMsg.buf[7] = 0xAD;
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -4,166 +4,181 @@
|
|||
#include "timers.h"
|
||||
#include "maths.h"
|
||||
|
||||
volatile uint16_t timePerDegree;
|
||||
volatile uint16_t timePerDegreex16;
|
||||
volatile uint16_t degreesPeruSx2048;
|
||||
volatile uint16_t timePerDegree;
|
||||
volatile uint16_t timePerDegreex16;
|
||||
volatile uint16_t degreesPeruSx2048;
|
||||
volatile unsigned long degreesPeruSx32768;
|
||||
|
||||
//These are only part of the experimental 2nd deriv calcs
|
||||
byte deltaToothCount = 0; //The last tooth that was used with the deltaV calc
|
||||
int rpmDelta;
|
||||
// These are only part of the experimental 2nd deriv calcs
|
||||
byte deltaToothCount = 0; // The last tooth that was used with the deltaV calc
|
||||
int rpmDelta;
|
||||
|
||||
/*
|
||||
* Converts a crank angle into a time from or since that angle occurred.
|
||||
* Positive angles are assumed to be in the future, negative angles in the past:
|
||||
* * Future angle calculations will use a predicted speed/acceleration
|
||||
* * Past angle calculations will use the known speed
|
||||
*
|
||||
* Currently 4 methods are planned and/or available:
|
||||
* 1) Last interval based on a full revolution
|
||||
* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent)
|
||||
* 3) Closed loop error correction (Alpha-beta filter)
|
||||
* 4) 2nd derivative prediction (Speed + acceleration)
|
||||
*/
|
||||
* Converts a crank angle into a time from or since that angle occurred.
|
||||
* Positive angles are assumed to be in the future, negative angles in the past:
|
||||
* * Future angle calculations will use a predicted speed/acceleration
|
||||
* * Past angle calculations will use the known speed
|
||||
*
|
||||
* Currently 4 methods are planned and/or available:
|
||||
* 1) Last interval based on a full revolution
|
||||
* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent)
|
||||
* 3) Closed loop error correction (Alpha-beta filter)
|
||||
* 4) 2nd derivative prediction (Speed + acceleration)
|
||||
*/
|
||||
unsigned long angleToTime(uint16_t angle, byte method)
|
||||
{
|
||||
unsigned long returnTime = 0;
|
||||
unsigned long returnTime = 0;
|
||||
|
||||
if( (method == CRANKMATH_METHOD_INTERVAL_REV) || (method == CRANKMATH_METHOD_INTERVAL_DEFAULT) )
|
||||
if((method == CRANKMATH_METHOD_INTERVAL_REV) || (method == CRANKMATH_METHOD_INTERVAL_DEFAULT))
|
||||
{
|
||||
returnTime = angleToTimeIntervalRev(angle);
|
||||
// returnTime = angle * (unsigned long)timePerDegree;
|
||||
}
|
||||
else if(method == CRANKMATH_METHOD_INTERVAL_TOOTH)
|
||||
{
|
||||
// Still uses a last interval method (ie retrospective), but bases the interval on the gap between the 2 most recent teeth rather than the last full revolution
|
||||
if(BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT))
|
||||
{
|
||||
returnTime = angleToTimeIntervalRev(angle);
|
||||
//returnTime = angle * (unsigned long)timePerDegree;
|
||||
}
|
||||
else if (method == CRANKMATH_METHOD_INTERVAL_TOOTH)
|
||||
{
|
||||
//Still uses a last interval method (ie retrospective), but bases the interval on the gap between the 2 most recent teeth rather than the last full revolution
|
||||
if(BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT))
|
||||
{
|
||||
noInterrupts();
|
||||
unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime);
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts
|
||||
interrupts();
|
||||
|
||||
returnTime = ( (toothTime * angle) / tempTriggerToothAngle );
|
||||
}
|
||||
else { returnTime = angleToTime(angle, CRANKMATH_METHOD_INTERVAL_REV); } //Safety check. This can occur if the last tooth seen was outside the normal pattern etc
|
||||
}
|
||||
noInterrupts();
|
||||
unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime);
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts
|
||||
interrupts();
|
||||
|
||||
return returnTime;
|
||||
returnTime = ((toothTime * angle) / tempTriggerToothAngle);
|
||||
}
|
||||
else { returnTime = angleToTime(angle, CRANKMATH_METHOD_INTERVAL_REV); } // Safety check. This can occur if the last tooth seen was outside the normal pattern etc
|
||||
}
|
||||
|
||||
return returnTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a time (uS) into an angle at current speed
|
||||
* Currently 4 methods are planned and/or available:
|
||||
* 1) Last interval based on a full revolution
|
||||
* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent)
|
||||
* 3) Closed loop error correction (Alpha-beta filter)
|
||||
* 4) 2nd derivative prediction (Speed + acceleration)
|
||||
*/
|
||||
* Convert a time (uS) into an angle at current speed
|
||||
* Currently 4 methods are planned and/or available:
|
||||
* 1) Last interval based on a full revolution
|
||||
* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent)
|
||||
* 3) Closed loop error correction (Alpha-beta filter)
|
||||
* 4) 2nd derivative prediction (Speed + acceleration)
|
||||
*/
|
||||
uint16_t timeToAngle(unsigned long time, byte method)
|
||||
{
|
||||
uint16_t returnAngle = 0;
|
||||
uint16_t returnAngle = 0;
|
||||
|
||||
if( (method == CRANKMATH_METHOD_INTERVAL_REV) || (method == CRANKMATH_METHOD_INTERVAL_DEFAULT) )
|
||||
if((method == CRANKMATH_METHOD_INTERVAL_REV) || (method == CRANKMATH_METHOD_INTERVAL_DEFAULT))
|
||||
{
|
||||
// A last interval method of calculating angle that does not take into account any acceleration. The interval used is the time taken to complete the last full revolution
|
||||
// degreesPeruSx2048 is the number of degrees the crank moves per uS. This value is almost always <1uS, so it is multiplied by 2048. This allows an angle calculation with only a multiply and a bitshift without any appreciable drop in accuracy
|
||||
returnAngle = fastTimeToAngle(time);
|
||||
}
|
||||
else if(method == CRANKMATH_METHOD_INTERVAL_TOOTH)
|
||||
{
|
||||
// Still uses a last interval method (ie retrospective), but bases the interval on the gap between the 2 most recent teeth rather than the last full revolution
|
||||
if(BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT))
|
||||
{
|
||||
//A last interval method of calculating angle that does not take into account any acceleration. The interval used is the time taken to complete the last full revolution
|
||||
//degreesPeruSx2048 is the number of degrees the crank moves per uS. This value is almost always <1uS, so it is multiplied by 2048. This allows an angle calculation with only a multiply and a bitshift without any appreciable drop in accuracy
|
||||
returnAngle = fastTimeToAngle(time);
|
||||
}
|
||||
else if (method == CRANKMATH_METHOD_INTERVAL_TOOTH)
|
||||
{
|
||||
//Still uses a last interval method (ie retrospective), but bases the interval on the gap between the 2 most recent teeth rather than the last full revolution
|
||||
if(BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT))
|
||||
{
|
||||
noInterrupts();
|
||||
unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime);
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts
|
||||
interrupts();
|
||||
noInterrupts();
|
||||
unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime);
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts
|
||||
interrupts();
|
||||
|
||||
returnAngle = ( (unsigned long)(time * tempTriggerToothAngle) / toothTime );
|
||||
}
|
||||
else { returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV); } //Safety check. This can occur if the last tooth seen was outside the normal pattern etc
|
||||
}
|
||||
else if (method == CRANKMATH_METHOD_ALPHA_BETA)
|
||||
{
|
||||
//Not yet implemented. Default to Rev
|
||||
returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV);
|
||||
}
|
||||
else if (method == CRANKMATH_METHOD_2ND_DERIVATIVE)
|
||||
{
|
||||
//Not yet implemented. Default to Rev
|
||||
returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV);
|
||||
returnAngle = ((unsigned long)(time * tempTriggerToothAngle) / toothTime);
|
||||
}
|
||||
else { returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV); } // Safety check. This can occur if the last tooth seen was outside the normal pattern etc
|
||||
}
|
||||
else if(method == CRANKMATH_METHOD_ALPHA_BETA)
|
||||
{
|
||||
// Not yet implemented. Default to Rev
|
||||
returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV);
|
||||
}
|
||||
else if(method == CRANKMATH_METHOD_2ND_DERIVATIVE)
|
||||
{
|
||||
// Not yet implemented. Default to Rev
|
||||
returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV);
|
||||
}
|
||||
|
||||
return returnAngle;
|
||||
|
||||
return returnAngle;
|
||||
}
|
||||
|
||||
void doCrankSpeedCalcs(void)
|
||||
{
|
||||
//********************************************************
|
||||
//How fast are we going? Need to know how long (uS) it will take to get from one tooth to the next. We then use that to estimate how far we are between the last tooth and the next one
|
||||
//We use a 1st Deriv acceleration prediction, but only when there is an even spacing between primary sensor teeth
|
||||
//Any decoder that has uneven spacing has its triggerToothAngle set to 0
|
||||
//THIS IS CURRENTLY DISABLED FOR ALL DECODERS! It needs more work.
|
||||
if( SECOND_DERIV_ENABLED && (BIT_CHECK(decoderState, BIT_DECODER_2ND_DERIV)) && (toothHistoryIndex >= 3) && (currentStatus.RPM < 2000) ) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm
|
||||
//********************************************************
|
||||
// How fast are we going? Need to know how long (uS) it will take to get from one tooth to the next. We then use that to estimate how far we are between the last tooth and the next one
|
||||
// We use a 1st Deriv acceleration prediction, but only when there is an even spacing between primary sensor teeth
|
||||
// Any decoder that has uneven spacing has its triggerToothAngle set to 0
|
||||
// THIS IS CURRENTLY DISABLED FOR ALL DECODERS! It needs more work.
|
||||
if(SECOND_DERIV_ENABLED && (BIT_CHECK(decoderState, BIT_DECODER_2ND_DERIV)) && (toothHistoryIndex >= 3) && (currentStatus.RPM < 2000)) // toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm
|
||||
{
|
||||
// Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth)
|
||||
// if (deltaToothCount != toothCurrentCount)
|
||||
{
|
||||
deltaToothCount = toothCurrentCount;
|
||||
int angle1, angle2; // These represent the crank angles that are travelled for the last 2 pulses
|
||||
if(configPage4.TrigPattern == 4)
|
||||
{
|
||||
//Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth)
|
||||
//if (deltaToothCount != toothCurrentCount)
|
||||
{
|
||||
deltaToothCount = toothCurrentCount;
|
||||
int angle1, angle2; //These represent the crank angles that are travelled for the last 2 pulses
|
||||
if(configPage4.TrigPattern == 4)
|
||||
{
|
||||
//Special case for 70/110 pattern on 4g63
|
||||
angle2 = triggerToothAngle; //Angle 2 is the most recent
|
||||
if (angle2 == 70) { angle1 = 110; }
|
||||
else { angle1 = 70; }
|
||||
}
|
||||
else if(configPage4.TrigPattern == 0)
|
||||
{
|
||||
//Special case for missing tooth decoder where the missing tooth was one of the last 2 seen
|
||||
if(toothCurrentCount == 1) { angle2 = 2*triggerToothAngle; angle1 = triggerToothAngle; }
|
||||
else if(toothCurrentCount == 2) { angle1 = 2*triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
else { angle1 = triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
}
|
||||
else { angle1 = triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
|
||||
uint32_t toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex-1]);
|
||||
uint32_t toothDeltaT = toothHistory[toothHistoryIndex];
|
||||
//long timeToLastTooth = micros() - toothLastToothTime;
|
||||
|
||||
rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT);
|
||||
}
|
||||
|
||||
timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
// Special case for 70/110 pattern on 4g63
|
||||
angle2 = triggerToothAngle; // Angle 2 is the most recent
|
||||
if(angle2 == 70) { angle1 = 110; }
|
||||
else { angle1 = 70; }
|
||||
}
|
||||
else
|
||||
else if(configPage4.TrigPattern == 0)
|
||||
{
|
||||
//If we can, attempt to get the timePerDegree by comparing the times of the last two teeth seen. This is only possible for evenly spaced teeth
|
||||
noInterrupts();
|
||||
if( (BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) && (toothLastToothTime > toothLastMinusOneToothTime) && (abs(currentStatus.rpmDOT) > 30) )
|
||||
// Special case for missing tooth decoder where the missing tooth was one of the last 2 seen
|
||||
if(toothCurrentCount == 1)
|
||||
{
|
||||
//noInterrupts();
|
||||
unsigned long tempToothLastToothTime = toothLastToothTime;
|
||||
unsigned long tempToothLastMinusOneToothTime = toothLastMinusOneToothTime;
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle;
|
||||
interrupts();
|
||||
timePerDegreex16 = (unsigned long)( (tempToothLastToothTime - tempToothLastMinusOneToothTime)*16) / tempTriggerToothAngle;
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
angle2 = 2 * triggerToothAngle;
|
||||
angle1 = triggerToothAngle;
|
||||
}
|
||||
else if(toothCurrentCount == 2)
|
||||
{
|
||||
angle1 = 2 * triggerToothAngle;
|
||||
angle2 = triggerToothAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
//long timeThisRevolution = (micros_safe() - toothOneTime);
|
||||
interrupts();
|
||||
//Take into account any likely acceleration that has occurred since the last full revolution completed:
|
||||
//long rpm_adjust = (timeThisRevolution * (long)currentStatus.rpmDOT) / 1000000;
|
||||
long rpm_adjust = 0;
|
||||
timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
angle1 = triggerToothAngle;
|
||||
angle2 = triggerToothAngle;
|
||||
}
|
||||
}
|
||||
degreesPeruSx2048 = 2048 / timePerDegree;
|
||||
degreesPeruSx32768 = 524288 / timePerDegreex16;
|
||||
else
|
||||
{
|
||||
angle1 = triggerToothAngle;
|
||||
angle2 = triggerToothAngle;
|
||||
}
|
||||
|
||||
uint32_t toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex - 1]);
|
||||
uint32_t toothDeltaT = toothHistory[toothHistoryIndex];
|
||||
// long timeToLastTooth = micros() - toothLastToothTime;
|
||||
|
||||
rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT);
|
||||
}
|
||||
|
||||
timePerDegreex16 = ldiv(2666656L, currentStatus.RPM + rpmDelta).quot; // This gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we can, attempt to get the timePerDegree by comparing the times of the last two teeth seen. This is only possible for evenly spaced teeth
|
||||
noInterrupts();
|
||||
if((BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) && (toothLastToothTime > toothLastMinusOneToothTime) && (abs(currentStatus.rpmDOT) > 30))
|
||||
{
|
||||
// noInterrupts();
|
||||
unsigned long tempToothLastToothTime = toothLastToothTime;
|
||||
unsigned long tempToothLastMinusOneToothTime = toothLastMinusOneToothTime;
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle;
|
||||
interrupts();
|
||||
timePerDegreex16 = (unsigned long)((tempToothLastToothTime - tempToothLastMinusOneToothTime) * 16) / tempTriggerToothAngle;
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
// long timeThisRevolution = (micros_safe() - toothOneTime);
|
||||
interrupts();
|
||||
// Take into account any likely acceleration that has occurred since the last full revolution completed:
|
||||
// long rpm_adjust = (timeThisRevolution * (long)currentStatus.rpmDOT) / 1000000;
|
||||
long rpm_adjust = 0;
|
||||
timePerDegreex16 = ldiv(2666656L, currentStatus.RPM + rpm_adjust).quot; // The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
}
|
||||
degreesPeruSx2048 = 2048 / timePerDegree;
|
||||
degreesPeruSx32768 = 524288 / timePerDegreex16;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,189 +6,181 @@ A full copy of the license may be found in the projects root directory
|
|||
|
||||
#ifdef USE_DISPLAY
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include "src/Adafruit_SSD1306/Adafruit_GFX.h"
|
||||
#include "src/Adafruit_SSD1306/Adafruit_SSD1306.h"
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include "src/Adafruit_SSD1306/Adafruit_GFX.h"
|
||||
#include "src/Adafruit_SSD1306/Adafruit_SSD1306.h"
|
||||
|
||||
Adafruit_SSD1306 display(pinDisplayReset);
|
||||
|
||||
void initialiseDisplay()
|
||||
{
|
||||
//Protection against older pin mappings where the crank/cam signals were on the SDA and SCL pins. This will cause the Arduino to lock hard if you try to initialise i2c devices when a crank signal is coming in
|
||||
// Protection against older pin mappings where the crank/cam signals were on the SDA and SCL pins. This will cause the Arduino to lock hard if you try to initialise i2c devices when a crank signal is coming in
|
||||
if(pinTrigger == 20 || pinTrigger == 21 || pinTrigger2 == 20 || pinTrigger2 == 21) { return; }
|
||||
|
||||
switch(configPage1.displayType)
|
||||
{
|
||||
case 1:
|
||||
display.SSD1306_SETCOMPINS_V = 0x02;
|
||||
break;
|
||||
case 2:
|
||||
display.SSD1306_SETCOMPINS_V = 0x12;
|
||||
break;
|
||||
case 3:
|
||||
display.SSD1306_SETCOMPINS_V = 0x12;
|
||||
break;
|
||||
case 4:
|
||||
display.SSD1306_SETCOMPINS_V = 0x12;
|
||||
break;
|
||||
}
|
||||
switch(configPage1.displayType)
|
||||
{
|
||||
case 1: display.SSD1306_SETCOMPINS_V = 0x02; break;
|
||||
case 2: display.SSD1306_SETCOMPINS_V = 0x12; break;
|
||||
case 3: display.SSD1306_SETCOMPINS_V = 0x12; break;
|
||||
case 4: display.SSD1306_SETCOMPINS_V = 0x12; break;
|
||||
}
|
||||
|
||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialise with the I2C addr 0x3C (for the 128x32)
|
||||
display.clearDisplay();
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0,0);
|
||||
display.print("RPM: ");
|
||||
display.setCursor(0,16);
|
||||
display.print("CPU: ");
|
||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialise with the I2C addr 0x3C (for the 128x32)
|
||||
display.clearDisplay();
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0, 0);
|
||||
display.print("RPM: ");
|
||||
display.setCursor(0, 16);
|
||||
display.print("CPU: ");
|
||||
}
|
||||
|
||||
void updateDisplay()
|
||||
{
|
||||
display.clearDisplay();
|
||||
display.setCursor(0,0);
|
||||
display.setCursor(0, 0);
|
||||
switch(configPage1.display1)
|
||||
{
|
||||
case 0:
|
||||
display.print("RPM: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.RPM);
|
||||
break;
|
||||
case 1:
|
||||
display.print("PW: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.PW1);
|
||||
break;
|
||||
case 2:
|
||||
display.print("Adv: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.advance);
|
||||
break;
|
||||
case 3:
|
||||
display.print("VE: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.VE);
|
||||
break;
|
||||
case 4:
|
||||
display.print("GamE: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.corrections);
|
||||
break;
|
||||
case 5:
|
||||
display.print("TPS: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.TPS);
|
||||
break;
|
||||
case 6:
|
||||
display.print("IAT: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.IAT);
|
||||
break;
|
||||
case 7:
|
||||
display.print("CLT: ");
|
||||
display.setCursor(28,0);
|
||||
display.setCursor(28, 0);
|
||||
display.print(currentStatus.coolant);
|
||||
break;
|
||||
}
|
||||
|
||||
display.setCursor(0,11);
|
||||
display.setCursor(0, 11);
|
||||
switch(configPage1.display3)
|
||||
{
|
||||
case 0:
|
||||
display.print("RPM: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.RPM);
|
||||
break;
|
||||
case 1:
|
||||
display.print("PW: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.PW1);
|
||||
break;
|
||||
case 2:
|
||||
display.print("Adv: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.advance);
|
||||
break;
|
||||
case 3:
|
||||
display.print("VE: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.VE);
|
||||
break;
|
||||
case 4:
|
||||
display.print("GamE: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.corrections);
|
||||
break;
|
||||
case 5:
|
||||
display.print("TPS: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.TPS);
|
||||
break;
|
||||
case 6:
|
||||
display.print("IAT: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.IAT);
|
||||
break;
|
||||
case 7:
|
||||
display.print("CLT: ");
|
||||
display.setCursor(28,11);
|
||||
display.setCursor(28, 11);
|
||||
display.print(currentStatus.coolant);
|
||||
break;
|
||||
}
|
||||
|
||||
display.setCursor(64,0);
|
||||
display.setCursor(64, 0);
|
||||
switch(configPage1.display2)
|
||||
{
|
||||
case 0:
|
||||
display.print("O2: ");
|
||||
display.setCursor(92,0);
|
||||
display.setCursor(92, 0);
|
||||
display.print(currentStatus.O2);
|
||||
break;
|
||||
case 1:
|
||||
display.print("Vdc: ");
|
||||
display.setCursor(92,0);
|
||||
display.setCursor(92, 0);
|
||||
display.print(currentStatus.battery10);
|
||||
break;
|
||||
case 2:
|
||||
display.print("CPU: ");
|
||||
display.setCursor(92,0);
|
||||
display.setCursor(92, 0);
|
||||
display.print(currentStatus.loopsPerSecond);
|
||||
break;
|
||||
case 3:
|
||||
display.print("Mem: ");
|
||||
display.setCursor(92,0);
|
||||
display.setCursor(92, 0);
|
||||
display.print(currentStatus.freeRAM);
|
||||
break;
|
||||
}
|
||||
|
||||
display.setCursor(64,11);
|
||||
display.setCursor(64, 11);
|
||||
switch(configPage1.display4)
|
||||
{
|
||||
case 0:
|
||||
display.print("O2: ");
|
||||
display.setCursor(92,11);
|
||||
display.setCursor(92, 11);
|
||||
display.print(currentStatus.O2);
|
||||
break;
|
||||
case 1:
|
||||
display.print("Vdc: ");
|
||||
display.setCursor(92,11);
|
||||
display.setCursor(92, 11);
|
||||
display.print(currentStatus.battery10);
|
||||
break;
|
||||
case 2:
|
||||
display.print("CPU: ");
|
||||
display.setCursor(92,11);
|
||||
display.setCursor(92, 11);
|
||||
display.print(currentStatus.loopsPerSecond);
|
||||
break;
|
||||
case 3:
|
||||
display.print("Mem: ");
|
||||
display.setCursor(92,11);
|
||||
display.setCursor(92, 11);
|
||||
display.print(currentStatus.freeRAM);
|
||||
break;
|
||||
}
|
||||
|
||||
int barWidth = ldiv(((unsigned long)currentStatus.RPM * 128), 9000).quot;
|
||||
//int barWidth = map(currentStatus.RPM, 0, 9000, 0, 128);
|
||||
// int barWidth = map(currentStatus.RPM, 0, 9000, 0, 128);
|
||||
display.fillRect(0, 20, barWidth, 10, 1);
|
||||
|
||||
display.display();
|
||||
|
|
|
@ -7,9 +7,9 @@ byte oilProtStartTime = 0;
|
|||
byte checkEngineProtect(void)
|
||||
{
|
||||
byte protectActive = 0;
|
||||
if(checkBoostLimit() || checkOilPressureLimit() || checkAFRLimit() )
|
||||
if(checkBoostLimit() || checkOilPressureLimit() || checkAFRLimit())
|
||||
{
|
||||
if( currentStatus.RPMdiv100 > configPage4.engineProtectMaxRPM ) { protectActive = 1; }
|
||||
if(currentStatus.RPMdiv100 > configPage4.engineProtectMaxRPM) { protectActive = 1; }
|
||||
}
|
||||
|
||||
return protectActive;
|
||||
|
@ -17,33 +17,33 @@ byte checkEngineProtect(void)
|
|||
|
||||
byte checkRevLimit(void)
|
||||
{
|
||||
//Hardcut RPM limit
|
||||
byte currentLimitRPM = 255; //Default to no limit (In case PROTECT_CUT_OFF is selected)
|
||||
// Hardcut RPM limit
|
||||
byte currentLimitRPM = 255; // Default to no limit (In case PROTECT_CUT_OFF is selected)
|
||||
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_RPM);
|
||||
BIT_CLEAR(currentStatus.spark, BIT_SPARK_HRDLIM);
|
||||
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_COOLANT);
|
||||
|
||||
if (configPage6.engineProtectType != PROTECT_CUT_OFF)
|
||||
if(configPage6.engineProtectType != PROTECT_CUT_OFF)
|
||||
{
|
||||
if(configPage9.hardRevMode == HARD_REV_FIXED)
|
||||
{
|
||||
currentLimitRPM = configPage4.HardRevLim;
|
||||
if ( (currentStatus.RPMdiv100 >= configPage4.HardRevLim) || ((softLimitTime > configPage4.SoftLimMax) && (currentStatus.RPMdiv100 >= configPage4.SoftRevLim)) )
|
||||
{
|
||||
BIT_SET(currentStatus.spark, BIT_SPARK_HRDLIM); //Legacy and likely to be removed at some point
|
||||
if((currentStatus.RPMdiv100 >= configPage4.HardRevLim) || ((softLimitTime > configPage4.SoftLimMax) && (currentStatus.RPMdiv100 >= configPage4.SoftRevLim)))
|
||||
{
|
||||
BIT_SET(currentStatus.spark, BIT_SPARK_HRDLIM); // Legacy and likely to be removed at some point
|
||||
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_RPM);
|
||||
}
|
||||
}
|
||||
else { BIT_CLEAR(currentStatus.spark, BIT_SPARK_HRDLIM); }
|
||||
}
|
||||
else if(configPage9.hardRevMode == HARD_REV_COOLANT )
|
||||
else if(configPage9.hardRevMode == HARD_REV_COOLANT)
|
||||
{
|
||||
currentLimitRPM = (int16_t)(table2D_getValue(&coolantProtectTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET));
|
||||
if(currentStatus.RPMdiv100 > currentLimitRPM)
|
||||
{
|
||||
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_COOLANT);
|
||||
BIT_SET(currentStatus.spark, BIT_SPARK_HRDLIM); //Legacy and likely to be removed at some point
|
||||
BIT_SET(currentStatus.spark, BIT_SPARK_HRDLIM); // Legacy and likely to be removed at some point
|
||||
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_RPM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,10 @@ byte checkBoostLimit(void)
|
|||
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
|
||||
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
|
||||
|
||||
if (configPage6.engineProtectType != PROTECT_CUT_OFF) {
|
||||
//Boost cutoff is very similar to launchControl, but with a check against MAP rather than a switch
|
||||
if( (configPage6.boostCutEnabled > 0) && (currentStatus.MAP > (configPage6.boostLimit * 2)) ) //The boost limit is divided by 2 to allow a limit up to 511kPa
|
||||
if(configPage6.engineProtectType != PROTECT_CUT_OFF)
|
||||
{
|
||||
// Boost cutoff is very similar to launchControl, but with a check against MAP rather than a switch
|
||||
if((configPage6.boostCutEnabled > 0) && (currentStatus.MAP > (configPage6.boostLimit * 2))) // The boost limit is divided by 2 to allow a limit up to 511kPa
|
||||
{
|
||||
boostLimitActive = 1;
|
||||
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_MAP);
|
||||
|
@ -94,28 +95,27 @@ byte checkBoostLimit(void)
|
|||
byte checkOilPressureLimit(void)
|
||||
{
|
||||
byte oilProtectActive = 0;
|
||||
bool alreadyActive = BIT_CHECK(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL);
|
||||
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL); //Will be set true below if required
|
||||
bool alreadyActive = BIT_CHECK(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL);
|
||||
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL); // Will be set true below if required
|
||||
|
||||
if (configPage6.engineProtectType != PROTECT_CUT_OFF)
|
||||
if(configPage6.engineProtectType != PROTECT_CUT_OFF)
|
||||
{
|
||||
if( (configPage10.oilPressureProtEnbl == true) && (configPage10.oilPressureEnable == true) )
|
||||
if((configPage10.oilPressureProtEnbl == true) && (configPage10.oilPressureEnable == true))
|
||||
{
|
||||
byte oilLimit = table2D_getValue(&oilPressureProtectTable, currentStatus.RPMdiv100);
|
||||
if(currentStatus.oilPressure < oilLimit)
|
||||
{
|
||||
//Check if this is the first time we've been below the limit
|
||||
// Check if this is the first time we've been below the limit
|
||||
if(oilProtStartTime == 0) { oilProtStartTime = (millis() / 100); }
|
||||
|
||||
/* Check if countdown has reached its target, if so then instruct to cut */
|
||||
if( (uint8_t(millis()/100) >= (uint16_t(oilProtStartTime + configPage10.oilPressureProtTime)) ) || (alreadyActive > 0) )
|
||||
if((uint8_t(millis() / 100) >= (uint16_t(oilProtStartTime + configPage10.oilPressureProtTime))) || (alreadyActive > 0))
|
||||
{
|
||||
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL);
|
||||
oilProtectActive = 1;
|
||||
}
|
||||
|
||||
}
|
||||
else { oilProtStartTime = 0; } //Reset the timer
|
||||
else { oilProtStartTime = 0; } // Reset the timer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,11 +124,11 @@ byte checkOilPressureLimit(void)
|
|||
|
||||
byte checkAFRLimit(void)
|
||||
{
|
||||
static bool checkAFRLimitActive = false;
|
||||
static bool afrProtectCountEnabled = false;
|
||||
static unsigned long afrProtectCount = 0;
|
||||
static constexpr char X2_MULTIPLIER = 2;
|
||||
static constexpr char X100_MULTIPLIER = 100;
|
||||
static bool checkAFRLimitActive = false;
|
||||
static bool afrProtectCountEnabled = false;
|
||||
static unsigned long afrProtectCount = 0;
|
||||
static constexpr char X2_MULTIPLIER = 2;
|
||||
static constexpr char X100_MULTIPLIER = 100;
|
||||
|
||||
/*
|
||||
To use this function, a wideband sensor is required.
|
||||
|
@ -136,7 +136,7 @@ byte checkAFRLimit(void)
|
|||
First of all, check whether engine protection is enabled,
|
||||
thereafter check whether AFR protection is enabled and at last
|
||||
if wideband sensor is used.
|
||||
|
||||
|
||||
After confirmation, the following conditions has to be met:
|
||||
- MAP above x kPa
|
||||
- RPM above x
|
||||
|
@ -161,7 +161,8 @@ byte checkAFRLimit(void)
|
|||
- whether AFR protection is enabled
|
||||
- whether wideband sensor is used
|
||||
*/
|
||||
if(configPage6.engineProtectType != PROTECT_CUT_OFF && configPage9.afrProtectEnabled && configPage6.egoType == EGO_TYPE_WIDE) {
|
||||
if(configPage6.engineProtectType != PROTECT_CUT_OFF && configPage9.afrProtectEnabled && configPage6.egoType == EGO_TYPE_WIDE)
|
||||
{
|
||||
/* Conditions */
|
||||
bool mapCondition = (currentStatus.MAP >= (configPage9.afrProtectMinMAP * X2_MULTIPLIER)) ? true : false;
|
||||
bool rpmCondition = (currentStatus.RPMdiv100 >= configPage9.afrProtectMinRPM) ? true : false;
|
||||
|
@ -176,42 +177,42 @@ byte checkAFRLimit(void)
|
|||
bool afrCondition;
|
||||
switch(configPage9.afrProtectEnabled)
|
||||
{
|
||||
case 1: afrCondition = (currentStatus.O2 >= configPage9.afrProtectDeviation) ? true : false; break; /* Fixed value */
|
||||
case 1: afrCondition = (currentStatus.O2 >= configPage9.afrProtectDeviation) ? true : false; break; /* Fixed value */
|
||||
case 2: afrCondition = (currentStatus.O2 >= (currentStatus.afrTarget + configPage9.afrProtectDeviation)) ? true : false; break; /* Deviation from target table */
|
||||
default: afrCondition = false; /* Unknown mode. Shouldn't even get here */
|
||||
default: afrCondition = false; /* Unknown mode. Shouldn't even get here */
|
||||
}
|
||||
|
||||
/* Check if conditions above are fulfilled */
|
||||
if(mapCondition && rpmCondition && tpsCondition && afrCondition)
|
||||
if(mapCondition && rpmCondition && tpsCondition && afrCondition)
|
||||
{
|
||||
/* All conditions fulfilled - start counter for 'protection delay' */
|
||||
if(!afrProtectCountEnabled)
|
||||
if(!afrProtectCountEnabled)
|
||||
{
|
||||
afrProtectCountEnabled = true;
|
||||
afrProtectCount = millis();
|
||||
afrProtectCount = millis();
|
||||
}
|
||||
|
||||
/* Check if countdown has reached its target, if so then instruct to cut */
|
||||
if(millis() >= (afrProtectCount + (configPage9.afrProtectCutTime * X100_MULTIPLIER)))
|
||||
if(millis() >= (afrProtectCount + (configPage9.afrProtectCutTime * X100_MULTIPLIER)))
|
||||
{
|
||||
checkAFRLimitActive = true;
|
||||
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_AFR);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conditions have presumably changed - deactivate and reset counter */
|
||||
if(afrProtectCountEnabled)
|
||||
if(afrProtectCountEnabled)
|
||||
{
|
||||
afrProtectCountEnabled = false;
|
||||
afrProtectCount = 0;
|
||||
afrProtectCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if condition for reactivation is fulfilled */
|
||||
if(checkAFRLimitActive && (currentStatus.TPS <= configPage9.afrProtectReactivationTPS))
|
||||
if(checkAFRLimitActive && (currentStatus.TPS <= configPage9.afrProtectReactivationTPS))
|
||||
{
|
||||
checkAFRLimitActive = false;
|
||||
checkAFRLimitActive = false;
|
||||
afrProtectCountEnabled = false;
|
||||
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_AFR);
|
||||
}
|
||||
|
@ -219,4 +220,3 @@ byte checkAFRLimit(void)
|
|||
|
||||
return checkAFRLimitActive;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ byte setError(byte errorID)
|
|||
{
|
||||
errorCodes[errorCount] = errorID;
|
||||
errorCount++;
|
||||
if(errorCount == 1) { BIT_SET(currentStatus.spark, BIT_SPARK_ERROR); } //Enable the error indicator
|
||||
if(errorCount == 1) { BIT_SET(currentStatus.spark, BIT_SPARK_ERROR); } // Enable the error indicator
|
||||
}
|
||||
return errorCount;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ void clearError(byte errorID)
|
|||
{
|
||||
byte clearedError = 255;
|
||||
|
||||
if (errorID == errorCodes[0]) { clearedError = 0; }
|
||||
if(errorID == errorCodes[0]) { clearedError = 0; }
|
||||
else if(errorID == errorCodes[1]) { clearedError = 1; }
|
||||
else if(errorID == errorCodes[2]) { clearedError = 2; }
|
||||
else if(errorID == errorCodes[3]) { clearedError = 3; }
|
||||
|
@ -37,37 +37,36 @@ void clearError(byte errorID)
|
|||
if(clearedError < MAX_ERRORS)
|
||||
{
|
||||
errorCodes[clearedError] = ERR_NONE;
|
||||
//Clear the required error and move any from above it 'down' in the error array
|
||||
for (byte x=clearedError; x < (errorCount-1); x++)
|
||||
// Clear the required error and move any from above it 'down' in the error array
|
||||
for(byte x = clearedError; x < (errorCount - 1); x++)
|
||||
{
|
||||
errorCodes[x] = errorCodes[x+1];
|
||||
errorCodes[x+1] = ERR_NONE;
|
||||
errorCodes[x] = errorCodes[x + 1];
|
||||
errorCodes[x + 1] = ERR_NONE;
|
||||
}
|
||||
|
||||
errorCount--;
|
||||
if(errorCount == 0) { BIT_CLEAR(currentStatus.spark, BIT_SPARK_ERROR); } //Enable the error indicator
|
||||
if(errorCount == 0) { BIT_CLEAR(currentStatus.spark, BIT_SPARK_ERROR); } // Enable the error indicator
|
||||
}
|
||||
}
|
||||
|
||||
byte getNextError(void)
|
||||
{
|
||||
packedError currentError;
|
||||
byte currentErrorNum = 0;
|
||||
byte currentErrorNum = 0;
|
||||
|
||||
if(errorCount > 0)
|
||||
{
|
||||
//We alternate through the errors once per second
|
||||
currentErrorNum = currentStatus.secl % errorCount; //Which error number will be returned. This changes once per second.
|
||||
// We alternate through the errors once per second
|
||||
currentErrorNum = currentStatus.secl % errorCount; // Which error number will be returned. This changes once per second.
|
||||
|
||||
currentError.errorNum = currentErrorNum;
|
||||
currentError.errorID = errorCodes[currentErrorNum];
|
||||
currentError.errorID = errorCodes[currentErrorNum];
|
||||
}
|
||||
else
|
||||
{
|
||||
currentError.errorNum = 0;
|
||||
currentError.errorID = 0;
|
||||
currentError.errorID = 0;
|
||||
}
|
||||
|
||||
|
||||
return *(byte*)¤tError; //Ugly, but this forces the cast of the currentError struct to a byte.
|
||||
return *(byte *)¤tError; // Ugly, but this forces the cast of the currentError struct to a byte.
|
||||
}
|
||||
|
|
|
@ -5,310 +5,287 @@
|
|||
|
||||
const char TSfirmwareVersion[] PROGMEM = "Speeduino";
|
||||
|
||||
const byte data_structure_version = 2; //This identifies the data structure when reading / writing. (outdated ?)
|
||||
const byte data_structure_version = 2; // This identifies the data structure when reading / writing. (outdated ?)
|
||||
|
||||
struct table3d16RpmLoad fuelTable; ///< 16x16 fuel map
|
||||
struct table3d16RpmLoad fuelTable2; ///< 16x16 fuel map
|
||||
struct table3d16RpmLoad ignitionTable; ///< 16x16 ignition map
|
||||
struct table3d16RpmLoad ignitionTable2; ///< 16x16 ignition map
|
||||
struct table3d16RpmLoad afrTable; ///< 16x16 afr target map
|
||||
struct table3d8RpmLoad stagingTable; ///< 8x8 fuel staging table
|
||||
struct table3d8RpmLoad boostTable; ///< 8x8 boost map
|
||||
struct table3d8RpmLoad boostTableLookupDuty; ///< 8x8 boost map lookup table
|
||||
struct table3d8RpmLoad vvtTable; ///< 8x8 vvt map
|
||||
struct table3d8RpmLoad vvt2Table; ///< 8x8 vvt2 map
|
||||
struct table3d8RpmLoad wmiTable; ///< 8x8 wmi map
|
||||
trimTable3d trim1Table; ///< 6x6 Fuel trim 1 map
|
||||
trimTable3d trim2Table; ///< 6x6 Fuel trim 2 map
|
||||
trimTable3d trim3Table; ///< 6x6 Fuel trim 3 map
|
||||
trimTable3d trim4Table; ///< 6x6 Fuel trim 4 map
|
||||
trimTable3d trim5Table; ///< 6x6 Fuel trim 5 map
|
||||
trimTable3d trim6Table; ///< 6x6 Fuel trim 6 map
|
||||
trimTable3d trim7Table; ///< 6x6 Fuel trim 7 map
|
||||
trimTable3d trim8Table; ///< 6x6 Fuel trim 8 map
|
||||
struct table3d4RpmLoad dwellTable; ///< 4x4 Dwell map
|
||||
struct table2D taeTable; ///< 4 bin TPS Acceleration Enrichment map (2D)
|
||||
struct table2D maeTable;
|
||||
struct table2D WUETable; ///< 10 bin Warm Up Enrichment map (2D)
|
||||
struct table2D ASETable; ///< 4 bin After Start Enrichment map (2D)
|
||||
struct table2D ASECountTable; ///< 4 bin After Start duration map (2D)
|
||||
struct table2D PrimingPulseTable; ///< 4 bin Priming pulsewidth map (2D)
|
||||
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 injectorAngleTable; ///< 4 bin injector angle curve (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 idleTargetTable; ///< 10 bin idle target table for idle timing (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)
|
||||
struct table2D rotarySplitTable; ///< 8 bin ignition split curve for rotary leading/trailing (2D)
|
||||
struct table2D flexFuelTable; ///< 6 bin flex fuel correction table for fuel adjustments (2D)
|
||||
struct table2D flexAdvTable; ///< 6 bin flex fuel correction table for timing advance (2D)
|
||||
struct table2D flexBoostTable; ///< 6 bin flex fuel correction table for boost adjustments (2D)
|
||||
struct table2D fuelTempTable; ///< 6 bin flex fuel correction table for fuel adjustments (2D)
|
||||
struct table2D knockWindowStartTable;
|
||||
struct table2D knockWindowDurationTable;
|
||||
struct table2D oilPressureProtectTable;
|
||||
struct table2D wmiAdvTable; //6 bin wmi correction table for timing advance (2D)
|
||||
struct table2D coolantProtectTable;
|
||||
struct table2D fanPWMTable;
|
||||
struct table2D rollingCutTable;
|
||||
struct table3d16RpmLoad fuelTable; ///< 16x16 fuel map
|
||||
struct table3d16RpmLoad fuelTable2; ///< 16x16 fuel map
|
||||
struct table3d16RpmLoad ignitionTable; ///< 16x16 ignition map
|
||||
struct table3d16RpmLoad ignitionTable2; ///< 16x16 ignition map
|
||||
struct table3d16RpmLoad afrTable; ///< 16x16 afr target map
|
||||
struct table3d8RpmLoad stagingTable; ///< 8x8 fuel staging table
|
||||
struct table3d8RpmLoad boostTable; ///< 8x8 boost map
|
||||
struct table3d8RpmLoad boostTableLookupDuty; ///< 8x8 boost map lookup table
|
||||
struct table3d8RpmLoad vvtTable; ///< 8x8 vvt map
|
||||
struct table3d8RpmLoad vvt2Table; ///< 8x8 vvt2 map
|
||||
struct table3d8RpmLoad wmiTable; ///< 8x8 wmi map
|
||||
trimTable3d trim1Table; ///< 6x6 Fuel trim 1 map
|
||||
trimTable3d trim2Table; ///< 6x6 Fuel trim 2 map
|
||||
trimTable3d trim3Table; ///< 6x6 Fuel trim 3 map
|
||||
trimTable3d trim4Table; ///< 6x6 Fuel trim 4 map
|
||||
trimTable3d trim5Table; ///< 6x6 Fuel trim 5 map
|
||||
trimTable3d trim6Table; ///< 6x6 Fuel trim 6 map
|
||||
trimTable3d trim7Table; ///< 6x6 Fuel trim 7 map
|
||||
trimTable3d trim8Table; ///< 6x6 Fuel trim 8 map
|
||||
struct table3d4RpmLoad dwellTable; ///< 4x4 Dwell map
|
||||
struct table2D taeTable; ///< 4 bin TPS Acceleration Enrichment map (2D)
|
||||
struct table2D maeTable;
|
||||
struct table2D WUETable; ///< 10 bin Warm Up Enrichment map (2D)
|
||||
struct table2D ASETable; ///< 4 bin After Start Enrichment map (2D)
|
||||
struct table2D ASECountTable; ///< 4 bin After Start duration map (2D)
|
||||
struct table2D PrimingPulseTable; ///< 4 bin Priming pulsewidth map (2D)
|
||||
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 injectorAngleTable; ///< 4 bin injector angle curve (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 idleTargetTable; ///< 10 bin idle target table for idle timing (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)
|
||||
struct table2D rotarySplitTable; ///< 8 bin ignition split curve for rotary leading/trailing (2D)
|
||||
struct table2D flexFuelTable; ///< 6 bin flex fuel correction table for fuel adjustments (2D)
|
||||
struct table2D flexAdvTable; ///< 6 bin flex fuel correction table for timing advance (2D)
|
||||
struct table2D flexBoostTable; ///< 6 bin flex fuel correction table for boost adjustments (2D)
|
||||
struct table2D fuelTempTable; ///< 6 bin flex fuel correction table for fuel adjustments (2D)
|
||||
struct table2D knockWindowStartTable;
|
||||
struct table2D knockWindowDurationTable;
|
||||
struct table2D oilPressureProtectTable;
|
||||
struct table2D wmiAdvTable; // 6 bin wmi correction table for timing advance (2D)
|
||||
struct table2D coolantProtectTable;
|
||||
struct table2D fanPWMTable;
|
||||
struct table2D rollingCutTable;
|
||||
|
||||
/// volatile inj*_pin_port and inj*_pin_mask vars are for the direct port manipulation of the injectors, coils and aux outputs.
|
||||
volatile PORT_TYPE *inj1_pin_port;
|
||||
volatile PORT_TYPE *inj1_pin_port;
|
||||
volatile PINMASK_TYPE inj1_pin_mask;
|
||||
volatile PORT_TYPE *inj2_pin_port;
|
||||
volatile PORT_TYPE *inj2_pin_port;
|
||||
volatile PINMASK_TYPE inj2_pin_mask;
|
||||
volatile PORT_TYPE *inj3_pin_port;
|
||||
volatile PORT_TYPE *inj3_pin_port;
|
||||
volatile PINMASK_TYPE inj3_pin_mask;
|
||||
volatile PORT_TYPE *inj4_pin_port;
|
||||
volatile PORT_TYPE *inj4_pin_port;
|
||||
volatile PINMASK_TYPE inj4_pin_mask;
|
||||
volatile PORT_TYPE *inj5_pin_port;
|
||||
volatile PORT_TYPE *inj5_pin_port;
|
||||
volatile PINMASK_TYPE inj5_pin_mask;
|
||||
volatile PORT_TYPE *inj6_pin_port;
|
||||
volatile PORT_TYPE *inj6_pin_port;
|
||||
volatile PINMASK_TYPE inj6_pin_mask;
|
||||
volatile PORT_TYPE *inj7_pin_port;
|
||||
volatile PORT_TYPE *inj7_pin_port;
|
||||
volatile PINMASK_TYPE inj7_pin_mask;
|
||||
volatile PORT_TYPE *inj8_pin_port;
|
||||
volatile PORT_TYPE *inj8_pin_port;
|
||||
volatile PINMASK_TYPE inj8_pin_mask;
|
||||
|
||||
volatile PORT_TYPE *ign1_pin_port;
|
||||
volatile PORT_TYPE *ign1_pin_port;
|
||||
volatile PINMASK_TYPE ign1_pin_mask;
|
||||
volatile PORT_TYPE *ign2_pin_port;
|
||||
volatile PORT_TYPE *ign2_pin_port;
|
||||
volatile PINMASK_TYPE ign2_pin_mask;
|
||||
volatile PORT_TYPE *ign3_pin_port;
|
||||
volatile PORT_TYPE *ign3_pin_port;
|
||||
volatile PINMASK_TYPE ign3_pin_mask;
|
||||
volatile PORT_TYPE *ign4_pin_port;
|
||||
volatile PORT_TYPE *ign4_pin_port;
|
||||
volatile PINMASK_TYPE ign4_pin_mask;
|
||||
volatile PORT_TYPE *ign5_pin_port;
|
||||
volatile PORT_TYPE *ign5_pin_port;
|
||||
volatile PINMASK_TYPE ign5_pin_mask;
|
||||
volatile PORT_TYPE *ign6_pin_port;
|
||||
volatile PORT_TYPE *ign6_pin_port;
|
||||
volatile PINMASK_TYPE ign6_pin_mask;
|
||||
volatile PORT_TYPE *ign7_pin_port;
|
||||
volatile PORT_TYPE *ign7_pin_port;
|
||||
volatile PINMASK_TYPE ign7_pin_mask;
|
||||
volatile PORT_TYPE *ign8_pin_port;
|
||||
volatile PORT_TYPE *ign8_pin_port;
|
||||
volatile PINMASK_TYPE ign8_pin_mask;
|
||||
|
||||
volatile PORT_TYPE *tach_pin_port;
|
||||
volatile PORT_TYPE *tach_pin_port;
|
||||
volatile PINMASK_TYPE tach_pin_mask;
|
||||
volatile PORT_TYPE *pump_pin_port;
|
||||
volatile PORT_TYPE *pump_pin_port;
|
||||
volatile PINMASK_TYPE pump_pin_mask;
|
||||
|
||||
volatile PORT_TYPE *flex_pin_port;
|
||||
volatile PORT_TYPE *flex_pin_port;
|
||||
volatile PINMASK_TYPE flex_pin_mask;
|
||||
|
||||
volatile PORT_TYPE *triggerPri_pin_port;
|
||||
volatile PORT_TYPE *triggerPri_pin_port;
|
||||
volatile PINMASK_TYPE triggerPri_pin_mask;
|
||||
volatile PORT_TYPE *triggerSec_pin_port;
|
||||
volatile PORT_TYPE *triggerSec_pin_port;
|
||||
volatile PINMASK_TYPE triggerSec_pin_mask;
|
||||
volatile PORT_TYPE *triggerThird_pin_port;
|
||||
volatile PORT_TYPE *triggerThird_pin_port;
|
||||
volatile PINMASK_TYPE triggerThird_pin_mask;
|
||||
|
||||
//These are variables used across multiple files
|
||||
bool initialisationComplete = false; ///< Tracks whether the setup() function has run completely (true = has run)
|
||||
byte fpPrimeTime = 0; ///< The time (in seconds, based on @ref statuses.secl) that the fuel pump started priming
|
||||
uint8_t softLimitTime = 0; //The time (in 0.1 seconds, based on seclx10) that the soft limiter started
|
||||
volatile uint16_t mainLoopCount; //Main loop counter (incremented at each main loop rev., used for maintaining currentStatus.loopsPerSecond)
|
||||
unsigned long revolutionTime; //The time in uS that one revolution would take at current speed (The time tooth 1 was last seen, minus the time it was seen prior to that)
|
||||
volatile unsigned long timer5_overflow_count = 0; //Increments every time counter 5 overflows. Used for the fast version of micros()
|
||||
volatile unsigned long ms_counter = 0; //A counter that increments once per ms
|
||||
uint16_t fixedCrankingOverride = 0;
|
||||
bool clutchTrigger;
|
||||
bool previousClutchTrigger;
|
||||
volatile uint32_t toothHistory[TOOTH_LOG_SIZE]; ///< Tooth trigger history - delta time (in uS) from last tooth (Indexed by @ref toothHistoryIndex)
|
||||
volatile uint8_t compositeLogHistory[TOOTH_LOG_SIZE];
|
||||
volatile bool fpPrimed = false; ///< Tracks whether or not the fuel pump priming has been completed yet
|
||||
volatile bool injPrimed = false; ///< Tracks whether or not the injectors priming has been completed yet
|
||||
volatile unsigned int toothHistoryIndex = 0; ///< Current index to @ref toothHistory array
|
||||
unsigned long currentLoopTime; /**< The time (in uS) that the current mainloop started */
|
||||
volatile uint16_t ignitionCount; /**< The count of ignition events that have taken place since the engine started */
|
||||
// These are variables used across multiple files
|
||||
bool initialisationComplete = false; ///< Tracks whether the setup() function has run completely (true = has run)
|
||||
byte fpPrimeTime = 0; ///< The time (in seconds, based on @ref statuses.secl) that the fuel pump started priming
|
||||
uint8_t softLimitTime = 0; // The time (in 0.1 seconds, based on seclx10) that the soft limiter started
|
||||
volatile uint16_t mainLoopCount; // Main loop counter (incremented at each main loop rev., used for maintaining currentStatus.loopsPerSecond)
|
||||
unsigned long revolutionTime; // The time in uS that one revolution would take at current speed (The time tooth 1 was last seen, minus the time it was seen prior to that)
|
||||
volatile unsigned long timer5_overflow_count = 0; // Increments every time counter 5 overflows. Used for the fast version of micros()
|
||||
volatile unsigned long ms_counter = 0; // A counter that increments once per ms
|
||||
uint16_t fixedCrankingOverride = 0;
|
||||
bool clutchTrigger;
|
||||
bool previousClutchTrigger;
|
||||
volatile uint32_t toothHistory[TOOTH_LOG_SIZE]; ///< Tooth trigger history - delta time (in uS) from last tooth (Indexed by @ref toothHistoryIndex)
|
||||
volatile uint8_t compositeLogHistory[TOOTH_LOG_SIZE];
|
||||
volatile bool fpPrimed = false; ///< Tracks whether or not the fuel pump priming has been completed yet
|
||||
volatile bool injPrimed = false; ///< Tracks whether or not the injectors priming has been completed yet
|
||||
volatile unsigned int toothHistoryIndex = 0; ///< Current index to @ref toothHistory array
|
||||
unsigned long currentLoopTime; /**< The time (in uS) that the current mainloop started */
|
||||
volatile uint16_t ignitionCount; /**< The count of ignition events that have taken place since the engine started */
|
||||
#if defined(CORE_SAMD21)
|
||||
PinStatus primaryTriggerEdge;
|
||||
PinStatus secondaryTriggerEdge;
|
||||
PinStatus tertiaryTriggerEdge;
|
||||
PinStatus primaryTriggerEdge;
|
||||
PinStatus secondaryTriggerEdge;
|
||||
PinStatus tertiaryTriggerEdge;
|
||||
#else
|
||||
byte primaryTriggerEdge;
|
||||
byte secondaryTriggerEdge;
|
||||
byte tertiaryTriggerEdge;
|
||||
byte primaryTriggerEdge;
|
||||
byte secondaryTriggerEdge;
|
||||
byte tertiaryTriggerEdge;
|
||||
#endif
|
||||
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
|
||||
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
|
||||
volatile uint32_t runSecsX10;
|
||||
volatile uint32_t seclx10;
|
||||
volatile byte HWTest_INJ = 0; /**< Each bit in this variable represents one of the injector channels and it's HW test status */
|
||||
volatile byte HWTest_INJ_50pc = 0; /**< Each bit in this variable represents one of the injector channels and it's 50% HW test status */
|
||||
volatile byte HWTest_IGN = 0; /**< Each bit in this variable represents one of the ignition channels and it's HW test status */
|
||||
volatile byte HWTest_IGN_50pc = 0;
|
||||
byte maxIgnOutputs = 1; /**< Number of ignition outputs being used by the current tune configuration */
|
||||
byte maxInjOutputs = 1; /**< Number of injection outputs being used by the current tune configuration */
|
||||
volatile byte HWTest_INJ = 0; /**< Each bit in this variable represents one of the injector channels and it's HW test status */
|
||||
volatile byte HWTest_INJ_50pc = 0; /**< Each bit in this variable represents one of the injector channels and it's 50% HW test status */
|
||||
volatile byte HWTest_IGN = 0; /**< Each bit in this variable represents one of the ignition channels and it's HW test status */
|
||||
volatile byte HWTest_IGN_50pc = 0;
|
||||
byte maxIgnOutputs = 1; /**< Number of ignition outputs being used by the current tune configuration */
|
||||
byte maxInjOutputs = 1; /**< Number of injection outputs being used by the current tune configuration */
|
||||
|
||||
//This needs to be here because using the config page directly can prevent burning the setting
|
||||
// This needs to be here because using the config page directly can prevent burning the setting
|
||||
byte resetControl = RESET_CONTROL_DISABLED;
|
||||
|
||||
volatile byte TIMER_mask;
|
||||
volatile byte LOOP_TIMER;
|
||||
|
||||
/// Various pin numbering (Injectors, Ign outputs, CAS, Cam, Sensors. etc.) assignments
|
||||
byte pinInjector1; ///< Output pin injector 1
|
||||
byte pinInjector2; ///< Output pin injector 2
|
||||
byte pinInjector3; ///< Output pin injector 3
|
||||
byte pinInjector4; ///< Output pin injector 4
|
||||
byte pinInjector5; ///< Output pin injector 5
|
||||
byte pinInjector6; ///< Output pin injector 6
|
||||
byte pinInjector7; ///< Output pin injector 7
|
||||
byte pinInjector8; ///< Output pin injector 8
|
||||
byte pinInjector1; ///< Output pin injector 1
|
||||
byte pinInjector2; ///< Output pin injector 2
|
||||
byte pinInjector3; ///< Output pin injector 3
|
||||
byte pinInjector4; ///< Output pin injector 4
|
||||
byte pinInjector5; ///< Output pin injector 5
|
||||
byte pinInjector6; ///< Output pin injector 6
|
||||
byte pinInjector7; ///< Output pin injector 7
|
||||
byte pinInjector8; ///< Output pin injector 8
|
||||
byte injectorOutputControl = OUTPUT_CONTROL_DIRECT; /**< Specifies whether the injectors are controlled directly (Via an IO pin)
|
||||
or using something like the MC33810. 0 = Direct (OUTPUT_CONTROL_DIRECT), 10 = MC33810 (OUTPUT_CONTROL_MC33810) */
|
||||
byte pinCoil1; ///< Pin for coil 1
|
||||
byte pinCoil2; ///< Pin for coil 2
|
||||
byte pinCoil3; ///< Pin for coil 3
|
||||
byte pinCoil4; ///< Pin for coil 4
|
||||
byte pinCoil5; ///< Pin for coil 5
|
||||
byte pinCoil6; ///< Pin for coil 6
|
||||
byte pinCoil7; ///< Pin for coil 7
|
||||
byte pinCoil8; ///< Pin for coil 8
|
||||
byte pinCoil1; ///< Pin for coil 1
|
||||
byte pinCoil2; ///< Pin for coil 2
|
||||
byte pinCoil3; ///< Pin for coil 3
|
||||
byte pinCoil4; ///< Pin for coil 4
|
||||
byte pinCoil5; ///< Pin for coil 5
|
||||
byte pinCoil6; ///< Pin for coil 6
|
||||
byte pinCoil7; ///< Pin for coil 7
|
||||
byte pinCoil8; ///< Pin for coil 8
|
||||
byte ignitionOutputControl = OUTPUT_CONTROL_DIRECT; /**< Specifies whether the coils are controlled directly (Via an IO pin)
|
||||
or using something like the MC33810. 0 = Direct (OUTPUT_CONTROL_DIRECT), 10 = MC33810 (OUTPUT_CONTROL_MC33810) */
|
||||
byte pinTrigger; ///< RPM1 (Typically CAS=crankshaft angle sensor) pin
|
||||
byte pinTrigger2; ///< RPM2 (Typically the Cam Sensor) pin
|
||||
byte pinTrigger3; ///< the 2nd cam sensor pin
|
||||
byte pinTPS; //TPS input pin
|
||||
byte pinMAP; //MAP sensor pin
|
||||
byte pinEMAP; //EMAP sensor pin
|
||||
byte pinMAP2; //2nd MAP sensor (Currently unused)
|
||||
byte pinIAT; //IAT sensor pin
|
||||
byte pinCLT; //CLS sensor pin
|
||||
byte pinO2; //O2 Sensor pin
|
||||
byte pinO2_2; //second O2 pin
|
||||
byte pinBat; //Battery voltage pin
|
||||
byte pinDisplayReset; // OLED reset pin
|
||||
byte pinTachOut; //Tacho output
|
||||
byte pinFuelPump; //Fuel pump on/off
|
||||
byte pinIdle1; //Single wire idle control
|
||||
byte pinIdle2; //2 wire idle control (Not currently used)
|
||||
byte pinIdleUp; //Input for triggering Idle Up
|
||||
byte pinIdleUpOutput; //Output that follows (normal or inverted) the idle up pin
|
||||
byte pinCTPS; //Input for triggering closed throttle state
|
||||
byte pinFuel2Input; //Input for switching to the 2nd fuel table
|
||||
byte pinSpark2Input; //Input for switching to the 2nd ignition table
|
||||
byte pinSpareTemp1; // Future use only
|
||||
byte pinSpareTemp2; // Future use only
|
||||
byte pinSpareOut1; //Generic output
|
||||
byte pinSpareOut2; //Generic output
|
||||
byte pinSpareOut3; //Generic output
|
||||
byte pinSpareOut4; //Generic output
|
||||
byte pinSpareOut5; //Generic output
|
||||
byte pinSpareOut6; //Generic output
|
||||
byte pinSpareHOut1; //spare high current output
|
||||
byte pinSpareHOut2; // spare high current output
|
||||
byte pinSpareLOut1; // spare low current output
|
||||
byte pinSpareLOut2; // spare low current output
|
||||
byte pinTrigger; ///< RPM1 (Typically CAS=crankshaft angle sensor) pin
|
||||
byte pinTrigger2; ///< RPM2 (Typically the Cam Sensor) pin
|
||||
byte pinTrigger3; ///< the 2nd cam sensor pin
|
||||
byte pinTPS; // TPS input pin
|
||||
byte pinMAP; // MAP sensor pin
|
||||
byte pinEMAP; // EMAP sensor pin
|
||||
byte pinMAP2; // 2nd MAP sensor (Currently unused)
|
||||
byte pinIAT; // IAT sensor pin
|
||||
byte pinCLT; // CLS sensor pin
|
||||
byte pinO2; // O2 Sensor pin
|
||||
byte pinO2_2; // second O2 pin
|
||||
byte pinBat; // Battery voltage pin
|
||||
byte pinDisplayReset; // OLED reset pin
|
||||
byte pinTachOut; // Tacho output
|
||||
byte pinFuelPump; // Fuel pump on/off
|
||||
byte pinIdle1; // Single wire idle control
|
||||
byte pinIdle2; // 2 wire idle control (Not currently used)
|
||||
byte pinIdleUp; // Input for triggering Idle Up
|
||||
byte pinIdleUpOutput; // Output that follows (normal or inverted) the idle up pin
|
||||
byte pinCTPS; // Input for triggering closed throttle state
|
||||
byte pinFuel2Input; // Input for switching to the 2nd fuel table
|
||||
byte pinSpark2Input; // Input for switching to the 2nd ignition table
|
||||
byte pinSpareTemp1; // Future use only
|
||||
byte pinSpareTemp2; // Future use only
|
||||
byte pinSpareOut1; // Generic output
|
||||
byte pinSpareOut2; // Generic output
|
||||
byte pinSpareOut3; // Generic output
|
||||
byte pinSpareOut4; // Generic output
|
||||
byte pinSpareOut5; // Generic output
|
||||
byte pinSpareOut6; // Generic output
|
||||
byte pinSpareHOut1; // spare high current output
|
||||
byte pinSpareHOut2; // spare high current output
|
||||
byte pinSpareLOut1; // spare low current output
|
||||
byte pinSpareLOut2; // spare low current output
|
||||
byte pinSpareLOut3;
|
||||
byte pinSpareLOut4;
|
||||
byte pinSpareLOut5;
|
||||
byte pinBoost;
|
||||
byte pinVVT_1; ///< vvt (variable valve timing) output 1
|
||||
byte pinVVT_2; ///< vvt (variable valve timing) output 2
|
||||
byte pinFan; ///< Cooling fan output (on/off? See: auxiliaries.ino)
|
||||
byte pinStepperDir; //Direction pin for the stepper motor driver
|
||||
byte pinStepperStep; //Step pin for the stepper motor driver
|
||||
byte pinStepperEnable; //Turning the DRV8825 driver on/off
|
||||
byte pinVVT_1; ///< vvt (variable valve timing) output 1
|
||||
byte pinVVT_2; ///< vvt (variable valve timing) output 2
|
||||
byte pinFan; ///< Cooling fan output (on/off? See: auxiliaries.ino)
|
||||
byte pinStepperDir; // Direction pin for the stepper motor driver
|
||||
byte pinStepperStep; // Step pin for the stepper motor driver
|
||||
byte pinStepperEnable; // Turning the DRV8825 driver on/off
|
||||
byte pinLaunch;
|
||||
byte pinIgnBypass; //The pin used for an ignition bypass (Optional)
|
||||
byte pinFlex; //Pin with the flex sensor attached
|
||||
byte pinVSS; // VSS (Vehicle speed sensor) Pin
|
||||
byte pinBaro; //Pin that an al barometric pressure sensor is attached to (If used)
|
||||
byte pinIgnBypass; // The pin used for an ignition bypass (Optional)
|
||||
byte pinFlex; // Pin with the flex sensor attached
|
||||
byte pinVSS; // VSS (Vehicle speed sensor) Pin
|
||||
byte pinBaro; // Pin that an al barometric pressure sensor is attached to (If used)
|
||||
byte pinResetControl; // Output pin used control resetting the Arduino
|
||||
byte pinFuelPressure;
|
||||
byte pinOilPressure;
|
||||
byte pinWMIEmpty; // Water tank empty sensor
|
||||
byte pinWMIEmpty; // Water tank empty sensor
|
||||
byte pinWMIIndicator; // No water indicator bulb
|
||||
byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid
|
||||
byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid
|
||||
byte pinMC33810_1_CS;
|
||||
byte pinMC33810_2_CS;
|
||||
byte pinSDEnable;
|
||||
#ifdef USE_SPI_EEPROM
|
||||
byte pinSPIFlash_CS;
|
||||
byte pinSPIFlash_CS;
|
||||
#endif
|
||||
byte pinAirConComp; // Air conditioning compressor output (See: auxiliaries.ino)
|
||||
byte pinAirConFan; // Stand-alone air conditioning fan output (See: auxiliaries.ino)
|
||||
byte pinAirConRequest; // Air conditioning request input (See: auxiliaries.ino)
|
||||
byte pinAirConComp; // Air conditioning compressor output (See: auxiliaries.ino)
|
||||
byte pinAirConFan; // Stand-alone air conditioning fan output (See: auxiliaries.ino)
|
||||
byte pinAirConRequest; // Air conditioning request input (See: auxiliaries.ino)
|
||||
|
||||
struct statuses currentStatus; /**< The master global "live" status struct. Contains all values that are updated frequently and used across modules */
|
||||
struct config2 configPage2;
|
||||
struct config4 configPage4;
|
||||
struct config6 configPage6;
|
||||
struct config9 configPage9;
|
||||
struct config2 configPage2;
|
||||
struct config4 configPage4;
|
||||
struct config6 configPage6;
|
||||
struct config9 configPage9;
|
||||
struct config10 configPage10;
|
||||
struct config13 configPage13;
|
||||
struct config15 configPage15;
|
||||
|
||||
//byte cltCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the coolant sensor calibration values */
|
||||
//byte iatCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the inlet air temperature sensor calibration values */
|
||||
//byte o2CalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the O2 sensor calibration values */
|
||||
// byte cltCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the coolant sensor calibration values */
|
||||
// byte iatCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the inlet air temperature sensor calibration values */
|
||||
// byte o2CalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the O2 sensor calibration values */
|
||||
|
||||
uint16_t cltCalibration_bins[32];
|
||||
uint16_t cltCalibration_values[32];
|
||||
uint16_t cltCalibration_bins[32];
|
||||
uint16_t cltCalibration_values[32];
|
||||
struct table2D cltCalibrationTable;
|
||||
uint16_t iatCalibration_bins[32];
|
||||
uint16_t iatCalibration_values[32];
|
||||
uint16_t iatCalibration_bins[32];
|
||||
uint16_t iatCalibration_values[32];
|
||||
struct table2D iatCalibrationTable;
|
||||
uint16_t o2Calibration_bins[32];
|
||||
uint8_t o2Calibration_values[32];
|
||||
struct table2D o2CalibrationTable;
|
||||
uint16_t o2Calibration_bins[32];
|
||||
uint8_t o2Calibration_values[32];
|
||||
struct table2D o2CalibrationTable;
|
||||
|
||||
//These function do checks on a pin to determine if it is already in use by another (higher importance) active function
|
||||
// These function do checks on a pin to determine if it is already in use by another (higher importance) active function
|
||||
inline bool pinIsOutput(byte pin)
|
||||
{
|
||||
bool used = false;
|
||||
bool isIdlePWM = (configPage6.iacAlgorithm > 0) && ((configPage6.iacAlgorithm <= 3) || (configPage6.iacAlgorithm == 6));
|
||||
bool used = false;
|
||||
bool isIdlePWM = (configPage6.iacAlgorithm > 0) && ((configPage6.iacAlgorithm <= 3) || (configPage6.iacAlgorithm == 6));
|
||||
bool isIdleSteper = (configPage6.iacAlgorithm > 3) && (configPage6.iacAlgorithm != 6);
|
||||
//Injector?
|
||||
if ((pin == pinInjector1)
|
||||
|| ((pin == pinInjector2) && (configPage2.nInjectors > 1))
|
||||
|| ((pin == pinInjector3) && (configPage2.nInjectors > 2))
|
||||
|| ((pin == pinInjector4) && (configPage2.nInjectors > 3))
|
||||
|| ((pin == pinInjector5) && (configPage2.nInjectors > 4))
|
||||
|| ((pin == pinInjector6) && (configPage2.nInjectors > 5))
|
||||
|| ((pin == pinInjector7) && (configPage2.nInjectors > 6))
|
||||
|| ((pin == pinInjector8) && (configPage2.nInjectors > 7)))
|
||||
// Injector?
|
||||
if((pin == pinInjector1) || ((pin == pinInjector2) && (configPage2.nInjectors > 1)) || ((pin == pinInjector3) && (configPage2.nInjectors > 2)) || ((pin == pinInjector4) && (configPage2.nInjectors > 3)) || ((pin == pinInjector5) && (configPage2.nInjectors > 4)) ||
|
||||
((pin == pinInjector6) && (configPage2.nInjectors > 5)) || ((pin == pinInjector7) && (configPage2.nInjectors > 6)) || ((pin == pinInjector8) && (configPage2.nInjectors > 7)))
|
||||
{
|
||||
used = true;
|
||||
}
|
||||
//Ignition?
|
||||
if ((pin == pinCoil1)
|
||||
|| ((pin == pinCoil2) && (maxIgnOutputs > 1))
|
||||
|| ((pin == pinCoil3) && (maxIgnOutputs > 2))
|
||||
|| ((pin == pinCoil4) && (maxIgnOutputs > 3))
|
||||
|| ((pin == pinCoil5) && (maxIgnOutputs > 4))
|
||||
|| ((pin == pinCoil6) && (maxIgnOutputs > 5))
|
||||
|| ((pin == pinCoil7) && (maxIgnOutputs > 6))
|
||||
|| ((pin == pinCoil8) && (maxIgnOutputs > 7)))
|
||||
// Ignition?
|
||||
if((pin == pinCoil1) || ((pin == pinCoil2) && (maxIgnOutputs > 1)) || ((pin == pinCoil3) && (maxIgnOutputs > 2)) || ((pin == pinCoil4) && (maxIgnOutputs > 3)) || ((pin == pinCoil5) && (maxIgnOutputs > 4)) || ((pin == pinCoil6) && (maxIgnOutputs > 5)) ||
|
||||
((pin == pinCoil7) && (maxIgnOutputs > 6)) || ((pin == pinCoil8) && (maxIgnOutputs > 7)))
|
||||
{
|
||||
used = true;
|
||||
}
|
||||
//Functions?
|
||||
if ((pin == pinFuelPump)
|
||||
|| ((pin == pinFan) && (configPage2.fanEnable == 1))
|
||||
|| ((pin == pinVVT_1) && (configPage6.vvtEnabled > 0))
|
||||
|| ((pin == pinVVT_1) && (configPage10.wmiEnabled > 0))
|
||||
|| ((pin == pinVVT_2) && (configPage10.vvt2Enabled > 0))
|
||||
|| ((pin == pinBoost) && (configPage6.boostEnabled == 1))
|
||||
|| ((pin == pinIdle1) && isIdlePWM)
|
||||
|| ((pin == pinIdle2) && isIdlePWM && (configPage6.iacChannels == 1))
|
||||
|| ((pin == pinStepperEnable) && isIdleSteper)
|
||||
|| ((pin == pinStepperStep) && isIdleSteper)
|
||||
|| ((pin == pinStepperDir) && isIdleSteper)
|
||||
|| (pin == pinTachOut)
|
||||
|| ((pin == pinAirConComp) && (configPage15.airConEnable > 0))
|
||||
|| ((pin == pinAirConFan) && (configPage15.airConEnable > 0) && (configPage15.airConFanEnabled > 0)) )
|
||||
// Functions?
|
||||
if((pin == pinFuelPump) || ((pin == pinFan) && (configPage2.fanEnable == 1)) || ((pin == pinVVT_1) && (configPage6.vvtEnabled > 0)) || ((pin == pinVVT_1) && (configPage10.wmiEnabled > 0)) || ((pin == pinVVT_2) && (configPage10.vvt2Enabled > 0)) ||
|
||||
((pin == pinBoost) && (configPage6.boostEnabled == 1)) || ((pin == pinIdle1) && isIdlePWM) || ((pin == pinIdle2) && isIdlePWM && (configPage6.iacChannels == 1)) || ((pin == pinStepperEnable) && isIdleSteper) || ((pin == pinStepperStep) && isIdleSteper) ||
|
||||
((pin == pinStepperDir) && isIdleSteper) || (pin == pinTachOut) || ((pin == pinAirConComp) && (configPage15.airConEnable > 0)) || ((pin == pinAirConFan) && (configPage15.airConEnable > 0) && (configPage15.airConFanEnabled > 0)))
|
||||
{
|
||||
used = true;
|
||||
}
|
||||
//Forbiden or hardware reserved? (Defined at board_xyz.h file)
|
||||
if ( pinIsReserved(pin) ) { used = true; }
|
||||
// Forbiden or hardware reserved? (Defined at board_xyz.h file)
|
||||
if(pinIsReserved(pin)) { used = true; }
|
||||
|
||||
return used;
|
||||
}
|
||||
|
@ -317,16 +294,10 @@ inline bool pinIsUsed(byte pin)
|
|||
{
|
||||
bool used = false;
|
||||
|
||||
//Analog input?
|
||||
if ( pinIsSensor(pin) )
|
||||
{
|
||||
used = true;
|
||||
}
|
||||
//Functions?
|
||||
if ( pinIsOutput(pin) )
|
||||
{
|
||||
used = true;
|
||||
}
|
||||
// Analog input?
|
||||
if(pinIsSensor(pin)) { used = true; }
|
||||
// Functions?
|
||||
if(pinIsOutput(pin)) { used = true; }
|
||||
|
||||
return used;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
5683
speeduino/init.ino
5683
speeduino/init.ino
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,7 @@
|
|||
#include "decoders.h"
|
||||
#include "init.h"
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns a numbered byte-field (partial field in case of multi-byte fields) from "current status" structure in the format expected by TunerStudio
|
||||
* Notes on fields:
|
||||
* - Numbered field will be fields from @ref currentStatus, but not at all in the internal order of strct (e.g. field RPM value, number 14 will be
|
||||
|
@ -20,68 +20,70 @@ byte getTSLogEntry(uint16_t byteNum)
|
|||
|
||||
switch(byteNum)
|
||||
{
|
||||
case 0: statusValue = currentStatus.secl; break; //secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0)
|
||||
case 1: statusValue = currentStatus.status1; break; //status1 Bitfield
|
||||
case 2: statusValue = currentStatus.engine; break; //Engine Status Bitfield
|
||||
case 0: statusValue = currentStatus.secl; break; // secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0)
|
||||
case 1: statusValue = currentStatus.status1; break; // status1 Bitfield
|
||||
case 2: statusValue = currentStatus.engine; break; // Engine Status Bitfield
|
||||
case 3: statusValue = currentStatus.syncLossCounter; break;
|
||||
case 4: statusValue = lowByte(currentStatus.MAP); break; //2 bytes for MAP
|
||||
case 4: statusValue = lowByte(currentStatus.MAP); break; // 2 bytes for MAP
|
||||
case 5: statusValue = highByte(currentStatus.MAP); break;
|
||||
case 6: statusValue = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); break; //mat
|
||||
case 7: statusValue = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); break; //Coolant ADC
|
||||
case 8: statusValue = currentStatus.batCorrection; break; //Battery voltage correction (%)
|
||||
case 9: statusValue = currentStatus.battery10; break; //battery voltage
|
||||
case 10: statusValue = currentStatus.O2; break; //O2
|
||||
case 11: statusValue = currentStatus.egoCorrection; break; //Exhaust gas correction (%)
|
||||
case 12: statusValue = currentStatus.iatCorrection; break; //Air temperature Correction (%)
|
||||
case 13: statusValue = currentStatus.wueCorrection; break; //Warmup enrichment (%)
|
||||
case 14: statusValue = lowByte(currentStatus.RPM); break; //rpm HB
|
||||
case 15: statusValue = highByte(currentStatus.RPM); break; //rpm LB
|
||||
case 16: statusValue = (byte)(currentStatus.AEamount >> 1); break; //TPS acceleration enrichment (%) divided by 2 (Can exceed 255)
|
||||
case 17: statusValue = lowByte(currentStatus.corrections); break; //Total GammaE (%)
|
||||
case 18: statusValue = highByte(currentStatus.corrections); break; //Total GammaE (%)
|
||||
case 19: statusValue = currentStatus.VE1; break; //VE 1 (%)
|
||||
case 20: statusValue = currentStatus.VE2; break; //VE 2 (%)
|
||||
case 6: statusValue = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); break; // mat
|
||||
case 7: statusValue = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); break; // Coolant ADC
|
||||
case 8: statusValue = currentStatus.batCorrection; break; // Battery voltage correction (%)
|
||||
case 9: statusValue = currentStatus.battery10; break; // battery voltage
|
||||
case 10: statusValue = currentStatus.O2; break; // O2
|
||||
case 11: statusValue = currentStatus.egoCorrection; break; // Exhaust gas correction (%)
|
||||
case 12: statusValue = currentStatus.iatCorrection; break; // Air temperature Correction (%)
|
||||
case 13: statusValue = currentStatus.wueCorrection; break; // Warmup enrichment (%)
|
||||
case 14: statusValue = lowByte(currentStatus.RPM); break; // rpm HB
|
||||
case 15: statusValue = highByte(currentStatus.RPM); break; // rpm LB
|
||||
case 16: statusValue = (byte)(currentStatus.AEamount >> 1); break; // TPS acceleration enrichment (%) divided by 2 (Can exceed 255)
|
||||
case 17: statusValue = lowByte(currentStatus.corrections); break; // Total GammaE (%)
|
||||
case 18: statusValue = highByte(currentStatus.corrections); break; // Total GammaE (%)
|
||||
case 19: statusValue = currentStatus.VE1; break; // VE 1 (%)
|
||||
case 20: statusValue = currentStatus.VE2; break; // VE 2 (%)
|
||||
case 21: statusValue = currentStatus.afrTarget; break;
|
||||
case 22: statusValue = lowByte(currentStatus.tpsDOT); break; //TPS DOT
|
||||
case 23: statusValue = highByte(currentStatus.tpsDOT); break; //TPS DOT
|
||||
case 22: statusValue = lowByte(currentStatus.tpsDOT); break; // TPS DOT
|
||||
case 23: statusValue = highByte(currentStatus.tpsDOT); break; // TPS DOT
|
||||
case 24: statusValue = currentStatus.advance; break;
|
||||
case 25: statusValue = currentStatus.TPS; break; // TPS (0% to 100%)
|
||||
|
||||
case 26:
|
||||
if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;}
|
||||
statusValue = lowByte(currentStatus.loopsPerSecond);
|
||||
|
||||
case 26:
|
||||
if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000; }
|
||||
statusValue = lowByte(currentStatus.loopsPerSecond);
|
||||
break;
|
||||
case 27:
|
||||
if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;}
|
||||
statusValue = highByte(currentStatus.loopsPerSecond);
|
||||
break;
|
||||
|
||||
case 28:
|
||||
currentStatus.freeRAM = freeRam();
|
||||
statusValue = lowByte(currentStatus.freeRAM); //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF);
|
||||
break;
|
||||
case 29:
|
||||
currentStatus.freeRAM = freeRam();
|
||||
statusValue = highByte(currentStatus.freeRAM);
|
||||
case 27:
|
||||
if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000; }
|
||||
statusValue = highByte(currentStatus.loopsPerSecond);
|
||||
break;
|
||||
|
||||
case 30: statusValue = (byte)(currentStatus.boostTarget >> 1); break; //Divide boost target by 2 to fit in a byte
|
||||
case 28:
|
||||
currentStatus.freeRAM = freeRam();
|
||||
statusValue = lowByte(currentStatus.freeRAM); //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF);
|
||||
break;
|
||||
case 29:
|
||||
currentStatus.freeRAM = freeRam();
|
||||
statusValue = highByte(currentStatus.freeRAM);
|
||||
break;
|
||||
|
||||
case 30: statusValue = (byte)(currentStatus.boostTarget >> 1); break; // Divide boost target by 2 to fit in a byte
|
||||
case 31: statusValue = (byte)(currentStatus.boostDuty / 100); break;
|
||||
case 32: statusValue = currentStatus.spark; break; //Spark related bitfield
|
||||
case 32:
|
||||
statusValue = currentStatus.spark;
|
||||
break; // Spark related bitfield
|
||||
|
||||
//rpmDOT must be sent as a signed integer
|
||||
// rpmDOT must be sent as a signed integer
|
||||
case 33: statusValue = lowByte(currentStatus.rpmDOT); break;
|
||||
case 34: statusValue = highByte(currentStatus.rpmDOT); break;
|
||||
|
||||
case 35: statusValue = currentStatus.ethanolPct; break; //Flex sensor value (or 0 if not used)
|
||||
case 36: statusValue = currentStatus.flexCorrection; break; //Flex fuel correction (% above or below 100)
|
||||
case 37: statusValue = currentStatus.flexIgnCorrection; break; //Ignition correction (Increased degrees of advance) for flex fuel
|
||||
case 35: statusValue = currentStatus.ethanolPct; break; // Flex sensor value (or 0 if not used)
|
||||
case 36: statusValue = currentStatus.flexCorrection; break; // Flex fuel correction (% above or below 100)
|
||||
case 37: statusValue = currentStatus.flexIgnCorrection; break; // Ignition correction (Increased degrees of advance) for flex fuel
|
||||
|
||||
case 38: statusValue = currentStatus.idleLoad; break;
|
||||
case 39: statusValue = currentStatus.testOutputs; break;
|
||||
|
||||
case 40: statusValue = currentStatus.O2_2; break; //O2
|
||||
case 41: statusValue = currentStatus.baro; break; //Barometer value
|
||||
case 40: statusValue = currentStatus.O2_2; break; // O2
|
||||
case 41: statusValue = currentStatus.baro; break; // Barometer value
|
||||
|
||||
case 42: statusValue = lowByte(currentStatus.canin[0]); break;
|
||||
case 43: statusValue = highByte(currentStatus.canin[0]); break;
|
||||
|
@ -119,14 +121,14 @@ byte getTSLogEntry(uint16_t byteNum)
|
|||
case 74: statusValue = currentStatus.tpsADC; break;
|
||||
case 75: statusValue = getNextError(); break;
|
||||
|
||||
case 76: statusValue = lowByte(currentStatus.PW1); break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 77: statusValue = highByte(currentStatus.PW1); break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 78: statusValue = lowByte(currentStatus.PW2); break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 79: statusValue = highByte(currentStatus.PW2); break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 80: statusValue = lowByte(currentStatus.PW3); break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 81: statusValue = highByte(currentStatus.PW3); break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 82: statusValue = lowByte(currentStatus.PW4); break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 83: statusValue = highByte(currentStatus.PW4); break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 76: statusValue = lowByte(currentStatus.PW1); break; // Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 77: statusValue = highByte(currentStatus.PW1); break; // Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 78: statusValue = lowByte(currentStatus.PW2); break; // Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 79: statusValue = highByte(currentStatus.PW2); break; // Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 80: statusValue = lowByte(currentStatus.PW3); break; // Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 81: statusValue = highByte(currentStatus.PW3); break; // Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 82: statusValue = lowByte(currentStatus.PW4); break; // Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 83: statusValue = highByte(currentStatus.PW4); break; // Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
|
||||
case 84: statusValue = currentStatus.status3; break;
|
||||
case 85: statusValue = currentStatus.engineProtectStatus; break;
|
||||
|
@ -139,15 +141,15 @@ byte getTSLogEntry(uint16_t byteNum)
|
|||
case 92: statusValue = currentStatus.CLIdleTarget; break;
|
||||
case 93: statusValue = lowByte(currentStatus.mapDOT); break;
|
||||
case 94: statusValue = highByte(currentStatus.mapDOT); break;
|
||||
case 95: statusValue = lowByte(currentStatus.vvt1Angle); break; //2 bytes for vvt1Angle
|
||||
case 95: statusValue = lowByte(currentStatus.vvt1Angle); break; // 2 bytes for vvt1Angle
|
||||
case 96: statusValue = highByte(currentStatus.vvt1Angle); break;
|
||||
case 97: statusValue = currentStatus.vvt1TargetAngle; break;
|
||||
case 98: statusValue = (byte)(currentStatus.vvt1Duty); break;
|
||||
case 99: statusValue = lowByte(currentStatus.flexBoostCorrection); break;
|
||||
case 100: statusValue = highByte(currentStatus.flexBoostCorrection); break;
|
||||
case 101: statusValue = currentStatus.baroCorrection; break;
|
||||
case 102: statusValue = currentStatus.VE; break; //Current VE (%). Can be equal to VE1 or VE2 or a calculated value from both of them
|
||||
case 103: statusValue = currentStatus.ASEValue; break; //Current ASE (%)
|
||||
case 102: statusValue = currentStatus.VE; break; // Current VE (%). Can be equal to VE1 or VE2 or a calculated value from both of them
|
||||
case 103: statusValue = currentStatus.ASEValue; break; // Current ASE (%)
|
||||
case 104: statusValue = lowByte(currentStatus.vss); break;
|
||||
case 105: statusValue = highByte(currentStatus.vss); break;
|
||||
case 106: statusValue = currentStatus.gear; break;
|
||||
|
@ -155,17 +157,17 @@ byte getTSLogEntry(uint16_t byteNum)
|
|||
case 108: statusValue = currentStatus.oilPressure; break;
|
||||
case 109: statusValue = currentStatus.wmiPW; break;
|
||||
case 110: statusValue = currentStatus.status4; break;
|
||||
case 111: statusValue = lowByte(currentStatus.vvt2Angle); break; //2 bytes for vvt2Angle
|
||||
case 111: statusValue = lowByte(currentStatus.vvt2Angle); break; // 2 bytes for vvt2Angle
|
||||
case 112: statusValue = highByte(currentStatus.vvt2Angle); break;
|
||||
case 113: statusValue = currentStatus.vvt2TargetAngle; break;
|
||||
case 114: statusValue = (byte)(currentStatus.vvt2Duty); break;
|
||||
case 115: statusValue = currentStatus.outputsStatus; break;
|
||||
case 116: statusValue = (byte)(currentStatus.fuelTemp + CALIBRATION_TEMPERATURE_OFFSET); break; //Fuel temperature from flex sensor
|
||||
case 117: statusValue = currentStatus.fuelTempCorrection; break; //Fuel temperature Correction (%)
|
||||
case 118: statusValue = currentStatus.advance1; break; //advance 1 (%)
|
||||
case 119: statusValue = currentStatus.advance2; break; //advance 2 (%)
|
||||
case 120: statusValue = currentStatus.TS_SD_Status; break; //SD card status
|
||||
case 121: statusValue = lowByte(currentStatus.EMAP); break; //2 bytes for EMAP
|
||||
case 116: statusValue = (byte)(currentStatus.fuelTemp + CALIBRATION_TEMPERATURE_OFFSET); break; // Fuel temperature from flex sensor
|
||||
case 117: statusValue = currentStatus.fuelTempCorrection; break; // Fuel temperature Correction (%)
|
||||
case 118: statusValue = currentStatus.advance1; break; // advance 1 (%)
|
||||
case 119: statusValue = currentStatus.advance2; break; // advance 2 (%)
|
||||
case 120: statusValue = currentStatus.TS_SD_Status; break; // SD card status
|
||||
case 121: statusValue = lowByte(currentStatus.EMAP); break; // 2 bytes for EMAP
|
||||
case 122: statusValue = highByte(currentStatus.EMAP); break;
|
||||
case 123: statusValue = currentStatus.fanDuty; break;
|
||||
case 124: statusValue = currentStatus.airConStatus; break;
|
||||
|
@ -176,7 +178,7 @@ byte getTSLogEntry(uint16_t byteNum)
|
|||
return statusValue;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Similar to the @ref getTSLogEntry function, however this returns a full, unadjusted (ie human readable) log entry value.
|
||||
* See logger.h for the field names and order
|
||||
* @param logIndex - The log index required. Note that this is NOT the byte number, but the index in the log
|
||||
|
@ -188,50 +190,50 @@ int16_t getReadableLogEntry(uint16_t logIndex)
|
|||
|
||||
switch(logIndex)
|
||||
{
|
||||
case 0: statusValue = currentStatus.secl; break; //secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0)
|
||||
case 1: statusValue = currentStatus.status1; break; //status1 Bitfield
|
||||
case 2: statusValue = currentStatus.engine; break; //Engine Status Bitfield
|
||||
case 0: statusValue = currentStatus.secl; break; // secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0)
|
||||
case 1: statusValue = currentStatus.status1; break; // status1 Bitfield
|
||||
case 2: statusValue = currentStatus.engine; break; // Engine Status Bitfield
|
||||
case 3: statusValue = currentStatus.syncLossCounter; break;
|
||||
case 4: statusValue = currentStatus.MAP; break; //2 bytes for MAP
|
||||
case 5: statusValue = currentStatus.IAT; break; //mat
|
||||
case 6: statusValue = currentStatus.coolant; break; //Coolant ADC
|
||||
case 7: statusValue = currentStatus.batCorrection; break; //Battery voltage correction (%)
|
||||
case 8: statusValue = currentStatus.battery10; break; //battery voltage
|
||||
case 9: statusValue = currentStatus.O2; break; //O2
|
||||
case 10: statusValue = currentStatus.egoCorrection; break; //Exhaust gas correction (%)
|
||||
case 11: statusValue = currentStatus.iatCorrection; break; //Air temperature Correction (%)
|
||||
case 12: statusValue = currentStatus.wueCorrection; break; //Warmup enrichment (%)
|
||||
case 13: statusValue = currentStatus.RPM; break; //rpm HB
|
||||
case 14: statusValue = currentStatus.AEamount; break; //TPS acceleration enrichment (%)
|
||||
case 15: statusValue = currentStatus.corrections; break; //Total GammaE (%)
|
||||
case 16: statusValue = currentStatus.VE1; break; //VE 1 (%)
|
||||
case 17: statusValue = currentStatus.VE2; break; //VE 2 (%)
|
||||
case 4: statusValue = currentStatus.MAP; break; // 2 bytes for MAP
|
||||
case 5: statusValue = currentStatus.IAT; break; // mat
|
||||
case 6: statusValue = currentStatus.coolant; break; // Coolant ADC
|
||||
case 7: statusValue = currentStatus.batCorrection; break; // Battery voltage correction (%)
|
||||
case 8: statusValue = currentStatus.battery10; break; // battery voltage
|
||||
case 9: statusValue = currentStatus.O2; break; // O2
|
||||
case 10: statusValue = currentStatus.egoCorrection; break; // Exhaust gas correction (%)
|
||||
case 11: statusValue = currentStatus.iatCorrection; break; // Air temperature Correction (%)
|
||||
case 12: statusValue = currentStatus.wueCorrection; break; // Warmup enrichment (%)
|
||||
case 13: statusValue = currentStatus.RPM; break; // rpm HB
|
||||
case 14: statusValue = currentStatus.AEamount; break; // TPS acceleration enrichment (%)
|
||||
case 15: statusValue = currentStatus.corrections; break; // Total GammaE (%)
|
||||
case 16: statusValue = currentStatus.VE1; break; // VE 1 (%)
|
||||
case 17: statusValue = currentStatus.VE2; break; // VE 2 (%)
|
||||
case 18: statusValue = currentStatus.afrTarget; break;
|
||||
case 19: statusValue = currentStatus.tpsDOT; break; //TPS DOT
|
||||
case 19: statusValue = currentStatus.tpsDOT; break; // TPS DOT
|
||||
case 20: statusValue = currentStatus.advance; break;
|
||||
case 21: statusValue = currentStatus.TPS; break; // TPS (0% to 100%)
|
||||
|
||||
case 22:
|
||||
if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;}
|
||||
statusValue = currentStatus.loopsPerSecond;
|
||||
|
||||
case 22:
|
||||
if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000; }
|
||||
statusValue = currentStatus.loopsPerSecond;
|
||||
break;
|
||||
|
||||
case 23:
|
||||
|
||||
case 23:
|
||||
currentStatus.freeRAM = freeRam();
|
||||
statusValue = currentStatus.freeRAM;
|
||||
break;
|
||||
statusValue = currentStatus.freeRAM;
|
||||
break;
|
||||
|
||||
case 24: statusValue = currentStatus.boostTarget; break;
|
||||
case 25: statusValue = currentStatus.boostDuty; break;
|
||||
case 26: statusValue = currentStatus.spark; break; //Spark related bitfield
|
||||
case 26: statusValue = currentStatus.spark; break; // Spark related bitfield
|
||||
case 27: statusValue = currentStatus.rpmDOT; break;
|
||||
case 28: statusValue = currentStatus.ethanolPct; break; //Flex sensor value (or 0 if not used)
|
||||
case 29: statusValue = currentStatus.flexCorrection; break; //Flex fuel correction (% above or below 100)
|
||||
case 30: statusValue = currentStatus.flexIgnCorrection; break; //Ignition correction (Increased degrees of advance) for flex fuel
|
||||
case 28: statusValue = currentStatus.ethanolPct; break; // Flex sensor value (or 0 if not used)
|
||||
case 29: statusValue = currentStatus.flexCorrection; break; // Flex fuel correction (% above or below 100)
|
||||
case 30: statusValue = currentStatus.flexIgnCorrection; break; // Ignition correction (Increased degrees of advance) for flex fuel
|
||||
case 31: statusValue = currentStatus.idleLoad; break;
|
||||
case 32: statusValue = currentStatus.testOutputs; break;
|
||||
case 33: statusValue = currentStatus.O2_2; break; //O2
|
||||
case 34: statusValue = currentStatus.baro; break; //Barometer value
|
||||
case 33: statusValue = currentStatus.O2_2; break; // O2
|
||||
case 34: statusValue = currentStatus.baro; break; // Barometer value
|
||||
|
||||
case 35: statusValue = currentStatus.canin[0]; break;
|
||||
case 36: statusValue = currentStatus.canin[1]; break;
|
||||
|
@ -249,19 +251,19 @@ int16_t getReadableLogEntry(uint16_t logIndex)
|
|||
case 48: statusValue = currentStatus.canin[13]; break;
|
||||
case 49: statusValue = currentStatus.canin[14]; break;
|
||||
case 50: statusValue = currentStatus.canin[15]; break;
|
||||
|
||||
|
||||
case 51: statusValue = currentStatus.tpsADC; break;
|
||||
case 52: statusValue = getNextError(); break;
|
||||
|
||||
case 53: statusValue = currentStatus.PW1; break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 54: statusValue = currentStatus.PW2; break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 55: statusValue = currentStatus.PW3; break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 56: statusValue = currentStatus.PW4; break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
|
||||
case 53: statusValue = currentStatus.PW1; break; // Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 54: statusValue = currentStatus.PW2; break; // Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 55: statusValue = currentStatus.PW3; break; // Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
case 56: statusValue = currentStatus.PW4; break; // Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
|
||||
|
||||
case 57: statusValue = currentStatus.status3; break;
|
||||
case 58: statusValue = currentStatus.engineProtectStatus; break;
|
||||
|
||||
case 59: break; //UNUSED!!
|
||||
case 59: break; // UNUSED!!
|
||||
|
||||
case 60: statusValue = currentStatus.fuelLoad; break;
|
||||
case 61: statusValue = currentStatus.ignLoad; break;
|
||||
|
@ -273,23 +275,23 @@ int16_t getReadableLogEntry(uint16_t logIndex)
|
|||
case 67: statusValue = currentStatus.vvt1Duty; break;
|
||||
case 68: statusValue = currentStatus.flexBoostCorrection; break;
|
||||
case 69: statusValue = currentStatus.baroCorrection; break;
|
||||
case 70: statusValue = currentStatus.VE; break; //Current VE (%). Can be equal to VE1 or VE2 or a calculated value from both of them
|
||||
case 71: statusValue = currentStatus.ASEValue; break; //Current ASE (%)
|
||||
case 70: statusValue = currentStatus.VE; break; // Current VE (%). Can be equal to VE1 or VE2 or a calculated value from both of them
|
||||
case 71: statusValue = currentStatus.ASEValue; break; // Current ASE (%)
|
||||
case 72: statusValue = currentStatus.vss; break;
|
||||
case 73: statusValue = currentStatus.gear; break;
|
||||
case 74: statusValue = currentStatus.fuelPressure; break;
|
||||
case 75: statusValue = currentStatus.oilPressure; break;
|
||||
case 76: statusValue = currentStatus.wmiPW; break;
|
||||
case 77: statusValue = currentStatus.status4; break;
|
||||
case 78: statusValue = currentStatus.vvt2Angle; break; //2 bytes for vvt2Angle
|
||||
case 78: statusValue = currentStatus.vvt2Angle; break; // 2 bytes for vvt2Angle
|
||||
case 79: statusValue = currentStatus.vvt2TargetAngle; break;
|
||||
case 80: statusValue = currentStatus.vvt2Duty; break;
|
||||
case 81: statusValue = currentStatus.outputsStatus; break;
|
||||
case 82: statusValue = currentStatus.fuelTemp; break; //Fuel temperature from flex sensor
|
||||
case 83: statusValue = currentStatus.fuelTempCorrection; break; //Fuel temperature Correction (%)
|
||||
case 84: statusValue = currentStatus.advance1; break; //advance 1 (%)
|
||||
case 85: statusValue = currentStatus.advance2; break; //advance 2 (%)
|
||||
case 86: statusValue = currentStatus.TS_SD_Status; break; //SD card status
|
||||
case 82: statusValue = currentStatus.fuelTemp; break; // Fuel temperature from flex sensor
|
||||
case 83: statusValue = currentStatus.fuelTempCorrection; break; // Fuel temperature Correction (%)
|
||||
case 84: statusValue = currentStatus.advance1; break; // advance 1 (%)
|
||||
case 85: statusValue = currentStatus.advance2; break; // advance 2 (%)
|
||||
case 86: statusValue = currentStatus.TS_SD_Status; break; // SD card status
|
||||
case 87: statusValue = currentStatus.EMAP; break;
|
||||
case 88: statusValue = currentStatus.fanDuty; break;
|
||||
case 89: statusValue = currentStatus.airConStatus; break;
|
||||
|
@ -299,11 +301,11 @@ int16_t getReadableLogEntry(uint16_t logIndex)
|
|||
return statusValue;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* An expansion to the @ref getReadableLogEntry function for systems that have an FPU. It will provide a floating point value for any parameter that this is appropriate for, otherwise will return the result of @ref getReadableLogEntry.
|
||||
* See logger.h for the field names and order
|
||||
* @param logIndex - The log index required. Note that this is NOT the byte number, but the index in the log
|
||||
* @return float value of the requested log entry.
|
||||
* @return float value of the requested log entry.
|
||||
*/
|
||||
#if FPU_MAX_SIZE >= 32
|
||||
float getReadableFloatLogEntry(uint16_t logIndex)
|
||||
|
@ -312,56 +314,50 @@ float getReadableFloatLogEntry(uint16_t logIndex)
|
|||
|
||||
switch(logIndex)
|
||||
{
|
||||
case 8: statusValue = currentStatus.battery10 / 10.0; break; //battery voltage
|
||||
case 8: statusValue = currentStatus.battery10 / 10.0; break; // battery voltage
|
||||
case 9: statusValue = currentStatus.O2 / 10.0; break;
|
||||
case 18: statusValue = currentStatus.afrTarget / 10.0; break;
|
||||
case 21: statusValue = currentStatus.TPS / 2.0; break; // TPS (0% to 100% = 0 to 200)
|
||||
case 33: statusValue = currentStatus.O2_2 / 10.0; break; //O2
|
||||
case 21: statusValue = currentStatus.TPS / 2.0; break; // TPS (0% to 100% = 0 to 200)
|
||||
case 33: statusValue = currentStatus.O2_2 / 10.0; break; // O2
|
||||
|
||||
case 53: statusValue = currentStatus.PW1 / 1000.0; break; //Pulsewidth 1 Have to convert from uS to mS.
|
||||
case 54: statusValue = currentStatus.PW2 / 1000.0; break; //Pulsewidth 2 Have to convert from uS to mS.
|
||||
case 55: statusValue = currentStatus.PW3 / 1000.0; break; //Pulsewidth 3 Have to convert from uS to mS.
|
||||
case 56: statusValue = currentStatus.PW4 / 1000.0; break; //Pulsewidth 4 Have to convert from uS to mS.
|
||||
case 53: statusValue = currentStatus.PW1 / 1000.0; break; // Pulsewidth 1 Have to convert from uS to mS.
|
||||
case 54: statusValue = currentStatus.PW2 / 1000.0; break; // Pulsewidth 2 Have to convert from uS to mS.
|
||||
case 55: statusValue = currentStatus.PW3 / 1000.0; break; // Pulsewidth 3 Have to convert from uS to mS.
|
||||
case 56: statusValue = currentStatus.PW4 / 1000.0; break; // Pulsewidth 4 Have to convert from uS to mS.
|
||||
|
||||
default: statusValue = getReadableLogEntry(logIndex); break; //If logIndex value is NOT a float based one, use the regular function
|
||||
default: statusValue = getReadableLogEntry(logIndex); break; // If logIndex value is NOT a float based one, use the regular function
|
||||
}
|
||||
|
||||
return statusValue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
/**
|
||||
* Searches the log 2 byte array to determine whether a given index is a regular single byte or a 2 byte field
|
||||
* Uses a boundless binary search for improved performance, but requires the fsIntIndex to remain in order
|
||||
* Refer: https://github.com/scandum/binary_search
|
||||
*
|
||||
*
|
||||
* @param key - Index in the log array to check
|
||||
* @return True if the index is a 2 byte log field. False if it is a single byte
|
||||
*/
|
||||
bool is2ByteEntry(uint8_t key)
|
||||
{
|
||||
bool isFound = false;
|
||||
bool isFound = false;
|
||||
unsigned int mid, bot;
|
||||
uint16_t array_size = sizeof(fsIntIndex);
|
||||
uint16_t array_size = sizeof(fsIntIndex);
|
||||
|
||||
if (array_size > 0)
|
||||
if(array_size > 0)
|
||||
{
|
||||
bot = 0;
|
||||
mid = array_size;
|
||||
|
||||
while (mid > 1)
|
||||
{
|
||||
if (key >= pgm_read_byte( &fsIntIndex[bot + mid / 2]) )
|
||||
{
|
||||
bot += mid++ / 2;
|
||||
}
|
||||
|
||||
while(mid > 1)
|
||||
{
|
||||
if(key >= pgm_read_byte(&fsIntIndex[bot + mid / 2])) { bot += mid++ / 2; }
|
||||
mid /= 2;
|
||||
}
|
||||
|
||||
if (key == pgm_read_byte(&fsIntIndex[bot]) )
|
||||
{
|
||||
isFound = true;
|
||||
}
|
||||
|
||||
if(key == pgm_read_byte(&fsIntIndex[bot])) { isFound = true; }
|
||||
}
|
||||
|
||||
return isFound;
|
||||
|
@ -369,53 +365,52 @@ bool is2ByteEntry(uint8_t key)
|
|||
|
||||
void startToothLogger(void)
|
||||
{
|
||||
currentStatus.toothLogEnabled = true;
|
||||
currentStatus.compositeTriggerUsed = 0; //Safety first (Should never be required)
|
||||
currentStatus.toothLogEnabled = true;
|
||||
currentStatus.compositeTriggerUsed = 0; // Safety first (Should never be required)
|
||||
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
|
||||
toothHistoryIndex = 0;
|
||||
|
||||
//Disconnect the standard interrupt and add the logger version
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE );
|
||||
// Disconnect the standard interrupt and add the logger version
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE);
|
||||
|
||||
if(VSS_USES_RPM2() != true)
|
||||
{
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger2));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void stopToothLogger(void)
|
||||
{
|
||||
currentStatus.toothLogEnabled = false;
|
||||
|
||||
//Disconnect the logger interrupts and attach the normal ones
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge );
|
||||
// Disconnect the logger interrupts and attach the normal ones
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge);
|
||||
|
||||
if(VSS_USES_RPM2() != true)
|
||||
{
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger2));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge);
|
||||
}
|
||||
}
|
||||
|
||||
void startCompositeLogger(void)
|
||||
{
|
||||
currentStatus.compositeTriggerUsed = 2;
|
||||
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
|
||||
currentStatus.toothLogEnabled = false; // Safety first (Should never be required)
|
||||
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
|
||||
toothHistoryIndex = 0;
|
||||
|
||||
//Disconnect the standard interrupt and add the logger version
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE );
|
||||
// Disconnect the standard interrupt and add the logger version
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE);
|
||||
|
||||
if( (VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true) )
|
||||
if((VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true))
|
||||
{
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger2));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,74 +418,73 @@ void stopCompositeLogger(void)
|
|||
{
|
||||
currentStatus.compositeTriggerUsed = 0;
|
||||
|
||||
//Disconnect the logger interrupts and attach the normal ones
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge );
|
||||
// Disconnect the logger interrupts and attach the normal ones
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge);
|
||||
|
||||
if( (VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true) )
|
||||
if((VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true))
|
||||
{
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger2));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge);
|
||||
}
|
||||
}
|
||||
|
||||
void startCompositeLoggerTertiary(void)
|
||||
{
|
||||
currentStatus.compositeTriggerUsed = 3;
|
||||
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
|
||||
currentStatus.toothLogEnabled = false; // Safety first (Should never be required)
|
||||
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
|
||||
toothHistoryIndex = 0;
|
||||
|
||||
//Disconnect the standard interrupt and add the logger version
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE );
|
||||
// Disconnect the standard interrupt and add the logger version
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger), loggerPrimaryISR, CHANGE);
|
||||
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger3) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger3), loggerTertiaryISR, CHANGE );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger3));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger3), loggerTertiaryISR, CHANGE);
|
||||
}
|
||||
|
||||
void stopCompositeLoggerTertiary(void)
|
||||
{
|
||||
currentStatus.compositeTriggerUsed = 0;
|
||||
|
||||
//Disconnect the logger interrupts and attach the normal ones
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge );
|
||||
// Disconnect the logger interrupts and attach the normal ones
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger), triggerHandler, primaryTriggerEdge);
|
||||
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger3) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger3), triggerTertiaryHandler, tertiaryTriggerEdge );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger3));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger3), triggerTertiaryHandler, tertiaryTriggerEdge);
|
||||
}
|
||||
|
||||
|
||||
void startCompositeLoggerCams(void)
|
||||
{
|
||||
currentStatus.compositeTriggerUsed = 4;
|
||||
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
|
||||
currentStatus.toothLogEnabled = false; // Safety first (Should never be required)
|
||||
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
|
||||
toothHistoryIndex = 0;
|
||||
|
||||
//Disconnect the standard interrupt and add the logger version
|
||||
if( (VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true) )
|
||||
// Disconnect the standard interrupt and add the logger version
|
||||
if((VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true))
|
||||
{
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger2));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE);
|
||||
}
|
||||
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger3) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger3), loggerTertiaryISR, CHANGE );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger3));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger3), loggerTertiaryISR, CHANGE);
|
||||
}
|
||||
|
||||
void stopCompositeLoggerCams(void)
|
||||
{
|
||||
currentStatus.compositeTriggerUsed = false;
|
||||
|
||||
//Disconnect the logger interrupts and attach the normal ones
|
||||
if( (VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true) )
|
||||
// Disconnect the logger interrupts and attach the normal ones
|
||||
if((VSS_USES_RPM2() != true) && (FLEX_USES_RPM2() != true))
|
||||
{
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger2));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge);
|
||||
}
|
||||
|
||||
detachInterrupt( digitalPinToInterrupt(pinTrigger3) );
|
||||
attachInterrupt( digitalPinToInterrupt(pinTrigger3), triggerTertiaryHandler, tertiaryTriggerEdge );
|
||||
detachInterrupt(digitalPinToInterrupt(pinTrigger3));
|
||||
attachInterrupt(digitalPinToInterrupt(pinTrigger3), triggerTertiaryHandler, tertiaryTriggerEdge);
|
||||
}
|
||||
|
|
|
@ -2,46 +2,43 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#ifdef USE_LIBDIVIDE
|
||||
#include "src/libdivide/constant_fast_div.h"
|
||||
#include "src/libdivide/constant_fast_div.h"
|
||||
|
||||
// Constants used for libdivide. Using predefined constants saves flash and RAM (.bss)
|
||||
// versus calling the libdivide generator functions (E.g. libdivide_s32_gen)
|
||||
const libdivide::libdivide_s16_t libdiv_s16_100 = { .magic = S16_MAGIC(100), .more = S16_MORE(100) };
|
||||
const libdivide::libdivide_u16_t libdiv_u16_100 = { .magic = U16_MAGIC(100), .more = U16_MORE(100) };
|
||||
const libdivide::libdivide_s16_t libdiv_s16_100 = {.magic = S16_MAGIC(100), .more = S16_MORE(100)};
|
||||
const libdivide::libdivide_u16_t libdiv_u16_100 = {.magic = U16_MAGIC(100), .more = U16_MORE(100)};
|
||||
// 32-bit constants generated here: https://godbolt.org/z/vP8Kfejo9
|
||||
const libdivide::libdivide_u32_t libdiv_u32_100 = { .magic = 2748779070, .more = 6 };
|
||||
const libdivide::libdivide_s32_t libdiv_s32_100 = { .magic = 1374389535, .more = 5 };
|
||||
const libdivide::libdivide_u32_t libdiv_u32_200 = { .magic = 2748779070, .more = 7 };
|
||||
const libdivide::libdivide_u32_t libdiv_u32_360 = { .magic = 1813430637, .more = 72 };
|
||||
const libdivide::libdivide_u32_t libdiv_u32_100 = {.magic = 2748779070, .more = 6};
|
||||
const libdivide::libdivide_s32_t libdiv_s32_100 = {.magic = 1374389535, .more = 5};
|
||||
const libdivide::libdivide_u32_t libdiv_u32_200 = {.magic = 2748779070, .more = 7};
|
||||
const libdivide::libdivide_u32_t libdiv_u32_360 = {.magic = 1813430637, .more = 72};
|
||||
#endif
|
||||
|
||||
//Replace the standard arduino map() function to use the div function instead
|
||||
// Replace the standard arduino map() function to use the div function instead
|
||||
int fastMap(unsigned long x, int in_min, int in_max, int out_min, int out_max)
|
||||
{
|
||||
unsigned long a = (x - (unsigned long)in_min);
|
||||
int b = (out_max - out_min);
|
||||
int c = (in_max - in_min);
|
||||
int d = (ldiv( (a * (long)b) , (long)c ).quot);
|
||||
int b = (out_max - out_min);
|
||||
int c = (in_max - in_min);
|
||||
int d = (ldiv((a * (long)b), (long)c).quot);
|
||||
return d + out_min;
|
||||
//return ldiv( ((x - in_min) * (out_max - out_min)) , (in_max - in_min) ).quot + out_min;
|
||||
//return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
// return ldiv( ((x - in_min) * (out_max - out_min)) , (in_max - in_min) ).quot + out_min;
|
||||
// return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
//Return x percent of y
|
||||
//This is a relatively fast approximation of a percentage value.
|
||||
unsigned long percentage(uint8_t x, unsigned long y)
|
||||
{
|
||||
return div100(y * x);
|
||||
}
|
||||
// Return x percent of y
|
||||
// This is a relatively fast approximation of a percentage value.
|
||||
unsigned long percentage(uint8_t x, unsigned long y) { return div100(y * x); }
|
||||
|
||||
//Same as above, but 0.5% accuracy
|
||||
// Same as above, but 0.5% accuracy
|
||||
unsigned long halfPercentage(uint8_t x, unsigned long y)
|
||||
{
|
||||
#ifdef USE_LIBDIVIDE
|
||||
return libdivide::libdivide_u32_do(y * x, &libdiv_u32_200);
|
||||
#ifdef USE_LIBDIVIDE
|
||||
return libdivide::libdivide_u32_do(y * x, &libdiv_u32_200);
|
||||
#else
|
||||
return (y * x) / 200;
|
||||
#endif
|
||||
return (y * x) / 200;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -49,20 +46,23 @@ unsigned long halfPercentage(uint8_t x, unsigned long y)
|
|||
*/
|
||||
inline long powint(int factor, unsigned int exponent)
|
||||
{
|
||||
long product = 1;
|
||||
long product = 1;
|
||||
unsigned int counter = exponent;
|
||||
while ( (counter--) > 0) { product *= factor; }
|
||||
while((counter--) > 0)
|
||||
{
|
||||
product *= factor;
|
||||
}
|
||||
return product;
|
||||
}
|
||||
|
||||
//Generates a random number from 1 to 100 (inclusive).
|
||||
//The initial seed used is always based on micros(), though this is unlikely to cause an issue as the first run is nearly random itself
|
||||
//Function requires 4 bytes to store state and seed, but operates very quickly (around 4uS per call)
|
||||
// Generates a random number from 1 to 100 (inclusive).
|
||||
// The initial seed used is always based on micros(), though this is unlikely to cause an issue as the first run is nearly random itself
|
||||
// Function requires 4 bytes to store state and seed, but operates very quickly (around 4uS per call)
|
||||
uint8_t a, x, y, z;
|
||||
uint8_t random1to100()
|
||||
{
|
||||
//Check if this is the first time being run. If so, seed the random number generator with micros()
|
||||
if( (a == 0) && (x == 0) && (y == 0) && (z == 0) )
|
||||
// Check if this is the first time being run. If so, seed the random number generator with micros()
|
||||
if((a == 0) && (x == 0) && (y == 0) && (z == 0))
|
||||
{
|
||||
x = micros() >> 24;
|
||||
y = micros() >> 16;
|
||||
|
@ -73,11 +73,10 @@ uint8_t random1to100()
|
|||
do
|
||||
{
|
||||
unsigned char t = x ^ (x << 4);
|
||||
x=y;
|
||||
y=z;
|
||||
z=a;
|
||||
a = z ^ t ^ ( z >> 1) ^ (t << 1);
|
||||
}
|
||||
while(a >= 100);
|
||||
return (a+1);
|
||||
x = y;
|
||||
y = z;
|
||||
z = a;
|
||||
a = z ^ t ^ (z >> 1) ^ (t << 1);
|
||||
} while(a >= 100);
|
||||
return (a + 1);
|
||||
}
|
||||
|
|
|
@ -1,129 +1,128 @@
|
|||
#include "globals.h"
|
||||
#include RTC_LIB_H //Defined in each boards .h file
|
||||
#ifdef RTC_ENABLED
|
||||
#include "rtc_common.h"
|
||||
|
||||
#include "rtc_common.h"
|
||||
|
||||
void initRTC()
|
||||
{
|
||||
|
||||
#if defined(CORE_TEENSY35) || defined(CORE_TEENSY36)|| defined(CORE_TEENSY41)
|
||||
setSyncProvider(getTeensy3Time);
|
||||
#if defined(CORE_TEENSY35) || defined(CORE_TEENSY36) || defined(CORE_TEENSY41)
|
||||
setSyncProvider(getTeensy3Time);
|
||||
#elif defined(CORE_STM32)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t rtc_getSecond()
|
||||
{
|
||||
uint8_t tempSecond = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempSecond = second();
|
||||
#elif defined(CORE_STM32)
|
||||
tempSecond = rtc.getSeconds();
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempSecond = second();
|
||||
#elif defined(CORE_STM32)
|
||||
tempSecond = rtc.getSeconds();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return tempSecond;
|
||||
}
|
||||
|
||||
uint8_t rtc_getMinute()
|
||||
{
|
||||
uint8_t tempMinute = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempMinute = minute();
|
||||
#elif defined(CORE_STM32)
|
||||
tempMinute = rtc.getMinutes();
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempMinute = minute();
|
||||
#elif defined(CORE_STM32)
|
||||
tempMinute = rtc.getMinutes();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return tempMinute;
|
||||
}
|
||||
|
||||
uint8_t rtc_getHour()
|
||||
{
|
||||
uint8_t tempHour = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempHour = hour();
|
||||
#elif defined(CORE_STM32)
|
||||
tempHour = rtc.getHours();
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempHour = hour();
|
||||
#elif defined(CORE_STM32)
|
||||
tempHour = rtc.getHours();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return tempHour;
|
||||
}
|
||||
|
||||
uint8_t rtc_getDay()
|
||||
{
|
||||
uint8_t tempDay = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempDay = day();
|
||||
#elif defined(CORE_STM32)
|
||||
tempDay = rtc.getDay();
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempDay = day();
|
||||
#elif defined(CORE_STM32)
|
||||
tempDay = rtc.getDay();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return tempDay;
|
||||
}
|
||||
|
||||
uint8_t rtc_getDOW()
|
||||
{
|
||||
uint8_t dow = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
dow = weekday();
|
||||
#elif defined(CORE_STM32)
|
||||
dow = rtc.getWeekDay();
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
dow = weekday();
|
||||
#elif defined(CORE_STM32)
|
||||
dow = rtc.getWeekDay();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return dow;
|
||||
}
|
||||
|
||||
uint8_t rtc_getMonth()
|
||||
{
|
||||
uint8_t tempMonth = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempMonth = month();
|
||||
#elif defined(CORE_STM32)
|
||||
tempMonth = rtc.getMonth();
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempMonth = month();
|
||||
#elif defined(CORE_STM32)
|
||||
tempMonth = rtc.getMonth();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return tempMonth;
|
||||
}
|
||||
|
||||
uint16_t rtc_getYear()
|
||||
{
|
||||
uint16_t tempYear = 0;
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempYear = year();
|
||||
#elif defined(CORE_STM32)
|
||||
//year in stm32 rtc is a byte. So add year 2000 to make it correct
|
||||
tempYear = (2000+rtc.getYear());
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
tempYear = year();
|
||||
#elif defined(CORE_STM32)
|
||||
// year in stm32 rtc is a byte. So add year 2000 to make it correct
|
||||
tempYear = (2000 + rtc.getYear());
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return tempYear;
|
||||
}
|
||||
|
||||
void rtc_setTime(byte second, byte minute, byte hour, byte day, byte month, uint16_t year)
|
||||
{
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
setTime(hour, minute, second, day, month, year);
|
||||
Teensy3Clock.set(now());
|
||||
#elif defined(CORE_STM32)
|
||||
//If RTC time has not been set earlier (no battery etc.) we need to stop the RTC and restart it with LSE_CLOCK to have accurate RTC.
|
||||
if (!rtc.isTimeSet()) {
|
||||
rtc.end();
|
||||
rtc.setClockSource(STM32RTC::LSE_CLOCK);
|
||||
rtc.begin();
|
||||
}
|
||||
rtc.setTime(hour, minute, second);
|
||||
//year in stm32 rtc is a byte. so subtract year 2000 to fit
|
||||
rtc.setDate(day, month, (year-2000));
|
||||
#ifdef RTC_ENABLED
|
||||
#if defined(CORE_TEENSY)
|
||||
setTime(hour, minute, second, day, month, year);
|
||||
Teensy3Clock.set(now());
|
||||
#elif defined(CORE_STM32)
|
||||
// If RTC time has not been set earlier (no battery etc.) we need to stop the RTC and restart it with LSE_CLOCK to have accurate RTC.
|
||||
if(!rtc.isTimeSet())
|
||||
{
|
||||
rtc.end();
|
||||
rtc.setClockSource(STM32RTC::LSE_CLOCK);
|
||||
rtc.begin();
|
||||
}
|
||||
rtc.setTime(hour, minute, second);
|
||||
// year in stm32 rtc is a byte. so subtract year 2000 to fit
|
||||
rtc.setDate(day, month, (year - 2000));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -6,127 +6,510 @@
|
|||
/** @file
|
||||
* Injector and Coil (toggle/open/close) control (under various situations, eg with particular cylinder count, rotary engine type or wasted spark ign, etc.).
|
||||
* Also accounts for presence of MC33810 injector/ignition (dwell, etc.) control circuit.
|
||||
* Functions here are typically assigned (at initialisation) to callback function variables (e.g. inj1StartFunction or inj1EndFunction)
|
||||
* Functions here are typically assigned (at initialisation) to callback function variables (e.g. inj1StartFunction or inj1EndFunction)
|
||||
* form where they are called (by scheduler.ino).
|
||||
*/
|
||||
inline void openInjector1(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector1_DIRECT(); } else { openInjector1_MC33810(); } }
|
||||
inline void closeInjector1(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector1_DIRECT(); } else { closeInjector1_MC33810(); } }
|
||||
inline void openInjector2(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector2_DIRECT(); } else { openInjector2_MC33810(); } }
|
||||
inline void closeInjector2(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector2_DIRECT(); } else { closeInjector2_MC33810(); } }
|
||||
inline void openInjector3(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector3_DIRECT(); } else { openInjector3_MC33810(); } }
|
||||
inline void closeInjector3(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector3_DIRECT(); } else { closeInjector3_MC33810(); } }
|
||||
inline void openInjector4(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector4_DIRECT(); } else { openInjector4_MC33810(); } }
|
||||
inline void closeInjector4(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector4_DIRECT(); } else { closeInjector4_MC33810(); } }
|
||||
inline void openInjector5(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector5_DIRECT(); } else { openInjector5_MC33810(); } }
|
||||
inline void closeInjector5(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector5_DIRECT(); } else { closeInjector5_MC33810(); } }
|
||||
inline void openInjector6(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector6_DIRECT(); } else { openInjector6_MC33810(); } }
|
||||
inline void closeInjector6(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector6_DIRECT(); } else { closeInjector6_MC33810(); } }
|
||||
inline void openInjector7(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector7_DIRECT(); } else { openInjector7_MC33810(); } }
|
||||
inline void closeInjector7(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector7_DIRECT(); } else { closeInjector7_MC33810(); } }
|
||||
inline void openInjector8(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector8_DIRECT(); } else { openInjector8_MC33810(); } }
|
||||
inline void closeInjector8(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector8_DIRECT(); } else { closeInjector8_MC33810(); } }
|
||||
inline void openInjector1(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector1_DIRECT(); }
|
||||
else { openInjector1_MC33810(); }
|
||||
}
|
||||
inline void closeInjector1(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector1_DIRECT(); }
|
||||
else { closeInjector1_MC33810(); }
|
||||
}
|
||||
inline void openInjector2(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector2_DIRECT(); }
|
||||
else { openInjector2_MC33810(); }
|
||||
}
|
||||
inline void closeInjector2(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector2_DIRECT(); }
|
||||
else { closeInjector2_MC33810(); }
|
||||
}
|
||||
inline void openInjector3(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector3_DIRECT(); }
|
||||
else { openInjector3_MC33810(); }
|
||||
}
|
||||
inline void closeInjector3(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector3_DIRECT(); }
|
||||
else { closeInjector3_MC33810(); }
|
||||
}
|
||||
inline void openInjector4(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector4_DIRECT(); }
|
||||
else { openInjector4_MC33810(); }
|
||||
}
|
||||
inline void closeInjector4(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector4_DIRECT(); }
|
||||
else { closeInjector4_MC33810(); }
|
||||
}
|
||||
inline void openInjector5(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector5_DIRECT(); }
|
||||
else { openInjector5_MC33810(); }
|
||||
}
|
||||
inline void closeInjector5(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector5_DIRECT(); }
|
||||
else { closeInjector5_MC33810(); }
|
||||
}
|
||||
inline void openInjector6(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector6_DIRECT(); }
|
||||
else { openInjector6_MC33810(); }
|
||||
}
|
||||
inline void closeInjector6(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector6_DIRECT(); }
|
||||
else { closeInjector6_MC33810(); }
|
||||
}
|
||||
inline void openInjector7(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector7_DIRECT(); }
|
||||
else { openInjector7_MC33810(); }
|
||||
}
|
||||
inline void closeInjector7(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector7_DIRECT(); }
|
||||
else { closeInjector7_MC33810(); }
|
||||
}
|
||||
inline void openInjector8(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { openInjector8_DIRECT(); }
|
||||
else { openInjector8_MC33810(); }
|
||||
}
|
||||
inline void closeInjector8(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { closeInjector8_DIRECT(); }
|
||||
else { closeInjector8_MC33810(); }
|
||||
}
|
||||
|
||||
inline void injector1Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector1Toggle_DIRECT(); } else { injector1Toggle_MC33810(); } }
|
||||
inline void injector2Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector2Toggle_DIRECT(); } else { injector2Toggle_MC33810(); } }
|
||||
inline void injector3Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector3Toggle_DIRECT(); } else { injector3Toggle_MC33810(); } }
|
||||
inline void injector4Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector4Toggle_DIRECT(); } else { injector4Toggle_MC33810(); } }
|
||||
inline void injector5Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector5Toggle_DIRECT(); } else { injector5Toggle_MC33810(); } }
|
||||
inline void injector6Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector6Toggle_DIRECT(); } else { injector6Toggle_MC33810(); } }
|
||||
inline void injector7Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector7Toggle_DIRECT(); } else { injector7Toggle_MC33810(); } }
|
||||
inline void injector8Toggle(void) { if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector8Toggle_DIRECT(); } else { injector8Toggle_MC33810(); } }
|
||||
inline void injector1Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector1Toggle_DIRECT(); }
|
||||
else { injector1Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector2Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector2Toggle_DIRECT(); }
|
||||
else { injector2Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector3Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector3Toggle_DIRECT(); }
|
||||
else { injector3Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector4Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector4Toggle_DIRECT(); }
|
||||
else { injector4Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector5Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector5Toggle_DIRECT(); }
|
||||
else { injector5Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector6Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector6Toggle_DIRECT(); }
|
||||
else { injector6Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector7Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector7Toggle_DIRECT(); }
|
||||
else { injector7Toggle_MC33810(); }
|
||||
}
|
||||
inline void injector8Toggle(void)
|
||||
{
|
||||
if(injectorOutputControl != OUTPUT_CONTROL_MC33810) { injector8Toggle_DIRECT(); }
|
||||
else { injector8Toggle_MC33810(); }
|
||||
}
|
||||
|
||||
inline void coil1Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1Toggle_DIRECT(); } else { coil1Toggle_MC33810(); } }
|
||||
inline void coil2Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2Toggle_DIRECT(); } else { coil2Toggle_MC33810(); } }
|
||||
inline void coil3Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3Toggle_DIRECT(); } else { coil3Toggle_MC33810(); } }
|
||||
inline void coil4Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4Toggle_DIRECT(); } else { coil4Toggle_MC33810(); } }
|
||||
inline void coil5Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5Toggle_DIRECT(); } else { coil5Toggle_MC33810(); } }
|
||||
inline void coil6Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6Toggle_DIRECT(); } else { coil6Toggle_MC33810(); } }
|
||||
inline void coil7Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7Toggle_DIRECT(); } else { coil7Toggle_MC33810(); } }
|
||||
inline void coil8Toggle(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8Toggle_DIRECT(); } else { coil8Toggle_MC33810(); } }
|
||||
inline void coil1Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1Toggle_DIRECT(); }
|
||||
else { coil1Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil2Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2Toggle_DIRECT(); }
|
||||
else { coil2Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil3Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3Toggle_DIRECT(); }
|
||||
else { coil3Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil4Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4Toggle_DIRECT(); }
|
||||
else { coil4Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil5Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5Toggle_DIRECT(); }
|
||||
else { coil5Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil6Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6Toggle_DIRECT(); }
|
||||
else { coil6Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil7Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7Toggle_DIRECT(); }
|
||||
else { coil7Toggle_MC33810(); }
|
||||
}
|
||||
inline void coil8Toggle(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8Toggle_DIRECT(); }
|
||||
else { coil8Toggle_MC33810(); }
|
||||
}
|
||||
|
||||
// These are for Semi-Sequential and 5 Cylinder injection
|
||||
//Standard 4 cylinder pairings
|
||||
void openInjector1and3(void) { openInjector1(); openInjector3(); }
|
||||
void closeInjector1and3(void) { closeInjector1(); closeInjector3(); }
|
||||
void openInjector2and4(void) { openInjector2(); openInjector4(); }
|
||||
void closeInjector2and4(void) { closeInjector2(); closeInjector4(); }
|
||||
//Alternative output pairings
|
||||
void openInjector1and4(void) { openInjector1(); openInjector4(); }
|
||||
void closeInjector1and4(void) { closeInjector1(); closeInjector4(); }
|
||||
void openInjector2and3(void) { openInjector2(); openInjector3(); }
|
||||
void closeInjector2and3(void) { closeInjector2(); closeInjector3(); }
|
||||
// Standard 4 cylinder pairings
|
||||
void openInjector1and3(void)
|
||||
{
|
||||
openInjector1();
|
||||
openInjector3();
|
||||
}
|
||||
void closeInjector1and3(void)
|
||||
{
|
||||
closeInjector1();
|
||||
closeInjector3();
|
||||
}
|
||||
void openInjector2and4(void)
|
||||
{
|
||||
openInjector2();
|
||||
openInjector4();
|
||||
}
|
||||
void closeInjector2and4(void)
|
||||
{
|
||||
closeInjector2();
|
||||
closeInjector4();
|
||||
}
|
||||
// Alternative output pairings
|
||||
void openInjector1and4(void)
|
||||
{
|
||||
openInjector1();
|
||||
openInjector4();
|
||||
}
|
||||
void closeInjector1and4(void)
|
||||
{
|
||||
closeInjector1();
|
||||
closeInjector4();
|
||||
}
|
||||
void openInjector2and3(void)
|
||||
{
|
||||
openInjector2();
|
||||
openInjector3();
|
||||
}
|
||||
void closeInjector2and3(void)
|
||||
{
|
||||
closeInjector2();
|
||||
closeInjector3();
|
||||
}
|
||||
|
||||
void openInjector3and5(void) { openInjector3(); openInjector5(); }
|
||||
void closeInjector3and5(void) { closeInjector3(); closeInjector5(); }
|
||||
void openInjector3and5(void)
|
||||
{
|
||||
openInjector3();
|
||||
openInjector5();
|
||||
}
|
||||
void closeInjector3and5(void)
|
||||
{
|
||||
closeInjector3();
|
||||
closeInjector5();
|
||||
}
|
||||
|
||||
void openInjector2and5(void) { openInjector2(); openInjector5(); }
|
||||
void closeInjector2and5(void) { closeInjector2(); closeInjector5(); }
|
||||
void openInjector3and6(void) { openInjector3(); openInjector6(); }
|
||||
void closeInjector3and6(void) { closeInjector3(); closeInjector6(); }
|
||||
void openInjector2and5(void)
|
||||
{
|
||||
openInjector2();
|
||||
openInjector5();
|
||||
}
|
||||
void closeInjector2and5(void)
|
||||
{
|
||||
closeInjector2();
|
||||
closeInjector5();
|
||||
}
|
||||
void openInjector3and6(void)
|
||||
{
|
||||
openInjector3();
|
||||
openInjector6();
|
||||
}
|
||||
void closeInjector3and6(void)
|
||||
{
|
||||
closeInjector3();
|
||||
closeInjector6();
|
||||
}
|
||||
|
||||
void openInjector1and5(void) { openInjector1(); openInjector5(); }
|
||||
void closeInjector1and5(void) { closeInjector1(); closeInjector5(); }
|
||||
void openInjector2and6(void) { openInjector2(); openInjector6(); }
|
||||
void closeInjector2and6(void) { closeInjector2(); closeInjector6(); }
|
||||
void openInjector3and7(void) { openInjector3(); openInjector7(); }
|
||||
void closeInjector3and7(void) { closeInjector3(); closeInjector7(); }
|
||||
void openInjector4and8(void) { openInjector4(); openInjector8(); }
|
||||
void closeInjector4and8(void) { closeInjector4(); closeInjector8(); }
|
||||
void openInjector1and5(void)
|
||||
{
|
||||
openInjector1();
|
||||
openInjector5();
|
||||
}
|
||||
void closeInjector1and5(void)
|
||||
{
|
||||
closeInjector1();
|
||||
closeInjector5();
|
||||
}
|
||||
void openInjector2and6(void)
|
||||
{
|
||||
openInjector2();
|
||||
openInjector6();
|
||||
}
|
||||
void closeInjector2and6(void)
|
||||
{
|
||||
closeInjector2();
|
||||
closeInjector6();
|
||||
}
|
||||
void openInjector3and7(void)
|
||||
{
|
||||
openInjector3();
|
||||
openInjector7();
|
||||
}
|
||||
void closeInjector3and7(void)
|
||||
{
|
||||
closeInjector3();
|
||||
closeInjector7();
|
||||
}
|
||||
void openInjector4and8(void)
|
||||
{
|
||||
openInjector4();
|
||||
openInjector8();
|
||||
}
|
||||
void closeInjector4and8(void)
|
||||
{
|
||||
closeInjector4();
|
||||
closeInjector8();
|
||||
}
|
||||
|
||||
inline void beginCoil1Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1Charging_DIRECT(); } else { coil1Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil1Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1StopCharging_DIRECT(); } else { coil1StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil1Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1Charging_DIRECT(); }
|
||||
else { coil1Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil1Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1StopCharging_DIRECT(); }
|
||||
else { coil1StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil2Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2Charging_DIRECT(); } else { coil2Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil2Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2StopCharging_DIRECT(); } else { coil2StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil2Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2Charging_DIRECT(); }
|
||||
else { coil2Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil2Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2StopCharging_DIRECT(); }
|
||||
else { coil2StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil3Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3Charging_DIRECT(); } else { coil3Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil3Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3StopCharging_DIRECT(); } else { coil3StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil3Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3Charging_DIRECT(); }
|
||||
else { coil3Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil3Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3StopCharging_DIRECT(); }
|
||||
else { coil3StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil4Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4Charging_DIRECT(); } else { coil4Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil4Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4StopCharging_DIRECT(); } else { coil4StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil4Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4Charging_DIRECT(); }
|
||||
else { coil4Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil4Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4StopCharging_DIRECT(); }
|
||||
else { coil4StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil5Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5Charging_DIRECT(); } else { coil5Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil5Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5StopCharging_DIRECT(); } else { coil5StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil5Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5Charging_DIRECT(); }
|
||||
else { coil5Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil5Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5StopCharging_DIRECT(); }
|
||||
else { coil5StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil6Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6Charging_DIRECT(); } else { coil6Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil6Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6StopCharging_DIRECT(); } else { coil6StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil6Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6Charging_DIRECT(); }
|
||||
else { coil6Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil6Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6StopCharging_DIRECT(); }
|
||||
else { coil6StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil7Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7Charging_DIRECT(); } else { coil7Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil7Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7StopCharging_DIRECT(); } else { coil7StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil7Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7Charging_DIRECT(); }
|
||||
else { coil7Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil7Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7StopCharging_DIRECT(); }
|
||||
else { coil7StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
inline void beginCoil8Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8Charging_DIRECT(); } else { coil8Charging_MC33810(); } tachoOutputOn(); }
|
||||
inline void endCoil8Charge(void) { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8StopCharging_DIRECT(); } else { coil8StopCharging_MC33810(); } tachoOutputOff(); }
|
||||
inline void beginCoil8Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8Charging_DIRECT(); }
|
||||
else { coil8Charging_MC33810(); }
|
||||
tachoOutputOn();
|
||||
}
|
||||
inline void endCoil8Charge(void)
|
||||
{
|
||||
if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8StopCharging_DIRECT(); }
|
||||
else { coil8StopCharging_MC33810(); }
|
||||
tachoOutputOff();
|
||||
}
|
||||
|
||||
//The below 3 calls are all part of the rotary ignition mode
|
||||
// The below 3 calls are all part of the rotary ignition mode
|
||||
inline void beginTrailingCoilCharge(void) { beginCoil2Charge(); }
|
||||
inline void endTrailingCoilCharge1(void) { endCoil2Charge(); beginCoil3Charge(); } //Sets ign3 (Trailing select) high
|
||||
inline void endTrailingCoilCharge2(void) { endCoil2Charge(); endCoil3Charge(); } //sets ign3 (Trailing select) low
|
||||
inline void endTrailingCoilCharge1(void)
|
||||
{
|
||||
endCoil2Charge();
|
||||
beginCoil3Charge();
|
||||
} // Sets ign3 (Trailing select) high
|
||||
inline void endTrailingCoilCharge2(void)
|
||||
{
|
||||
endCoil2Charge();
|
||||
endCoil3Charge();
|
||||
} // sets ign3 (Trailing select) low
|
||||
|
||||
//As above but for ignition (Wasted COP mode)
|
||||
void beginCoil1and3Charge(void) { beginCoil1Charge(); beginCoil3Charge(); }
|
||||
void endCoil1and3Charge(void) { endCoil1Charge(); endCoil3Charge(); }
|
||||
void beginCoil2and4Charge(void) { beginCoil2Charge(); beginCoil4Charge(); }
|
||||
void endCoil2and4Charge(void) { endCoil2Charge(); endCoil4Charge(); }
|
||||
// As above but for ignition (Wasted COP mode)
|
||||
void beginCoil1and3Charge(void)
|
||||
{
|
||||
beginCoil1Charge();
|
||||
beginCoil3Charge();
|
||||
}
|
||||
void endCoil1and3Charge(void)
|
||||
{
|
||||
endCoil1Charge();
|
||||
endCoil3Charge();
|
||||
}
|
||||
void beginCoil2and4Charge(void)
|
||||
{
|
||||
beginCoil2Charge();
|
||||
beginCoil4Charge();
|
||||
}
|
||||
void endCoil2and4Charge(void)
|
||||
{
|
||||
endCoil2Charge();
|
||||
endCoil4Charge();
|
||||
}
|
||||
|
||||
//For 6cyl wasted COP mode)
|
||||
void beginCoil1and4Charge(void) { beginCoil1Charge(); beginCoil4Charge(); }
|
||||
void endCoil1and4Charge(void) { endCoil1Charge(); endCoil4Charge(); }
|
||||
void beginCoil2and5Charge(void) { beginCoil2Charge(); beginCoil5Charge(); }
|
||||
void endCoil2and5Charge(void) { endCoil2Charge(); endCoil5Charge(); }
|
||||
void beginCoil3and6Charge(void) { beginCoil3Charge(); beginCoil6Charge(); }
|
||||
void endCoil3and6Charge(void) { endCoil3Charge(); endCoil6Charge(); }
|
||||
// For 6cyl wasted COP mode)
|
||||
void beginCoil1and4Charge(void)
|
||||
{
|
||||
beginCoil1Charge();
|
||||
beginCoil4Charge();
|
||||
}
|
||||
void endCoil1and4Charge(void)
|
||||
{
|
||||
endCoil1Charge();
|
||||
endCoil4Charge();
|
||||
}
|
||||
void beginCoil2and5Charge(void)
|
||||
{
|
||||
beginCoil2Charge();
|
||||
beginCoil5Charge();
|
||||
}
|
||||
void endCoil2and5Charge(void)
|
||||
{
|
||||
endCoil2Charge();
|
||||
endCoil5Charge();
|
||||
}
|
||||
void beginCoil3and6Charge(void)
|
||||
{
|
||||
beginCoil3Charge();
|
||||
beginCoil6Charge();
|
||||
}
|
||||
void endCoil3and6Charge(void)
|
||||
{
|
||||
endCoil3Charge();
|
||||
endCoil6Charge();
|
||||
}
|
||||
|
||||
//For 8cyl wasted COP mode)
|
||||
void beginCoil1and5Charge(void) { beginCoil1Charge(); beginCoil5Charge(); }
|
||||
void endCoil1and5Charge(void) { endCoil1Charge(); endCoil5Charge(); }
|
||||
void beginCoil2and6Charge(void) { beginCoil2Charge(); beginCoil6Charge(); }
|
||||
void endCoil2and6Charge(void) { endCoil2Charge(); endCoil6Charge(); }
|
||||
void beginCoil3and7Charge(void) { beginCoil3Charge(); beginCoil7Charge(); }
|
||||
void endCoil3and7Charge(void) { endCoil3Charge(); endCoil7Charge(); }
|
||||
void beginCoil4and8Charge(void) { beginCoil4Charge(); beginCoil8Charge(); }
|
||||
void endCoil4and8Charge(void) { endCoil4Charge(); endCoil8Charge(); }
|
||||
// For 8cyl wasted COP mode)
|
||||
void beginCoil1and5Charge(void)
|
||||
{
|
||||
beginCoil1Charge();
|
||||
beginCoil5Charge();
|
||||
}
|
||||
void endCoil1and5Charge(void)
|
||||
{
|
||||
endCoil1Charge();
|
||||
endCoil5Charge();
|
||||
}
|
||||
void beginCoil2and6Charge(void)
|
||||
{
|
||||
beginCoil2Charge();
|
||||
beginCoil6Charge();
|
||||
}
|
||||
void endCoil2and6Charge(void)
|
||||
{
|
||||
endCoil2Charge();
|
||||
endCoil6Charge();
|
||||
}
|
||||
void beginCoil3and7Charge(void)
|
||||
{
|
||||
beginCoil3Charge();
|
||||
beginCoil7Charge();
|
||||
}
|
||||
void endCoil3and7Charge(void)
|
||||
{
|
||||
endCoil3Charge();
|
||||
endCoil7Charge();
|
||||
}
|
||||
void beginCoil4and8Charge(void)
|
||||
{
|
||||
beginCoil4Charge();
|
||||
beginCoil8Charge();
|
||||
}
|
||||
void endCoil4and8Charge(void)
|
||||
{
|
||||
endCoil4Charge();
|
||||
endCoil8Charge();
|
||||
}
|
||||
|
||||
void tachoOutputOn(void) { if(configPage6.tachoMode) { TACHO_PULSE_LOW(); } else { tachoOutputFlag = READY; } }
|
||||
void tachoOutputOff(void) { if(configPage6.tachoMode) { TACHO_PULSE_HIGH(); } }
|
||||
void tachoOutputOn(void)
|
||||
{
|
||||
if(configPage6.tachoMode) { TACHO_PULSE_LOW(); }
|
||||
else { tachoOutputFlag = READY; }
|
||||
}
|
||||
void tachoOutputOff(void)
|
||||
{
|
||||
if(configPage6.tachoMode) { TACHO_PULSE_HIGH(); }
|
||||
}
|
||||
|
||||
void nullCallback(void) { return; }
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,14 +4,14 @@
|
|||
|
||||
void calculateSecondaryFuel(void)
|
||||
{
|
||||
//If the secondary fuel table is in use, also get the VE value from there
|
||||
BIT_CLEAR(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); //Clear the bit indicating that the 2nd fuel table is in use.
|
||||
// If the secondary fuel table is in use, also get the VE value from there
|
||||
BIT_CLEAR(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); // Clear the bit indicating that the 2nd fuel table is in use.
|
||||
if(configPage10.fuel2Mode > 0)
|
||||
{
|
||||
{
|
||||
if(configPage10.fuel2Mode == FUEL2_MODE_MULTIPLY)
|
||||
{
|
||||
currentStatus.VE2 = getVE2();
|
||||
//Fuel 2 table is treated as a % value. Table 1 and 2 are multiplied together and divided by 100
|
||||
// Fuel 2 table is treated as a % value. Table 1 and 2 are multiplied together and divided by 100
|
||||
uint16_t combinedVE = ((uint16_t)currentStatus.VE1 * (uint16_t)currentStatus.VE2) / 100;
|
||||
if(combinedVE <= 255) { currentStatus.VE = combinedVE; }
|
||||
else { currentStatus.VE = 255; }
|
||||
|
@ -19,47 +19,47 @@ void calculateSecondaryFuel(void)
|
|||
else if(configPage10.fuel2Mode == FUEL2_MODE_ADD)
|
||||
{
|
||||
currentStatus.VE2 = getVE2();
|
||||
//Fuel tables are added together, but a check is made to make sure this won't overflow the 8-bit VE value
|
||||
// Fuel tables are added together, but a check is made to make sure this won't overflow the 8-bit VE value
|
||||
uint16_t combinedVE = (uint16_t)currentStatus.VE1 + (uint16_t)currentStatus.VE2;
|
||||
if(combinedVE <= 255) { currentStatus.VE = combinedVE; }
|
||||
else { currentStatus.VE = 255; }
|
||||
}
|
||||
else if(configPage10.fuel2Mode == FUEL2_MODE_CONDITIONAL_SWITCH )
|
||||
else if(configPage10.fuel2Mode == FUEL2_MODE_CONDITIONAL_SWITCH)
|
||||
{
|
||||
if(configPage10.fuel2SwitchVariable == FUEL2_CONDITION_RPM)
|
||||
{
|
||||
if(currentStatus.RPM > configPage10.fuel2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); //Set the bit indicating that the 2nd fuel table is in use.
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); // Set the bit indicating that the 2nd fuel table is in use.
|
||||
currentStatus.VE2 = getVE2();
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
}
|
||||
}
|
||||
else if(configPage10.fuel2SwitchVariable == FUEL2_CONDITION_MAP)
|
||||
{
|
||||
if(currentStatus.MAP > configPage10.fuel2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); //Set the bit indicating that the 2nd fuel table is in use.
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); // Set the bit indicating that the 2nd fuel table is in use.
|
||||
currentStatus.VE2 = getVE2();
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
}
|
||||
}
|
||||
else if(configPage10.fuel2SwitchVariable == FUEL2_CONDITION_TPS)
|
||||
{
|
||||
if(currentStatus.TPS > configPage10.fuel2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); //Set the bit indicating that the 2nd fuel table is in use.
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); // Set the bit indicating that the 2nd fuel table is in use.
|
||||
currentStatus.VE2 = getVE2();
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
}
|
||||
}
|
||||
else if(configPage10.fuel2SwitchVariable == FUEL2_CONDITION_ETH)
|
||||
{
|
||||
if(currentStatus.ethanolPct > configPage10.fuel2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); //Set the bit indicating that the 2nd fuel table is in use.
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); // Set the bit indicating that the 2nd fuel table is in use.
|
||||
currentStatus.VE2 = getVE2();
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,79 +67,78 @@ void calculateSecondaryFuel(void)
|
|||
{
|
||||
if(digitalRead(pinFuel2Input) == configPage10.fuel2InputPolarity)
|
||||
{
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); //Set the bit indicating that the 2nd fuel table is in use.
|
||||
BIT_SET(currentStatus.status3, BIT_STATUS3_FUEL2_ACTIVE); // Set the bit indicating that the 2nd fuel table is in use.
|
||||
currentStatus.VE2 = getVE2();
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
currentStatus.VE = currentStatus.VE2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void calculateSecondarySpark(void)
|
||||
{
|
||||
//Same as above but for the secondary ignition table
|
||||
BIT_CLEAR(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Clear the bit indicating that the 2nd spark table is in use.
|
||||
// Same as above but for the secondary ignition table
|
||||
BIT_CLEAR(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Clear the bit indicating that the 2nd spark table is in use.
|
||||
if(configPage10.spark2Mode > 0)
|
||||
{
|
||||
{
|
||||
if(configPage10.spark2Mode == SPARK2_MODE_MULTIPLY)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE);
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
//make sure we don't have a negative value in the multiplier table (sharing a signed 8 bit table)
|
||||
// make sure we don't have a negative value in the multiplier table (sharing a signed 8 bit table)
|
||||
if(currentStatus.advance2 < 0) { currentStatus.advance2 = 0; }
|
||||
//Spark 2 table is treated as a % value. Table 1 and 2 are multiplied together and divided by 100
|
||||
// Spark 2 table is treated as a % value. Table 1 and 2 are multiplied together and divided by 100
|
||||
int16_t combinedAdvance = ((int16_t)currentStatus.advance1 * (int16_t)currentStatus.advance2) / 100;
|
||||
//make sure we don't overflow and accidentally set negative timing, currentStatus.advance can only hold a signed 8 bit value
|
||||
// make sure we don't overflow and accidentally set negative timing, currentStatus.advance can only hold a signed 8 bit value
|
||||
if(combinedAdvance <= 127) { currentStatus.advance = combinedAdvance; }
|
||||
else { currentStatus.advance = 127; }
|
||||
}
|
||||
else if(configPage10.spark2Mode == SPARK2_MODE_ADD)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Set the bit indicating that the 2nd spark table is in use.
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Set the bit indicating that the 2nd spark table is in use.
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
//Spark tables are added together, but a check is made to make sure this won't overflow the 8-bit VE value
|
||||
// Spark tables are added together, but a check is made to make sure this won't overflow the 8-bit VE value
|
||||
int16_t combinedAdvance = (int16_t)currentStatus.advance1 + (int16_t)currentStatus.advance2;
|
||||
//make sure we don't overflow and accidentally set negative timing, currentStatus.advance can only hold a signed 8 bit value
|
||||
// make sure we don't overflow and accidentally set negative timing, currentStatus.advance can only hold a signed 8 bit value
|
||||
if(combinedAdvance <= 127) { currentStatus.advance = combinedAdvance; }
|
||||
else { currentStatus.advance = 127; }
|
||||
}
|
||||
else if(configPage10.spark2Mode == SPARK2_MODE_CONDITIONAL_SWITCH )
|
||||
else if(configPage10.spark2Mode == SPARK2_MODE_CONDITIONAL_SWITCH)
|
||||
{
|
||||
if(configPage10.spark2SwitchVariable == SPARK2_CONDITION_RPM)
|
||||
{
|
||||
if(currentStatus.RPM > configPage10.spark2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Set the bit indicating that the 2nd spark table is in use.
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Set the bit indicating that the 2nd spark table is in use.
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
}
|
||||
}
|
||||
else if(configPage10.spark2SwitchVariable == SPARK2_CONDITION_MAP)
|
||||
{
|
||||
if(currentStatus.MAP > configPage10.spark2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Set the bit indicating that the 2nd spark table is in use.
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Set the bit indicating that the 2nd spark table is in use.
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
}
|
||||
}
|
||||
else if(configPage10.spark2SwitchVariable == SPARK2_CONDITION_TPS)
|
||||
{
|
||||
if(currentStatus.TPS > configPage10.spark2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Set the bit indicating that the 2nd spark table is in use.
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Set the bit indicating that the 2nd spark table is in use.
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
}
|
||||
}
|
||||
else if(configPage10.spark2SwitchVariable == SPARK2_CONDITION_ETH)
|
||||
{
|
||||
if(currentStatus.ethanolPct > configPage10.spark2SwitchValue)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Set the bit indicating that the 2nd spark table is in use.
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Set the bit indicating that the 2nd spark table is in use.
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,74 +146,73 @@ void calculateSecondarySpark(void)
|
|||
{
|
||||
if(digitalRead(pinSpark2Input) == configPage10.spark2InputPolarity)
|
||||
{
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); //Set the bit indicating that the 2nd spark table is in use.
|
||||
BIT_SET(currentStatus.spark2, BIT_SPARK2_SPARK2_ACTIVE); // Set the bit indicating that the 2nd spark table is in use.
|
||||
currentStatus.advance2 = getAdvance2();
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
currentStatus.advance = currentStatus.advance2;
|
||||
}
|
||||
}
|
||||
|
||||
//Apply the fixed timing correction manually. This has to be done again here if any of the above conditions are met to prevent any of the seconadary calculations applying instead of fixec timing
|
||||
// Apply the fixed timing correction manually. This has to be done again here if any of the above conditions are met to prevent any of the seconadary calculations applying instead of fixec timing
|
||||
currentStatus.advance = correctionFixedTiming(currentStatus.advance);
|
||||
currentStatus.advance = correctionCrankingFixedTiming(currentStatus.advance); //This overrides the regular fixed timing, must come last
|
||||
currentStatus.advance = correctionCrankingFixedTiming(currentStatus.advance); // This overrides the regular fixed timing, must come last
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Looks up and returns the VE value from the secondary fuel table
|
||||
*
|
||||
*
|
||||
* This performs largely the same operations as getVE() however the lookup is of the secondary fuel table and uses the secondary load source
|
||||
* @return byte
|
||||
* @return byte
|
||||
*/
|
||||
byte getVE2(void)
|
||||
{
|
||||
byte tempVE = 100;
|
||||
if( configPage10.fuel2Algorithm == LOAD_SOURCE_MAP)
|
||||
if(configPage10.fuel2Algorithm == LOAD_SOURCE_MAP)
|
||||
{
|
||||
//Speed Density
|
||||
// Speed Density
|
||||
currentStatus.fuelLoad2 = currentStatus.MAP;
|
||||
}
|
||||
else if (configPage10.fuel2Algorithm == LOAD_SOURCE_TPS)
|
||||
else if(configPage10.fuel2Algorithm == LOAD_SOURCE_TPS)
|
||||
{
|
||||
//Alpha-N
|
||||
// Alpha-N
|
||||
currentStatus.fuelLoad2 = currentStatus.TPS * 2;
|
||||
}
|
||||
else if (configPage10.fuel2Algorithm == LOAD_SOURCE_IMAPEMAP)
|
||||
else if(configPage10.fuel2Algorithm == LOAD_SOURCE_IMAPEMAP)
|
||||
{
|
||||
//IMAP / EMAP
|
||||
// IMAP / EMAP
|
||||
currentStatus.fuelLoad2 = (currentStatus.MAP * 100) / currentStatus.EMAP;
|
||||
}
|
||||
else { currentStatus.fuelLoad2 = currentStatus.MAP; } //Fallback position
|
||||
tempVE = get3DTableValue(&fuelTable2, currentStatus.fuelLoad2, currentStatus.RPM); //Perform lookup into fuel map for RPM vs MAP value
|
||||
else { currentStatus.fuelLoad2 = currentStatus.MAP; } // Fallback position
|
||||
tempVE = get3DTableValue(&fuelTable2, currentStatus.fuelLoad2, currentStatus.RPM); // Perform lookup into fuel map for RPM vs MAP value
|
||||
|
||||
return tempVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a lookup of the second ignition advance table. The values used to look this up will be RPM and whatever load source the user has configured
|
||||
*
|
||||
*
|
||||
* @return byte The current target advance value in degrees
|
||||
*/
|
||||
byte getAdvance2(void)
|
||||
{
|
||||
byte tempAdvance = 0;
|
||||
if (configPage10.spark2Algorithm == LOAD_SOURCE_MAP) //Check which fuelling algorithm is being used
|
||||
if(configPage10.spark2Algorithm == LOAD_SOURCE_MAP) // Check which fuelling algorithm is being used
|
||||
{
|
||||
//Speed Density
|
||||
// Speed Density
|
||||
currentStatus.ignLoad2 = currentStatus.MAP;
|
||||
}
|
||||
else if(configPage10.spark2Algorithm == LOAD_SOURCE_TPS)
|
||||
{
|
||||
//Alpha-N
|
||||
// Alpha-N
|
||||
currentStatus.ignLoad2 = currentStatus.TPS * 2;
|
||||
|
||||
}
|
||||
else if (configPage10.spark2Algorithm == LOAD_SOURCE_IMAPEMAP)
|
||||
else if(configPage10.spark2Algorithm == LOAD_SOURCE_IMAPEMAP)
|
||||
{
|
||||
//IMAP / EMAP
|
||||
// IMAP / EMAP
|
||||
currentStatus.ignLoad2 = (currentStatus.MAP * 100) / currentStatus.EMAP;
|
||||
}
|
||||
else { currentStatus.ignLoad2 = currentStatus.MAP; }
|
||||
tempAdvance = get3DTableValue(&ignitionTable2, currentStatus.ignLoad2, currentStatus.RPM) - OFFSET_IGNITION; //As above, but for ignition advance
|
||||
tempAdvance = get3DTableValue(&ignitionTable2, currentStatus.ignLoad2, currentStatus.RPM) - OFFSET_IGNITION; // As above, but for ignition advance
|
||||
tempAdvance = correctionsIgn(tempAdvance);
|
||||
|
||||
return tempAdvance;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -10,11 +10,11 @@ Note that this may clear some of the existing values of the table
|
|||
*/
|
||||
#include "table2d.h"
|
||||
#if !defined(UNIT_TEST)
|
||||
#include "globals.h"
|
||||
#include "globals.h"
|
||||
#endif
|
||||
|
||||
|
||||
static inline uint8_t getCacheTime(void) {
|
||||
static inline uint8_t getCacheTime(void)
|
||||
{
|
||||
#if !defined(UNIT_TEST)
|
||||
return currentStatus.secl;
|
||||
#else
|
||||
|
@ -31,66 +31,66 @@ Unfortunately this means many of the lines are duplicated depending on this
|
|||
*/
|
||||
int table2D_getValue(struct table2D *fromTable, int X_in)
|
||||
{
|
||||
//Orig memory usage = 5414
|
||||
int returnValue = 0;
|
||||
bool valueFound = false;
|
||||
// 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;
|
||||
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 == getCacheTime()) )
|
||||
// Check whether the X input is the same as last time this ran
|
||||
if((X_in == fromTable->lastInput) && (fromTable->cacheTime == getCacheTime()))
|
||||
{
|
||||
returnValue = fromTable->lastOutput;
|
||||
valueFound = true;
|
||||
valueFound = true;
|
||||
}
|
||||
//If the requested X value is greater/small than the maximum/minimum bin, simply return that value
|
||||
// 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;
|
||||
valueFound = true;
|
||||
}
|
||||
else if(X <= table2D_getAxisValue(fromTable, xMin))
|
||||
{
|
||||
returnValue = table2D_getRawValue(fromTable, xMin);
|
||||
valueFound = true;
|
||||
valueFound = true;
|
||||
}
|
||||
//Finally if none of that is found
|
||||
// Finally if none of that is found
|
||||
else
|
||||
{
|
||||
fromTable->cacheTime = getCacheTime(); //As we're not using the cache value, set the current secl value to track when this new value was calculated
|
||||
fromTable->cacheTime = getCacheTime(); // As we're not using the cache value, set the current secl value to track when this new value was calculated
|
||||
|
||||
//1st check is whether we're still in the same X bin as last time
|
||||
// 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) )
|
||||
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--)
|
||||
// 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
|
||||
xMinValue = table2D_getAxisValue(fromTable, x - 1); // fetch next Min
|
||||
|
||||
//Checks the case where the X value is exactly what was requested
|
||||
if (X == xMaxValue)
|
||||
// Checks the case where the X value is exactly what was requested
|
||||
if(X == xMaxValue)
|
||||
{
|
||||
returnValue = table2D_getRawValue(fromTable, x); //Simply return the corresponding value
|
||||
valueFound = true;
|
||||
returnValue = table2D_getRawValue(fromTable, x); // Simply return the corresponding value
|
||||
valueFound = true;
|
||||
break;
|
||||
}
|
||||
else if (X > xMinValue)
|
||||
else if(X > xMinValue)
|
||||
{
|
||||
// Value is in the current bin
|
||||
xMax = x;
|
||||
xMax = x;
|
||||
fromTable->lastXMax = xMax;
|
||||
xMin = x-1;
|
||||
xMin = x - 1;
|
||||
fromTable->lastXMin = xMin;
|
||||
break;
|
||||
}
|
||||
|
@ -98,9 +98,9 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
|
|||
xMaxValue = xMinValue; // for the next bin, our Min is their Max
|
||||
}
|
||||
}
|
||||
} //X_in same as last time
|
||||
} // X_in same as last time
|
||||
|
||||
if (valueFound == false)
|
||||
if(valueFound == false)
|
||||
{
|
||||
int16_t m = X - xMinValue;
|
||||
int16_t n = xMaxValue - xMinValue;
|
||||
|
@ -111,13 +111,13 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
|
|||
/* Float version (if m, yMax, yMin and n were float's)
|
||||
int yVal = (m * (yMax - yMin)) / n;
|
||||
*/
|
||||
|
||||
//Non-Float version
|
||||
int16_t yVal = ( ((int32_t) m) * (yMax-yMin) ) / n;
|
||||
returnValue = yMin + yVal;
|
||||
|
||||
// Non-Float version
|
||||
int16_t yVal = (((int32_t)m) * (yMax - yMin)) / n;
|
||||
returnValue = yMin + yVal;
|
||||
}
|
||||
|
||||
fromTable->lastInput = X_in;
|
||||
fromTable->lastInput = X_in;
|
||||
fromTable->lastOutput = returnValue;
|
||||
|
||||
return returnValue;
|
||||
|
@ -125,37 +125,36 @@ int table2D_getValue(struct table2D *fromTable, int X_in)
|
|||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
* @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]; }
|
||||
else if(fromTable->axisSize == SIZE_SIGNED_BYTE) { returnValue = ((int8_t*)fromTable->axisX)[X_in]; }
|
||||
|
||||
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]; }
|
||||
else if(fromTable->axisSize == SIZE_SIGNED_BYTE) { returnValue = ((int8_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_index
|
||||
* @return int16_t
|
||||
*
|
||||
* @param fromTable
|
||||
* @param X_index
|
||||
* @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]; }
|
||||
else if(fromTable->valueSize == SIZE_SIGNED_BYTE) { returnValue = ((int8_t*)fromTable->values)[X_index]; }
|
||||
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]; }
|
||||
else if(fromTable->valueSize == SIZE_SIGNED_BYTE) { returnValue = ((int8_t *)fromTable->values)[X_index]; }
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
|
|
@ -27,29 +27,28 @@ Timers are typically low resolution (Compared to Schedulers), with maximum frequ
|
|||
|
||||
void initialiseTimers(void)
|
||||
{
|
||||
lastRPM_100ms = 0;
|
||||
loop33ms = 0;
|
||||
loop66ms = 0;
|
||||
loop100ms = 0;
|
||||
loop250ms = 0;
|
||||
loopSec = 0;
|
||||
lastRPM_100ms = 0;
|
||||
loop33ms = 0;
|
||||
loop66ms = 0;
|
||||
loop100ms = 0;
|
||||
loop250ms = 0;
|
||||
loopSec = 0;
|
||||
tachoOutputFlag = TACHO_INACTIVE;
|
||||
}
|
||||
|
||||
|
||||
//Timer2 Overflow Interrupt Vector, called when the timer overflows.
|
||||
//Executes every ~1ms.
|
||||
#if defined(CORE_AVR) //AVR chips use the ISR for this
|
||||
//This MUST be no block. Turning NO_BLOCK off messes with timing accuracy.
|
||||
ISR(TIMER2_OVF_vect, ISR_NOBLOCK) //cppcheck-suppress misra-c2012-8.2
|
||||
// Timer2 Overflow Interrupt Vector, called when the timer overflows.
|
||||
// Executes every ~1ms.
|
||||
#if defined(CORE_AVR) // AVR chips use the ISR for this
|
||||
// This MUST be no block. Turning NO_BLOCK off messes with timing accuracy.
|
||||
ISR(TIMER2_OVF_vect, ISR_NOBLOCK) // cppcheck-suppress misra-c2012-8.2
|
||||
#else
|
||||
void oneMSInterval(void) //Most ARM chips can simply call a function
|
||||
void oneMSInterval(void) // Most ARM chips can simply call a function
|
||||
#endif
|
||||
{
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_1KHZ);
|
||||
ms_counter++;
|
||||
|
||||
//Increment Loop Counters
|
||||
// Increment Loop Counters
|
||||
loop33ms++;
|
||||
loop66ms++;
|
||||
loop100ms++;
|
||||
|
@ -58,213 +57,275 @@ void oneMSInterval(void) //Most ARM chips can simply call a function
|
|||
|
||||
unsigned long targetOverdwellTime;
|
||||
|
||||
//Overdwell check
|
||||
targetOverdwellTime = micros() - dwellLimit_uS; //Set a target time in the past that all coil charging must have begun after. If the coil charge began before this time, it's been running too long
|
||||
bool isCrankLocked = configPage4.ignCranklock && (currentStatus.RPM < currentStatus.crankRPM); //Dwell limiter is disabled during cranking on setups using the locked cranking timing. WE HAVE to do the RPM check here as relying on the engine cranking bit can be potentially too slow in updating
|
||||
//Check first whether each spark output is currently on. Only check it's dwell time if it is
|
||||
// Overdwell check
|
||||
targetOverdwellTime = micros() - dwellLimit_uS; // Set a target time in the past that all coil charging must have begun after. If the coil charge began before this time, it's been running too long
|
||||
bool isCrankLocked = configPage4.ignCranklock && (currentStatus.RPM < currentStatus.crankRPM); // Dwell limiter is disabled during cranking on setups using the locked cranking timing. WE HAVE to do the RPM check here as relying on the engine cranking bit can be potentially too slow in updating
|
||||
// Check first whether each spark output is currently on. Only check it's dwell time if it is
|
||||
|
||||
if(ignitionSchedule1.Status == RUNNING) { if( (ignitionSchedule1.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign1EndFunction(); ignitionSchedule1.Status = OFF; } }
|
||||
if(ignitionSchedule2.Status == RUNNING) { if( (ignitionSchedule2.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign2EndFunction(); ignitionSchedule2.Status = OFF; } }
|
||||
if(ignitionSchedule3.Status == RUNNING) { if( (ignitionSchedule3.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign3EndFunction(); ignitionSchedule3.Status = OFF; } }
|
||||
if(ignitionSchedule4.Status == RUNNING) { if( (ignitionSchedule4.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign4EndFunction(); ignitionSchedule4.Status = OFF; } }
|
||||
if(ignitionSchedule5.Status == RUNNING) { if( (ignitionSchedule5.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign5EndFunction(); ignitionSchedule5.Status = OFF; } }
|
||||
if(ignitionSchedule6.Status == RUNNING) { if( (ignitionSchedule6.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign6EndFunction(); ignitionSchedule6.Status = OFF; } }
|
||||
if(ignitionSchedule7.Status == RUNNING) { if( (ignitionSchedule7.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign7EndFunction(); ignitionSchedule7.Status = OFF; } }
|
||||
if(ignitionSchedule8.Status == RUNNING) { if( (ignitionSchedule8.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign8EndFunction(); ignitionSchedule8.Status = OFF; } }
|
||||
if(ignitionSchedule1.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule1.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign1EndFunction();
|
||||
ignitionSchedule1.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule2.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule2.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign2EndFunction();
|
||||
ignitionSchedule2.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule3.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule3.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign3EndFunction();
|
||||
ignitionSchedule3.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule4.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule4.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign4EndFunction();
|
||||
ignitionSchedule4.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule5.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule5.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign5EndFunction();
|
||||
ignitionSchedule5.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule6.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule6.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign6EndFunction();
|
||||
ignitionSchedule6.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule7.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule7.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign7EndFunction();
|
||||
ignitionSchedule7.Status = OFF;
|
||||
}
|
||||
}
|
||||
if(ignitionSchedule8.Status == RUNNING)
|
||||
{
|
||||
if((ignitionSchedule8.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true))
|
||||
{
|
||||
ign8EndFunction();
|
||||
ignitionSchedule8.Status = OFF;
|
||||
}
|
||||
}
|
||||
|
||||
//Tacho is flagged as being ready for a pulse by the ignition outputs, or the sweep interval upon startup
|
||||
// Tacho is flagged as being ready for a pulse by the ignition outputs, or the sweep interval upon startup
|
||||
|
||||
// See if we're in power-on sweep mode
|
||||
if( tachoSweepEnabled )
|
||||
if(tachoSweepEnabled)
|
||||
{
|
||||
if( (currentStatus.engine != 0) || (ms_counter >= TACHO_SWEEP_TIME_MS) ) { tachoSweepEnabled = false; } // Stop the sweep after SWEEP_TIME, or if real tach signals have started
|
||||
else
|
||||
if((currentStatus.engine != 0) || (ms_counter >= TACHO_SWEEP_TIME_MS)) { tachoSweepEnabled = false; } // Stop the sweep after SWEEP_TIME, or if real tach signals have started
|
||||
else
|
||||
{
|
||||
// Ramp the needle smoothly to the max over the SWEEP_RAMP time
|
||||
if( ms_counter < TACHO_SWEEP_RAMP_MS ) { tachoSweepAccum += map(ms_counter, 0, TACHO_SWEEP_RAMP_MS, 0, tachoSweepIncr); }
|
||||
else { tachoSweepAccum += tachoSweepIncr; }
|
||||
|
||||
if(ms_counter < TACHO_SWEEP_RAMP_MS) { tachoSweepAccum += map(ms_counter, 0, TACHO_SWEEP_RAMP_MS, 0, tachoSweepIncr); }
|
||||
else { tachoSweepAccum += tachoSweepIncr; }
|
||||
|
||||
// Each time it rolls over, it's time to pulse the Tach
|
||||
if( tachoSweepAccum >= MS_PER_SEC )
|
||||
{
|
||||
if(tachoSweepAccum >= MS_PER_SEC)
|
||||
{
|
||||
tachoOutputFlag = READY;
|
||||
tachoSweepAccum -= MS_PER_SEC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Tacho output check. This code will not do anything if tacho pulse duration is fixed to coil dwell.
|
||||
// Tacho output check. This code will not do anything if tacho pulse duration is fixed to coil dwell.
|
||||
if(tachoOutputFlag == READY)
|
||||
{
|
||||
//Check for half speed tacho
|
||||
if( (configPage2.tachoDiv == 0) || (tachoAlt == true) )
|
||||
{
|
||||
// Check for half speed tacho
|
||||
if((configPage2.tachoDiv == 0) || (tachoAlt == true))
|
||||
{
|
||||
TACHO_PULSE_LOW();
|
||||
//ms_counter is cast down to a byte as the tacho duration can only be in the range of 1-6, so no extra resolution above that is required
|
||||
tachoEndTime = (uint8_t)ms_counter + configPage2.tachoDuration;
|
||||
// ms_counter is cast down to a byte as the tacho duration can only be in the range of 1-6, so no extra resolution above that is required
|
||||
tachoEndTime = (uint8_t)ms_counter + configPage2.tachoDuration;
|
||||
tachoOutputFlag = ACTIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Don't run on this pulse (Half speed tacho)
|
||||
// Don't run on this pulse (Half speed tacho)
|
||||
tachoOutputFlag = TACHO_INACTIVE;
|
||||
}
|
||||
tachoAlt = !tachoAlt; //Flip the alternating value in case half speed tacho is in use.
|
||||
tachoAlt = !tachoAlt; // Flip the alternating value in case half speed tacho is in use.
|
||||
}
|
||||
else if(tachoOutputFlag == ACTIVE)
|
||||
{
|
||||
//If the tacho output is already active, check whether it's reached it's end time
|
||||
// If the tacho output is already active, check whether it's reached it's end time
|
||||
if((uint8_t)ms_counter == tachoEndTime)
|
||||
{
|
||||
TACHO_PULSE_HIGH();
|
||||
tachoOutputFlag = TACHO_INACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//30Hz loop
|
||||
if (loop33ms == 33)
|
||||
// 30Hz loop
|
||||
if(loop33ms == 33)
|
||||
{
|
||||
loop33ms = 0;
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_30HZ);
|
||||
}
|
||||
|
||||
//15Hz loop
|
||||
if (loop66ms == 66)
|
||||
// 15Hz loop
|
||||
if(loop66ms == 66)
|
||||
{
|
||||
loop66ms = 0;
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_15HZ);
|
||||
}
|
||||
|
||||
//10Hz loop
|
||||
if (loop100ms == 100)
|
||||
// 10Hz loop
|
||||
if(loop100ms == 100)
|
||||
{
|
||||
loop100ms = 0; //Reset counter
|
||||
loop100ms = 0; // Reset counter
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_10HZ);
|
||||
|
||||
currentStatus.rpmDOT = (currentStatus.RPM - lastRPM_100ms) * 10; //This is the RPM per second that the engine has accelerated/decelerated in the last loop
|
||||
lastRPM_100ms = currentStatus.RPM; //Record the current RPM for next calc
|
||||
currentStatus.rpmDOT = (currentStatus.RPM - lastRPM_100ms) * 10; // This is the RPM per second that the engine has accelerated/decelerated in the last loop
|
||||
lastRPM_100ms = currentStatus.RPM; // Record the current RPM for next calc
|
||||
|
||||
if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN) ) { runSecsX10++; }
|
||||
if(BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN)) { runSecsX10++; }
|
||||
else { runSecsX10 = 0; }
|
||||
|
||||
if ( (injPrimed == false) && (seclx10 == configPage2.primingDelay) && (currentStatus.RPM == 0) ) { beginInjectorPriming(); injPrimed = true; }
|
||||
if((injPrimed == false) && (seclx10 == configPage2.primingDelay) && (currentStatus.RPM == 0))
|
||||
{
|
||||
beginInjectorPriming();
|
||||
injPrimed = true;
|
||||
}
|
||||
seclx10++;
|
||||
}
|
||||
|
||||
//4Hz loop
|
||||
if (loop250ms == 250)
|
||||
// 4Hz loop
|
||||
if(loop250ms == 250)
|
||||
{
|
||||
loop250ms = 0; //Reset Counter
|
||||
loop250ms = 0; // Reset Counter
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_4HZ);
|
||||
#if defined(CORE_STM32) //debug purpose, only visual for running code
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
#endif
|
||||
#if defined(CORE_STM32) // debug purpose, only visual for running code
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
#endif
|
||||
|
||||
#if defined(CORE_AVR)
|
||||
//Reset watchdog timer (Not active currently)
|
||||
//wdt_reset();
|
||||
//DIY watchdog
|
||||
//This is a sign of a crash:
|
||||
//if( (initialisationComplete == true) && (last250msLoopCount == mainLoopCount) ) { setup(); }
|
||||
//else { last250msLoopCount = mainLoopCount; }
|
||||
#endif
|
||||
#if defined(CORE_AVR)
|
||||
// Reset watchdog timer (Not active currently)
|
||||
// wdt_reset();
|
||||
// DIY watchdog
|
||||
// This is a sign of a crash:
|
||||
// if( (initialisationComplete == true) && (last250msLoopCount == mainLoopCount) ) { setup(); }
|
||||
// else { last250msLoopCount = mainLoopCount; }
|
||||
#endif
|
||||
}
|
||||
|
||||
//1Hz loop
|
||||
if (loopSec == 1000)
|
||||
// 1Hz loop
|
||||
if(loopSec == 1000)
|
||||
{
|
||||
loopSec = 0; //Reset counter.
|
||||
loopSec = 0; // Reset counter.
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_1HZ);
|
||||
|
||||
dwellLimit_uS = (1000 * configPage4.dwellLimit); //Update uS value in case setting has changed
|
||||
dwellLimit_uS = (1000 * configPage4.dwellLimit); // Update uS value in case setting has changed
|
||||
currentStatus.crankRPM = ((unsigned int)configPage4.crankRPM * 10);
|
||||
|
||||
//**************************************************************************************************************************************************
|
||||
//This updates the runSecs variable
|
||||
//If the engine is running or cranking, we need to update the run time counter.
|
||||
if (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN))
|
||||
{ //NOTE - There is a potential for a ~1sec gap between engine crank starting and the runSec number being incremented. This may delay ASE!
|
||||
if (currentStatus.runSecs <= 254) //Ensure we cap out at 255 and don't overflow. (which would reset ASE and cause problems with the closed loop fuelling (Which has to wait for the O2 to warmup))
|
||||
{ currentStatus.runSecs++; } //Increment our run counter by 1 second.
|
||||
// This updates the runSecs variable
|
||||
// If the engine is running or cranking, we need to update the run time counter.
|
||||
if(BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN))
|
||||
{ // NOTE - There is a potential for a ~1sec gap between engine crank starting and the runSec number being incremented. This may delay ASE!
|
||||
if(currentStatus.runSecs <= 254) // Ensure we cap out at 255 and don't overflow. (which would reset ASE and cause problems with the closed loop fuelling (Which has to wait for the O2 to warmup))
|
||||
{
|
||||
currentStatus.runSecs++;
|
||||
} // Increment our run counter by 1 second.
|
||||
}
|
||||
//**************************************************************************************************************************************************
|
||||
//This records the number of main loops the system has completed in the last second
|
||||
// This records the number of main loops the system has completed in the last second
|
||||
currentStatus.loopsPerSecond = mainLoopCount;
|
||||
mainLoopCount = 0;
|
||||
mainLoopCount = 0;
|
||||
//**************************************************************************************************************************************************
|
||||
//increment secl (secl is simply a counter that increments every second and is used to track whether the system has unexpectedly reset
|
||||
// increment secl (secl is simply a counter that increments every second and is used to track whether the system has unexpectedly reset
|
||||
currentStatus.secl++;
|
||||
//**************************************************************************************************************************************************
|
||||
//Check the fan output status
|
||||
if (configPage2.fanEnable >= 1)
|
||||
// Check the fan output status
|
||||
if(configPage2.fanEnable >= 1)
|
||||
{
|
||||
fanControl(); // Function to turn the cooling fan on/off
|
||||
fanControl(); // Function to turn the cooling fan on/off
|
||||
}
|
||||
|
||||
//Check whether fuel pump priming is complete
|
||||
// Check whether fuel pump priming is complete
|
||||
if(fpPrimed == false)
|
||||
{
|
||||
//fpPrimeTime is the time that the pump priming started. This is 0 on startup, but can be changed if the unit has been running on USB power and then had the ignition turned on (Which starts the priming again)
|
||||
if( (currentStatus.secl - fpPrimeTime) >= configPage2.fpPrime)
|
||||
// fpPrimeTime is the time that the pump priming started. This is 0 on startup, but can be changed if the unit has been running on USB power and then had the ignition turned on (Which starts the priming again)
|
||||
if((currentStatus.secl - fpPrimeTime) >= configPage2.fpPrime)
|
||||
{
|
||||
fpPrimed = true; //Mark the priming as being completed
|
||||
fpPrimed = true; // Mark the priming as being completed
|
||||
if(currentStatus.RPM == 0)
|
||||
{
|
||||
//If we reach here then the priming is complete, however only turn off the fuel pump if the engine isn't running
|
||||
// If we reach here then the priming is complete, however only turn off the fuel pump if the engine isn't running
|
||||
digitalWrite(pinFuelPump, LOW);
|
||||
currentStatus.fuelPumpOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//**************************************************************************************************************************************************
|
||||
//Set the flex reading (if enabled). The flexCounter is updated with every pulse from the sensor. If cleared once per second, we get a frequency reading
|
||||
// Set the flex reading (if enabled). The flexCounter is updated with every pulse from the sensor. If cleared once per second, we get a frequency reading
|
||||
if(configPage2.flexEnabled == true)
|
||||
{
|
||||
byte tempEthPct = 0;
|
||||
byte tempEthPct = 0;
|
||||
if(flexCounter < 50)
|
||||
{
|
||||
tempEthPct = 0; //Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
|
||||
tempEthPct = 0; // Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
|
||||
flexCounter = 0;
|
||||
}
|
||||
else if (flexCounter > 151) //1 pulse buffer
|
||||
else if(flexCounter > 151) // 1 pulse buffer
|
||||
{
|
||||
|
||||
if(flexCounter < 169)
|
||||
{
|
||||
tempEthPct = 100;
|
||||
tempEthPct = 100;
|
||||
flexCounter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//This indicates an error condition. Spec of the sensor is that errors are above 170Hz)
|
||||
tempEthPct = 0;
|
||||
// This indicates an error condition. Spec of the sensor is that errors are above 170Hz)
|
||||
tempEthPct = 0;
|
||||
flexCounter = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tempEthPct = flexCounter - 50; //Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
|
||||
tempEthPct = flexCounter - 50; // Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
|
||||
flexCounter = 0;
|
||||
}
|
||||
|
||||
//Off by 1 error check
|
||||
if (tempEthPct == 1) { tempEthPct = 0; }
|
||||
// Off by 1 error check
|
||||
if(tempEthPct == 1) { tempEthPct = 0; }
|
||||
|
||||
currentStatus.ethanolPct = ADC_FILTER(tempEthPct, configPage4.FILTER_FLEX, currentStatus.ethanolPct);
|
||||
|
||||
//Continental flex sensor fuel temperature can be read with following formula: (Temperature = (41.25 * pulse width(ms)) - 81.25). 1000μs = -40C and 5000μs = 125C
|
||||
// Continental flex sensor fuel temperature can be read with following formula: (Temperature = (41.25 * pulse width(ms)) - 81.25). 1000μs = -40C and 5000μs = 125C
|
||||
if(flexPulseWidth > 5000) { flexPulseWidth = 5000; }
|
||||
else if(flexPulseWidth < 1000) { flexPulseWidth = 1000; }
|
||||
currentStatus.fuelTemp = div100( (int16_t)(((4224 * (long)flexPulseWidth) >> 10) - 8125) );
|
||||
currentStatus.fuelTemp = div100((int16_t)(((4224 * (long)flexPulseWidth) >> 10) - 8125));
|
||||
}
|
||||
|
||||
//**************************************************************************************************************************************************
|
||||
//Handle any of the hardware testing outputs
|
||||
if( BIT_CHECK(currentStatus.testOutputs, 1) )
|
||||
// Handle any of the hardware testing outputs
|
||||
if(BIT_CHECK(currentStatus.testOutputs, 1))
|
||||
{
|
||||
//Check whether any of the fuel outputs is on
|
||||
// Check whether any of the fuel outputs is on
|
||||
|
||||
//Check for injector outputs on 50%
|
||||
// Check for injector outputs on 50%
|
||||
if(BIT_CHECK(HWTest_INJ_50pc, INJ1_CMD_BIT)) { injector1Toggle(); }
|
||||
if(BIT_CHECK(HWTest_INJ_50pc, INJ2_CMD_BIT)) { injector2Toggle(); }
|
||||
if(BIT_CHECK(HWTest_INJ_50pc, INJ3_CMD_BIT)) { injector3Toggle(); }
|
||||
|
@ -274,7 +335,7 @@ void oneMSInterval(void) //Most ARM chips can simply call a function
|
|||
if(BIT_CHECK(HWTest_INJ_50pc, INJ7_CMD_BIT)) { injector7Toggle(); }
|
||||
if(BIT_CHECK(HWTest_INJ_50pc, INJ8_CMD_BIT)) { injector8Toggle(); }
|
||||
|
||||
//Check for ignition outputs on 50%
|
||||
// Check for ignition outputs on 50%
|
||||
if(BIT_CHECK(HWTest_IGN_50pc, IGN1_CMD_BIT)) { coil1Toggle(); }
|
||||
if(BIT_CHECK(HWTest_IGN_50pc, IGN2_CMD_BIT)) { coil2Toggle(); }
|
||||
if(BIT_CHECK(HWTest_IGN_50pc, IGN3_CMD_BIT)) { coil3Toggle(); }
|
||||
|
@ -284,10 +345,9 @@ void oneMSInterval(void) //Most ARM chips can simply call a function
|
|||
if(BIT_CHECK(HWTest_IGN_50pc, IGN7_CMD_BIT)) { coil7Toggle(); }
|
||||
if(BIT_CHECK(HWTest_IGN_50pc, IGN8_CMD_BIT)) { coil8Toggle(); }
|
||||
}
|
||||
|
||||
}
|
||||
#if defined(CORE_AVR) //AVR chips use the ISR for this
|
||||
//Reset Timer2 to trigger in another ~1ms
|
||||
TCNT2 = 131; //Preload timer2 with 100 cycles, leaving 156 till overflow.
|
||||
#if defined(CORE_AVR) // AVR chips use the ISR for this
|
||||
// Reset Timer2 to trigger in another ~1ms
|
||||
TCNT2 = 131; // Preload timer2 with 100 cycles, leaving 156 till overflow.
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -16,44 +16,44 @@
|
|||
|
||||
void doUpdates(void)
|
||||
{
|
||||
#define CURRENT_DATA_VERSION 22
|
||||
//Only the latest update for small flash devices must be retained
|
||||
#ifndef SMALL_FLASH_MODE
|
||||
#define CURRENT_DATA_VERSION 22
|
||||
// Only the latest update for small flash devices must be retained
|
||||
#ifndef SMALL_FLASH_MODE
|
||||
|
||||
//May 2017 firmware introduced a -40 offset on the ignition table. Update that table to +40
|
||||
// May 2017 firmware introduced a -40 offset on the ignition table. Update that table to +40
|
||||
if(readEEPROMVersion() == 2)
|
||||
{
|
||||
auto table_it = ignitionTable.values.begin();
|
||||
while (!table_it.at_end())
|
||||
while(!table_it.at_end())
|
||||
{
|
||||
auto row = *table_it;
|
||||
while (!row.at_end())
|
||||
while(!row.at_end())
|
||||
{
|
||||
*row = *row + 40;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
++table_it;
|
||||
}
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(3);
|
||||
}
|
||||
//June 2017 required the forced addition of some CAN values to avoid weird errors
|
||||
// June 2017 required the forced addition of some CAN values to avoid weird errors
|
||||
if(readEEPROMVersion() == 3)
|
||||
{
|
||||
configPage9.speeduino_tsCanId = 0;
|
||||
configPage9.true_address = 256;
|
||||
configPage9.speeduino_tsCanId = 0;
|
||||
configPage9.true_address = 256;
|
||||
configPage9.realtime_base_address = 336;
|
||||
|
||||
//There was a bad value in the May base tune for the spark duration setting, fix it here if it's a problem
|
||||
// There was a bad value in the May base tune for the spark duration setting, fix it here if it's a problem
|
||||
if(configPage4.sparkDur == 255) { configPage4.sparkDur = 10; }
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(4);
|
||||
}
|
||||
//July 2017 adds a cranking enrichment curve in place of the single value. This converts that single value to the curve
|
||||
// July 2017 adds a cranking enrichment curve in place of the single value. This converts that single value to the curve
|
||||
if(readEEPROMVersion() == 4)
|
||||
{
|
||||
//Some default values for the bins (Doesn't matter too much here as the values against them will all be identical)
|
||||
// Some default values for the bins (Doesn't matter too much here as the values against them will all be identical)
|
||||
configPage10.crankingEnrichBins[0] = 0;
|
||||
configPage10.crankingEnrichBins[1] = 40;
|
||||
configPage10.crankingEnrichBins[2] = 70;
|
||||
|
@ -67,47 +67,48 @@ void doUpdates(void)
|
|||
writeAllConfig();
|
||||
storeEEPROMVersion(5);
|
||||
}
|
||||
//September 2017 had a major change to increase the minimum table size to 128. This required multiple pieces of data being moved around
|
||||
// September 2017 had a major change to increase the minimum table size to 128. This required multiple pieces of data being moved around
|
||||
if(readEEPROMVersion() == 5)
|
||||
{
|
||||
//Data after page 4 has to move back 128 bytes
|
||||
for(int x=0; x < 1152; x++)
|
||||
// Data after page 4 has to move back 128 bytes
|
||||
for(int x = 0; x < 1152; x++)
|
||||
{
|
||||
int endMem = EEPROM_CONFIG10_END - x;
|
||||
int startMem = endMem - 128; //
|
||||
int endMem = EEPROM_CONFIG10_END - x;
|
||||
int startMem = endMem - 128; //
|
||||
byte currentVal = EEPROM.read(startMem);
|
||||
EEPROM.update(endMem, currentVal);
|
||||
}
|
||||
//The remaining data only has to move back 64 bytes
|
||||
for(int x=0; x < 352; x++)
|
||||
// The remaining data only has to move back 64 bytes
|
||||
for(int x = 0; x < 352; x++)
|
||||
{
|
||||
int endMem = EEPROM_CONFIG10_END - 1152 - x;
|
||||
int startMem = endMem - 64; //
|
||||
int endMem = EEPROM_CONFIG10_END - 1152 - x;
|
||||
int startMem = endMem - 64; //
|
||||
byte currentVal = EEPROM.read(startMem);
|
||||
EEPROM.update(endMem, currentVal);
|
||||
}
|
||||
|
||||
storeEEPROMVersion(6);
|
||||
loadConfig(); //Reload the config after changing everything in EEPROM
|
||||
loadConfig(); // Reload the config after changing everything in EEPROM
|
||||
}
|
||||
//November 2017 added the staging table that comes after boost and vvt in the EEPROM. This required multiple pieces of data being moved around
|
||||
// November 2017 added the staging table that comes after boost and vvt in the EEPROM. This required multiple pieces of data being moved around
|
||||
if(readEEPROMVersion() == 6)
|
||||
{
|
||||
//Data after page 8 has to move back 82 bytes
|
||||
for(int x=0; x < 529; x++)
|
||||
// Data after page 8 has to move back 82 bytes
|
||||
for(int x = 0; x < 529; x++)
|
||||
{
|
||||
int endMem = EEPROM_CONFIG10_END - x;
|
||||
int startMem = endMem - 82; //
|
||||
int endMem = EEPROM_CONFIG10_END - x;
|
||||
int startMem = endMem - 82; //
|
||||
byte currentVal = EEPROM.read(startMem);
|
||||
EEPROM.update(endMem, currentVal);
|
||||
}
|
||||
|
||||
storeEEPROMVersion(7);
|
||||
loadConfig(); //Reload the config after changing everything in EEPROM
|
||||
loadConfig(); // Reload the config after changing everything in EEPROM
|
||||
}
|
||||
|
||||
if (readEEPROMVersion() == 7) {
|
||||
//Convert whatever flex fuel settings are there into the new tables
|
||||
if(readEEPROMVersion() == 7)
|
||||
{
|
||||
// Convert whatever flex fuel settings are there into the new tables
|
||||
|
||||
configPage10.flexBoostBins[0] = 0;
|
||||
configPage10.flexBoostAdj[0] = (int8_t)configPage2.aeColdPct;
|
||||
|
@ -118,20 +119,20 @@ void doUpdates(void)
|
|||
configPage10.flexAdvBins[0] = 0;
|
||||
configPage10.flexAdvAdj[0] = configPage2.aeTaperMin;
|
||||
|
||||
for (uint8_t x = 1; x < 6; x++)
|
||||
for(uint8_t x = 1; x < 6; x++)
|
||||
{
|
||||
uint8_t pct = x * 20;
|
||||
uint8_t pct = x * 20;
|
||||
configPage10.flexBoostBins[x] = pct;
|
||||
configPage10.flexFuelBins[x] = pct;
|
||||
configPage10.flexAdvBins[x] = pct;
|
||||
configPage10.flexFuelBins[x] = pct;
|
||||
configPage10.flexAdvBins[x] = pct;
|
||||
|
||||
int16_t boostAdder = (((configPage2.aeColdTaperMin - (int8_t)configPage2.aeColdPct) * pct) / 100) + (int8_t)configPage2.aeColdPct;
|
||||
int16_t boostAdder = (((configPage2.aeColdTaperMin - (int8_t)configPage2.aeColdPct) * pct) / 100) + (int8_t)configPage2.aeColdPct;
|
||||
configPage10.flexBoostAdj[x] = boostAdder;
|
||||
|
||||
uint8_t fuelAdder = (((configPage2.idleUpAdder - configPage2.idleUpPin) * pct) / 100) + configPage2.idleUpPin;
|
||||
uint8_t fuelAdder = (((configPage2.idleUpAdder - configPage2.idleUpPin) * pct) / 100) + configPage2.idleUpPin;
|
||||
configPage10.flexFuelAdj[x] = fuelAdder;
|
||||
|
||||
uint8_t advanceAdder = (((configPage2.aeTaperMax - configPage2.aeTaperMin) * pct) / 100) + configPage2.aeTaperMin;
|
||||
uint8_t advanceAdder = (((configPage2.aeTaperMax - configPage2.aeTaperMin) * pct) / 100) + configPage2.aeTaperMin;
|
||||
configPage10.flexAdvAdj[x] = advanceAdder;
|
||||
}
|
||||
|
||||
|
@ -139,13 +140,13 @@ void doUpdates(void)
|
|||
storeEEPROMVersion(8);
|
||||
}
|
||||
|
||||
if (readEEPROMVersion() == 8)
|
||||
if(readEEPROMVersion() == 8)
|
||||
{
|
||||
//May 2018 adds separate load sources for fuel and ignition. Copy the existing load algorithm into Both
|
||||
configPage2.fuelAlgorithm = configPage2.legacyMAP; //Was configPage2.unused2_38c
|
||||
configPage2.ignAlgorithm = configPage2.legacyMAP; //Was configPage2.unused2_38c
|
||||
// May 2018 adds separate load sources for fuel and ignition. Copy the existing load algorithm into Both
|
||||
configPage2.fuelAlgorithm = configPage2.legacyMAP; // Was configPage2.unused2_38c
|
||||
configPage2.ignAlgorithm = configPage2.legacyMAP; // Was configPage2.unused2_38c
|
||||
|
||||
//Add option back in for open or closed loop boost. For all current configs to use closed
|
||||
// Add option back in for open or closed loop boost. For all current configs to use closed
|
||||
configPage4.boostType = 1;
|
||||
|
||||
writeAllConfig();
|
||||
|
@ -154,14 +155,14 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 9)
|
||||
{
|
||||
//October 2018 set default values for all the aux in variables (These were introduced in Aug, but no defaults were set then)
|
||||
//All aux channels set to Off
|
||||
for (byte AuxinChan = 0; AuxinChan <16 ; AuxinChan++)
|
||||
// October 2018 set default values for all the aux in variables (These were introduced in Aug, but no defaults were set then)
|
||||
// All aux channels set to Off
|
||||
for(byte AuxinChan = 0; AuxinChan < 16; AuxinChan++)
|
||||
{
|
||||
configPage9.caninput_sel[AuxinChan] = 0;
|
||||
}
|
||||
|
||||
//Ability to change the analog filter values was added. Set default values for these:
|
||||
// Ability to change the analog filter values was added. Set default values for these:
|
||||
configPage4.ADCFILTER_TPS = ADCFILTER_TPS_DEFAULT;
|
||||
configPage4.ADCFILTER_CLT = ADCFILTER_CLT_DEFAULT;
|
||||
configPage4.ADCFILTER_IAT = ADCFILTER_IAT_DEFAULT;
|
||||
|
@ -176,42 +177,42 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 10)
|
||||
{
|
||||
//May 2019 version adds the use of a 2D table for the priming pulse rather than a single value.
|
||||
//This sets all the values in the 2D table to be the same as the previous single value
|
||||
configPage2.primePulse[0] = configPage2.aeColdTaperMax / 5; //New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
configPage2.primePulse[1] = configPage2.aeColdTaperMax / 5; //New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
configPage2.primePulse[2] = configPage2.aeColdTaperMax / 5; //New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
configPage2.primePulse[3] = configPage2.aeColdTaperMax / 5; //New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
//Set some sane default temperatures for this table
|
||||
// May 2019 version adds the use of a 2D table for the priming pulse rather than a single value.
|
||||
// This sets all the values in the 2D table to be the same as the previous single value
|
||||
configPage2.primePulse[0] = configPage2.aeColdTaperMax / 5; // New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
configPage2.primePulse[1] = configPage2.aeColdTaperMax / 5; // New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
configPage2.primePulse[2] = configPage2.aeColdTaperMax / 5; // New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
configPage2.primePulse[3] = configPage2.aeColdTaperMax / 5; // New priming pulse values are in the range 0-127.5 rather than 0-25.5 so they must be divided by 5
|
||||
// Set some sane default temperatures for this table
|
||||
configPage2.primeBins[0] = 0;
|
||||
configPage2.primeBins[1] = 40;
|
||||
configPage2.primeBins[2] = 70;
|
||||
configPage2.primeBins[3] = 100;
|
||||
|
||||
//Also added is coolant based ASE for both duration and amount
|
||||
//All the adder amounts are set to what the single value was previously
|
||||
// Also added is coolant based ASE for both duration and amount
|
||||
// All the adder amounts are set to what the single value was previously
|
||||
configPage2.asePct[0] = configPage2.aeColdTaperMin;
|
||||
configPage2.asePct[1] = configPage2.aeColdTaperMin;
|
||||
configPage2.asePct[2] = configPage2.aeColdTaperMin;
|
||||
configPage2.asePct[3] = configPage2.aeColdTaperMin;
|
||||
//ASE duration is set to 10s for all coolant values
|
||||
// ASE duration is set to 10s for all coolant values
|
||||
configPage2.aseCount[0] = 10;
|
||||
configPage2.aseCount[1] = 10;
|
||||
configPage2.aseCount[2] = 10;
|
||||
configPage2.aseCount[3] = 10;
|
||||
//Finally the coolant bins for the above are set to sane values (Remembering these are offset values)
|
||||
// Finally the coolant bins for the above are set to sane values (Remembering these are offset values)
|
||||
configPage2.aseBins[0] = 0;
|
||||
configPage2.aseBins[1] = 20;
|
||||
configPage2.aseBins[2] = 60;
|
||||
configPage2.aseBins[3] = 80;
|
||||
|
||||
//Coolant based ignition advance was added also. Set sane values
|
||||
configPage4.cltAdvBins[0] = 0;
|
||||
configPage4.cltAdvBins[1] = 30;
|
||||
configPage4.cltAdvBins[2] = 60;
|
||||
configPage4.cltAdvBins[3] = 70;
|
||||
configPage4.cltAdvBins[4] = 85;
|
||||
configPage4.cltAdvBins[5] = 100;
|
||||
// Coolant based ignition advance was added also. Set sane values
|
||||
configPage4.cltAdvBins[0] = 0;
|
||||
configPage4.cltAdvBins[1] = 30;
|
||||
configPage4.cltAdvBins[2] = 60;
|
||||
configPage4.cltAdvBins[3] = 70;
|
||||
configPage4.cltAdvBins[4] = 85;
|
||||
configPage4.cltAdvBins[5] = 100;
|
||||
configPage4.cltAdvValues[0] = 0;
|
||||
configPage4.cltAdvValues[1] = 0;
|
||||
configPage4.cltAdvValues[2] = 0;
|
||||
|
@ -219,44 +220,42 @@ void doUpdates(void)
|
|||
configPage4.cltAdvValues[4] = 0;
|
||||
configPage4.cltAdvValues[5] = 0;
|
||||
|
||||
|
||||
//March 19 added a tacho pulse duration that could default to stupidly high values. Check if this is the case and fix it if found. 6ms is the maximum allowed value
|
||||
// March 19 added a tacho pulse duration that could default to stupidly high values. Check if this is the case and fix it if found. 6ms is the maximum allowed value
|
||||
if(configPage2.tachoDuration > 6) { configPage2.tachoDuration = 3; }
|
||||
|
||||
//MAP based AE was introduced, force the AE mode to be TPS for all existing tunes
|
||||
configPage2.aeMode = AE_MODE_TPS;
|
||||
// MAP based AE was introduced, force the AE mode to be TPS for all existing tunes
|
||||
configPage2.aeMode = AE_MODE_TPS;
|
||||
configPage2.maeThresh = configPage2.taeThresh;
|
||||
//Set some sane values for the MAP AE curve
|
||||
// Set some sane values for the MAP AE curve
|
||||
configPage4.maeRates[0] = 75;
|
||||
configPage4.maeRates[1] = 75;
|
||||
configPage4.maeRates[2] = 75;
|
||||
configPage4.maeRates[3] = 75;
|
||||
configPage4.maeBins[0] = 7;
|
||||
configPage4.maeBins[1] = 12;
|
||||
configPage4.maeBins[2] = 20;
|
||||
configPage4.maeBins[3] = 40;
|
||||
configPage4.maeBins[0] = 7;
|
||||
configPage4.maeBins[1] = 12;
|
||||
configPage4.maeBins[2] = 20;
|
||||
configPage4.maeBins[3] = 40;
|
||||
|
||||
//The 2nd fuel table was added. To prevent issues, force it to be disabled.
|
||||
// The 2nd fuel table was added. To prevent issues, force it to be disabled.
|
||||
configPage10.fuel2Mode = 0;
|
||||
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(11);
|
||||
}
|
||||
|
||||
if(readEEPROMVersion() == 11)
|
||||
{
|
||||
//Sep 2019
|
||||
//A battery calibration offset value was introduced. Set default value to 0
|
||||
// Sep 2019
|
||||
// A battery calibration offset value was introduced. Set default value to 0
|
||||
configPage4.batVoltCorrect = 0;
|
||||
|
||||
//An option was added to select the older method of performing MAP reads with the pullup resistor active
|
||||
// An option was added to select the older method of performing MAP reads with the pullup resistor active
|
||||
configPage2.legacyMAP = 0;
|
||||
|
||||
//Secondary fuel table was added for switching. Make sure it's all turned off initially
|
||||
configPage10.fuel2Mode = 0;
|
||||
configPage10.fuel2SwitchVariable = 0; //Set switch variable to RPM
|
||||
configPage10.fuel2SwitchValue = 7000; //7000 RPM switch point is safe
|
||||
// Secondary fuel table was added for switching. Make sure it's all turned off initially
|
||||
configPage10.fuel2Mode = 0;
|
||||
configPage10.fuel2SwitchVariable = 0; // Set switch variable to RPM
|
||||
configPage10.fuel2SwitchValue = 7000; // 7000 RPM switch point is safe
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(12);
|
||||
|
@ -264,11 +263,11 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 12)
|
||||
{
|
||||
//Nov 2019
|
||||
//New option to only apply voltage correction to dead time. Set existing tunes to use old method
|
||||
// Nov 2019
|
||||
// New option to only apply voltage correction to dead time. Set existing tunes to use old method
|
||||
configPage2.battVCorMode = BATTV_COR_MODE_WHOLE;
|
||||
|
||||
//Manual baro correction curve was added. Give it some default values (All baro readings set to 100%)
|
||||
// Manual baro correction curve was added. Give it some default values (All baro readings set to 100%)
|
||||
configPage4.baroFuelBins[0] = 80;
|
||||
configPage4.baroFuelBins[1] = 85;
|
||||
configPage4.baroFuelBins[2] = 90;
|
||||
|
@ -287,17 +286,17 @@ void doUpdates(void)
|
|||
configPage4.baroFuelValues[6] = 100;
|
||||
configPage4.baroFuelValues[7] = 100;
|
||||
|
||||
//Idle advance curve was added. Add default values
|
||||
configPage2.idleAdvEnabled = 0; //Turn this off by default
|
||||
configPage2.idleAdvTPS = 5; //Active below 5% tps
|
||||
configPage2.idleAdvRPM = 20; //Active below 2000 RPM
|
||||
configPage4.idleAdvBins[0] = 30;
|
||||
configPage4.idleAdvBins[1] = 40;
|
||||
configPage4.idleAdvBins[2] = 50;
|
||||
configPage4.idleAdvBins[3] = 60;
|
||||
configPage4.idleAdvBins[4] = 70;
|
||||
configPage4.idleAdvBins[5] = 80;
|
||||
configPage4.idleAdvValues[0] = 15; //These values offset by 15, so this is just making this equal to 0
|
||||
// Idle advance curve was added. Add default values
|
||||
configPage2.idleAdvEnabled = 0; // Turn this off by default
|
||||
configPage2.idleAdvTPS = 5; // Active below 5% tps
|
||||
configPage2.idleAdvRPM = 20; // Active below 2000 RPM
|
||||
configPage4.idleAdvBins[0] = 30;
|
||||
configPage4.idleAdvBins[1] = 40;
|
||||
configPage4.idleAdvBins[2] = 50;
|
||||
configPage4.idleAdvBins[3] = 60;
|
||||
configPage4.idleAdvBins[4] = 70;
|
||||
configPage4.idleAdvBins[5] = 80;
|
||||
configPage4.idleAdvValues[0] = 15; // These values offset by 15, so this is just making this equal to 0
|
||||
configPage4.idleAdvValues[1] = 15;
|
||||
configPage4.idleAdvValues[2] = 15;
|
||||
configPage4.idleAdvValues[3] = 15;
|
||||
|
@ -310,113 +309,112 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 13)
|
||||
{
|
||||
//202005
|
||||
//Cranking enrichment range 0..1275% instead of older 0.255, so need to divide old values by 5
|
||||
// 202005
|
||||
// Cranking enrichment range 0..1275% instead of older 0.255, so need to divide old values by 5
|
||||
configPage10.crankingEnrichValues[0] = configPage10.crankingEnrichValues[0] / 5;
|
||||
configPage10.crankingEnrichValues[1] = configPage10.crankingEnrichValues[1] / 5;
|
||||
configPage10.crankingEnrichValues[2] = configPage10.crankingEnrichValues[2] / 5;
|
||||
configPage10.crankingEnrichValues[3] = configPage10.crankingEnrichValues[3] / 5;
|
||||
|
||||
//Added the injector timing curve
|
||||
//Set all the values to be the same as the first one.
|
||||
configPage2.injAng[0] = configPage2.injAng[0]; //Obviously not needed, but here for completeness
|
||||
// Added the injector timing curve
|
||||
// Set all the values to be the same as the first one.
|
||||
configPage2.injAng[0] = configPage2.injAng[0]; // Obviously not needed, but here for completeness
|
||||
configPage2.injAng[1] = configPage2.injAng[0];
|
||||
configPage2.injAng[2] = configPage2.injAng[0];
|
||||
configPage2.injAng[3] = configPage2.injAng[0];
|
||||
//The RPMs are divided by 100
|
||||
// The RPMs are divided by 100
|
||||
configPage2.injAngRPM[0] = 5;
|
||||
configPage2.injAngRPM[1] = 25;
|
||||
configPage2.injAngRPM[2] = 45;
|
||||
configPage2.injAngRPM[3] = 65;
|
||||
|
||||
//Introduced a DFCO delay option. Default it to 0
|
||||
// Introduced a DFCO delay option. Default it to 0
|
||||
configPage2.dfcoDelay = 0;
|
||||
//Introduced a minimum temperature for DFCO. Default it to 40C
|
||||
configPage2.dfcoMinCLT = 80; //CALIBRATION_TEMPERATURE_OFFSET is 40
|
||||
// Introduced a minimum temperature for DFCO. Default it to 40C
|
||||
configPage2.dfcoMinCLT = 80; // CALIBRATION_TEMPERATURE_OFFSET is 40
|
||||
|
||||
//Update flex fuel ignition config values for 40 degrees offset
|
||||
for (int i=0; i<6; i++)
|
||||
// Update flex fuel ignition config values for 40 degrees offset
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
configPage10.flexAdvAdj[i] += 40;
|
||||
}
|
||||
|
||||
//AE cold modifier added. Default to sane values
|
||||
configPage2.aeColdPct = 100;
|
||||
|
||||
// AE cold modifier added. Default to sane values
|
||||
configPage2.aeColdPct = 100;
|
||||
configPage2.aeColdTaperMin = 40;
|
||||
configPage2.aeColdTaperMax = 100;
|
||||
|
||||
//New PID resolution, old resolution was 100% for each increase, 100% now is stored as 32
|
||||
// New PID resolution, old resolution was 100% for each increase, 100% now is stored as 32
|
||||
if(configPage6.idleKP >= 8) { configPage6.idleKP = 255; }
|
||||
else { configPage6.idleKP = configPage6.idleKP<<5; }
|
||||
else { configPage6.idleKP = configPage6.idleKP << 5; }
|
||||
if(configPage6.idleKI >= 8) { configPage6.idleKI = 255; }
|
||||
else { configPage6.idleKI = configPage6.idleKI<<5; }
|
||||
else { configPage6.idleKI = configPage6.idleKI << 5; }
|
||||
if(configPage6.idleKD >= 8) { configPage6.idleKD = 255; }
|
||||
else { configPage6.idleKD = configPage6.idleKD<<5; }
|
||||
else { configPage6.idleKD = configPage6.idleKD << 5; }
|
||||
if(configPage10.vvtCLKP >= 8) { configPage10.vvtCLKP = 255; }
|
||||
else { configPage10.vvtCLKP = configPage10.vvtCLKP<<5; }
|
||||
else { configPage10.vvtCLKP = configPage10.vvtCLKP << 5; }
|
||||
if(configPage10.vvtCLKI >= 8) { configPage10.vvtCLKI = 255; }
|
||||
else { configPage10.vvtCLKI = configPage10.vvtCLKI<<5; }
|
||||
else { configPage10.vvtCLKI = configPage10.vvtCLKI << 5; }
|
||||
if(configPage10.vvtCLKD >= 8) { configPage10.vvtCLKD = 255; }
|
||||
else { configPage10.vvtCLKD = configPage10.vvtCLKD<<5; }
|
||||
else { configPage10.vvtCLKD = configPage10.vvtCLKD << 5; }
|
||||
|
||||
//Cranking enrichment to run taper added. Default it to 0,1 secs
|
||||
// Cranking enrichment to run taper added. Default it to 0,1 secs
|
||||
configPage10.crankingEnrichTaper = 1;
|
||||
|
||||
//ASE to run taper added. Default it to 0,1 secs
|
||||
|
||||
// ASE to run taper added. Default it to 0,1 secs
|
||||
configPage2.aseTaperTime = 1;
|
||||
|
||||
// there is now option for fixed and relative timing retard for soft limit. This sets the soft limiter to the old fixed timing mode.
|
||||
configPage2.SoftLimitMode = SOFT_LIMIT_FIXED;
|
||||
|
||||
//VSS was added for testing, disable it by default
|
||||
// VSS was added for testing, disable it by default
|
||||
configPage2.vssMode = 0;
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(14);
|
||||
|
||||
}
|
||||
|
||||
if(readEEPROMVersion() == 14)
|
||||
{
|
||||
//202008
|
||||
// 202008
|
||||
|
||||
//MAJOR update to move the coolant, IAT and O2 calibrations to 2D tables
|
||||
// MAJOR update to move the coolant, IAT and O2 calibrations to 2D tables
|
||||
int y;
|
||||
for(int x=0; x<(CALIBRATION_TABLE_SIZE/16); x++) //Each calibration table is 512 bytes long
|
||||
for(int x = 0; x < (CALIBRATION_TABLE_SIZE / 16); x++) // Each calibration table is 512 bytes long
|
||||
{
|
||||
y = EEPROM_CALIBRATION_CLT_OLD + (x * 16);
|
||||
y = EEPROM_CALIBRATION_CLT_OLD + (x * 16);
|
||||
cltCalibration_values[x] = EEPROM.read(y);
|
||||
cltCalibration_bins[x] = (x * 32);
|
||||
cltCalibration_bins[x] = (x * 32);
|
||||
|
||||
y = EEPROM_CALIBRATION_IAT_OLD + (x * 16);
|
||||
y = EEPROM_CALIBRATION_IAT_OLD + (x * 16);
|
||||
iatCalibration_values[x] = EEPROM.read(y);
|
||||
iatCalibration_bins[x] = (x * 32);
|
||||
iatCalibration_bins[x] = (x * 32);
|
||||
|
||||
y = EEPROM_CALIBRATION_O2_OLD + (x * 16);
|
||||
y = EEPROM_CALIBRATION_O2_OLD + (x * 16);
|
||||
o2Calibration_values[x] = EEPROM.read(y);
|
||||
o2Calibration_bins[x] = (x * 32);
|
||||
o2Calibration_bins[x] = (x * 32);
|
||||
}
|
||||
writeCalibration();
|
||||
|
||||
//Oil and fuel pressure inputs were introduced. Disable them both by default
|
||||
// Oil and fuel pressure inputs were introduced. Disable them both by default
|
||||
configPage10.oilPressureProtEnbl = false;
|
||||
configPage10.oilPressureEnable = false;
|
||||
configPage10.fuelPressureEnable = false;
|
||||
|
||||
//wmi
|
||||
configPage10.wmiEnabled = 0;
|
||||
configPage10.wmiMode = 0;
|
||||
configPage10.wmiOffset = 0;
|
||||
configPage10.oilPressureEnable = false;
|
||||
configPage10.fuelPressureEnable = false;
|
||||
|
||||
// wmi
|
||||
configPage10.wmiEnabled = 0;
|
||||
configPage10.wmiMode = 0;
|
||||
configPage10.wmiOffset = 0;
|
||||
configPage10.wmiIndicatorEnabled = 0;
|
||||
configPage10.wmiEmptyEnabled = 0;
|
||||
configPage10.wmiAdvEnabled = 0;
|
||||
for(int i=0; i<6; i++)
|
||||
configPage10.wmiEmptyEnabled = 0;
|
||||
configPage10.wmiAdvEnabled = 0;
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
configPage10.wmiAdvBins[i] = i*100/2;
|
||||
configPage10.wmiAdvAdj[i] = OFFSET_IGNITION;
|
||||
configPage10.wmiAdvBins[i] = i * 100 / 2;
|
||||
configPage10.wmiAdvAdj[i] = OFFSET_IGNITION;
|
||||
}
|
||||
|
||||
//Programmable outputs added. Set all to disabled
|
||||
// Programmable outputs added. Set all to disabled
|
||||
configPage13.outputPin[0] = 0;
|
||||
configPage13.outputPin[1] = 0;
|
||||
configPage13.outputPin[2] = 0;
|
||||
|
@ -426,15 +424,15 @@ void doUpdates(void)
|
|||
configPage13.outputPin[6] = 0;
|
||||
configPage13.outputPin[7] = 0;
|
||||
|
||||
//New multiply MAP option added. Set new option to be the same as old
|
||||
// New multiply MAP option added. Set new option to be the same as old
|
||||
configPage2.multiplyMAP = configPage2.crkngAddCLTAdv;
|
||||
//New AE option added to allow for PW added in addition to existing PW multiply
|
||||
configPage2.aeApplyMode = 0; //Set the AE mode to Multiply
|
||||
// New AE option added to allow for PW added in addition to existing PW multiply
|
||||
configPage2.aeApplyMode = 0; // Set the AE mode to Multiply
|
||||
|
||||
//Injector priming delay added
|
||||
// Injector priming delay added
|
||||
configPage2.primingDelay = 0;
|
||||
//ASE taper time added
|
||||
configPage2.aseTaperTime = 10; //1 second taper
|
||||
// ASE taper time added
|
||||
configPage2.aseTaperTime = 10; // 1 second taper
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(15);
|
||||
|
@ -442,25 +440,25 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 15)
|
||||
{
|
||||
//202012
|
||||
configPage10.spark2Mode = 0; //Disable 2nd spark table
|
||||
// 202012
|
||||
configPage10.spark2Mode = 0; // Disable 2nd spark table
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(16);
|
||||
}
|
||||
|
||||
//Move this #endif to only do latest updates to safe ROM space on small devices.
|
||||
#endif
|
||||
// Move this #endif to only do latest updates to safe ROM space on small devices.
|
||||
#endif
|
||||
if(readEEPROMVersion() == 16)
|
||||
{
|
||||
//Fix for wrong placed page 13
|
||||
for(int x=EEPROM_CONFIG14_END; x>=EEPROM_CONFIG13_START; x--)
|
||||
// Fix for wrong placed page 13
|
||||
for(int x = EEPROM_CONFIG14_END; x >= EEPROM_CONFIG13_START; x--)
|
||||
{
|
||||
EEPROM.update(x, EEPROM.read(x-112));
|
||||
EEPROM.update(x, EEPROM.read(x - 112));
|
||||
}
|
||||
|
||||
configPage6.iacPWMrun = false; // just in case. This should be false anyways, but sill.
|
||||
configPage2.useDwellMap = 0; //Dwell map added, use old fixed value as default
|
||||
configPage6.iacPWMrun = false; // just in case. This should be false anyways, but sill.
|
||||
configPage2.useDwellMap = 0; // Dwell map added, use old fixed value as default
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(17);
|
||||
|
@ -468,44 +466,44 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 17)
|
||||
{
|
||||
//VVT stuff has now 0.5 accuracy, so shift values in vvt table by one.
|
||||
// VVT stuff has now 0.5 accuracy, so shift values in vvt table by one.
|
||||
auto table_it = vvtTable.values.begin();
|
||||
while (!table_it.at_end())
|
||||
while(!table_it.at_end())
|
||||
{
|
||||
auto row = *table_it;
|
||||
while (!row.at_end())
|
||||
while(!row.at_end())
|
||||
{
|
||||
*row = *row << 1;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
++table_it;
|
||||
}
|
||||
|
||||
configPage10.vvtCLholdDuty = configPage10.vvtCLholdDuty << 1;
|
||||
configPage10.vvtCLminDuty = configPage10.vvtCLminDuty << 1;
|
||||
configPage10.vvtCLmaxDuty = configPage10.vvtCLmaxDuty << 1;
|
||||
configPage10.vvtCLminDuty = configPage10.vvtCLminDuty << 1;
|
||||
configPage10.vvtCLmaxDuty = configPage10.vvtCLmaxDuty << 1;
|
||||
|
||||
//VVT2 added, so default values and disable it
|
||||
configPage10.vvt2Enabled = 0;
|
||||
configPage4.vvt2PWMdir = 0;
|
||||
// VVT2 added, so default values and disable it
|
||||
configPage10.vvt2Enabled = 0;
|
||||
configPage4.vvt2PWMdir = 0;
|
||||
configPage10.TrigEdgeThrd = 0;
|
||||
|
||||
//Old use as On/Off selection is removed, so change VVT mode to On/Off based on that
|
||||
// Old use as On/Off selection is removed, so change VVT mode to On/Off based on that
|
||||
if(configPage6.tachoMode == 1) { configPage6.vvtMode = VVT_MODE_ONOFF; }
|
||||
|
||||
//Closed loop VVT improvements. Set safety limits to max/min working values and filter to minimum.
|
||||
configPage10.vvtCLMinAng = 0;
|
||||
configPage10.vvtCLMaxAng = 200;
|
||||
// Closed loop VVT improvements. Set safety limits to max/min working values and filter to minimum.
|
||||
configPage10.vvtCLMinAng = 0;
|
||||
configPage10.vvtCLMaxAng = 200;
|
||||
configPage4.ANGLEFILTER_VVT = 0;
|
||||
|
||||
configPage2.idleAdvDelay *= 2; //Increased resolution to 0.5 second
|
||||
|
||||
//RPM switch point added for map sample method. Set to 0 to not affect existing tunes.
|
||||
configPage2.idleAdvDelay *= 2; // Increased resolution to 0.5 second
|
||||
|
||||
// RPM switch point added for map sample method. Set to 0 to not affect existing tunes.
|
||||
configPage2.mapSwitchPoint = 0;
|
||||
|
||||
configPage9.boostByGearEnabled = 0;
|
||||
|
||||
//Added possibility to set minimum programmable output time
|
||||
// Added possibility to set minimum programmable output time
|
||||
configPage13.outputTimeLimit[0] = 0;
|
||||
configPage13.outputTimeLimit[1] = 0;
|
||||
configPage13.outputTimeLimit[2] = 0;
|
||||
|
@ -521,11 +519,11 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 18)
|
||||
{
|
||||
//202202
|
||||
// 202202
|
||||
configPage2.fanEnable = configPage6.fanUnused; // PWM Fan mode added, but take the previous setting of Fan in use.
|
||||
|
||||
//TPS resolution increased to 0.5%
|
||||
//configPage2.taeThresh *= 2;
|
||||
// TPS resolution increased to 0.5%
|
||||
// configPage2.taeThresh *= 2;
|
||||
configPage2.idleAdvTPS *= 2;
|
||||
configPage2.iacTPSlimit *= 2;
|
||||
configPage4.floodClear *= 2;
|
||||
|
@ -540,8 +538,8 @@ void doUpdates(void)
|
|||
// Each table Y axis need to be updated as well if TPS is the source
|
||||
if(configPage2.fuelAlgorithm == LOAD_SOURCE_TPS)
|
||||
{
|
||||
multiplyTableLoad(&fuelTable, fuelTable.type_key, 4);
|
||||
multiplyTableLoad(&afrTable, afrTable.type_key, 4);
|
||||
multiplyTableLoad(&fuelTable, fuelTable.type_key, 4);
|
||||
multiplyTableLoad(&afrTable, afrTable.type_key, 4);
|
||||
multiplyTableLoad(&trim1Table, trim1Table.type_key, 4);
|
||||
multiplyTableLoad(&trim2Table, trim2Table.type_key, 4);
|
||||
multiplyTableLoad(&trim3Table, trim3Table.type_key, 4);
|
||||
|
@ -551,7 +549,7 @@ void doUpdates(void)
|
|||
multiplyTableLoad(&trim7Table, trim7Table.type_key, 4);
|
||||
multiplyTableLoad(&trim8Table, trim8Table.type_key, 4);
|
||||
if(configPage4.sparkMode == IGN_MODE_ROTARY)
|
||||
{
|
||||
{
|
||||
for(uint8_t x = 0; x < 8; x++)
|
||||
{
|
||||
configPage10.rotarySplitBins[x] *= 2;
|
||||
|
@ -565,138 +563,137 @@ void doUpdates(void)
|
|||
|
||||
if(configPage6.vvtLoadSource == VVT_LOAD_TPS)
|
||||
{
|
||||
//NOTE: The VVT tables all had 1.0 as the multiply value rather than 2.0 used in all other tables. For this reason they only need to be multiplied by 2 when updating
|
||||
// NOTE: The VVT tables all had 1.0 as the multiply value rather than 2.0 used in all other tables. For this reason they only need to be multiplied by 2 when updating
|
||||
multiplyTableLoad(&vvtTable, vvtTable.type_key, 2);
|
||||
multiplyTableLoad(&vvt2Table, vvt2Table.type_key, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
//NOTE: The VVT tables all had 1.0 as the multiply value rather than 2.0 used in all other tables. For this reason they need to be divided by 2 when updating
|
||||
// NOTE: The VVT tables all had 1.0 as the multiply value rather than 2.0 used in all other tables. For this reason they need to be divided by 2 when updating
|
||||
divideTableLoad(&vvtTable, vvtTable.type_key, 2);
|
||||
divideTableLoad(&vvt2Table, vvt2Table.type_key, 2);
|
||||
}
|
||||
|
||||
|
||||
configPage4.vvtDelay = 0;
|
||||
configPage4.vvtDelay = 0;
|
||||
configPage4.vvtMinClt = 0;
|
||||
|
||||
//Set SD logging related settings to zero.
|
||||
// Set SD logging related settings to zero.
|
||||
configPage13.onboard_log_csv_separator = 0;
|
||||
configPage13.onboard_log_file_style = 0;
|
||||
configPage13.onboard_log_file_rate = 0;
|
||||
configPage13.onboard_log_filenaming = 0;
|
||||
configPage13.onboard_log_storage = 0;
|
||||
configPage13.onboard_log_trigger_boot = 0;
|
||||
configPage13.onboard_log_trigger_RPM = 0;
|
||||
configPage13.onboard_log_trigger_prot = 0;
|
||||
configPage13.onboard_log_trigger_Vbat = 0;
|
||||
configPage13.onboard_log_trigger_Epin = 0;
|
||||
configPage13.onboard_log_tr1_duration = 0;
|
||||
configPage13.onboard_log_tr2_thr_on = 0;
|
||||
configPage13.onboard_log_tr2_thr_off = 0;
|
||||
configPage13.onboard_log_tr3_thr_RPM = 0;
|
||||
configPage13.onboard_log_tr3_thr_MAP = 0;
|
||||
configPage13.onboard_log_tr3_thr_Oil = 0;
|
||||
configPage13.onboard_log_tr3_thr_AFR = 0;
|
||||
configPage13.onboard_log_tr4_thr_on = 0;
|
||||
configPage13.onboard_log_tr4_thr_off = 0;
|
||||
configPage13.onboard_log_tr5_Epin_pin = 0;
|
||||
configPage13.onboard_log_file_style = 0;
|
||||
configPage13.onboard_log_file_rate = 0;
|
||||
configPage13.onboard_log_filenaming = 0;
|
||||
configPage13.onboard_log_storage = 0;
|
||||
configPage13.onboard_log_trigger_boot = 0;
|
||||
configPage13.onboard_log_trigger_RPM = 0;
|
||||
configPage13.onboard_log_trigger_prot = 0;
|
||||
configPage13.onboard_log_trigger_Vbat = 0;
|
||||
configPage13.onboard_log_trigger_Epin = 0;
|
||||
configPage13.onboard_log_tr1_duration = 0;
|
||||
configPage13.onboard_log_tr2_thr_on = 0;
|
||||
configPage13.onboard_log_tr2_thr_off = 0;
|
||||
configPage13.onboard_log_tr3_thr_RPM = 0;
|
||||
configPage13.onboard_log_tr3_thr_MAP = 0;
|
||||
configPage13.onboard_log_tr3_thr_Oil = 0;
|
||||
configPage13.onboard_log_tr3_thr_AFR = 0;
|
||||
configPage13.onboard_log_tr4_thr_on = 0;
|
||||
configPage13.onboard_log_tr4_thr_off = 0;
|
||||
configPage13.onboard_log_tr5_Epin_pin = 0;
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(19);
|
||||
}
|
||||
|
||||
|
||||
if(readEEPROMVersion() == 19)
|
||||
{
|
||||
//202207
|
||||
// 202207
|
||||
|
||||
//Option added to select injector pairing on 4 cylinder engines
|
||||
if( configPage4.inj4cylPairing > INJ_PAIR_14_23 ) { configPage4.inj4cylPairing = 0; } //Check valid value
|
||||
if( configPage2.nCylinders == 4 )
|
||||
// Option added to select injector pairing on 4 cylinder engines
|
||||
if(configPage4.inj4cylPairing > INJ_PAIR_14_23) { configPage4.inj4cylPairing = 0; } // Check valid value
|
||||
if(configPage2.nCylinders == 4)
|
||||
{
|
||||
if ( configPage2.injLayout == INJ_SEQUENTIAL ) { configPage4.inj4cylPairing = INJ_PAIR_13_24; } //Since #478 engine will always start in semi, make the sequence right for the majority of inlie 4 engines
|
||||
else { configPage4.inj4cylPairing = INJ_PAIR_14_23; } //Force setting to use the default mode from previous FW versions. This is to prevent issues on any setups that have been wired accordingly
|
||||
if(configPage2.injLayout == INJ_SEQUENTIAL) { configPage4.inj4cylPairing = INJ_PAIR_13_24; } // Since #478 engine will always start in semi, make the sequence right for the majority of inlie 4 engines
|
||||
else { configPage4.inj4cylPairing = INJ_PAIR_14_23; } // Force setting to use the default mode from previous FW versions. This is to prevent issues on any setups that have been wired accordingly
|
||||
}
|
||||
|
||||
configPage9.hardRevMode = 1; //Set hard rev limiter to Fixed mode
|
||||
configPage6.tachoMode = 0;
|
||||
configPage9.hardRevMode = 1; // Set hard rev limiter to Fixed mode
|
||||
configPage6.tachoMode = 0;
|
||||
|
||||
//CAN broadcast introduced
|
||||
// CAN broadcast introduced
|
||||
configPage2.canBMWCluster = 0;
|
||||
configPage2.canVAGCluster = 0;
|
||||
|
||||
|
||||
configPage15.boostDCWhenDisabled = 0;
|
||||
configPage15.boostControlEnable = EN_BOOST_CONTROL_BARO;
|
||||
|
||||
//Fill the boostTableLookupDuty with all 50% duty cycle. This is the same as the hardcoded 50% DC that had been used before.
|
||||
//This makes the boostcontrol fully backwards compatible.
|
||||
configPage15.boostControlEnable = EN_BOOST_CONTROL_BARO;
|
||||
|
||||
// Fill the boostTableLookupDuty with all 50% duty cycle. This is the same as the hardcoded 50% DC that had been used before.
|
||||
// This makes the boostcontrol fully backwards compatible.
|
||||
auto table_it = boostTableLookupDuty.values.begin();
|
||||
while (!table_it.at_end())
|
||||
while(!table_it.at_end())
|
||||
{
|
||||
auto row = *table_it;
|
||||
while (!row.at_end())
|
||||
while(!row.at_end())
|
||||
{
|
||||
*row = 50*2;
|
||||
*row = 50 * 2;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
++table_it;
|
||||
}
|
||||
|
||||
//Set some sensible values at the RPM axis
|
||||
auto table_X = boostTableLookupDuty.axisX.begin();
|
||||
uint16_t i = 0;
|
||||
while (!table_X.at_end())
|
||||
// Set some sensible values at the RPM axis
|
||||
auto table_X = boostTableLookupDuty.axisX.begin();
|
||||
uint16_t i = 0;
|
||||
while(!table_X.at_end())
|
||||
{
|
||||
++i;
|
||||
*table_X = 1000+(500*i);
|
||||
*table_X = 1000 + (500 * i);
|
||||
++table_X;
|
||||
}
|
||||
|
||||
//Set some sensible values at the boosttarget axis
|
||||
// Set some sensible values at the boosttarget axis
|
||||
auto table_Y = boostTableLookupDuty.axisY.begin();
|
||||
i = 0;
|
||||
while (!table_Y.at_end())
|
||||
i = 0;
|
||||
while(!table_Y.at_end())
|
||||
{
|
||||
++i;
|
||||
*table_Y = (120 + 10*i);
|
||||
*table_Y = (120 + 10 * i);
|
||||
++table_Y;
|
||||
}
|
||||
|
||||
//AFR Protection added, add default values
|
||||
configPage9.afrProtectEnabled = 0; //Disable by default
|
||||
configPage9.afrProtectMinMAP = 90; //Is divided by 2, vlue represents 180kPa
|
||||
configPage9.afrProtectMinRPM = 40; //4000 RPM min
|
||||
configPage9.afrProtectMinTPS = 160; //80% TPS min
|
||||
configPage9.afrProtectDeviation = 14; //1.4 AFR deviation
|
||||
|
||||
// AFR Protection added, add default values
|
||||
configPage9.afrProtectEnabled = 0; // Disable by default
|
||||
configPage9.afrProtectMinMAP = 90; // Is divided by 2, vlue represents 180kPa
|
||||
configPage9.afrProtectMinRPM = 40; // 4000 RPM min
|
||||
configPage9.afrProtectMinTPS = 160; // 80% TPS min
|
||||
configPage9.afrProtectDeviation = 14; // 1.4 AFR deviation
|
||||
|
||||
writeAllConfig();
|
||||
storeEEPROMVersion(20);
|
||||
}
|
||||
|
||||
if(readEEPROMVersion() == 20)
|
||||
{
|
||||
//202305
|
||||
configPage2.taeMinChange = 4; //Default is 2% minimum change to match prior behaviour. (4 = 2% account for 0.5 resolution)
|
||||
configPage2.maeMinChange = 2; //Default is 2% minimum change to match prior behaviour.
|
||||
// 202305
|
||||
configPage2.taeMinChange = 4; // Default is 2% minimum change to match prior behaviour. (4 = 2% account for 0.5 resolution)
|
||||
configPage2.maeMinChange = 2; // Default is 2% minimum change to match prior behaviour.
|
||||
|
||||
configPage2.decelAmount = 100; //Default decel fuel amount is 100%, so no change in fueling in decel as before.
|
||||
//full status structure has been changed. Update programmable outputs settings to match.
|
||||
for (uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
|
||||
configPage2.decelAmount = 100; // Default decel fuel amount is 100%, so no change in fueling in decel as before.
|
||||
// full status structure has been changed. Update programmable outputs settings to match.
|
||||
for(uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
|
||||
{
|
||||
if ((configPage13.firstDataIn[y] > 22) && (configPage13.firstDataIn[y] < 240)) {configPage13.firstDataIn[y]++;}
|
||||
if ((configPage13.firstDataIn[y] > 92) && (configPage13.firstDataIn[y] < 240)) {configPage13.firstDataIn[y]++;}
|
||||
if ((configPage13.secondDataIn[y] > 22) && (configPage13.secondDataIn[y] < 240)) {configPage13.secondDataIn[y]++;}
|
||||
if ((configPage13.secondDataIn[y] > 92) && (configPage13.secondDataIn[y] < 240)) {configPage13.secondDataIn[y]++;}
|
||||
if((configPage13.firstDataIn[y] > 22) && (configPage13.firstDataIn[y] < 240)) { configPage13.firstDataIn[y]++; }
|
||||
if((configPage13.firstDataIn[y] > 92) && (configPage13.firstDataIn[y] < 240)) { configPage13.firstDataIn[y]++; }
|
||||
if((configPage13.secondDataIn[y] > 22) && (configPage13.secondDataIn[y] < 240)) { configPage13.secondDataIn[y]++; }
|
||||
if((configPage13.secondDataIn[y] > 92) && (configPage13.secondDataIn[y] < 240)) { configPage13.secondDataIn[y]++; }
|
||||
}
|
||||
|
||||
//AC Control (configPage15)
|
||||
//Set A/C default values - these line up with the ini file defaults
|
||||
|
||||
// AC Control (configPage15)
|
||||
// Set A/C default values - these line up with the ini file defaults
|
||||
configPage15.airConEnable = 0;
|
||||
|
||||
//Oil Pressure protection delay added. Set to 0 to match existing behaviour
|
||||
// Oil Pressure protection delay added. Set to 0 to match existing behaviour
|
||||
configPage10.oilPressureProtTime = 0;
|
||||
|
||||
//Option to power stepper motor constantly was added. Default to previous behaviour
|
||||
// Option to power stepper motor constantly was added. Default to previous behaviour
|
||||
configPage9.iacStepperPower = 0;
|
||||
|
||||
writeAllConfig();
|
||||
|
@ -705,9 +702,9 @@ void doUpdates(void)
|
|||
|
||||
if(readEEPROMVersion() == 21)
|
||||
{
|
||||
//202306
|
||||
// 202306
|
||||
|
||||
//Rolling cut curve added. Default values
|
||||
// Rolling cut curve added. Default values
|
||||
configPage15.rollingProtRPMDelta[0] = -30;
|
||||
configPage15.rollingProtRPMDelta[1] = -20;
|
||||
configPage15.rollingProtRPMDelta[2] = -10;
|
||||
|
@ -720,13 +717,13 @@ void doUpdates(void)
|
|||
writeAllConfig();
|
||||
storeEEPROMVersion(22);
|
||||
}
|
||||
|
||||
//Final check is always for 255 and 0 (Brand new arduino)
|
||||
if( (readEEPROMVersion() == 0) || (readEEPROMVersion() == 255) )
|
||||
|
||||
// Final check is always for 255 and 0 (Brand new arduino)
|
||||
if((readEEPROMVersion() == 0) || (readEEPROMVersion() == 255))
|
||||
{
|
||||
configPage9.true_address = 0x200;
|
||||
|
||||
//Programmable outputs added. Set all to disabled
|
||||
|
||||
// Programmable outputs added. Set all to disabled
|
||||
configPage13.outputPin[0] = 0;
|
||||
configPage13.outputPin[1] = 0;
|
||||
configPage13.outputPin[2] = 0;
|
||||
|
@ -741,8 +738,8 @@ void doUpdates(void)
|
|||
storeEEPROMVersion(CURRENT_DATA_VERSION);
|
||||
}
|
||||
|
||||
//Check to see if someone has downgraded versions:
|
||||
if( readEEPROMVersion() > CURRENT_DATA_VERSION ) { storeEEPROMVersion(CURRENT_DATA_VERSION); }
|
||||
// Check to see if someone has downgraded versions:
|
||||
if(readEEPROMVersion() > CURRENT_DATA_VERSION) { storeEEPROMVersion(CURRENT_DATA_VERSION); }
|
||||
}
|
||||
|
||||
void multiplyTableLoad(const void *pTable, table_type_t key, uint8_t multiplier)
|
||||
|
@ -750,7 +747,7 @@ void multiplyTableLoad(const void *pTable, table_type_t key, uint8_t multiplier)
|
|||
auto y_it = y_begin(pTable, key);
|
||||
while(!y_it.at_end())
|
||||
{
|
||||
*y_it = *y_it * multiplier;
|
||||
*y_it = *y_it * multiplier;
|
||||
++y_it;
|
||||
}
|
||||
}
|
||||
|
@ -760,7 +757,7 @@ void divideTableLoad(const void *pTable, table_type_t key, uint8_t divisor)
|
|||
auto y_it = y_begin(pTable, key);
|
||||
while(!y_it.at_end())
|
||||
{
|
||||
*y_it = *y_it / divisor; //Previous TS scale was 2.0, now is 0.5, 4x increase
|
||||
*y_it = *y_it / divisor; // Previous TS scale was 2.0, now is 0.5, 4x increase
|
||||
++y_it;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
|
||||
uint8_t ioDelay[sizeof(configPage13.outputPin)];
|
||||
uint8_t ioOutDelay[sizeof(configPage13.outputPin)];
|
||||
uint8_t pinIsValid = 0;
|
||||
uint8_t pinIsValid = 0;
|
||||
uint8_t currentRuleStatus = 0;
|
||||
|
||||
|
||||
/** Translate between the pin list that appears in TS and the actual pin numbers.
|
||||
For the **digital IO**, this will simply return the same number as the rawPin value as those are mapped directly.
|
||||
For **analog pins**, it will translate them into the correct internal pin number.
|
||||
|
@ -37,8 +36,8 @@ byte pinTranslate(byte rawPin)
|
|||
return outputPin;
|
||||
}
|
||||
/** Translate a pin number (0 - 22) to the relevant Ax (analog) pin reference.
|
||||
* This is required as some ARM chips do not have all analog pins in order (EG pin A15 != A14 + 1).
|
||||
* */
|
||||
* This is required as some ARM chips do not have all analog pins in order (EG pin A15 != A14 + 1).
|
||||
* */
|
||||
byte pinTranslateAnalog(byte rawPin)
|
||||
{
|
||||
byte outputPin = rawPin;
|
||||
|
@ -58,45 +57,44 @@ byte pinTranslateAnalog(byte rawPin)
|
|||
case 11: outputPin = A11; break;
|
||||
case 12: outputPin = A12; break;
|
||||
case 13: outputPin = A13; break;
|
||||
#if BOARD_MAX_ADC_PINS >= 14
|
||||
case 14: outputPin = A14; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 15
|
||||
case 15: outputPin = A15; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 16
|
||||
case 16: outputPin = A16; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 17
|
||||
case 17: outputPin = A17; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 18
|
||||
case 18: outputPin = A18; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 19
|
||||
case 19: outputPin = A19; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 20
|
||||
case 20: outputPin = A20; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 21
|
||||
case 21: outputPin = A21; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 22
|
||||
case 22: outputPin = A22; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 14
|
||||
case 14: outputPin = A14; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 15
|
||||
case 15: outputPin = A15; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 16
|
||||
case 16: outputPin = A16; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 17
|
||||
case 17: outputPin = A17; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 18
|
||||
case 18: outputPin = A18; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 19
|
||||
case 19: outputPin = A19; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 20
|
||||
case 20: outputPin = A20; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 21
|
||||
case 21: outputPin = A21; break;
|
||||
#endif
|
||||
#if BOARD_MAX_ADC_PINS >= 22
|
||||
case 22: outputPin = A22; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return outputPin;
|
||||
}
|
||||
|
||||
|
||||
void setResetControlPinState(void)
|
||||
{
|
||||
BIT_CLEAR(currentStatus.status3, BIT_STATUS3_RESET_PREVENT);
|
||||
|
||||
/* Setup reset control initial state */
|
||||
switch (resetControl)
|
||||
switch(resetControl)
|
||||
{
|
||||
case RESET_CONTROL_PREVENT_WHEN_RUNNING:
|
||||
/* Set the reset control pin LOW and change it to HIGH later when we get sync. */
|
||||
|
@ -121,19 +119,19 @@ void setResetControlPinState(void)
|
|||
void initialiseProgrammableIO(void)
|
||||
{
|
||||
uint8_t outputPin;
|
||||
for (uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
|
||||
for(uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
|
||||
{
|
||||
ioDelay[y] = 0;
|
||||
ioDelay[y] = 0;
|
||||
ioOutDelay[y] = 0;
|
||||
outputPin = configPage13.outputPin[y];
|
||||
if (outputPin > 0)
|
||||
outputPin = configPage13.outputPin[y];
|
||||
if(outputPin > 0)
|
||||
{
|
||||
if ( outputPin >= 128 ) //Cascate rule usage
|
||||
if(outputPin >= 128) // Cascate rule usage
|
||||
{
|
||||
BIT_WRITE(currentStatus.outputsStatus, y, BIT_CHECK(configPage13.outputInverted, y));
|
||||
BIT_SET(pinIsValid, y);
|
||||
}
|
||||
else if ( !pinIsUsed(outputPin) )
|
||||
else if(!pinIsUsed(outputPin))
|
||||
{
|
||||
pinMode(outputPin, OUTPUT);
|
||||
digitalWrite(outputPin, BIT_CHECK(configPage13.outputInverted, y));
|
||||
|
@ -153,83 +151,83 @@ void checkProgrammableIO(void)
|
|||
{
|
||||
int16_t data, data2;
|
||||
uint8_t dataRequested;
|
||||
bool firstCheck, secondCheck;
|
||||
bool firstCheck, secondCheck;
|
||||
|
||||
for (uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
|
||||
for(uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
|
||||
{
|
||||
firstCheck = false;
|
||||
firstCheck = false;
|
||||
secondCheck = false;
|
||||
if ( BIT_CHECK(pinIsValid, y) ) //if outputPin == 0 it is disabled
|
||||
if(BIT_CHECK(pinIsValid, y)) // if outputPin == 0 it is disabled
|
||||
{
|
||||
dataRequested = configPage13.firstDataIn[y];
|
||||
if ( dataRequested > 239U ) //Somehow using 239 uses 9 bytes of RAM, why??
|
||||
if(dataRequested > 239U) // Somehow using 239 uses 9 bytes of RAM, why??
|
||||
{
|
||||
dataRequested -= REUSE_RULES;
|
||||
if ( dataRequested <= sizeof(configPage13.outputPin) ) { data = BIT_CHECK(currentRuleStatus, dataRequested); }
|
||||
if(dataRequested <= sizeof(configPage13.outputPin)) { data = BIT_CHECK(currentRuleStatus, dataRequested); }
|
||||
else { data = 0; }
|
||||
}
|
||||
else { data = ProgrammableIOGetData(dataRequested); }
|
||||
data2 = configPage13.firstTarget[y];
|
||||
|
||||
if ( (configPage13.operation[y].firstCompType == COMPARATOR_EQUAL) && (data == data2) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_NOT_EQUAL) && (data != data2) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_GREATER) && (data > data2) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_GREATER_EQUAL) && (data >= data2) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_LESS) && (data < data2) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_LESS_EQUAL) && (data <= data2) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_AND) && ((data & data2) != 0) ) { firstCheck = true; }
|
||||
else if ( (configPage13.operation[y].firstCompType == COMPARATOR_XOR) && ((data ^ data2) != 0) ) { firstCheck = true; }
|
||||
if((configPage13.operation[y].firstCompType == COMPARATOR_EQUAL) && (data == data2)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_NOT_EQUAL) && (data != data2)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_GREATER) && (data > data2)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_GREATER_EQUAL) && (data >= data2)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_LESS) && (data < data2)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_LESS_EQUAL) && (data <= data2)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_AND) && ((data & data2) != 0)) { firstCheck = true; }
|
||||
else if((configPage13.operation[y].firstCompType == COMPARATOR_XOR) && ((data ^ data2) != 0)) { firstCheck = true; }
|
||||
|
||||
if (configPage13.operation[y].bitwise != BITWISE_DISABLED)
|
||||
if(configPage13.operation[y].bitwise != BITWISE_DISABLED)
|
||||
{
|
||||
dataRequested = configPage13.secondDataIn[y];
|
||||
if ( dataRequested <= (REUSE_RULES + sizeof(configPage13.outputPin)) ) //Failsafe check
|
||||
if(dataRequested <= (REUSE_RULES + sizeof(configPage13.outputPin))) // Failsafe check
|
||||
{
|
||||
if ( dataRequested > 239U ) //Somehow using 239 uses 9 bytes of RAM, why??
|
||||
if(dataRequested > 239U) // Somehow using 239 uses 9 bytes of RAM, why??
|
||||
{
|
||||
dataRequested -= REUSE_RULES;
|
||||
data = BIT_CHECK(currentRuleStatus, dataRequested);
|
||||
}
|
||||
else { data = ProgrammableIOGetData(dataRequested); }
|
||||
data2 = configPage13.secondTarget[y];
|
||||
|
||||
if ( (configPage13.operation[y].secondCompType == COMPARATOR_EQUAL) && (data == data2) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_NOT_EQUAL) && (data != data2) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_GREATER) && (data > data2) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_GREATER_EQUAL) && (data >= data2) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_LESS) && (data < data2) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_LESS_EQUAL) && (data <= data2) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_AND) && ((data & data2) != 0) ) { secondCheck = true; }
|
||||
else if ( (configPage13.operation[y].secondCompType == COMPARATOR_XOR) && ((data ^ data2) != 0) ) { secondCheck = true; }
|
||||
|
||||
if (configPage13.operation[y].bitwise == BITWISE_AND) { firstCheck &= secondCheck; }
|
||||
if (configPage13.operation[y].bitwise == BITWISE_OR) { firstCheck |= secondCheck; }
|
||||
if (configPage13.operation[y].bitwise == BITWISE_XOR) { firstCheck ^= secondCheck; }
|
||||
if((configPage13.operation[y].secondCompType == COMPARATOR_EQUAL) && (data == data2)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_NOT_EQUAL) && (data != data2)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_GREATER) && (data > data2)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_GREATER_EQUAL) && (data >= data2)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_LESS) && (data < data2)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_LESS_EQUAL) && (data <= data2)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_AND) && ((data & data2) != 0)) { secondCheck = true; }
|
||||
else if((configPage13.operation[y].secondCompType == COMPARATOR_XOR) && ((data ^ data2) != 0)) { secondCheck = true; }
|
||||
|
||||
if(configPage13.operation[y].bitwise == BITWISE_AND) { firstCheck &= secondCheck; }
|
||||
if(configPage13.operation[y].bitwise == BITWISE_OR) { firstCheck |= secondCheck; }
|
||||
if(configPage13.operation[y].bitwise == BITWISE_XOR) { firstCheck ^= secondCheck; }
|
||||
}
|
||||
}
|
||||
|
||||
//If the limiting time is active(>0) and using maximum time
|
||||
if (BIT_CHECK(configPage13.kindOfLimiting, y))
|
||||
// If the limiting time is active(>0) and using maximum time
|
||||
if(BIT_CHECK(configPage13.kindOfLimiting, y))
|
||||
{
|
||||
if(firstCheck)
|
||||
{
|
||||
if ((configPage13.outputTimeLimit[y] != 0) && (ioOutDelay[y] >= configPage13.outputTimeLimit[y])) { firstCheck = false; } //Time has counted, disable the output
|
||||
if((configPage13.outputTimeLimit[y] != 0) && (ioOutDelay[y] >= configPage13.outputTimeLimit[y])) { firstCheck = false; } // Time has counted, disable the output
|
||||
}
|
||||
else
|
||||
{
|
||||
//Released before Maximum time, set delay to maximum to flip the output next
|
||||
// Released before Maximum time, set delay to maximum to flip the output next
|
||||
if(BIT_CHECK(currentStatus.outputsStatus, y)) { ioOutDelay[y] = configPage13.outputTimeLimit[y]; }
|
||||
else { ioOutDelay[y] = 0; } //Reset the counter for next time
|
||||
else { ioOutDelay[y] = 0; } // Reset the counter for next time
|
||||
}
|
||||
}
|
||||
|
||||
if ( (firstCheck == true) && (configPage13.outputDelay[y] < 255) )
|
||||
if((firstCheck == true) && (configPage13.outputDelay[y] < 255))
|
||||
{
|
||||
if (ioDelay[y] >= configPage13.outputDelay[y])
|
||||
if(ioDelay[y] >= configPage13.outputDelay[y])
|
||||
{
|
||||
bool bitStatus = BIT_CHECK(configPage13.outputInverted, y) ^ firstCheck;
|
||||
if (BIT_CHECK(currentStatus.outputsStatus, y) && (ioOutDelay[y] < configPage13.outputTimeLimit[y])) { ioOutDelay[y]++; }
|
||||
if (configPage13.outputPin[y] < 128) { digitalWrite(configPage13.outputPin[y], bitStatus); }
|
||||
if(BIT_CHECK(currentStatus.outputsStatus, y) && (ioOutDelay[y] < configPage13.outputTimeLimit[y])) { ioOutDelay[y]++; }
|
||||
if(configPage13.outputPin[y] < 128) { digitalWrite(configPage13.outputPin[y], bitStatus); }
|
||||
else { BIT_WRITE(currentRuleStatus, y, bitStatus); }
|
||||
BIT_WRITE(currentStatus.outputsStatus, y, bitStatus);
|
||||
}
|
||||
|
@ -237,10 +235,10 @@ void checkProgrammableIO(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (ioOutDelay[y] >= configPage13.outputTimeLimit[y])
|
||||
if(ioOutDelay[y] >= configPage13.outputTimeLimit[y])
|
||||
{
|
||||
bool bitStatus = BIT_CHECK(configPage13.outputInverted, y) ^ firstCheck;
|
||||
if (configPage13.outputPin[y] < 128) { digitalWrite(configPage13.outputPin[y], bitStatus); }
|
||||
if(configPage13.outputPin[y] < 128) { digitalWrite(configPage13.outputPin[y], bitStatus); }
|
||||
else { BIT_WRITE(currentRuleStatus, y, bitStatus); }
|
||||
BIT_WRITE(currentStatus.outputsStatus, y, bitStatus);
|
||||
if(!BIT_CHECK(configPage13.kindOfLimiting, y)) { ioOutDelay[y] = 0; }
|
||||
|
@ -260,7 +258,7 @@ void checkProgrammableIO(void)
|
|||
int16_t ProgrammableIOGetData(uint16_t index)
|
||||
{
|
||||
int16_t result;
|
||||
if ( index < LOG_ENTRY_SIZE )
|
||||
if(index < LOG_ENTRY_SIZE)
|
||||
{
|
||||
/*
|
||||
for(uint8_t x = 0; x<sizeof(fsIntIndex); x++)
|
||||
|
@ -271,14 +269,13 @@ int16_t ProgrammableIOGetData(uint16_t index)
|
|||
if (x >= sizeof(fsIntIndex)) { result = getTSLogEntry(index); } // 8-bit, coerce to 16 bit result
|
||||
else { result = word(getTSLogEntry(index+1), getTSLogEntry(index)); } // Assemble 2 bytes to word of 16 bit result
|
||||
*/
|
||||
if(is2ByteEntry(index)) { result = word(getTSLogEntry(index+1), getTSLogEntry(index)); }
|
||||
if(is2ByteEntry(index)) { result = word(getTSLogEntry(index + 1), getTSLogEntry(index)); }
|
||||
else { result = getTSLogEntry(index); }
|
||||
|
||||
|
||||
//Special cases for temperatures
|
||||
if( (index == 6) || (index == 7) ) { result -= CALIBRATION_TEMPERATURE_OFFSET; }
|
||||
// Special cases for temperatures
|
||||
if((index == 6) || (index == 7)) { result -= CALIBRATION_TEMPERATURE_OFFSET; }
|
||||
}
|
||||
else if ( index == 239U ) { result = (int16_t)max((uint32_t)runSecsX10, (uint32_t)32768); } //STM32 used std lib
|
||||
else { result = -1; } //Index is bigger than fullStatus array
|
||||
else if(index == 239U) { result = (int16_t)max((uint32_t)runSecsX10, (uint32_t)32768); } // STM32 used std lib
|
||||
else { result = -1; } // Index is bigger than fullStatus array
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue