automation around outputs section #197
This commit is contained in:
parent
5b461e82fb
commit
2cd8863492
|
@ -9,6 +9,7 @@ java -DSystemOut.name=logs/gen_output_channels \
|
|||
-cache_zip_file tunerstudio/generated/cache.zip \
|
||||
-prepend integration/rusefi_config.txt \
|
||||
-definition console/binary/output_channels.txt \
|
||||
-ts_outputs_section console/binary/output_channels.ini \
|
||||
-cache . \
|
||||
-with_c_defines false \
|
||||
-c_destination console/binary/ts_outputs_generated.h
|
|
@ -184,38 +184,40 @@ enable2ndByteCanID = false
|
|||
; see TunerStudioOutputChannels struct
|
||||
;
|
||||
|
||||
; Bit flags
|
||||
sd_present = bits, U32, 0, [0:0], "true", "false";
|
||||
isIgnitionEnabledIndicator=bits,U32, 0, [1:1], "true", "false";
|
||||
isInjectionEnabledIndicator=bits,U32,0, [2:2], "true", "false";
|
||||
sd_logging_internal = bits U32 , 0, [3:3], "true", "false"
|
||||
isCylinderCleanupActivated=bits,U32, 0, [4:4], "true", "false";
|
||||
isFuelPumpOn = bits, U32, 0, [5:5], "true", "false";
|
||||
isFanOn = bits, U32, 0, [6:6], "true", "false";
|
||||
isO2HeaterOn = bits, U32, 0, [7:7], "true", "false";
|
||||
checkEngine= bits, U32, 0, [8:8], "true", "false";
|
||||
needBurn = bits, U32, 0, [9:9], "true", "false";
|
||||
sd_msd = bits, U32, 0, [10:10], "true", "false"
|
||||
clutchUpState =bits, U32, 0, [11:11], "true", "false";
|
||||
clutchDownState =bits, U32, 0, [12:12], "true", "false";
|
||||
isFan2On = bits, U32, 0, [13:13], "true", "false"
|
||||
brakePedalState=bits, U32, 0, [15:15], "true", "false";
|
||||
toothLogReady =bits, U32, 0, [16:16], "true", "false";
|
||||
acSwitchState =bits, U32, 0, [17:17], "true", "false";
|
||||
isTpsError = bits, U32, 0, [18:18], "true", "false";
|
||||
isCltError = bits, U32, 0, [19:19], "true", "false";
|
||||
isIatError = bits, U32, 0, [21:21], "true", "false";
|
||||
acState = bits, U32, 0, [22:22], "true", "false";
|
||||
isTriggerError = bits, U32, 0, [23:23], "true", "false";
|
||||
hasCriticalError=bits, U32, 0, [24:24], "true", "false";
|
||||
isWarnNow =bits, U32, 0, [25:25], "true", "false";
|
||||
isPedalError =bits, U32, 0, [26:26], "true", "false";
|
||||
isTps2Error = bits, U32, 0, [29:29], "true", "false";
|
||||
isIdleClosedLoop= bits, U32, 0, [30:30], "true", "false";
|
||||
isIdleCoasting = bits, U32, 0, [31:31], "true", "false";
|
||||
sd_present = bits, U32, 0, [0:0]
|
||||
isIgnitionEnabledIndicator = bits, U32, 0, [1:1]
|
||||
isInjectionEnabledIndicator = bits, U32, 0, [2:2]
|
||||
sd_logging_internal = bits, U32, 0, [3:3]
|
||||
isCylinderCleanupActivated = bits, U32, 0, [4:4]
|
||||
isFuelPumpOn = bits, U32, 0, [5:5]
|
||||
isFanOn = bits, U32, 0, [6:6]
|
||||
isO2HeaterOn = bits, U32, 0, [7:7]
|
||||
checkEngine = bits, U32, 0, [8:8]
|
||||
needBurn = bits, U32, 0, [9:9]
|
||||
sd_msd = bits, U32, 0, [10:10]
|
||||
clutchUpState = bits, U32, 0, [11:11]
|
||||
clutchDownState = bits, U32, 0, [12:12]
|
||||
isFan2On = bits, U32, 0, [13:13]
|
||||
unusedb14 = bits, U32, 0, [14:14]
|
||||
brakePedalState = bits, U32, 0, [15:15]
|
||||
toothLogReady = bits, U32, 0, [16:16]
|
||||
acSwitchState = bits, U32, 0, [17:17]
|
||||
isTpsError = bits, U32, 0, [18:18]
|
||||
isCltError = bits, U32, 0, [19:19]
|
||||
isMapError = bits, U32, 0, [20:20]
|
||||
isIatError = bits, U32, 0, [21:21]
|
||||
acState = bits, U32, 0, [22:22]
|
||||
isTriggerError = bits, U32, 0, [23:23]
|
||||
hasCriticalError = bits, U32, 0, [24:24]
|
||||
isWarnNow = bits, U32, 0, [25:25]
|
||||
isPedalError = bits, U32, 0, [26:26]
|
||||
isKnockChipOk = bits, U32, 0, [27:27]
|
||||
launchTriggered = bits, U32, 0, [28:28]
|
||||
isTps2Error = bits, U32, 0, [29:29]
|
||||
isIdleClosedLoop = bits, U32, 0, [30:30]
|
||||
isIdleCoasting = bits, U32, 0, [31:31]
|
||||
RPMValue = scalar, U16, 4, "RPM", 1, 0
|
||||
|
||||
; RPM, vss
|
||||
RPMValue = scalar, U16, 4, "RPM", 1, 0.00000
|
||||
rpmAcceleration = scalar, S16, 6, "RPM/s", 1, 0
|
||||
speedToRpmRatio = scalar, S16, 8, "value",{1/@@PACK_MULT_PERCENT@@}, 0
|
||||
vehicleSpeedKph = scalar, U08, 10, "kph", 1, 0.0
|
||||
|
|
Binary file not shown.
|
@ -30,6 +30,7 @@ import java.util.zip.CRC32;
|
|||
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
|
||||
public class ConfigDefinition {
|
||||
private static final String SIGNATURE_HASH = "SIGNATURE_HASH";
|
||||
private static String TS_OUTPUTS_SECTION = null;
|
||||
public static String MESSAGE;
|
||||
|
||||
private static final String ROM_RAIDER_XML_TEMPLATE = "rusefi_template.xml";
|
||||
|
@ -89,7 +90,7 @@ public class ConfigDefinition {
|
|||
|
||||
SystemOut.println(ConfigDefinition.class + " Invoked with " + Arrays.toString(args));
|
||||
|
||||
String tsPath = null;
|
||||
String tsInputFileFolder = null;
|
||||
String destCHeaderFileName = null;
|
||||
String destCDefinesFileName = null;
|
||||
String destCFsioConstantsFileName = null;
|
||||
|
@ -128,7 +129,10 @@ public class ConfigDefinition {
|
|||
inputFiles.add(definitionInputFile);
|
||||
break;
|
||||
case KEY_TS_DESTINATION:
|
||||
tsPath = args[i + 1];
|
||||
tsInputFileFolder = args[i + 1];
|
||||
break;
|
||||
case "-ts_outputs_section":
|
||||
TS_OUTPUTS_SECTION = args[i + 1];
|
||||
break;
|
||||
case KEY_C_DESTINATION:
|
||||
destCHeaderFileName = args[i + 1];
|
||||
|
@ -209,12 +213,12 @@ public class ConfigDefinition {
|
|||
}
|
||||
|
||||
List<String> inputAllFiles = new ArrayList<>(inputFiles);
|
||||
if (tsPath != null) {
|
||||
if (tsInputFileFolder != null) {
|
||||
// used to update .ini files
|
||||
inputAllFiles.add(TSProjectConsumer.getTsFileInputName(tsPath));
|
||||
inputAllFiles.add(TSProjectConsumer.getTsFileInputName(tsInputFileFolder));
|
||||
}
|
||||
|
||||
boolean needToUpdateTsFiles = isNeedToUpdateTsFiles(tsPath, cachePath, cacheZipFile, inputAllFiles);
|
||||
boolean needToUpdateTsFiles = isNeedToUpdateTsFiles(tsInputFileFolder, cachePath, cacheZipFile, inputAllFiles);
|
||||
|
||||
boolean needToUpdateOtherFiles = CachingStrategy.checkIfOutputFilesAreOutdated(inputFiles, cachePath, cacheZipFile);
|
||||
if (!needToUpdateTsFiles && !needToUpdateOtherFiles) {
|
||||
|
@ -232,7 +236,7 @@ public class ConfigDefinition {
|
|||
|
||||
ParseState parseState = new ParseState(state.enumsReader);
|
||||
// Add the variable for the config signature
|
||||
long crc32 = signatureHash(state, parseState, tsPath, inputAllFiles);
|
||||
long crc32 = signatureHash(state, parseState, tsInputFileFolder, inputAllFiles);
|
||||
|
||||
handleFiringOrder(firingEnumFileName, state.variableRegistry, parseState);
|
||||
|
||||
|
@ -281,9 +285,12 @@ public class ConfigDefinition {
|
|||
BufferedReader definitionReader = new BufferedReader(new InputStreamReader(new FileInputStream(definitionInputFile), IoUtils.CHARSET.name()));
|
||||
|
||||
List<ConfigurationConsumer> destinations = new ArrayList<>();
|
||||
if (tsPath != null && needToUpdateTsFiles) {
|
||||
if (TS_OUTPUTS_SECTION != null) {
|
||||
destinations.add(new OutputsSectionConsumer(TS_OUTPUTS_SECTION, state));
|
||||
}
|
||||
if (tsInputFileFolder != null && needToUpdateTsFiles) {
|
||||
CharArrayWriter tsWriter = new CharArrayWriter();
|
||||
destinations.add(new TSProjectConsumer(tsWriter, tsPath, state));
|
||||
destinations.add(new TSProjectConsumer(tsWriter, tsInputFileFolder, state));
|
||||
|
||||
VariableRegistry tmpRegistry = new VariableRegistry();
|
||||
// store the CRC32 as a built-in variable
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package com.rusefi.output;
|
||||
|
||||
import com.rusefi.ConfigStructure;
|
||||
import com.rusefi.ReaderState;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class OutputsSectionConsumer implements ConfigurationConsumer {
|
||||
private final String tsOutputsSectionFileName;
|
||||
private final TsOutput tsOutput;
|
||||
private final ReaderState state;
|
||||
private final CharArrayWriter tsWriter = new CharArrayWriter();
|
||||
|
||||
public OutputsSectionConsumer(String tsOutputsSectionFileName, ReaderState state) {
|
||||
this.tsOutputsSectionFileName = tsOutputsSectionFileName;
|
||||
tsOutput = new TsOutput(state, false);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFile() throws IOException {
|
||||
}
|
||||
|
||||
public CharArrayWriter getTsWriter() {
|
||||
return tsWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFile() throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEndStruct(ConfigStructure structure) throws IOException {
|
||||
System.out.println("handleEndStruct");
|
||||
|
||||
if (state.stack.isEmpty()) {
|
||||
tsOutput.writeTunerStudio(structure, "", tsWriter, 0);
|
||||
|
||||
if (tsOutputsSectionFileName != null) {
|
||||
FileWriter fos = new FileWriter(tsOutputsSectionFileName);
|
||||
fos.write(tsWriter.toCharArray());
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.rusefi.output;
|
||||
|
||||
import com.opensr5.ini.field.IniField;
|
||||
import com.rusefi.*;
|
||||
import com.rusefi.util.LazyFile;
|
||||
import com.rusefi.util.Output;
|
||||
|
@ -8,8 +7,8 @@ import com.rusefi.util.SystemOut;
|
|||
|
||||
import java.io.*;
|
||||
|
||||
import static com.rusefi.util.IoUtils.CHARSET;
|
||||
import static com.rusefi.ToolUtil.EOL;
|
||||
import static com.rusefi.util.IoUtils.CHARSET;
|
||||
|
||||
public class TSProjectConsumer implements ConfigurationConsumer {
|
||||
private static final String TS_FILE_INPUT_NAME = "rusefi.input";
|
||||
|
@ -19,153 +18,23 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
public static final String SETTING_CONTEXT_HELP_END = "SettingContextHelpEnd";
|
||||
public static final String SETTING_CONTEXT_HELP = "SettingContextHelp";
|
||||
public static String TS_FILE_OUTPUT_NAME = "rusefi.ini";
|
||||
private final StringBuilder settingContextHelp = new StringBuilder();
|
||||
|
||||
private final CharArrayWriter tsWriter;
|
||||
private final String tsPath;
|
||||
private final ReaderState state;
|
||||
private int totalTsSize;
|
||||
private final TsOutput tsOutput;
|
||||
|
||||
public TSProjectConsumer(CharArrayWriter tsWriter, String tsPath, ReaderState state) {
|
||||
this.tsWriter = tsWriter;
|
||||
this.tsPath = tsPath;
|
||||
tsOutput = new TsOutput(state, true);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
// also known as TS tooltips
|
||||
public StringBuilder getSettingContextHelp() {
|
||||
return settingContextHelp;
|
||||
}
|
||||
|
||||
private int writeTunerStudio(ConfigField configField, String prefix, Writer tsHeader, int tsPosition, ConfigField next, int bitIndex) throws IOException {
|
||||
String nameWithPrefix = prefix + configField.getName();
|
||||
|
||||
if (configField.isDirective() && configField.getComment() != null) {
|
||||
tsHeader.write(configField.getComment());
|
||||
tsHeader.write(EOL);
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
ConfigStructure cs = configField.getState().structures.get(configField.getType());
|
||||
if (configField.getComment() != null && configField.getComment().trim().length() > 0 && cs == null) {
|
||||
settingContextHelp.append("\t" + nameWithPrefix + " = \"" + configField.getCommentContent() + "\"" + EOL);
|
||||
}
|
||||
state.variableRegistry.register(nameWithPrefix + "_offset", tsPosition);
|
||||
|
||||
if (cs != null) {
|
||||
String extraPrefix = cs.withPrefix ? configField.getName() + "_" : "";
|
||||
return writeTunerStudio(cs, prefix + extraPrefix, tsHeader, tsPosition);
|
||||
}
|
||||
|
||||
if (configField.isBit()) {
|
||||
tsHeader.write(nameWithPrefix + " = bits, U32,");
|
||||
tsHeader.write(" " + tsPosition + ", [");
|
||||
tsHeader.write(bitIndex + ":" + bitIndex);
|
||||
tsHeader.write("], \"" + configField.getFalseName() + "\", \"" + configField.getTrueName() + "\"");
|
||||
tsHeader.write(EOL);
|
||||
|
||||
tsPosition += configField.getSize(next);
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
if (configField.getState().tsCustomLine.containsKey(configField.getType())) {
|
||||
String bits = configField.getState().tsCustomLine.get(configField.getType());
|
||||
if (!bits.startsWith("bits")) {
|
||||
bits = handleTsInfo(bits, 5);
|
||||
}
|
||||
|
||||
bits = bits.replaceAll("@OFFSET@", "" + tsPosition);
|
||||
tsHeader.write(nameWithPrefix + " = " + bits);
|
||||
|
||||
tsPosition += configField.getState().tsCustomSize.get(configField.getType());
|
||||
} else if (configField.getTsInfo() == null) {
|
||||
throw new IllegalArgumentException("Need TS info for " + configField.getName() + " at "+ prefix);
|
||||
} else if (configField.getArraySizes().length == 0) {
|
||||
tsHeader.write(nameWithPrefix + " = scalar, ");
|
||||
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
|
||||
tsHeader.write(" " + tsPosition + ",");
|
||||
tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1));
|
||||
tsPosition += configField.getSize(next);
|
||||
} else if (configField.getSize(next) == 0) {
|
||||
// write nothing for empty array
|
||||
// TS does not like those
|
||||
} else {
|
||||
tsHeader.write(nameWithPrefix + " = array, ");
|
||||
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
|
||||
tsHeader.write(" " + tsPosition + ",");
|
||||
tsHeader.write(" [");
|
||||
boolean first = true;
|
||||
for (int size : configField.getArraySizes()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
tsHeader.write("x");
|
||||
}
|
||||
tsHeader.write(Integer.toString(size));
|
||||
}
|
||||
tsHeader.write("], " + handleTsInfo(configField.getTsInfo(), 1));
|
||||
|
||||
tsPosition += configField.getSize(next);
|
||||
}
|
||||
tsHeader.write(EOL);
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
private static String handleTsInfo(String tsInfo, int mutliplierIndex) {
|
||||
try {
|
||||
String[] fields = tsInfo.split("\\,");
|
||||
if (fields.length > mutliplierIndex) {
|
||||
/**
|
||||
* Evaluate static math on .ini layer to simplify rusEFI java and rusEFI PHP project consumers
|
||||
* https://github.com/rusefi/web_backend/issues/97
|
||||
*/
|
||||
double val = IniField.parseDouble(fields[mutliplierIndex]);
|
||||
|
||||
if (val == 0) {
|
||||
fields[mutliplierIndex] = " 0";
|
||||
} else if (val == 1) {
|
||||
fields[mutliplierIndex] = " 1";
|
||||
} else {
|
||||
fields[mutliplierIndex] = " " + val;
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String f : fields) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(f);
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException("While parsing " + tsInfo, e);
|
||||
}
|
||||
}
|
||||
|
||||
private int writeTunerStudio(ConfigStructure configStructure, String prefix, Writer tsHeader, int tsPosition) throws IOException {
|
||||
BitState bitState = new BitState();
|
||||
ConfigField prev = ConfigField.VOID;
|
||||
int prevTsPosition = tsPosition;
|
||||
for (int i = 0; i < configStructure.tsFields.size(); i++) {
|
||||
ConfigField next = i == configStructure.tsFields.size() - 1 ? ConfigField.VOID : configStructure.tsFields.get(i + 1);
|
||||
ConfigField cf = configStructure.tsFields.get(i);
|
||||
|
||||
// if duplicate names, use previous position
|
||||
if (cf.getName().equals(prev.getName())) {
|
||||
tsPosition = prevTsPosition;
|
||||
}
|
||||
|
||||
// Update 'prev' state needed for duplicate names recognition
|
||||
if (!cf.isDirective()) {
|
||||
prevTsPosition = tsPosition;
|
||||
prev = cf;
|
||||
}
|
||||
|
||||
tsPosition = writeTunerStudio(cf, prefix, tsHeader, tsPosition, next, bitState.get());
|
||||
|
||||
bitState.incrementBitIndex(cf, next);
|
||||
}
|
||||
return tsPosition;
|
||||
return tsOutput.getSettingContextHelp();
|
||||
}
|
||||
|
||||
protected void writeTunerStudioFile(String tsPath, String fieldsSection) throws IOException {
|
||||
|
@ -186,9 +55,9 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
tsHeader.write("pageSize = " + totalTsSize + ToolUtil.EOL);
|
||||
tsHeader.write("page = 1" + ToolUtil.EOL);
|
||||
tsHeader.write(fieldsSection);
|
||||
if (settingContextHelp.length() > 0) {
|
||||
if (tsOutput.getSettingContextHelp().length() > 0) {
|
||||
tsHeader.write("[" + SETTING_CONTEXT_HELP + "]" + ToolUtil.EOL);
|
||||
tsHeader.write(settingContextHelp.toString() + ToolUtil.EOL + ToolUtil.EOL);
|
||||
tsHeader.write(tsOutput.getSettingContextHelp().toString() + ToolUtil.EOL + ToolUtil.EOL);
|
||||
tsHeader.write("; " + SETTING_CONTEXT_HELP_END + ToolUtil.EOL);
|
||||
}
|
||||
tsHeader.write("; " + CONFIG_DEFINITION_END + ToolUtil.EOL);
|
||||
|
@ -282,7 +151,7 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
public void handleEndStruct(ConfigStructure structure) throws IOException {
|
||||
state.variableRegistry.register(structure.name + "_size", structure.getTotalSize());
|
||||
if (state.stack.isEmpty()) {
|
||||
totalTsSize = writeTunerStudio(structure, "", tsWriter, 0);
|
||||
totalTsSize = tsOutput.writeTunerStudio(structure, "", tsWriter, 0);
|
||||
tsWriter.write("; total TS size = " + totalTsSize + EOL);
|
||||
state.variableRegistry.register("TOTAL_CONFIG_SIZE", totalTsSize);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
package com.rusefi.output;
|
||||
|
||||
import com.opensr5.ini.field.IniField;
|
||||
import com.rusefi.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.rusefi.ToolUtil.EOL;
|
||||
|
||||
public class TsOutput {
|
||||
private final StringBuilder settingContextHelp = new StringBuilder();
|
||||
private final ReaderState state;
|
||||
private final boolean longForm;
|
||||
|
||||
public TsOutput(ReaderState state, boolean longForm) {
|
||||
this.state = state;
|
||||
this.longForm = longForm;
|
||||
}
|
||||
|
||||
public StringBuilder getSettingContextHelp() {
|
||||
return settingContextHelp;
|
||||
}
|
||||
|
||||
private int writeTunerStudio(ConfigField configField, String prefix, Writer tsHeader, int tsPosition, ConfigField next, int bitIndex) throws IOException {
|
||||
String nameWithPrefix = prefix + configField.getName();
|
||||
|
||||
if (configField.isDirective() && configField.getComment() != null) {
|
||||
tsHeader.write(configField.getComment());
|
||||
tsHeader.write(EOL);
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
ConfigStructure cs = configField.getState().structures.get(configField.getType());
|
||||
if (configField.getComment() != null && configField.getComment().trim().length() > 0 && cs == null) {
|
||||
settingContextHelp.append("\t" + nameWithPrefix + " = \"" + configField.getCommentContent() + "\"" + EOL);
|
||||
}
|
||||
state.variableRegistry.register(nameWithPrefix + "_offset", tsPosition);
|
||||
|
||||
if (cs != null) {
|
||||
String extraPrefix = cs.withPrefix ? configField.getName() + "_" : "";
|
||||
return writeTunerStudio(cs, prefix + extraPrefix, tsHeader, tsPosition);
|
||||
}
|
||||
|
||||
if (configField.isBit()) {
|
||||
tsHeader.write(nameWithPrefix + " = bits, U32,");
|
||||
tsHeader.write(" " + tsPosition + ", [");
|
||||
tsHeader.write(bitIndex + ":" + bitIndex);
|
||||
tsHeader.write("]");
|
||||
if (longForm)
|
||||
tsHeader.write(", \"" + configField.getFalseName() + "\", \"" + configField.getTrueName() + "\"");
|
||||
tsHeader.write(EOL);
|
||||
|
||||
tsPosition += configField.getSize(next);
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
if (configField.getState().tsCustomLine.containsKey(configField.getType())) {
|
||||
String bits = configField.getState().tsCustomLine.get(configField.getType());
|
||||
if (!bits.startsWith("bits")) {
|
||||
bits = handleTsInfo(bits, 5);
|
||||
}
|
||||
|
||||
bits = bits.replaceAll("@OFFSET@", "" + tsPosition);
|
||||
tsHeader.write(nameWithPrefix + " = " + bits);
|
||||
|
||||
tsPosition += configField.getState().tsCustomSize.get(configField.getType());
|
||||
} else if (configField.getTsInfo() == null) {
|
||||
throw new IllegalArgumentException("Need TS info for " + configField.getName() + " at " + prefix);
|
||||
} else if (configField.getArraySizes().length == 0) {
|
||||
tsHeader.write(nameWithPrefix + " = scalar, ");
|
||||
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
|
||||
tsHeader.write(" " + tsPosition + ",");
|
||||
tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1));
|
||||
tsPosition += configField.getSize(next);
|
||||
} else if (configField.getSize(next) == 0) {
|
||||
// write nothing for empty array
|
||||
// TS does not like those
|
||||
} else {
|
||||
tsHeader.write(nameWithPrefix + " = array, ");
|
||||
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
|
||||
tsHeader.write(" " + tsPosition + ",");
|
||||
tsHeader.write(" [");
|
||||
boolean first = true;
|
||||
for (int size : configField.getArraySizes()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
tsHeader.write("x");
|
||||
}
|
||||
tsHeader.write(Integer.toString(size));
|
||||
}
|
||||
tsHeader.write("], " + handleTsInfo(configField.getTsInfo(), 1));
|
||||
|
||||
tsPosition += configField.getSize(next);
|
||||
}
|
||||
tsHeader.write(EOL);
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
protected int writeTunerStudio(ConfigStructure configStructure, String prefix, Writer tsHeader, int tsPosition) throws IOException {
|
||||
BitState bitState = new BitState();
|
||||
ConfigField prev = ConfigField.VOID;
|
||||
int prevTsPosition = tsPosition;
|
||||
for (int i = 0; i < configStructure.tsFields.size(); i++) {
|
||||
ConfigField next = i == configStructure.tsFields.size() - 1 ? ConfigField.VOID : configStructure.tsFields.get(i + 1);
|
||||
ConfigField cf = configStructure.tsFields.get(i);
|
||||
|
||||
// if duplicate names, use previous position
|
||||
if (cf.getName().equals(prev.getName())) {
|
||||
tsPosition = prevTsPosition;
|
||||
}
|
||||
|
||||
// Update 'prev' state needed for duplicate names recognition
|
||||
if (!cf.isDirective()) {
|
||||
prevTsPosition = tsPosition;
|
||||
prev = cf;
|
||||
}
|
||||
|
||||
tsPosition = writeTunerStudio(cf, prefix, tsHeader, tsPosition, next, bitState.get());
|
||||
|
||||
bitState.incrementBitIndex(cf, next);
|
||||
}
|
||||
return tsPosition;
|
||||
}
|
||||
|
||||
|
||||
private String handleTsInfo(String tsInfo, int multiplierIndex) {
|
||||
try {
|
||||
String[] fields = tsInfo.split("\\,");
|
||||
if (fields.length > multiplierIndex) {
|
||||
/**
|
||||
* Evaluate static math on .ini layer to simplify rusEFI java and rusEFI PHP project consumers
|
||||
* https://github.com/rusefi/web_backend/issues/97
|
||||
*/
|
||||
double val = IniField.parseDouble(fields[multiplierIndex]);
|
||||
|
||||
if (val == 0) {
|
||||
fields[multiplierIndex] = " 0";
|
||||
} else if (val == 1) {
|
||||
fields[multiplierIndex] = " 1";
|
||||
} else {
|
||||
fields[multiplierIndex] = " " + val;
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!longForm) {
|
||||
String[] subarray = new String[3];
|
||||
System.arraycopy(fields, 0, subarray, 0, subarray.length);
|
||||
fields = subarray;
|
||||
}
|
||||
for (String f : fields) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(f);
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException("While parsing " + tsInfo, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.rusefi.test;
|
||||
|
||||
import com.rusefi.ReaderState;
|
||||
import com.rusefi.output.ConfigurationConsumer;
|
||||
import com.rusefi.output.OutputsSectionConsumer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Collections;
|
||||
|
||||
public class OutputsTest {
|
||||
@Test
|
||||
public void generateSomething() throws IOException {
|
||||
String test = "struct total\n" +
|
||||
"float afr_type;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
|
||||
"uint8_t afr_typet;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
|
||||
"bit isForcedInduction;Does the vehicle have a turbo or supercharger?\n" +
|
||||
"bit enableFan1WithAc;+Turn on this fan when AC is on.\n" +
|
||||
"end_struct\n";
|
||||
ReaderState state = new ReaderState();
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
|
||||
OutputsSectionConsumer tsProjectConsumer = new OutputsSectionConsumer(null, state);
|
||||
state.readBufferedReader(reader, Collections.singletonList(tsProjectConsumer));
|
||||
|
||||
|
||||
Assert.assertEquals("afr_type = scalar, F32, 0, \"ms\", 1, 0\n" +
|
||||
"afr_typet = scalar, U08, 4, \"ms\", 1, 0\n" +
|
||||
"isForcedInduction = bits, U32, 5, [0:0]\n" +
|
||||
"enableFan1WithAc = bits, U32, 5, [1:1]\n" +
|
||||
"unusedBit_4_2 = bits, U32, 5, [2:2]\n" +
|
||||
"unusedBit_4_3 = bits, U32, 5, [3:3]\n" +
|
||||
"unusedBit_4_4 = bits, U32, 5, [4:4]\n" +
|
||||
"unusedBit_4_5 = bits, U32, 5, [5:5]\n" +
|
||||
"unusedBit_4_6 = bits, U32, 5, [6:6]\n" +
|
||||
"unusedBit_4_7 = bits, U32, 5, [7:7]\n" +
|
||||
"unusedBit_4_8 = bits, U32, 5, [8:8]\n" +
|
||||
"unusedBit_4_9 = bits, U32, 5, [9:9]\n" +
|
||||
"unusedBit_4_10 = bits, U32, 5, [10:10]\n" +
|
||||
"unusedBit_4_11 = bits, U32, 5, [11:11]\n" +
|
||||
"unusedBit_4_12 = bits, U32, 5, [12:12]\n" +
|
||||
"unusedBit_4_13 = bits, U32, 5, [13:13]\n" +
|
||||
"unusedBit_4_14 = bits, U32, 5, [14:14]\n" +
|
||||
"unusedBit_4_15 = bits, U32, 5, [15:15]\n" +
|
||||
"unusedBit_4_16 = bits, U32, 5, [16:16]\n" +
|
||||
"unusedBit_4_17 = bits, U32, 5, [17:17]\n" +
|
||||
"unusedBit_4_18 = bits, U32, 5, [18:18]\n" +
|
||||
"unusedBit_4_19 = bits, U32, 5, [19:19]\n" +
|
||||
"unusedBit_4_20 = bits, U32, 5, [20:20]\n" +
|
||||
"unusedBit_4_21 = bits, U32, 5, [21:21]\n" +
|
||||
"unusedBit_4_22 = bits, U32, 5, [22:22]\n" +
|
||||
"unusedBit_4_23 = bits, U32, 5, [23:23]\n" +
|
||||
"unusedBit_4_24 = bits, U32, 5, [24:24]\n" +
|
||||
"unusedBit_4_25 = bits, U32, 5, [25:25]\n" +
|
||||
"unusedBit_4_26 = bits, U32, 5, [26:26]\n" +
|
||||
"unusedBit_4_27 = bits, U32, 5, [27:27]\n" +
|
||||
"unusedBit_4_28 = bits, U32, 5, [28:28]\n" +
|
||||
"unusedBit_4_29 = bits, U32, 5, [29:29]\n" +
|
||||
"unusedBit_4_30 = bits, U32, 5, [30:30]\n" +
|
||||
"unusedBit_4_31 = bits, U32, 5, [31:31]\n" +
|
||||
"alignmentFill_at_9 = array, U08, 9, [3], \"units\", 1, 0\n", new String(tsProjectConsumer.getTsWriter().toCharArray()));
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue