Enhanced programmable outputs (#589)

* Enhanced programmable outputs

Added possibility to set minimum programmable output time.

Added names for the comparators to make it more user friendly, TS will complain about the change for existing tune.

Added more possibilities

Added possibility to set a minimum or a maximum output time

Added possibility to combine any number of rules or all of them

I got a lot of requests for this feature.

Keeps the RAM usage the same.

fix

* Fixed maximum timing

* Fix STM32 build
This commit is contained in:
Vitor Moreno B. Sales 2021-07-18 20:11:04 -03:00 committed by GitHub
parent 0e3514980e
commit 118e3d40a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 207 additions and 206 deletions

View File

@ -71,13 +71,22 @@
#define all_IO_Pins = "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID"
#define IO_Pins_no_def = "INVALID", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID"
#define bitwise_def = "Disabled", "AND", "OR", "XOR"
#define comparator_def = "==", "!=", ">", ">=", "<", "<=", "INVALID", "INVALID"
#define comp_IO_Pins = "Disabled", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID"
#define fullStatus_def_1= "seconds", "status bits", "Engine status", "syncLossCounter", "MAP (Kpa)", "INVALID", "IAT / MAT", "coolant", "batCorrection", "battery voltage x10", "O2", "egoCorrection", "iatCorrection", "wueCorrection", "RPM", "INVALID", "AEamount/2", "GammaE", "INVALID", "VE1", "VE2", "AFR Target", "TPS DOT", "Advance", "TPS", "loopsPerSecond", "INVALID", "free RAM", "INVALID", "boostTarget/2", "Boost duty", "spark bits", "RPM DOT"
#define fullStatus_def_2= "INVALID", "ethanolPct", "flexCorrection", "flexIgnCorrection", "idle Load", "testOutputs", "O2_2", "baro", "Aux in 1", "INVALID", "Aux in 2", "INVALID", "Aux in 3", "INVALID", "Aux in 4", "INVALID", "Aux in 5", "INVALID", "Aux in 6", "INVALID", "Aux in 7", "INVALID", "Aux in 8", "INVALID", "Aux in 9", "INVALID", "Aux in 10", "INVALID", "Aux in 11", "INVALID", "Aux in 12", "INVALID", "Aux in 13", "INVALID", "Aux in 14"
#define fullStatus_def_3= "INVALID", "Aux in 15", "INVALID", "Aux in 16", "INVALID", "TPS ADC", "Error code", "Pulsewidth 1", "INVALID", "Pulsewidth 2", "INVALID", "Pulsewidth 3", "INVALID", "Pulsewidth 4", "INVALID", "status bits 3", "engineProtectStatus", "Fuel load", "INVALID", "Ignition load", "INVALID", "dwell", "INVALID", "idle C.L. target", "MAP DOT", "VVT1 Angle", "VVT1 Target", "VVT1 duty", "flexBoostCorrection", "INVALID", "baro Correction"
#define fullStatus_def_4= "Current VE", "ASE Value", "vss", "INVALID", "Gear", "Fuel Pressure", "Oil Pressure", "INVALID", "WMI duty", "WMI empty", "VVT2 angle", "VVT2 target", "VVT2 duty", "outputs status", "Fuel temp", "Fuel temp correction", "Advance 1", "Advance 2"
#define fullStatus_def = $fullStatus_def_1, $fullStatus_def_2, $fullStatus_def_3, $fullStatus_def_4
#define comparator_def = "== (equal)", "!= (different)", "> (greater)", ">= (greater/equal)", "< (smaller)", "<= (smaller/equal)", "& (and)", "^ (xor)"
#define comp_IO_Pins_0 = "Disabled", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID"
#define comp_IO_Pins_1 = "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define comp_IO_Pins_2 = "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define comp_IO_Pins_3 = "Virtual" ;128th
#define comp_IO_Pins = $comp_IO_Pins_0, $comp_IO_Pins_1, $comp_IO_Pins_2, $comp_IO_Pins_3
;All definitions of splited fullStatus should keep 32 options
#define fullStatus_def_1= "seconds", "status bits", "Engine status", "syncLossCounter", "MAP (Kpa)", "INVALID", "IAT / MAT", "coolant", "batCorrection", "battery voltage x10", "O2", "egoCorrection", "iatCorrection", "wueCorrection", "RPM", "INVALID", "AEamount/2", "GammaE", "INVALID", "VE1", "VE2", "AFR Target", "TPS DOT", "Advance", "TPS", "loopsPerSecond", "INVALID", "free RAM", "INVALID", "boostTarget/2", "Boost duty", "spark bits"
#define fullStatus_def_2= "RPM DOT", "INVALID", "ethanolPct", "flexCorrection", "flexIgnCorrection", "idle Load", "testOutputs", "O2_2", "baro", "Aux in 1", "INVALID", "Aux in 2", "INVALID", "Aux in 3", "INVALID", "Aux in 4", "INVALID", "Aux in 5", "INVALID", "Aux in 6", "INVALID", "Aux in 7", "INVALID", "Aux in 8", "INVALID", "Aux in 9", "INVALID", "Aux in 10", "INVALID", "Aux in 11", "INVALID", "Aux in 12"
#define fullStatus_def_3= "INVALID", "Aux in 13", "INVALID", "Aux in 14", "INVALID", "Aux in 15", "INVALID", "Aux in 16", "INVALID", "TPS ADC", "Error code", "Pulsewidth 1", "INVALID", "Pulsewidth 2", "INVALID", "Pulsewidth 3", "INVALID", "Pulsewidth 4", "INVALID", "status bits 3", "engineProtectStatus", "Fuel load", "INVALID", "Ignition load", "INVALID", "dwell", "INVALID", "idle C.L. target", "MAP DOT", "VVT1 Angle", "VVT1 Target", "VVT1 duty"
#define fullStatus_def_4= "flexBoostCorrection", "INVALID", "baro correction", "Current VE", "ASE Value", "vss", "INVALID", "Gear", "Fuel Pressure", "Oil Pressure", "WMI duty", "WMI empty", "VVT2 angle", "VVT2 target", "VVT2 duty", "outputs status", "Fuel temp", "Fuel temp correction", "Advance 1", "Advance 2", "SD status", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def_6= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def_7= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def_8= "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "running seconds x10", "Rule 1", "Rule 2", "Rule 3", "Rule 4", "Rule 5", "Rule 6", "Rule 7", "Rule 8", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define fullStatus_def = $fullStatus_def_1, $fullStatus_def_2, $fullStatus_def_3, $fullStatus_def_4, $fullStatus_def_5, $fullStatus_def_6, $fullStatus_def_7, $fullStatus_def_8
boostTableLabels = bits, U08, [0:1], "Duty Cycle %", "kPa"
boostByGearLabels = bits, U08, [0:1], "", "%", "kPa", ""
@ -1203,7 +1212,14 @@ page = 13
outputInverted5 = bits, U08, 0, [5:5], "Active high", "Active low"
outputInverted6 = bits, U08, 0, [6:6], "Active high", "Active low"
outputInverted7 = bits, U08, 0, [7:7], "Active high", "Active low"
unused12_1 = scalar, U08, 1, "bits", 1.000, 0.000
kindOfLimiting0 = bits, U08, 1, [0:0], "Minimum", "Maximum"
kindOfLimiting1 = bits, U08, 1, [1:1], "Minimum", "Maximum"
kindOfLimiting2 = bits, U08, 1, [2:2], "Minimum", "Maximum"
kindOfLimiting3 = bits, U08, 1, [3:3], "Minimum", "Maximum"
kindOfLimiting4 = bits, U08, 1, [4:4], "Minimum", "Maximum"
kindOfLimiting5 = bits, U08, 1, [5:5], "Minimum", "Maximum"
kindOfLimiting6 = bits, U08, 1, [6:6], "Minimum", "Maximum"
kindOfLimiting7 = bits, U08, 1, [7:7], "Minimum", "Maximum"
outputPin = array, U08, 2, [ 8], "", 1.0, 0.0, 0.0, 255.0, 0
outputPin0 = bits, U08, 2, [0:7], $comp_IO_Pins
outputPin1 = bits, U08, 3, [0:7], $comp_IO_Pins
@ -1232,7 +1248,8 @@ page = 13
secondDataIn5= bits, U08, 31, [0:7], $fullStatus_def
secondDataIn6= bits, U08, 32, [0:7], $fullStatus_def
secondDataIn7= bits, U08, 33, [0:7], $fullStatus_def
unused13_35_49 = array, U08, 34, [ 16] "%", 1.0, 0.0, 0.0, 100.0, 0
outputTimeLimit = array, U08, 34, [ 8], "S", 0.1, 0.0, 0.0, 25.5, 1
unused13_35_49 = array, U08, 42, [ 8] "%", 1.0, 0.0, 0.0, 100.0, 0
firstTarget = array, S16, 50, [ 8], "", 1.0, 0.0, -32768.0, 32768.0, 0
secondTarget = array, S16, 66, [ 8], "", 1.0, 0.0, -32768.0, 32768.0, 0
firstCompType0 = bits, U08, 82, [0:2], $comparator_def
@ -3590,173 +3607,6 @@ menuDialog = main
displayOnlyField = "Programmable out 7", outputPin6, {outputPin[6]}
displayOnlyField = "Programmable out 8", outputPin7, {outputPin[7]}
dialog = prgm_out_pin_selection_1, "", yAxis
field = ""
field = "", outputInverted0, {outputPin[0]}
field = "", outputInverted1, {outputPin[1]}
field = "", outputInverted2, {outputPin[2]}
field = "", outputInverted3, {outputPin[3]}
field = "", outputInverted4, {outputPin[4]}
field = "", outputInverted5, {outputPin[5]}
field = "", outputInverted6, {outputPin[6]}
field = "", outputInverted7, {outputPin[7]}
dialog = prgm_out_pin_selection_2, "", yAxis
field = ""
field = "if(", firstDataIn0, {outputPin[0]}
field = "if(", firstDataIn1, {outputPin[1]}
field = "if(", firstDataIn2, {outputPin[2]}
field = "if(", firstDataIn3, {outputPin[3]}
field = "if(", firstDataIn4, {outputPin[4]}
field = "if(", firstDataIn5, {outputPin[5]}
field = "if(", firstDataIn6, {outputPin[6]}
field = "if(", firstDataIn7, {outputPin[7]}
dialog = prgm_out_pin_selection_3, "", yAxis
field = ""
field = "", firstCompType0, {outputPin[0]}
field = "", firstCompType1, {outputPin[1]}
field = "", firstCompType2, {outputPin[2]}
field = "", firstCompType3, {outputPin[3]}
field = "", firstCompType4, {outputPin[4]}
field = "", firstCompType5, {outputPin[5]}
field = "", firstCompType6, {outputPin[6]}
field = "", firstCompType7, {outputPin[7]}
dialog = prgm_out_pin_selection_4, "", yAxis
field = ""
field = "", firstTarget[0], {outputPin[0]}
field = "", firstTarget[1], {outputPin[1]}
field = "", firstTarget[2], {outputPin[2]}
field = "", firstTarget[3], {outputPin[3]}
field = "", firstTarget[4], {outputPin[4]}
field = "", firstTarget[5], {outputPin[5]}
field = "", firstTarget[6], {outputPin[6]}
field = "", firstTarget[7], {outputPin[7]}
dialog = prgm_out_pin_selection_5, "", yAxis
field = ""
field = "if(", firstDataIn[0], {outputPin[0]}
field = "if(", firstDataIn[1], {outputPin[1]}
field = "if(", firstDataIn[2], {outputPin[2]}
field = "if(", firstDataIn[3], {outputPin[3]}
field = "if(", firstDataIn[4], {outputPin[4]}
field = "if(", firstDataIn[5], {outputPin[5]}
field = "if(", firstDataIn[6], {outputPin[6]}
field = "if(", firstDataIn[7], {outputPin[7]}
dialog = prgm_out_pin_selection_6, "", yAxis
field = ""
field = "", firstCompType0, {outputPin[0]}
field = "", firstCompType1, {outputPin[1]}
field = "", firstCompType2, {outputPin[2]}
field = "", firstCompType3, {outputPin[3]}
field = "", firstCompType4, {outputPin[4]}
field = "", firstCompType5, {outputPin[5]}
field = "", firstCompType6, {outputPin[6]}
field = "", firstCompType7, {outputPin[7]}
dialog = prgm_out_pin_selection_, "", yAxis
field = ""
field = "", firstTarget[0], {outputPin[0]}
field = "", firstTarget[1], {outputPin[1]}
field = "", firstTarget[2], {outputPin[2]}
field = "", firstTarget[3], {outputPin[3]}
field = "", firstTarget[4], {outputPin[4]}
field = "", firstTarget[5], {outputPin[5]}
field = "", firstTarget[6], {outputPin[6]}
field = "", firstTarget[7], {outputPin[7]}
dialog = prgm_out_pin_selection_5, "", yAxis
field = ""
field = ")", bitwise0, {outputPin[0]}
field = ")", bitwise1, {outputPin[1]}
field = ")", bitwise2, {outputPin[2]}
field = ")", bitwise3, {outputPin[3]}
field = ")", bitwise4, {outputPin[4]}
field = ")", bitwise5, {outputPin[6]}
field = ")", bitwise6, {outputPin[6]}
field = ")", bitwise7, {outputPin[7]}
dialog = prgm_out_pin_selection_6, "", yAxis
field = ""
field = "", secondDataIn0, {outputPin[0] && bitwise0}
field = "", secondDataIn1, {outputPin[1] && bitwise1}
field = "", secondDataIn2, {outputPin[2] && bitwise2}
field = "", secondDataIn3, {outputPin[3] && bitwise3}
field = "", secondDataIn4, {outputPin[4] && bitwise4}
field = "", secondDataIn5, {outputPin[5] && bitwise5}
field = "", secondDataIn6, {outputPin[6] && bitwise6}
field = "", secondDataIn7, {outputPin[7] && bitwise7}
dialog = prgm_out_pin_selection_7, "", yAxis
field = ""
field = "", secondCompType0, {outputPin[0] && bitwise0}
field = "", secondCompType1, {outputPin[1] && bitwise1}
field = "", secondCompType2, {outputPin[2] && bitwise2}
field = "", secondCompType3, {outputPin[3] && bitwise3}
field = "", secondCompType4, {outputPin[4] && bitwise4}
field = "", secondCompType5, {outputPin[5] && bitwise5}
field = "", secondCompType6, {outputPin[6] && bitwise6}
field = "", secondCompType6, {outputPin[7] && bitwise7}
dialog = prgm_out_pin_selection_8, "", yAxis
field = ""
field = "", secondTarget[0], {outputPin[0] && bitwise0}
field = "", secondTarget[1], {outputPin[1] && bitwise1}
field = "", secondTarget[2], {outputPin[2] && bitwise2}
field = "", secondTarget[3], {outputPin[3] && bitwise3}
field = "", secondTarget[4], {outputPin[4] && bitwise4}
field = "", secondTarget[5], {outputPin[5] && bitwise5}
field = "", secondTarget[6], {outputPin[6] && bitwise6}
field = "", secondTarget[7], {outputPin[7] && bitwise7}
dialog = prgm_out_pin_selection_9, "", yAxis
field = ""
field = "during", outputDelay[0], {outputPin[0]}
field = "during", outputDelay[1], {outputPin[1]}
field = "during", outputDelay[2], {outputPin[2]}
field = "during", outputDelay[3], {outputPin[3]}
field = "during", outputDelay[4], {outputPin[4]}
field = "during", outputDelay[5], {outputPin[5]}
field = "during", outputDelay[6], {outputPin[6]}
field = "during", outputDelay[7], {outputPin[7]}
dialog = prgm_out_alias, "", yAxis
field = " Input Alias"
field = "", prgm_out00Alias, {outputPin[0]}
field = "", prgm_out01Alias, {outputPin[1]}
field = "", prgm_out02Alias, {outputPin[2]}
field = "", prgm_out03Alias, {outputPin[3]}
field = "", prgm_out04Alias, {outputPin[4]}
field = "", prgm_out05Alias, {outputPin[5]}
field = "", prgm_out06Alias, {outputPin[6]}
field = "", prgm_out07Alias, {outputPin[7]}
dialog = prgm_out_channelenable, "", yAxis
field = "Pin No:"
field = "", outputPin0
field = "", outputPin1
field = "", outputPin2
field = "", outputPin3
field = "", outputPin4
field = "", outputPin5
field = "", outputPin6
field = "", outputPin7
dialog = prgm_out_unique, "",xAxis
panel = prgm_out_channelenable
panel = prgm_out_alias
panel = prgm_out_pin_selection_1
panel = prgm_out_pin_selection_2
panel = prgm_out_pin_selection_3
panel = prgm_out_pin_selection_4
panel = prgm_out_pin_selection_5
panel = prgm_out_pin_selection_6
panel = prgm_out_pin_selection_7
panel = prgm_out_pin_selection_8
panel = prgm_out_pin_selection_9
;Rule 1
dialog = prgm_out_rules_1_condition_1, "Condition 1", xAxis
field = "", firstDataIn0, {outputPin[0]}
@ -3830,78 +3680,157 @@ menuDialog = main
field = "", secondCompType7, {outputPin[7] && bitwise7}
field = "", secondTarget[7], {outputPin[7] && bitwise7}
dialog = prgm_out_rules_1_output_limit_1, "", xAxis
field = "", kindOfLimiting0, {outputPin[0]}
field = "output time", outputTimeLimit[0], {outputPin[0]}
dialog = prgm_out_rules_2_output_limit_1, "", xAxis
field = "", kindOfLimiting1, {outputPin[1]}
field = "output time", outputTimeLimit[1], {outputPin[1]}
dialog = prgm_out_rules_3_output_limit_1, "", xAxis
field = "", kindOfLimiting2, {outputPin[2]}
field = "output time", outputTimeLimit[2], {outputPin[2]}
dialog = prgm_out_rules_4_output_limit_1, "", xAxis
field = "", kindOfLimiting3, {outputPin[3]}
field = "output time", outputTimeLimit[3], {outputPin[3]}
dialog = prgm_out_rules_5_output_limit_1, "", xAxis
field = "", kindOfLimiting4, {outputPin[4]}
field = "output time", outputTimeLimit[4], {outputPin[4]}
dialog = prgm_out_rules_6_output_limit_1, "", xAxis
field = "", kindOfLimiting5, {outputPin[5]}
field = "output time", outputTimeLimit[5], {outputPin[5]}
dialog = prgm_out_rules_7_output_limit_1, "", xAxis
field = "", kindOfLimiting6, {outputPin[6]}
field = "output time", outputTimeLimit[6], {outputPin[6]}
dialog = prgm_out_rules_8_output_limit_1, "", xAxis
field = "", kindOfLimiting7, {outputPin[7]}
field = "output time", outputTimeLimit[7], {outputPin[7]}
dialog = prgm_out_rules_1_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_1_output_limit_1
dialog = prgm_out_rules_2_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_2_output_limit_1
dialog = prgm_out_rules_3_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_3_output_limit_1
dialog = prgm_out_rules_4_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_4_output_limit_1
dialog = prgm_out_rules_5_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_5_output_limit_1
dialog = prgm_out_rules_6_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_6_output_limit_1
dialog = prgm_out_rules_7_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_7_output_limit_1
dialog = prgm_out_rules_8_output_limit, "Limit time active", yAxis
field = "#Set 0.0 to disable the limit"
panel = prgm_out_rules_8_output_limit_1
dialog = prgm_out_rules_1, "Rule 1", yAxis
field = "Output Pin Num", outputPin0
field = "Rule Alias", prgm_out00Alias, {outputPin[0]}
field = "Output Polarity", outputInverted0, {outputPin[0]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[0], {outputPin[0]}
field = "2nd Condition", bitwise0, {outputPin[0]}
panel = prgm_out_rules_1_condition_1
panel = prgm_out_rules_1_condition_2
panel = prgm_out_rules_1_output_limit
dialog = prgm_out_rules_2, "Rule 2", yAxis
field = "Output Pin Num", outputPin1
field = "Rule Alias", prgm_out01Alias, {outputPin[1]}
field = "Output Polarity", outputInverted1, {outputPin[1]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[1], {outputPin[1]}
field = "2nd Condition", bitwise1, {outputPin[1]}
panel = prgm_out_rules_2_condition_1
panel = prgm_out_rules_2_condition_2
panel = prgm_out_rules_2_output_limit
dialog = prgm_out_rules_3, "Rule 3", yAxis
field = "Output Pin Num", outputPin2
field = "Rule Alias", prgm_out02Alias, {outputPin[2]}
field = "Output Polarity", outputInverted2, {outputPin[2]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[2], {outputPin[2]}
field = "2nd Condition", bitwise2, {outputPin[2]}
panel = prgm_out_rules_3_condition_1
panel = prgm_out_rules_3_condition_2
panel = prgm_out_rules_3_output_limit
dialog = prgm_out_rules_4, "Rule 4", yAxis
field = "Output Pin Num", outputPin3
field = "Rule Alias", prgm_out03Alias, {outputPin[3]}
field = "Output Polarity", outputInverted3, {outputPin[3]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[3], {outputPin[3]}
field = "2nd Condition", bitwise3, {outputPin[3]}
panel = prgm_out_rules_4_condition_1
panel = prgm_out_rules_4_condition_2
panel = prgm_out_rules_4_output_limit
dialog = prgm_out_rules_5, "Rule 5", yAxis
field = "Output Pin Num", outputPin4
field = "Rule Alias", prgm_out04Alias, {outputPin[4]}
field = "Output Polarity", outputInverted4, {outputPin[4]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[4], {outputPin[4]}
field = "2nd Condition", bitwise4, {outputPin[4]}
panel = prgm_out_rules_5_condition_1
panel = prgm_out_rules_5_condition_2
panel = prgm_out_rules_5_output_limit
dialog = prgm_out_rules_6, "Rule 6", yAxis
field = "Output Pin Num", outputPin5
field = "Rule Alias", prgm_out05Alias, {outputPin[5]}
field = "Output Polarity", outputInverted5, {outputPin[5]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[5], {outputPin[5]}
field = "2nd Condition", bitwise5, {outputPin[5]}
panel = prgm_out_rules_6_condition_1
panel = prgm_out_rules_6_condition_2
panel = prgm_out_rules_6_output_limit
dialog = prgm_out_rules_7, "Rule 7", yAxis
field = "Output Pin Num", outputPin6
field = "Rule Alias", prgm_out06Alias, {outputPin[6]}
field = "Output Polarity", outputInverted6, {outputPin[6]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[6], {outputPin[6]}
field = "2nd Condition", bitwise6, {outputPin[6]}
panel = prgm_out_rules_7_condition_1
panel = prgm_out_rules_7_condition_2
panel = prgm_out_rules_7_output_limit
dialog = prgm_out_rules_8, "Rule 8", yAxis
field = "Output Pin Num", outputPin7
field = "Rule Alias", prgm_out07Alias, {outputPin[7]}
field = "Output Polarity", outputInverted7, {outputPin[7]}
field = "#Set 0.0 to disable the delay"
field = "Activation Delay", outputDelay[7], {outputPin[7]}
field = "2nd Condition", bitwise7, {outputPin[7]}
panel = prgm_out_rules_8_condition_1
panel = prgm_out_rules_8_condition_2
panel = prgm_out_rules_8_output_limit
dialog = prgm_out_rules_master, "", card
panel = prgm_out_rules_1, Center, { prgm_out_selection == 0 }

View File

@ -154,6 +154,7 @@
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
#define BIT_CHECK(var,pos) !!((var) & (1U<<(pos)))
#define BIT_TOGGLE(var,pos) ((var)^= 1UL << (pos))
#define BIT_WRITE(var, pos, bitvalue) ((bitvalue) ? BIT_SET(var, pos) : bitClear(var, pos))
#define interruptSafe(c) (noInterrupts(); {c} interrupts();) //Wraps any code between nointerrupt and interrupt calls
@ -535,7 +536,7 @@ extern int ignition7StartAngle;
extern int ignition8StartAngle;
//These are variables used across multiple files
extern const byte PROGMEM fsIntIndex[34];
extern const byte PROGMEM fsIntIndex[33];
extern bool initialisationComplete; //Tracks whether the setup() function has run completely
extern byte fpPrimeTime; //The time (in seconds, based on currentStatus.secl) that the fuel pump started priming
extern volatile uint16_t mainLoopCount;
@ -1359,13 +1360,14 @@ Page 13 - Programmable outputs logic rules.
128 bytes long. Rules implemented in utilities.ino @ref checkProgrammableIO().
*/
struct config13 {
uint8_t outputInverted; ///< Invert (on/off) value before writing to output pin (for all programmable I/O:s?).
uint8_t unused12_1; // Unused
uint8_t outputInverted; ///< Invert (on/off) value before writing to output pin (for all programmable I/O:s).
uint8_t kindOfLimiting; ///< Select which kind of output limiting are active (0 - minimum | 1 - maximum)
uint8_t outputPin[8]; ///< Disable(0) or enable (set to valid pin number) Programmable Pin (output/target pin to set)
uint8_t outputDelay[8]; ///< Output write delay for each programmable I/O (Unit: 0.1S ?)
uint8_t outputDelay[8]; ///< Output write delay for each programmable I/O (Unit: 0.1S)
uint8_t firstDataIn[8]; ///< Set of first I/O vars to compare
uint8_t secondDataIn[8];///< Set of second I/O vars to compare
uint8_t unused_13[16]; // Unused
uint8_t outputTimeLimit[8]; ///< Output delay for each programmable I/O, kindOfLimiting bit dependant(Unit: 0.1S)
uint8_t unused_13[8]; // Unused
int16_t firstTarget[8]; ///< first target value to compare with numeric comp
int16_t secondTarget[8];///< second target value to compare with bitwise op
//89bytes

View File

@ -121,7 +121,7 @@ int ignition8EndAngle = 0;
//These are variables used across multiple files
/// int (member) indexes in fullStatus array
const byte PROGMEM fsIntIndex[34] = {4, 14, 17, 25, 27, 32, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 75, 77, 79, 81, 85, 87, 89, 93, 97, 102, 190 };
const byte PROGMEM fsIntIndex[] = {4, 14, 17, 25, 27, 32, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 75, 77, 79, 81, 85, 87, 89, 93, 97, 102, 190 };
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
volatile uint16_t mainLoopCount; //Main loop counter (incremented at each main loop rev., used for maintaining currentStatus.loopsPerSecond)

View File

@ -24,7 +24,7 @@
// 2. Offset to intra-entity byte
// Page sizes as defined in the .ini file
constexpr const uint16_t ini_page_sizes[] = { 0, 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 };
constexpr const uint16_t PROGMEM ini_page_sizes[] = { 0, 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 };
// What section of a 3D table the offset mapped to
enum table3D_section_t {
@ -318,7 +318,7 @@ uint8_t getPageCount()
uint16_t getPageSize(byte pageNum)
{
return ini_page_sizes[pageNum];
return pgm_read_word(&(ini_page_sizes[pageNum]));
}
void setPageValue(byte pageNum, uint16_t offset, byte value)

View File

@ -496,6 +496,16 @@ void doUpdates()
configPage9.boostByGearEnabled = 0;
//Added possibility to set minimum programmable output time
configPage13.outputTimeLimit[0] = 0;
configPage13.outputTimeLimit[1] = 0;
configPage13.outputTimeLimit[2] = 0;
configPage13.outputTimeLimit[3] = 0;
configPage13.outputTimeLimit[4] = 0;
configPage13.outputTimeLimit[5] = 0;
configPage13.outputTimeLimit[6] = 0;
configPage13.outputTimeLimit[7] = 0;
writeAllConfig();
EEPROM.write(EEPROM_DATA_VERSION, 18);
}

View File

@ -14,15 +14,20 @@ These are some utility functions and variables used through the main code
#define COMPARATOR_GREATER_EQUAL 3
#define COMPARATOR_LESS 4
#define COMPARATOR_LESS_EQUAL 5
#define COMPARATOR_CHANGE 6
#define COMPARATOR_AND 6
#define COMPARATOR_XOR 7
#define BITWISE_DISABLED 0
#define BITWISE_AND 1
#define BITWISE_OR 2
#define BITWISE_XOR 3
extern uint16_t ioDelay[sizeof(configPage13.outputPin)];
#define REUSE_RULES 240
extern uint8_t ioOutDelay[sizeof(configPage13.outputPin)];
extern uint8_t ioDelay[sizeof(configPage13.outputPin)];
extern uint8_t pinIsValid;
extern uint8_t currentRuleStatus;
//uint8_t outputPin[sizeof(configPage13.outputPin)];
void setResetControlPinState();

View File

@ -13,8 +13,10 @@
#include "decoders.h"
#include "comms.h"
uint16_t ioDelay[sizeof(configPage13.outputPin)];
uint8_t ioDelay[sizeof(configPage13.outputPin)];
uint8_t ioOutDelay[sizeof(configPage13.outputPin)];
uint8_t pinIsValid = 0;
uint8_t currentRuleStatus = 0;
/** Translate between the pin list that appears in TS and the actual pin numbers.
@ -115,16 +117,27 @@ void setResetControlPinState()
//*********************************************************************************************************************************************************************************
void initialiseProgrammableIO()
{
uint8_t outputPin;
for (uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
{
if ( (configPage13.outputPin[y] > 0) && (configPage13.outputPin[y] < BOARD_MAX_DIGITAL_PINS) )
ioDelay[y] = 0;
ioOutDelay[y] = 0;
outputPin = configPage13.outputPin[y];
if (outputPin > 0)
{
if ( !pinIsUsed(configPage13.outputPin[y]) )
if ( outputPin >= 128 ) //Cascate rule usage
{
pinMode(configPage13.outputPin[y], OUTPUT);
digitalWrite(configPage13.outputPin[y], (configPage13.outputInverted & (1U << y)));
BIT_WRITE(currentStatus.outputsStatus, y, BIT_CHECK(configPage13.outputInverted, y));
BIT_SET(pinIsValid, y);
}
else if ( !pinIsUsed(outputPin) )
{
pinMode(outputPin, OUTPUT);
digitalWrite(outputPin, BIT_CHECK(configPage13.outputInverted, y));
BIT_WRITE(currentStatus.outputsStatus, y, BIT_CHECK(configPage13.outputInverted, y));
BIT_SET(pinIsValid, y);
}
else { BIT_CLEAR(pinIsValid, y); }
}
}
}
@ -136,6 +149,7 @@ void initialiseProgrammableIO()
void checkProgrammableIO()
{
int16_t data, data2;
uint8_t dataRequested;
bool firstCheck, secondCheck;
for (uint8_t y = 0; y < sizeof(configPage13.outputPin); y++)
@ -143,9 +157,15 @@ void checkProgrammableIO()
firstCheck = false;
secondCheck = false;
if ( BIT_CHECK(pinIsValid, y) ) //if outputPin == 0 it is disabled
{
//byte theIndex = configPage13.firstDataIn[y];
data = ProgrammableIOGetData(configPage13.firstDataIn[y]);
{
dataRequested = configPage13.firstDataIn[y];
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); }
else { data = 0; }
}
else { data = ProgrammableIOGetData(dataRequested); }
data2 = configPage13.firstTarget[y];
if ( (configPage13.operation[y].firstCompType == COMPARATOR_EQUAL) && (data == data2) ) { firstCheck = true; }
@ -154,12 +174,20 @@ void checkProgrammableIO()
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.secondDataIn[y] < LOG_ENTRY_SIZE ) //Failsafe check
dataRequested = configPage13.secondDataIn[y];
if ( dataRequested <= (REUSE_RULES + sizeof(configPage13.outputPin)) ) //Failsafe check
{
data = ProgrammableIOGetData(configPage13.secondDataIn[y]);
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; }
@ -168,31 +196,57 @@ void checkProgrammableIO()
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 ( (firstCheck == true) && (configPage13.outputDelay[y] != 0) && (configPage13.outputDelay[y] < 255) )
//If the limiting time is active(>0) and using maximum time
if (BIT_CHECK(configPage13.kindOfLimiting, y))
{
if ( (ioDelay[y] >= configPage13.outputDelay[y]) )
if(firstCheck)
{
if (configPage13.outputPin[y] <= 128) { digitalWrite(configPage13.outputPin[y], (configPage13.outputInverted & (1U << y)) ^ firstCheck); }
if (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
if(BIT_CHECK(currentStatus.outputsStatus, y)) { ioOutDelay[y] = configPage13.outputTimeLimit[y]; }
else { ioOutDelay[y] = 0; } //Reset the counter for next time
}
}
if ( (firstCheck == true) && (configPage13.outputDelay[y] < 255) )
{
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); }
else { BIT_WRITE(currentRuleStatus, y, bitStatus); }
BIT_WRITE(currentStatus.outputsStatus, y, bitStatus);
}
else { ioDelay[y]++; }
}
else
{
if ( configPage13.outputPin[y] <= 128 ) { digitalWrite(configPage13.outputPin[y], (configPage13.outputInverted & (1U << y)) ^ firstCheck); }
if ( firstCheck == false ) { ioDelay[y] = 0; }
if (ioOutDelay[y] >= configPage13.outputTimeLimit[y])
{
bool bitStatus = BIT_CHECK(configPage13.outputInverted, y) ^ firstCheck;
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; }
}
else { ioOutDelay[y]++; }
ioDelay[y] = 0;
}
if ( firstCheck == true ) { BIT_SET(currentStatus.outputsStatus, y); }
else { BIT_CLEAR(currentStatus.outputsStatus, y); }
}
else { BIT_CLEAR(currentStatus.outputsStatus, y); }
}
}
/** Get single I/O data var (from currentStatus) for comparison.
@ -210,7 +264,7 @@ int16_t ProgrammableIOGetData(uint16_t index)
for(x = 0; x<sizeof(fsIntIndex); x++)
{
// Stop at desired field
if (fsIntIndex[x] == index) { break; }
if (pgm_read_byte(&(fsIntIndex[x])) == index) { break; }
}
if (x >= sizeof(fsIntIndex)) { result = getStatusEntry(index); } // 8-bit, coerce to 16 bit result
else { result = word(getStatusEntry(index+1), getStatusEntry(index)); } // Assemble 2 bytes to word of 16 bit result
@ -219,6 +273,7 @@ int16_t ProgrammableIOGetData(uint16_t index)
//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
return result;
}