From 977ffa311951d10a764956464cbd1b5a488f9382 Mon Sep 17 00:00:00 2001 From: tx_haggis <13982343+adbancroft@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:07:12 -0500 Subject: [PATCH] MISRA: clean up logger header (#1108) * Move log header definitions inside sd_logger.ino It's the only place they are used. * Convert to CPP - fixes build error * Encapsulate fsIntIndex * MISRA fixes * Convert logger.ino -> cpp * Conditonal compile - reclaim memory --- speeduino/{SD_logger.ino => SD_logger.cpp} | 255 ++++++++++++++++++++ speeduino/SD_logger.h | 8 +- speeduino/init.h | 4 +- speeduino/init.ino | 30 +++ speeduino/{logger.ino => logger.cpp} | 74 +++--- speeduino/logger.h | 266 +-------------------- speeduino/scheduler.h | 8 + speeduino/scheduler.ino | 8 + speeduino/utilities.ino | 11 - 9 files changed, 345 insertions(+), 319 deletions(-) rename speeduino/{SD_logger.ino => SD_logger.cpp} (53%) rename speeduino/{logger.ino => logger.cpp} (91%) diff --git a/speeduino/SD_logger.ino b/speeduino/SD_logger.cpp similarity index 53% rename from speeduino/SD_logger.ino rename to speeduino/SD_logger.cpp index 0b6b9a15..c98b4766 100644 --- a/speeduino/SD_logger.ino +++ b/speeduino/SD_logger.cpp @@ -13,6 +13,261 @@ #include "rtc_common.h" #include "maths.h" +//List of logger field names. This must be in the same order and length as logger_updateLogdataCSV() +constexpr char header_0[] PROGMEM = "secl"; +constexpr char header_1[] PROGMEM = "status1"; +constexpr char header_2[] PROGMEM = "engine"; +constexpr char header_3[] PROGMEM = "Sync Loss #"; +constexpr char header_4[] PROGMEM = "MAP"; +constexpr char header_5[] PROGMEM = "IAT(C)"; +constexpr char header_6[] PROGMEM = "CLT(C)"; +constexpr char header_7[] PROGMEM = "Battery Correction"; +constexpr char header_8[] PROGMEM = "Battery V"; +constexpr char header_9[] PROGMEM = "AFR"; +constexpr char header_10[] PROGMEM = "EGO Correction"; +constexpr char header_11[] PROGMEM = "IAT Correction"; +constexpr char header_12[] PROGMEM = "WUE Correction"; +constexpr char header_13[] PROGMEM = "RPM"; +constexpr char header_14[] PROGMEM = "Accel. Correction"; +constexpr char header_15[] PROGMEM = "Gamma Correction"; +constexpr char header_16[] PROGMEM = "VE1"; +constexpr char header_17[] PROGMEM = "VE2"; +constexpr char header_18[] PROGMEM = "AFR Target"; +constexpr char header_19[] PROGMEM = "TPSdot"; +constexpr char header_20[] PROGMEM = "Advance Current"; +constexpr char header_21[] PROGMEM = "TPS"; +constexpr char header_22[] PROGMEM = "Loops/S"; +constexpr char header_23[] PROGMEM = "Free RAM"; +constexpr char header_24[] PROGMEM = "Boost Target"; +constexpr char header_25[] PROGMEM = "Boost Duty"; +constexpr char header_26[] PROGMEM = "status2"; +constexpr char header_27[] PROGMEM = "rpmDOT"; +constexpr char header_28[] PROGMEM = "Eth%"; +constexpr char header_29[] PROGMEM = "Flex Fuel Correction"; +constexpr char header_30[] PROGMEM = "Flex Adv Correction"; +constexpr char header_31[] PROGMEM = "IAC Steps/Duty"; +constexpr char header_32[] PROGMEM = "testoutputs"; +constexpr char header_33[] PROGMEM = "AFR2"; +constexpr char header_34[] PROGMEM = "Baro"; +constexpr char header_35[] PROGMEM = "AUX_IN 0"; +constexpr char header_36[] PROGMEM = "AUX_IN 1"; +constexpr char header_37[] PROGMEM = "AUX_IN 2"; +constexpr char header_38[] PROGMEM = "AUX_IN 3"; +constexpr char header_39[] PROGMEM = "AUX_IN 4"; +constexpr char header_40[] PROGMEM = "AUX_IN 5"; +constexpr char header_41[] PROGMEM = "AUX_IN 6"; +constexpr char header_42[] PROGMEM = "AUX_IN 7"; +constexpr char header_43[] PROGMEM = "AUX_IN 8"; +constexpr char header_44[] PROGMEM = "AUX_IN 9"; +constexpr char header_45[] PROGMEM = "AUX_IN 10"; +constexpr char header_46[] PROGMEM = "AUX_IN 11"; +constexpr char header_47[] PROGMEM = "AUX_IN 12"; +constexpr char header_48[] PROGMEM = "AUX_IN 13"; +constexpr char header_49[] PROGMEM = "AUX_IN 14"; +constexpr char header_50[] PROGMEM = "AUX_IN 15"; +constexpr char header_51[] PROGMEM = "TPS ADC"; +constexpr char header_52[] PROGMEM = "Errors"; +constexpr char header_53[] PROGMEM = "PW"; +constexpr char header_54[] PROGMEM = "PW2"; +constexpr char header_55[] PROGMEM = "PW3"; +constexpr char header_56[] PROGMEM = "PW4"; +constexpr char header_57[] PROGMEM = "status3"; +constexpr char header_58[] PROGMEM = "Engine Protect"; +constexpr char header_59[] PROGMEM = ""; +constexpr char header_60[] PROGMEM = "Fuel Load"; +constexpr char header_61[] PROGMEM = "Ign Load"; +constexpr char header_62[] PROGMEM = "Dwell Requested"; +constexpr char header_63[] PROGMEM = "Idle Target (RPM)"; +constexpr char header_64[] PROGMEM = "MAP DOT"; +constexpr char header_65[] PROGMEM = "VVT1 Angle"; +constexpr char header_66[] PROGMEM = "VVT1 Target"; +constexpr char header_67[] PROGMEM = "VVT1 Duty"; +constexpr char header_68[] PROGMEM = "Flex Boost Adj"; +constexpr char header_69[] PROGMEM = "Baro Correction"; +constexpr char header_70[] PROGMEM = "VE Current"; +constexpr char header_71[] PROGMEM = "ASE Correction"; +constexpr char header_72[] PROGMEM = "Vehicle Speed"; +constexpr char header_73[] PROGMEM = "Gear"; +constexpr char header_74[] PROGMEM = "Fuel Pressure"; +constexpr char header_75[] PROGMEM = "Oil Pressure"; +constexpr char header_76[] PROGMEM = "WMI PW"; +constexpr char header_77[] PROGMEM = "status4"; +constexpr char header_78[] PROGMEM = "VVT2 Angle"; +constexpr char header_79[] PROGMEM = "VVT2 Target"; +constexpr char header_80[] PROGMEM = "VVT2 Duty"; +constexpr char header_81[] PROGMEM = "outputs"; +constexpr char header_82[] PROGMEM = "Fuel Temp"; +constexpr char header_83[] PROGMEM = "Fuel Temp Correction"; +constexpr char header_84[] PROGMEM = "Advance 1"; +constexpr char header_85[] PROGMEM = "Advance 2"; +constexpr char header_86[] PROGMEM = "SD Status"; +constexpr char header_87[] PROGMEM = "EMAP"; +constexpr char header_88[] PROGMEM = "Fan Duty"; +constexpr char header_89[] PROGMEM = "AirConStatus"; +constexpr char header_90[] PROGMEM = "Dwell Actual"; +/* +constexpr char header_91[] PROGMEM = ""; +constexpr char header_92[] PROGMEM = ""; +constexpr char header_93[] PROGMEM = ""; +constexpr char header_94[] PROGMEM = ""; +constexpr char header_95[] PROGMEM = ""; +constexpr char header_96[] PROGMEM = ""; +constexpr char header_97[] PROGMEM = ""; +constexpr char header_98[] PROGMEM = ""; +constexpr char header_99[] PROGMEM = ""; +constexpr char header_100[] PROGMEM = ""; +constexpr char header_101[] PROGMEM = ""; +constexpr char header_102[] PROGMEM = ""; +constexpr char header_103[] PROGMEM = ""; +constexpr char header_104[] PROGMEM = ""; +constexpr char header_105[] PROGMEM = ""; +constexpr char header_106[] PROGMEM = ""; +constexpr char header_107[] PROGMEM = ""; +constexpr char header_108[] PROGMEM = ""; +constexpr char header_109[] PROGMEM = ""; +constexpr char header_110[] PROGMEM = ""; +constexpr char header_111[] PROGMEM = ""; +constexpr char header_112[] PROGMEM = ""; +constexpr char header_113[] PROGMEM = ""; +constexpr char header_114[] PROGMEM = ""; +constexpr char header_115[] PROGMEM = ""; +constexpr char header_116[] PROGMEM = ""; +constexpr char header_117[] PROGMEM = ""; +constexpr char header_118[] PROGMEM = ""; +constexpr char header_119[] PROGMEM = ""; +constexpr char header_120[] PROGMEM = ""; +constexpr char header_121[] PROGMEM = ""; +*/ + +constexpr const char* header_table[] PROGMEM = { header_0,\ + header_1,\ + header_2,\ + header_3,\ + header_4,\ + header_5,\ + header_6,\ + header_7,\ + header_8,\ + header_9,\ + header_10,\ + header_11,\ + header_12,\ + header_13,\ + header_14,\ + header_15,\ + header_16,\ + header_17,\ + header_18,\ + header_19,\ + header_20,\ + header_21,\ + header_22,\ + header_23,\ + header_24,\ + header_25,\ + header_26,\ + header_27,\ + header_28,\ + header_29,\ + header_30,\ + header_31,\ + header_32,\ + header_33,\ + header_34,\ + header_35,\ + header_36,\ + header_37,\ + header_38,\ + header_39,\ + header_40,\ + header_41,\ + header_42,\ + header_43,\ + header_44,\ + header_45,\ + header_46,\ + header_47,\ + header_48,\ + header_49,\ + header_50,\ + header_51,\ + header_52,\ + header_53,\ + header_54,\ + header_55,\ + header_56,\ + header_57,\ + header_58,\ + header_59,\ + header_60,\ + header_61,\ + header_62,\ + header_63,\ + header_64,\ + header_65,\ + header_66,\ + header_67,\ + header_68,\ + header_69,\ + header_70,\ + header_71,\ + header_72,\ + header_73,\ + header_74,\ + header_75,\ + header_76,\ + header_77,\ + header_78,\ + header_79,\ + header_80,\ + header_81,\ + header_82,\ + header_83,\ + header_84,\ + header_85,\ + header_86,\ + header_87,\ + header_88,\ + header_89,\ + header_90,\ + /* + header_91,\ + header_92,\ + header_93,\ + header_94,\ + header_95,\ + header_96,\ + header_97,\ + header_98,\ + header_99,\ + header_100,\ + header_101,\ + header_102,\ + header_103,\ + header_104,\ + header_105,\ + header_106,\ + header_107,\ + header_108,\ + header_109,\ + header_110,\ + header_111,\ + header_112,\ + header_113,\ + header_114,\ + header_115,\ + header_116,\ + header_117,\ + header_118,\ + header_119,\ + header_120,\ + header_121,\ + */ + }; +#define SD_LOG_NUM_FIELDS 91 /**< The number of fields that are in the log. This is always smaller than the entry size due to some fields being 2 bytes */ + +static_assert(sizeof(header_table) == (sizeof(char*) * SD_LOG_NUM_FIELDS), "Number of header table titles must match number of log fields"); + SdExFat sd; ExFile logFile; RingBuf rb; diff --git a/speeduino/SD_logger.h b/speeduino/SD_logger.h index ddb43bdf..13bb353b 100644 --- a/speeduino/SD_logger.h +++ b/speeduino/SD_logger.h @@ -8,8 +8,6 @@ #else #include "SdFat.h" #endif -#include "logger.h" -//#include #include "RingBuf.h" @@ -43,6 +41,12 @@ #define SD_CS_PIN 10 //This is a made up value for now #endif +#ifndef UNIT_TEST // Scope guard for unit testing + #define SD_LOG_ENTRY_SIZE 127 /**< The size of the live data packet used by the SD card.*/ +#else + #define SD_LOG_ENTRY_SIZE 1 /**< The size of the live data packet used by the SD card.*/ +#endif + //Test values only #define SD_LOG_FILE_SIZE 10000000 //Default 10mb file size #define MAX_LOG_FILES 10000 diff --git a/speeduino/init.h b/speeduino/init.h index 44d57248..46d34329 100644 --- a/speeduino/init.h +++ b/speeduino/init.h @@ -7,7 +7,7 @@ void setPinMapping(byte boardID); void changeHalfToFullSync(void); void changeFullToHalfSync(void); -#define VSS_USES_RPM2() ((configPage2.vssMode > 1) && (pinVSS == pinTrigger2) && !BIT_CHECK(decoderState, BIT_DECODER_HAS_SECONDARY)) // VSS is on the same pin as RPM2 and RPM2 is not used as part of the decoder -#define FLEX_USES_RPM2() ((configPage2.flexEnabled > 0) && (pinFlex == pinTrigger2) && !BIT_CHECK(decoderState, BIT_DECODER_HAS_SECONDARY)) // Same as above, but for Flex sensor +#define VSS_USES_RPM2() ((configPage2.vssMode > 1U) && (pinVSS == pinTrigger2) && !BIT_CHECK(decoderState, BIT_DECODER_HAS_SECONDARY)) // VSS is on the same pin as RPM2 and RPM2 is not used as part of the decoder +#define FLEX_USES_RPM2() ((configPage2.flexEnabled > 0U) && (pinFlex == pinTrigger2) && !BIT_CHECK(decoderState, BIT_DECODER_HAS_SECONDARY)) // Same as above, but for Flex sensor #endif \ No newline at end of file diff --git a/speeduino/init.ino b/speeduino/init.ino index deb61710..305ab927 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -987,8 +987,10 @@ void initialiseAll(void) inj3EndFunction = closeInjector3; inj4StartFunction = openInjector4; inj4EndFunction = closeInjector4; +#if (INJ_CHANNELS >= 5) inj5StartFunction = openInjector5; inj5EndFunction = closeInjector5; +#endif break; case INJ_SEMISEQUENTIAL: @@ -1052,8 +1054,10 @@ void initialiseAll(void) inj3EndFunction = closeInjector3; inj4StartFunction = openInjector4; inj4EndFunction = closeInjector4; +#if (INJ_CHANNELS >= 5) inj5StartFunction = openInjector5; inj5EndFunction = closeInjector5; +#endif } break; @@ -1067,14 +1071,22 @@ void initialiseAll(void) inj3EndFunction = closeInjector3; inj4StartFunction = openInjector4; inj4EndFunction = closeInjector4; +#if (INJ_CHANNELS >= 5) inj5StartFunction = openInjector5; inj5EndFunction = closeInjector5; +#endif +#if (INJ_CHANNELS >= 6) inj6StartFunction = openInjector6; inj6EndFunction = closeInjector6; +#endif +#if (INJ_CHANNELS >= 7) inj7StartFunction = openInjector7; inj7EndFunction = closeInjector7; +#endif +#if (INJ_CHANNELS >= 8) inj8StartFunction = openInjector8; inj8EndFunction = closeInjector8; +#endif break; default: @@ -1087,8 +1099,10 @@ void initialiseAll(void) inj3EndFunction = closeInjector3; inj4StartFunction = openInjector4; inj4EndFunction = closeInjector4; +#if (INJ_CHANNELS >= 5) inj5StartFunction = openInjector5; inj5EndFunction = closeInjector5; +#endif break; } @@ -1118,14 +1132,22 @@ void initialiseAll(void) ign3EndFunction = endCoil1Charge; ign4StartFunction = beginCoil1Charge; ign4EndFunction = endCoil1Charge; +#if (INJ_CHANNELS >= 5) ign5StartFunction = beginCoil1Charge; ign5EndFunction = endCoil1Charge; +#endif +#if (INJ_CHANNELS >= 6) ign6StartFunction = beginCoil1Charge; ign6EndFunction = endCoil1Charge; +#endif +#if (INJ_CHANNELS >= 7) ign7StartFunction = beginCoil1Charge; ign7EndFunction = endCoil1Charge; +#endif +#if (INJ_CHANNELS >= 5) ign8StartFunction = beginCoil1Charge; ign8EndFunction = endCoil1Charge; +#endif break; case IGN_MODE_WASTEDCOP: @@ -3602,14 +3624,22 @@ void changeHalfToFullSync(void) inj3EndFunction = closeInjector3; inj4StartFunction = openInjector4; inj4EndFunction = closeInjector4; +#if (INJ_CHANNELS >= 5) inj5StartFunction = openInjector5; inj5EndFunction = closeInjector5; +#endif +#if (INJ_CHANNELS >= 6) inj6StartFunction = openInjector6; inj6EndFunction = closeInjector6; +#endif +#if (INJ_CHANNELS >= 7) inj7StartFunction = openInjector7; inj7EndFunction = closeInjector7; +#endif +#if (INJ_CHANNELS >= 8) inj8StartFunction = openInjector8; inj8EndFunction = closeInjector8; +#endif switch (configPage2.nCylinders) { diff --git a/speeduino/logger.ino b/speeduino/logger.cpp similarity index 91% rename from speeduino/logger.ino rename to speeduino/logger.cpp index 5ff2befb..86b7867e 100644 --- a/speeduino/logger.ino +++ b/speeduino/logger.cpp @@ -3,6 +3,8 @@ #include "errors.h" #include "decoders.h" #include "init.h" +#include "maths.h" +#include "utilities.h" /** * Returns a numbered byte-field (partial field in case of multi-byte fields) from "current status" structure in the format expected by TunerStudio @@ -26,8 +28,8 @@ byte getTSLogEntry(uint16_t byteNum) 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 = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); break; //mat - case 7: statusValue = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); break; //Coolant ADC + 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 @@ -36,7 +38,7 @@ byte getTSLogEntry(uint16_t byteNum) 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 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 (%) @@ -48,11 +50,11 @@ byte getTSLogEntry(uint16_t byteNum) case 25: statusValue = currentStatus.TPS; break; // TPS (0% to 100%) case 26: - if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;} + if(currentStatus.loopsPerSecond > 60000U) { currentStatus.loopsPerSecond = 60000U;} statusValue = lowByte(currentStatus.loopsPerSecond); break; case 27: - if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;} + if(currentStatus.loopsPerSecond > 60000U) { currentStatus.loopsPerSecond = 60000U;} statusValue = highByte(currentStatus.loopsPerSecond); break; @@ -65,8 +67,8 @@ byte getTSLogEntry(uint16_t byteNum) 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 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 @@ -142,7 +144,7 @@ byte getTSLogEntry(uint16_t byteNum) 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 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; @@ -158,9 +160,9 @@ byte getTSLogEntry(uint16_t byteNum) 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 114: statusValue = lowByte(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 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 (%) @@ -171,6 +173,7 @@ byte getTSLogEntry(uint16_t byteNum) 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; @@ -212,7 +215,7 @@ int16_t getReadableLogEntry(uint16_t logIndex) case 21: statusValue = currentStatus.TPS; break; // TPS (0% to 100%) case 22: - if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;} + if(currentStatus.loopsPerSecond > 60000U) { currentStatus.loopsPerSecond = 60000U;} statusValue = currentStatus.loopsPerSecond; break; @@ -294,6 +297,7 @@ int16_t getReadableLogEntry(uint16_t logIndex) 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; @@ -305,7 +309,7 @@ int16_t getReadableLogEntry(uint16_t logIndex) * @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 FPU_MAX_SIZE >= 32 +#if defined(FPU_MAX_SIZE) && FPU_MAX_SIZE >= 32 //cppcheck-suppress misra-c2012-20.9 float getReadableFloatLogEntry(uint16_t logIndex) { float statusValue = 0.0; @@ -333,46 +337,38 @@ float getReadableFloatLogEntry(uint16_t logIndex) /** * 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; - unsigned int mid, bot; - uint16_t array_size = sizeof(fsIntIndex); + // 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 }; - if (array_size > 0) - { - bot = 0; - mid = array_size; + unsigned int bot = 0U; + unsigned int mid = _countof(fsIntIndex); - while (mid > 1) - { - if (key >= pgm_read_byte( &fsIntIndex[bot + mid / 2]) ) - { - bot += mid++ / 2; - } - mid /= 2; - } - - if (key == pgm_read_byte(&fsIntIndex[bot]) ) + while (mid > 1U) + { + if (key >= pgm_read_byte( &fsIntIndex[bot + mid / 2U]) ) { - isFound = true; + bot += mid++ / 2U; } + mid /= 2U; } - return isFound; + return key == pgm_read_byte(&fsIntIndex[bot]); } void startToothLogger(void) { currentStatus.toothLogEnabled = true; - currentStatus.compositeTriggerUsed = 0; //Safety first (Should never be required) + currentStatus.compositeTriggerUsed = 0U; //Safety first (Should never be required) BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY); - toothHistoryIndex = 0; + toothHistoryIndex = 0U; //Disconnect the standard interrupt and add the logger version detachInterrupt( digitalPinToInterrupt(pinTrigger) ); @@ -403,10 +399,10 @@ void stopToothLogger(void) void startCompositeLogger(void) { - currentStatus.compositeTriggerUsed = 2; + currentStatus.compositeTriggerUsed = 2U; currentStatus.toothLogEnabled = false; //Safety first (Should never be required) BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY); - toothHistoryIndex = 0; + toothHistoryIndex = 0U; //Disconnect the standard interrupt and add the logger version detachInterrupt( digitalPinToInterrupt(pinTrigger) ); @@ -421,7 +417,7 @@ void startCompositeLogger(void) void stopCompositeLogger(void) { - currentStatus.compositeTriggerUsed = 0; + currentStatus.compositeTriggerUsed = 0U; //Disconnect the logger interrupts and attach the normal ones detachInterrupt( digitalPinToInterrupt(pinTrigger) ); @@ -436,10 +432,10 @@ void stopCompositeLogger(void) void startCompositeLoggerTertiary(void) { - currentStatus.compositeTriggerUsed = 3; + currentStatus.compositeTriggerUsed = 3U; currentStatus.toothLogEnabled = false; //Safety first (Should never be required) BIT_CLEAR(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY); - toothHistoryIndex = 0; + toothHistoryIndex = 0U; //Disconnect the standard interrupt and add the logger version detachInterrupt( digitalPinToInterrupt(pinTrigger) ); diff --git a/speeduino/logger.h b/speeduino/logger.h index e35a7e74..62dc123c 100644 --- a/speeduino/logger.h +++ b/speeduino/logger.h @@ -9,22 +9,17 @@ #ifndef LOGGER_H #define LOGGER_H -#include #include "globals.h" // Needed for FPU_MAX_SIZE #ifndef UNIT_TEST // Scope guard for unit testing #define LOG_ENTRY_SIZE 127 /**< The size of the live data packet. This MUST match ochBlockSize setting in the ini file */ - #define SD_LOG_ENTRY_SIZE 127 /**< The size of the live data packet used by the SD card.*/ #else #define LOG_ENTRY_SIZE 1 /**< The size of the live data packet. This MUST match ochBlockSize setting in the ini file */ - #define SD_LOG_ENTRY_SIZE 1 /**< The size of the live data packet used by the SD card.*/ #endif -#define SD_LOG_NUM_FIELDS 91 /**< The number of fields that are in the log. This is always smaller than the entry size due to some fields being 2 bytes */ - byte getTSLogEntry(uint16_t byteNum); int16_t getReadableLogEntry(uint16_t logIndex); -#if FPU_MAX_SIZE >= 32 +#if defined(FPU_MAX_SIZE) && FPU_MAX_SIZE >= 32 //cppcheck-suppress misra-c2012-20.9 float getReadableFloatLogEntry(uint16_t logIndex); #endif bool is2ByteEntry(uint8_t key); @@ -41,263 +36,4 @@ void stopCompositeLoggerTertiary(void); void startCompositeLoggerCams(void); void stopCompositeLoggerCams(void); -// 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 !!!! -const 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 }; - -//List of logger field names. This must be in the same order and length as logger_updateLogdataCSV() -const char header_0[] PROGMEM = "secl"; -const char header_1[] PROGMEM = "status1"; -const char header_2[] PROGMEM = "engine"; -const char header_3[] PROGMEM = "Sync Loss #"; -const char header_4[] PROGMEM = "MAP"; -const char header_5[] PROGMEM = "IAT(C)"; -const char header_6[] PROGMEM = "CLT(C)"; -const char header_7[] PROGMEM = "Battery Correction"; -const char header_8[] PROGMEM = "Battery V"; -const char header_9[] PROGMEM = "AFR"; -const char header_10[] PROGMEM = "EGO Correction"; -const char header_11[] PROGMEM = "IAT Correction"; -const char header_12[] PROGMEM = "WUE Correction"; -const char header_13[] PROGMEM = "RPM"; -const char header_14[] PROGMEM = "Accel. Correction"; -const char header_15[] PROGMEM = "Gamma Correction"; -const char header_16[] PROGMEM = "VE1"; -const char header_17[] PROGMEM = "VE2"; -const char header_18[] PROGMEM = "AFR Target"; -const char header_19[] PROGMEM = "TPSdot"; -const char header_20[] PROGMEM = "Advance Current"; -const char header_21[] PROGMEM = "TPS"; -const char header_22[] PROGMEM = "Loops/S"; -const char header_23[] PROGMEM = "Free RAM"; -const char header_24[] PROGMEM = "Boost Target"; -const char header_25[] PROGMEM = "Boost Duty"; -const char header_26[] PROGMEM = "status2"; -const char header_27[] PROGMEM = "rpmDOT"; -const char header_28[] PROGMEM = "Eth%"; -const char header_29[] PROGMEM = "Flex Fuel Correction"; -const char header_30[] PROGMEM = "Flex Adv Correction"; -const char header_31[] PROGMEM = "IAC Steps/Duty"; -const char header_32[] PROGMEM = "testoutputs"; -const char header_33[] PROGMEM = "AFR2"; -const char header_34[] PROGMEM = "Baro"; -const char header_35[] PROGMEM = "AUX_IN 0"; -const char header_36[] PROGMEM = "AUX_IN 1"; -const char header_37[] PROGMEM = "AUX_IN 2"; -const char header_38[] PROGMEM = "AUX_IN 3"; -const char header_39[] PROGMEM = "AUX_IN 4"; -const char header_40[] PROGMEM = "AUX_IN 5"; -const char header_41[] PROGMEM = "AUX_IN 6"; -const char header_42[] PROGMEM = "AUX_IN 7"; -const char header_43[] PROGMEM = "AUX_IN 8"; -const char header_44[] PROGMEM = "AUX_IN 9"; -const char header_45[] PROGMEM = "AUX_IN 10"; -const char header_46[] PROGMEM = "AUX_IN 11"; -const char header_47[] PROGMEM = "AUX_IN 12"; -const char header_48[] PROGMEM = "AUX_IN 13"; -const char header_49[] PROGMEM = "AUX_IN 14"; -const char header_50[] PROGMEM = "AUX_IN 15"; -const char header_51[] PROGMEM = "TPS ADC"; -const char header_52[] PROGMEM = "Errors"; -const char header_53[] PROGMEM = "PW"; -const char header_54[] PROGMEM = "PW2"; -const char header_55[] PROGMEM = "PW3"; -const char header_56[] PROGMEM = "PW4"; -const char header_57[] PROGMEM = "status3"; -const char header_58[] PROGMEM = "Engine Protect"; -const char header_59[] PROGMEM = ""; -const char header_60[] PROGMEM = "Fuel Load"; -const char header_61[] PROGMEM = "Ign Load"; -const char header_62[] PROGMEM = "Dwell Requested"; -const char header_63[] PROGMEM = "Idle Target (RPM)"; -const char header_64[] PROGMEM = "MAP DOT"; -const char header_65[] PROGMEM = "VVT1 Angle"; -const char header_66[] PROGMEM = "VVT1 Target"; -const char header_67[] PROGMEM = "VVT1 Duty"; -const char header_68[] PROGMEM = "Flex Boost Adj"; -const char header_69[] PROGMEM = "Baro Correction"; -const char header_70[] PROGMEM = "VE Current"; -const char header_71[] PROGMEM = "ASE Correction"; -const char header_72[] PROGMEM = "Vehicle Speed"; -const char header_73[] PROGMEM = "Gear"; -const char header_74[] PROGMEM = "Fuel Pressure"; -const char header_75[] PROGMEM = "Oil Pressure"; -const char header_76[] PROGMEM = "WMI PW"; -const char header_77[] PROGMEM = "status4"; -const char header_78[] PROGMEM = "VVT2 Angle"; -const char header_79[] PROGMEM = "VVT2 Target"; -const char header_80[] PROGMEM = "VVT2 Duty"; -const char header_81[] PROGMEM = "outputs"; -const char header_82[] PROGMEM = "Fuel Temp"; -const char header_83[] PROGMEM = "Fuel Temp Correction"; -const char header_84[] PROGMEM = "Advance 1"; -const char header_85[] PROGMEM = "Advance 2"; -const char header_86[] PROGMEM = "SD Status"; -const char header_87[] PROGMEM = "EMAP"; -const char header_88[] PROGMEM = "Fan Duty"; -const char header_89[] PROGMEM = "AirConStatus"; -const char header_90[] PROGMEM = "Dwell Actual"; -/* -const char header_91[] PROGMEM = ""; -const char header_92[] PROGMEM = ""; -const char header_93[] PROGMEM = ""; -const char header_94[] PROGMEM = ""; -const char header_95[] PROGMEM = ""; -const char header_96[] PROGMEM = ""; -const char header_97[] PROGMEM = ""; -const char header_98[] PROGMEM = ""; -const char header_99[] PROGMEM = ""; -const char header_100[] PROGMEM = ""; -const char header_101[] PROGMEM = ""; -const char header_102[] PROGMEM = ""; -const char header_103[] PROGMEM = ""; -const char header_104[] PROGMEM = ""; -const char header_105[] PROGMEM = ""; -const char header_106[] PROGMEM = ""; -const char header_107[] PROGMEM = ""; -const char header_108[] PROGMEM = ""; -const char header_109[] PROGMEM = ""; -const char header_110[] PROGMEM = ""; -const char header_111[] PROGMEM = ""; -const char header_112[] PROGMEM = ""; -const char header_113[] PROGMEM = ""; -const char header_114[] PROGMEM = ""; -const char header_115[] PROGMEM = ""; -const char header_116[] PROGMEM = ""; -const char header_117[] PROGMEM = ""; -const char header_118[] PROGMEM = ""; -const char header_119[] PROGMEM = ""; -const char header_120[] PROGMEM = ""; -const char header_121[] PROGMEM = ""; -*/ - -const char* const header_table[] PROGMEM = { header_0,\ - header_1,\ - header_2,\ - header_3,\ - header_4,\ - header_5,\ - header_6,\ - header_7,\ - header_8,\ - header_9,\ - header_10,\ - header_11,\ - header_12,\ - header_13,\ - header_14,\ - header_15,\ - header_16,\ - header_17,\ - header_18,\ - header_19,\ - header_20,\ - header_21,\ - header_22,\ - header_23,\ - header_24,\ - header_25,\ - header_26,\ - header_27,\ - header_28,\ - header_29,\ - header_30,\ - header_31,\ - header_32,\ - header_33,\ - header_34,\ - header_35,\ - header_36,\ - header_37,\ - header_38,\ - header_39,\ - header_40,\ - header_41,\ - header_42,\ - header_43,\ - header_44,\ - header_45,\ - header_46,\ - header_47,\ - header_48,\ - header_49,\ - header_50,\ - header_51,\ - header_52,\ - header_53,\ - header_54,\ - header_55,\ - header_56,\ - header_57,\ - header_58,\ - header_59,\ - header_60,\ - header_61,\ - header_62,\ - header_63,\ - header_64,\ - header_65,\ - header_66,\ - header_67,\ - header_68,\ - header_69,\ - header_70,\ - header_71,\ - header_72,\ - header_73,\ - header_74,\ - header_75,\ - header_76,\ - header_77,\ - header_78,\ - header_79,\ - header_80,\ - header_81,\ - header_82,\ - header_83,\ - header_84,\ - header_85,\ - header_86,\ - header_87,\ - header_88,\ - header_89,\ - header_90,\ - /* - header_91,\ - header_92,\ - header_93,\ - header_94,\ - header_95,\ - header_96,\ - header_97,\ - header_98,\ - header_99,\ - header_100,\ - header_101,\ - header_102,\ - header_103,\ - header_104,\ - header_105,\ - header_106,\ - header_107,\ - header_108,\ - header_109,\ - header_110,\ - header_111,\ - header_112,\ - header_113,\ - header_114,\ - header_115,\ - header_116,\ - header_117,\ - header_118,\ - header_119,\ - header_120,\ - header_121,\ - */ - }; - -static_assert(sizeof(header_table) == (sizeof(char*) * SD_LOG_NUM_FIELDS), "Number of header table titles must match number of log fields"); - #endif diff --git a/speeduino/scheduler.h b/speeduino/scheduler.h index b59e4e27..7af2c1d4 100644 --- a/speeduino/scheduler.h +++ b/speeduino/scheduler.h @@ -58,14 +58,22 @@ extern void (*inj3StartFunction)(void); extern void (*inj3EndFunction)(void); extern void (*inj4StartFunction)(void); extern void (*inj4EndFunction)(void); +#if (INJ_CHANNELS >= 5) extern void (*inj5StartFunction)(void); extern void (*inj5EndFunction)(void); +#endif +#if (INJ_CHANNELS >= 6) extern void (*inj6StartFunction)(void); extern void (*inj6EndFunction)(void); +#endif +#if (INJ_CHANNELS >= 7) extern void (*inj7StartFunction)(void); extern void (*inj7EndFunction)(void); +#endif +#if (INJ_CHANNELS >= 8) extern void (*inj8StartFunction)(void); extern void (*inj8EndFunction)(void); +#endif /** @name IgnitionCallbacks * These are the (global) function pointers that get called to begin and end the ignition coil charging. diff --git a/speeduino/scheduler.ino b/speeduino/scheduler.ino index a649fb37..c38dd3b7 100644 --- a/speeduino/scheduler.ino +++ b/speeduino/scheduler.ino @@ -56,14 +56,22 @@ void (*inj3StartFunction)(void); void (*inj3EndFunction)(void); void (*inj4StartFunction)(void); void (*inj4EndFunction)(void); +#if (INJ_CHANNELS >= 5) void (*inj5StartFunction)(void); void (*inj5EndFunction)(void); +#endif +#if (INJ_CHANNELS >= 6) void (*inj6StartFunction)(void); void (*inj6EndFunction)(void); +#endif +#if (INJ_CHANNELS >= 7) void (*inj7StartFunction)(void); void (*inj7EndFunction)(void); +#endif +#if (INJ_CHANNELS >= 8) void (*inj8StartFunction)(void); void (*inj8EndFunction)(void); +#endif void (*ign1StartFunction)(void); void (*ign1EndFunction)(void); diff --git a/speeduino/utilities.ino b/speeduino/utilities.ino index cf17b41e..aa76381b 100644 --- a/speeduino/utilities.ino +++ b/speeduino/utilities.ino @@ -253,7 +253,6 @@ void checkProgrammableIO(void) } } /** Get single I/O data var (from currentStatus) for comparison. - * Uses member offset index @ref fsIntIndex to lookup realtime 'live' data from @ref currentStatus. * @param index - Field index/number (?) * @return 16 bit (int) result */ @@ -262,19 +261,9 @@ int16_t ProgrammableIOGetData(uint16_t index) int16_t result; if ( index < LOG_ENTRY_SIZE ) { - /* - for(uint8_t x = 0; 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)); } else { result = getTSLogEntry(index); } - //Special cases for temperatures if( (index == 6) || (index == 7) ) { result -= CALIBRATION_TEMPERATURE_OFFSET; } }