speeduino/speeduino/logger.cpp

634 lines
36 KiB
C++

#include "globals.h"
#include "logger.h"
#include "errors.h"
#include "decoders.h"
#include "init.h"
#include "maths.h"
#include "utilities.h"
#include BOARD_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
* 2nd field in struct)
* - The fields stored in multi-byte types will be accessed lowbyte and highbyte separately (e.g. PW1 will be broken into numbered byte-fields 75,76)
* - Values have the value offsets and shifts expected by TunerStudio. They will not all be a 'human readable value'
* @param byteNum - byte-Field number. This is not the entry number (As some entries have multiple byets), but the byte number that is needed
* @return Field value in 1 byte size struct fields or 1 byte partial value (chunk) on multibyte fields.
*/
byte getTSLogEntry(uint16_t byteNum)
{
byte statusValue = 0;
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 3: statusValue = currentStatus.syncLossCounter; break;
case 4: statusValue = lowByte(currentStatus.MAP); break; //2 bytes for MAP
case 5: statusValue = highByte(currentStatus.MAP); break;
case 6: statusValue = lowByte(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); break; //mat
case 7: statusValue = lowByte(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 = lowByte(currentStatus.AEamount >> 1U); 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 24: statusValue = currentStatus.advance; break;
case 25: statusValue = currentStatus.TPS; break; // TPS (0% to 100%)
case 26:
if(currentStatus.loopsPerSecond > 60000U) { currentStatus.loopsPerSecond = 60000U;}
statusValue = lowByte(currentStatus.loopsPerSecond);
break;
case 27:
if(currentStatus.loopsPerSecond > 60000U) { currentStatus.loopsPerSecond = 60000U;}
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);
break;
case 30: statusValue = lowByte(currentStatus.boostTarget >> 1U); break; //Divide boost target by 2 to fit in a byte
case 31: statusValue = lowByte(div100(currentStatus.boostDuty)); break;
case 32: statusValue = currentStatus.spark; break; //Spark related bitfield
//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 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 42: statusValue = lowByte(currentStatus.canin[0]); break;
case 43: statusValue = highByte(currentStatus.canin[0]); break;
case 44: statusValue = lowByte(currentStatus.canin[1]); break;
case 45: statusValue = highByte(currentStatus.canin[1]); break;
case 46: statusValue = lowByte(currentStatus.canin[2]); break;
case 47: statusValue = highByte(currentStatus.canin[2]); break;
case 48: statusValue = lowByte(currentStatus.canin[3]); break;
case 49: statusValue = highByte(currentStatus.canin[3]); break;
case 50: statusValue = lowByte(currentStatus.canin[4]); break;
case 51: statusValue = highByte(currentStatus.canin[4]); break;
case 52: statusValue = lowByte(currentStatus.canin[5]); break;
case 53: statusValue = highByte(currentStatus.canin[5]); break;
case 54: statusValue = lowByte(currentStatus.canin[6]); break;
case 55: statusValue = highByte(currentStatus.canin[6]); break;
case 56: statusValue = lowByte(currentStatus.canin[7]); break;
case 57: statusValue = highByte(currentStatus.canin[7]); break;
case 58: statusValue = lowByte(currentStatus.canin[8]); break;
case 59: statusValue = highByte(currentStatus.canin[8]); break;
case 60: statusValue = lowByte(currentStatus.canin[9]); break;
case 61: statusValue = highByte(currentStatus.canin[9]); break;
case 62: statusValue = lowByte(currentStatus.canin[10]); break;
case 63: statusValue = highByte(currentStatus.canin[10]); break;
case 64: statusValue = lowByte(currentStatus.canin[11]); break;
case 65: statusValue = highByte(currentStatus.canin[11]); break;
case 66: statusValue = lowByte(currentStatus.canin[12]); break;
case 67: statusValue = highByte(currentStatus.canin[12]); break;
case 68: statusValue = lowByte(currentStatus.canin[13]); break;
case 69: statusValue = highByte(currentStatus.canin[13]); break;
case 70: statusValue = lowByte(currentStatus.canin[14]); break;
case 71: statusValue = highByte(currentStatus.canin[14]); break;
case 72: statusValue = lowByte(currentStatus.canin[15]); break;
case 73: statusValue = highByte(currentStatus.canin[15]); break;
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 84: statusValue = currentStatus.status3; break;
case 85: statusValue = currentStatus.engineProtectStatus; break;
case 86: statusValue = lowByte(currentStatus.fuelLoad); break;
case 87: statusValue = highByte(currentStatus.fuelLoad); break;
case 88: statusValue = lowByte(currentStatus.ignLoad); break;
case 89: statusValue = highByte(currentStatus.ignLoad); break;
case 90: statusValue = lowByte(currentStatus.dwell); break;
case 91: statusValue = highByte(currentStatus.dwell); break;
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 96: statusValue = highByte(currentStatus.vvt1Angle); break;
case 97: statusValue = currentStatus.vvt1TargetAngle; break;
case 98: statusValue = lowByte(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 104: statusValue = lowByte(currentStatus.vss); break;
case 105: statusValue = highByte(currentStatus.vss); break;
case 106: statusValue = currentStatus.gear; break;
case 107: statusValue = currentStatus.fuelPressure; break;
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 112: statusValue = highByte(currentStatus.vvt2Angle); break;
case 113: statusValue = currentStatus.vvt2TargetAngle; break;
case 114: statusValue = lowByte(currentStatus.vvt2Duty); break;
case 115: statusValue = currentStatus.outputsStatus; break;
case 116: statusValue = lowByte(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;
case 125: statusValue = lowByte(currentStatus.actualDwell); break;
case 126: statusValue = highByte(currentStatus.actualDwell); break;
default: statusValue = 0; // MISRA check
}
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
* @return Raw, unadjusted value of the log entry. No offset or multiply is applied like it is with the TS log
*/
int16_t getReadableLogEntry(uint16_t logIndex)
{
int16_t statusValue = 0;
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 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 18: statusValue = currentStatus.afrTarget; break;
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 > 60000U) { currentStatus.loopsPerSecond = 60000U;}
statusValue = currentStatus.loopsPerSecond;
break;
case 23:
currentStatus.freeRAM = freeRam();
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 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 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 35: statusValue = currentStatus.canin[0]; break;
case 36: statusValue = currentStatus.canin[1]; break;
case 37: statusValue = currentStatus.canin[2]; break;
case 38: statusValue = currentStatus.canin[3]; break;
case 39: statusValue = currentStatus.canin[4]; break;
case 40: statusValue = currentStatus.canin[5]; break;
case 41: statusValue = currentStatus.canin[6]; break;
case 42: statusValue = currentStatus.canin[7]; break;
case 43: statusValue = currentStatus.canin[8]; break;
case 44: statusValue = currentStatus.canin[9]; break;
case 45: statusValue = currentStatus.canin[10]; break;
case 46: statusValue = currentStatus.canin[11]; break;
case 47: statusValue = currentStatus.canin[12]; break;
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 57: statusValue = currentStatus.status3; break;
case 58: statusValue = currentStatus.engineProtectStatus; break;
case 59: break; //UNUSED!!
case 60: statusValue = currentStatus.fuelLoad; break;
case 61: statusValue = currentStatus.ignLoad; break;
case 62: statusValue = (int16_t)currentStatus.dwell; break;
case 63: statusValue = currentStatus.CLIdleTarget; break;
case 64: statusValue = currentStatus.mapDOT; break;
case 65: statusValue = currentStatus.vvt1Angle; break;
case 66: statusValue = currentStatus.vvt1TargetAngle; break;
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 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 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 87: statusValue = currentStatus.EMAP; break;
case 88: statusValue = currentStatus.fanDuty; break;
case 89: statusValue = currentStatus.airConStatus; break;
case 90: statusValue = currentStatus.actualDwell; break;
default: statusValue = 0; // MISRA check
}
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.
*/
#if defined(FPU_MAX_SIZE) && FPU_MAX_SIZE >= 32 //cppcheck-suppress misra-c2012-20.9
float getReadableFloatLogEntry(uint16_t logIndex)
{
float statusValue = 0.0;
switch(logIndex)
{
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 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
}
return statusValue;
}
#endif
uint8_t getLegacySecondarySerialLogEntry(uint16_t byteNum)
{
uint8_t statusValue = 0;
currentStatus.spark ^= (-currentStatus.hasSync ^ currentStatus.spark) & (1U << BIT_SPARK_SYNC); //Set the sync bit of the Spark variable to match the hasSync variable
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, inj1Status(0), inj2Status(1), inj3Status(2), inj4Status(3), DFCOOn(4), boostCutFuel(5), toothLog1Ready(6), toothLog2Ready(7)
case 2: statusValue = currentStatus.engine; break; //Engine Status Bitfield, running(0), crank(1), ase(2), warmup(3), tpsaccaen(4), tpsacden(5), mapaccaen(6), mapaccden(7)
case 3: statusValue = (byte)div100(currentStatus.dwell); break; //Dwell in ms * 10
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 = currentStatus.AEamount; break; //acceleration enrichment (%)
case 17: statusValue = currentStatus.corrections; break; //Total GammaE (%)
case 18: statusValue = currentStatus.VE; break; //Current VE 1 (%)
case 19: statusValue = currentStatus.afrTarget; break;
case 20: statusValue = lowByte(currentStatus.PW1); break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
case 21: statusValue = highByte(currentStatus.PW1); break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
case 22: statusValue = (uint8_t)(currentStatus.tpsDOT / 10); break; //TPS DOT
case 23: statusValue = currentStatus.advance; break;
case 24: statusValue = currentStatus.TPS; break; // TPS (0% to 100%)
case 25: statusValue = lowByte(currentStatus.loopsPerSecond); break;
case 26: statusValue = highByte(currentStatus.loopsPerSecond); break;
case 27: currentStatus.freeRAM = freeRam(); statusValue = lowByte(currentStatus.freeRAM); break; //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF); break;
case 28: currentStatus.freeRAM = freeRam(); statusValue = highByte(currentStatus.freeRAM); break;
case 29: statusValue = (byte)(currentStatus.boostTarget >> 1); break; //Divide boost target by 2 to fit in a byte
case 30: statusValue = (byte)(currentStatus.boostDuty / 100); break;
case 31: statusValue = currentStatus.spark; break; //Spark related bitfield, launchHard(0), launchSoft(1), hardLimitOn(2), softLimitOn(3), boostCutSpark(4), error(5), idleControlOn(6), sync(7)
case 32: statusValue = lowByte(currentStatus.rpmDOT); break;
case 33: statusValue = highByte(currentStatus.rpmDOT); break;
case 34: statusValue = currentStatus.ethanolPct; break; //Flex sensor value (or 0 if not used)
case 35: statusValue = currentStatus.flexCorrection; break; //Flex fuel correction (% above or below 100)
case 36: statusValue = currentStatus.flexIgnCorrection; break; //Ignition correction (Increased degrees of advance) for flex fuel
case 37: statusValue = currentStatus.idleLoad; break;
case 38: statusValue = currentStatus.testOutputs; break; // testEnabled(0), testActive(1)
case 39: statusValue = currentStatus.O2_2; break; //O2
case 40: statusValue = currentStatus.baro; break; //Barometer value
case 41: statusValue = lowByte(currentStatus.canin[0]); break;
case 42: statusValue = highByte(currentStatus.canin[0]); break;
case 43: statusValue = lowByte(currentStatus.canin[1]); break;
case 44: statusValue = highByte(currentStatus.canin[1]); break;
case 45: statusValue = lowByte(currentStatus.canin[2]); break;
case 46: statusValue = highByte(currentStatus.canin[2]); break;
case 47: statusValue = lowByte(currentStatus.canin[3]); break;
case 48: statusValue = highByte(currentStatus.canin[3]); break;
case 49: statusValue = lowByte(currentStatus.canin[4]); break;
case 50: statusValue = highByte(currentStatus.canin[4]); break;
case 51: statusValue = lowByte(currentStatus.canin[5]); break;
case 52: statusValue = highByte(currentStatus.canin[5]); break;
case 53: statusValue = lowByte(currentStatus.canin[6]); break;
case 54: statusValue = highByte(currentStatus.canin[6]); break;
case 55: statusValue = lowByte(currentStatus.canin[7]); break;
case 56: statusValue = highByte(currentStatus.canin[7]); break;
case 57: statusValue = lowByte(currentStatus.canin[8]); break;
case 58: statusValue = highByte(currentStatus.canin[8]); break;
case 59: statusValue = lowByte(currentStatus.canin[9]); break;
case 60: statusValue = highByte(currentStatus.canin[9]); break;
case 61: statusValue = lowByte(currentStatus.canin[10]); break;
case 62: statusValue = highByte(currentStatus.canin[10]); break;
case 63: statusValue = lowByte(currentStatus.canin[11]); break;
case 64: statusValue = highByte(currentStatus.canin[11]); break;
case 65: statusValue = lowByte(currentStatus.canin[12]); break;
case 66: statusValue = highByte(currentStatus.canin[12]); break;
case 67: statusValue = lowByte(currentStatus.canin[13]); break;
case 68: statusValue = highByte(currentStatus.canin[13]); break;
case 69: statusValue = lowByte(currentStatus.canin[14]); break;
case 70: statusValue = highByte(currentStatus.canin[14]); break;
case 71: statusValue = lowByte(currentStatus.canin[15]); break;
case 72: statusValue = highByte(currentStatus.canin[15]); break;
case 73: statusValue = currentStatus.tpsADC; break;
case 74: statusValue = getNextError(); break; // errorNum (0:1), currentError(2:7)
case 75: statusValue = currentStatus.launchCorrection; break;
case 76: statusValue = lowByte(currentStatus.PW2); break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
case 77: statusValue = highByte(currentStatus.PW2); break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS.
case 78: statusValue = lowByte(currentStatus.PW3); break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
case 79: statusValue = highByte(currentStatus.PW3); break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS.
case 80: statusValue = lowByte(currentStatus.PW4); break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
case 81: statusValue = highByte(currentStatus.PW4); break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
case 82: statusValue = currentStatus.status3; break; // resentLockOn(0), nitrousOn(1), fuel2Active(2), vssRefresh(3), halfSync(4), nSquirts(6:7)
case 83: statusValue = currentStatus.engineProtectStatus; break; //RPM(0), MAP(1), OIL(2), AFR(3), Unused(4:7)
case 84: statusValue = lowByte(currentStatus.fuelLoad); break;
case 85: statusValue = highByte(currentStatus.fuelLoad); break;
case 86: statusValue = lowByte(currentStatus.ignLoad); break;
case 87: statusValue = highByte(currentStatus.ignLoad); break;
case 88: statusValue = lowByte(currentStatus.injAngle); break;
case 89: statusValue = highByte(currentStatus.injAngle); break;
case 90: statusValue = currentStatus.idleLoad; break;
case 91: statusValue = currentStatus.CLIdleTarget; break; //closed loop idle target
case 92: statusValue = (uint8_t)(currentStatus.mapDOT / 10); break; //rate of change of the map
case 93: statusValue = (int8_t)currentStatus.vvt1Angle; break;
case 94: statusValue = currentStatus.vvt1TargetAngle; break;
case 95: statusValue = currentStatus.vvt1Duty; break;
case 96: statusValue = lowByte(currentStatus.flexBoostCorrection); break;
case 97: statusValue = highByte(currentStatus.flexBoostCorrection); break;
case 98: statusValue = currentStatus.baroCorrection; break;
case 99: statusValue = currentStatus.ASEValue; break; //Current ASE (%)
case 100: statusValue = lowByte(currentStatus.vss); break; //speed reading from the speed sensor
case 101: statusValue = highByte(currentStatus.vss); break;
case 102: statusValue = currentStatus.gear; break;
case 103: statusValue = currentStatus.fuelPressure; break;
case 104: statusValue = currentStatus.oilPressure; break;
case 105: statusValue = currentStatus.wmiPW; break;
case 106: statusValue = currentStatus.status4; break; // wmiEmptyBit(0), vvt1Error(1), vvt2Error(2), fanStatus(3), UnusedBits(4:7)
case 107: statusValue = (int8_t)currentStatus.vvt2Angle; break;
case 108: statusValue = currentStatus.vvt2TargetAngle; break;
case 109: statusValue = currentStatus.vvt2Duty; break;
case 110: statusValue = currentStatus.outputsStatus; break;
case 111: statusValue = (byte)(currentStatus.fuelTemp + CALIBRATION_TEMPERATURE_OFFSET); break; //Fuel temperature from flex sensor
case 112: statusValue = currentStatus.fuelTempCorrection; break; //Fuel temperature Correction (%)
case 113: statusValue = currentStatus.VE1; break; //VE 1 (%)
case 114: statusValue = currentStatus.VE2; break; //VE 2 (%)
case 115: statusValue = currentStatus.advance1; break; //advance 1
case 116: statusValue = currentStatus.advance2; break; //advance 2
case 117: statusValue = currentStatus.nitrous_status; break;
case 118: statusValue = currentStatus.TS_SD_Status; break; //SD card status
case 119: statusValue = lowByte(currentStatus.EMAP); break; //2 bytes for EMAP
case 120: statusValue = highByte(currentStatus.EMAP); break;
case 121: statusValue = currentStatus.fanDuty; break;
case 122: statusValue = currentStatus.airConStatus; break;
}
return statusValue;
}
/**
* 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
*
* @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)
{
// This array indicates which index values from the log are 2 byte values
// This array MUST remain in ascending order
// !!!! WARNING: If any value above 255 is required in this array, changes MUST be made to is2ByteEntry() function !!!!
static constexpr byte PROGMEM fsIntIndex[] = {4, 14, 17, 22, 26, 28, 33, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 76, 78, 80, 82, 86, 88, 90, 93, 95, 99, 104, 111, 121, 125 };
unsigned int bot = 0U;
unsigned int mid = _countof(fsIntIndex);
while (mid > 1U)
{
if (key >= pgm_read_byte( &fsIntIndex[bot + mid / 2U]) )
{
bot += mid++ / 2U;
}
mid /= 2U;
}
return key == pgm_read_byte(&fsIntIndex[bot]);
}
void startToothLogger(void)
{
currentStatus.toothLogEnabled = true;
currentStatus.compositeTriggerUsed = 0U; //Safety first (Should never be required)
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
toothHistoryIndex = 0U;
//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 );
}
}
void stopToothLogger(void)
{
currentStatus.toothLogEnabled = false;
//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 );
}
}
void startCompositeLogger(void)
{
currentStatus.compositeTriggerUsed = 2U;
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
toothHistoryIndex = 0U;
//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) )
{
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
attachInterrupt( digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, CHANGE );
}
}
void stopCompositeLogger(void)
{
currentStatus.compositeTriggerUsed = 0U;
//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) )
{
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
attachInterrupt( digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge );
}
}
void startCompositeLoggerTertiary(void)
{
currentStatus.compositeTriggerUsed = 3U;
currentStatus.toothLogEnabled = false; //Safety first (Should never be required)
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY);
toothHistoryIndex = 0U;
//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 );
}
void stopCompositeLoggerTertiary(void)
{
currentStatus.compositeTriggerUsed = 0;
//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 );
}
void startCompositeLoggerCams(void)
{
currentStatus.compositeTriggerUsed = 4;
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) )
{
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
attachInterrupt( digitalPinToInterrupt(pinTrigger2), loggerSecondaryISR, 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) )
{
detachInterrupt( digitalPinToInterrupt(pinTrigger2) );
attachInterrupt( digitalPinToInterrupt(pinTrigger2), triggerSecondaryHandler, secondaryTriggerEdge );
}
detachInterrupt( digitalPinToInterrupt(pinTrigger3) );
attachInterrupt( digitalPinToInterrupt(pinTrigger3), triggerTertiaryHandler, tertiaryTriggerEdge );
}