diff --git a/firmware/console/binary/live_data.cpp b/firmware/console/binary/live_data.cpp index 466c5205b6..9555f6ab05 100644 --- a/firmware/console/binary/live_data.cpp +++ b/firmware/console/binary/live_data.cpp @@ -56,8 +56,12 @@ const ac_control_s* getLiveDataAddr() { } template<> -const fan_control_s* getLiveDataAddr() { - return &engine->fan1; +const fan_control_s* getLiveDataAddr(size_t idx) { + switch (idx) { + case 0: return &engine->fan1; + case 1: return &engine->fan2; + default: return nullptr; + } } template<> @@ -117,8 +121,7 @@ const ignition_state_s* getLiveDataAddr() { } template<> -const electronic_throttle_s* getLiveDataAddr() { - // todo: figure out how to handle two units? +const electronic_throttle_s* getLiveDataAddr(size_t) { // return engine->etbControllers[0]; return nullptr; } diff --git a/firmware/controllers/actuators/idle_state.txt b/firmware/controllers/actuators/idle_state.txt index 40b00221e1..850c7b2138 100644 --- a/firmware/controllers/actuators/idle_state.txt +++ b/firmware/controllers/actuators/idle_state.txt @@ -2,7 +2,9 @@ struct_no_prefix idle_state_s custom idle_state_e 4 bits, S32, @OFFSET@, [0:2], "not important" idle_state_e idleState -custom percent_t 4 bits, F32, @OFFSET@, [0:2], "not important" + + custom percent_t 4 scalar, F32, @OFFSET@, "", 1, 0, 0, 100, 2 + percent_t currentIdlePosition;that's current position with CLT and IAT corrections percent_t baseIdlePosition;current position without adjustments (iacByTpsTaper, afterCrankingIACtaperDuration) percent_t iacByTpsTaper;iacByTpsTaper portion of idle diff --git a/firmware/controllers/algo/engine_state.txt b/firmware/controllers/algo/engine_state.txt index 11326505df..20390e27bd 100644 --- a/firmware/controllers/algo/engine_state.txt +++ b/firmware/controllers/algo/engine_state.txt @@ -72,10 +72,10 @@ end_struct ! actually define a member of 'running_fuel_s' type running_fuel_s running -custom percent_t 4 bits, F32, @OFFSET@, [0:2], "not important" - -percent_t etbFeedForward; + custom percent_t 4 scalar, F32, @OFFSET@, "", 1, 0, 0, 100, 2 + ! todo: move these to ETB state, not engine + percent_t etbFeedForward percent_t targetFromTable ! spark-related diff --git a/firmware/controllers/algo/tps_accel_state.txt b/firmware/controllers/algo/tps_accel_state.txt index d8cbbaf4e5..14a7ce7796 100644 --- a/firmware/controllers/algo/tps_accel_state.txt +++ b/firmware/controllers/algo/tps_accel_state.txt @@ -1,10 +1,10 @@ struct_no_prefix tps_accel_state_s -custom percent_t 4 bits, F32, @OFFSET@, [0:2], "not important" +custom percent_t 4 scalar, F32, @OFFSET@, "", 1, 0, 0, 100, 2 -percent_t tpsFrom; -percent_t tpsTo; -percent_t deltaTps; +percent_t tpsFrom +percent_t tpsTo +percent_t deltaTps floatms_t extraFuel; float valueFromTable; diff --git a/firmware/integration/LiveData.yaml b/firmware/integration/LiveData.yaml index 78c98a745a..401a69fd42 100644 --- a/firmware/integration/LiveData.yaml +++ b/firmware/integration/LiveData.yaml @@ -21,10 +21,12 @@ Usages: - name: knock_controller java: KnockController.java folder: controllers/engine_cycle + output_name: knock - name: high_pressure_fuel_pump java: HighPressureFuelPump.java folder: controllers/engine_cycle + output_name: hpfp - name: injector_model java: InjectorModel.java @@ -37,23 +39,28 @@ Usages: - name: boost_control java: BoostControl.java folder: controllers/actuators + output_name: boost - name: ac_control java: AcControl.java folder: controllers/actuators prepend: integration/rusefi_config.txt + output_name: ac - name: fan_control java: FanControl.java folder: controllers/actuators + output_name: [ "fan1", "fan2" ] - name: fuel_pump_control java: FuelPump.java folder: controllers/actuators + output_name: fuelPump - name: main_relay java: MainRelay.java folder: controllers/actuators + output_name: mainRelay #todo: handle ETB pid and Idle pid which point at same pid_state.txt # - name: pid_state @@ -95,3 +102,4 @@ Usages: - name: electronic_throttle java: ElectronicThrottle.java folder: controllers/actuators + output_name: [ "etb1", "etb2" ] diff --git a/java_tools/ConfigDefinition.jar b/java_tools/ConfigDefinition.jar index 7666317cef..16def966d9 100644 Binary files a/java_tools/ConfigDefinition.jar and b/java_tools/ConfigDefinition.jar differ diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/UsagesReader.java b/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/UsagesReader.java index ba0d7e3a25..a13fa59407 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/UsagesReader.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/UsagesReader.java @@ -3,6 +3,10 @@ package com.rusefi.ldmp; import com.devexperts.logging.Logging; import com.rusefi.ConfigDefinition; import com.rusefi.ReaderState; +import com.rusefi.RusefiParseErrorStrategy; +import com.rusefi.newparse.ParseState; +import com.rusefi.newparse.outputs.OutputChannelWriter; +import com.rusefi.newparse.parsing.Definition; import com.rusefi.output.*; import org.yaml.snakeyaml.Yaml; @@ -74,7 +78,7 @@ public class UsagesReader { JavaSensorsConsumer javaSensorsConsumer = new JavaSensorsConsumer(); String tsOutputsDestination = "console/binary/"; - ConfigurationConsumer outputsSections = new OutputsSectionConsumer(tsOutputsDestination + File.separator + "generated/output_channels.ini"); + OutputChannelWriter outputChannelWriter = new OutputChannelWriter(tsOutputsDestination + File.separator + "generated/output_channels.ini"); ConfigurationConsumer dataLogConsumer = new DataLogConsumer(tsOutputsDestination + File.separator + "generated/data_logs.ini"); @@ -87,11 +91,11 @@ public class UsagesReader { log.info("Starting " + name + " at " + startingPosition); ReaderState state = new ReaderState(); - state.setDefinitionInputFile(folder + File.separator + name + ".txt"); + String definitionInputFile = folder + File.separator + name + ".txt"; + state.setDefinitionInputFile(definitionInputFile); state.withC_Defines = withCDefines; state.addDestination(javaSensorsConsumer, - outputsSections, dataLogConsumer ); FragmentDialogConsumer fragmentDialogConsumer = new FragmentDialogConsumer(name); @@ -102,6 +106,26 @@ public class UsagesReader { state.addJavaDestination("../java_console/models/src/main/java/com/rusefi/config/generated/" + javaName); state.doJob(); + { + ParseState parseState = new ParseState(state.enumsReader); + + parseState.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed); + + if (prepend != null && !prepend.isEmpty()) { + RusefiParseErrorStrategy.parseDefinitionFile(parseState.getListener(), prepend); + } + + RusefiParseErrorStrategy.parseDefinitionFile(parseState.getListener(), definitionInputFile); + + // if (outputNames.length == 0) { + outputChannelWriter.writeOutputChannels(parseState, null); + // } else { + // for (int i = 0; i < outputNames.length; i++) { + // outputChannelWriter.writeOutputChannels(parseState, outputNames[i]); + // } + // } + } + fancyNewStuff.append(fragmentDialogConsumer.getContent()); fancyNewMenu.append(fragmentDialogConsumer.menuLine()); diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ArrayLayout.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ArrayLayout.java index a7b3dd94e5..9794faf977 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ArrayLayout.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ArrayLayout.java @@ -73,4 +73,9 @@ public class ArrayLayout extends Layout { this.prototypeLayout.writeCLayout(ps, this.length); } } + + @Override + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + this.prototypeLayout.writeOutputChannelLayout(ps, prefixer, offsetAdd, this.length); + } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/BitGroupLayout.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/BitGroupLayout.java index 2b82ab2bc6..ac466ca1e0 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/BitGroupLayout.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/BitGroupLayout.java @@ -89,4 +89,22 @@ public class BitGroupLayout extends Layout { } } } + + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + int actualOffset = this.offset + offsetAdd; + + for (int i = 0; i < bits.size(); i++) { + BitLayout bit = bits.get(i); + + ps.print(prefixer.get(bit.name)); + ps.print(" = bits, U32, "); + ps.print(actualOffset); + ps.print(", ["); + ps.print(i + ":" + i); + + ps.print("]"); + + ps.println(); + } + } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/EnumLayout.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/EnumLayout.java index a2612667db..f7f4e8966e 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/EnumLayout.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/EnumLayout.java @@ -72,4 +72,15 @@ public class EnumLayout extends Layout { this.writeCOffsetHeader(ps, this.options.comment, this.options.units); ps.println("\t" + this.enumType + " " + this.name + "[" + arrayLength[0] + "];"); } + + @Override + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + // Output an enum as a scalar, since there's no TS support for enum output channels + ps.print(prefixer.get(name)); + ps.print(" = scalar, "); + ps.print(this.type.tsType); + ps.print(", "); + ps.print(this.offset + offsetAdd); + ps.println(", \"\", 1, 0"); + } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/Layout.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/Layout.java index 944ee27041..0de19559ee 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/Layout.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/Layout.java @@ -67,4 +67,20 @@ public abstract class Layout { public void writeCLayout(PrintStream ps, int[] arrayLength) { throw new IllegalStateException("This type can't be in an array!"); } + + public void writeOutputChannelLayout(PrintStream ps, String prefix, int offsetAdd) { + StructNamePrefixer prefixer = new StructNamePrefixer(); + + if (prefix != null) { + prefixer.push(prefix); + } + + writeOutputChannelLayout(ps, prefixer, offsetAdd); + } + + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { } + + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayLength) { + throw new IllegalStateException("This type can't be in an array!"); + } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ScalarLayout.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ScalarLayout.java index 69e493e1c7..4b231923e8 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ScalarLayout.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/ScalarLayout.java @@ -147,4 +147,40 @@ public class ScalarLayout extends Layout { ps.println("\t" + cTypeName + " " + this.name + "[" + al + "];"); } + + private void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, String name) { + ps.print(prefixer.get(name)); + //ps.print(" = " + fieldType + ", "); + ps.print(" = scalar, "); + ps.print(this.type.tsType); + ps.print(", "); + ps.print(this.offset + offsetAdd); + ps.print(", "); + ps.print(this.options.units); + ps.print(", "); + ps.print(FieldOptions.tryRound(this.options.scale)); + ps.print(", "); + ps.print(FieldOptions.tryRound(this.options.offset)); + + ps.println(); + } + + @Override + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + writeOutputChannelLayout(ps, prefixer, offsetAdd, this.name); + } + + @Override + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayLength) { + if (arrayLength.length != 1) { + throw new IllegalStateException("Output channels don't support multi dimension arrays"); + } + + int elementOffset = offsetAdd; + + for (int i = 0; i < arrayLength[0]; i++) { + writeOutputChannelLayout(ps, prefixer, elementOffset, this.name + (i + 1)); + elementOffset += type.size; + } + } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/StructLayout.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/StructLayout.java index 57eab6edb0..2a984a2de6 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/StructLayout.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/layout/StructLayout.java @@ -192,8 +192,22 @@ public class StructLayout extends Layout { this.children.forEach(c -> c.writeCLayout(ps)); - ps.println("\t/** total size " + getSize() + "*/"); ps.println("};"); + ps.println("static_assert(sizeof(" + this.typeName + ") == " + getSize() + ");"); + ps.println(); } + + @Override + protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + if (!this.noPrefix) { + prefixer.push(this.name); + } + + this.children.forEach(c -> c.writeOutputChannelLayout(ps, prefixer, offsetAdd)); + + if (!this.noPrefix) { + prefixer.pop(); + } + } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/CStructWriter.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/CStructWriter.java index f1d6463dc7..cb3f7ed0c9 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/CStructWriter.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/CStructWriter.java @@ -8,12 +8,9 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; -/** - * proposed alternative which does not seem to be covered by any unit tests - */ public class CStructWriter { public void writeCStructs(ParseState parser, String outputFile) throws FileNotFoundException { - writeCStructs(parser, new PrintStream(new FileOutputStream(outputFile))); + writeCStructs(parser, new PrintStreamAlwaysUnix(new FileOutputStream(outputFile))); } public void writeCStructs(ParseState parser, PrintStream ps) { diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/OutputChannelWriter.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/OutputChannelWriter.java new file mode 100644 index 0000000000..09d30ea6e4 --- /dev/null +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/OutputChannelWriter.java @@ -0,0 +1,34 @@ +package com.rusefi.newparse.outputs; + +import com.rusefi.newparse.ParseState; +import com.rusefi.newparse.layout.StructLayout; +import com.rusefi.newparse.parsing.Struct; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; + +public class OutputChannelWriter { + private final PrintStream ps; + + public OutputChannelWriter(String outputFile) throws FileNotFoundException { + this.ps = new PrintStreamAlwaysUnix(new FileOutputStream(outputFile)); + } + + public OutputChannelWriter(PrintStream ps) { + this.ps = ps; + } + + private int cumulativeSize = 0; + + public void writeOutputChannels(ParseState parser, String namePrefix) throws FileNotFoundException { + // Assume the last struct is the one we want... + Struct s = parser.getStructs().get(parser.getStructs().size() - 1); + + StructLayout sl = new StructLayout(0, "root", s); + sl.writeOutputChannelLayout(ps, namePrefix, cumulativeSize); + + cumulativeSize += sl.getSize(); + ps.println("; total TS size = " + cumulativeSize); + } +} diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/PrintStreamAlwaysUnix.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/PrintStreamAlwaysUnix.java new file mode 100644 index 0000000000..4401b21894 --- /dev/null +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/PrintStreamAlwaysUnix.java @@ -0,0 +1,26 @@ +package com.rusefi.newparse.outputs; + +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +public class PrintStreamAlwaysUnix extends PrintStream { + public PrintStreamAlwaysUnix(OutputStream out) { + super(out); + } + + public PrintStreamAlwaysUnix(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException { + super(out, autoFlush, encoding); + } + + @Override + public void println() { + print('\n'); + } + + @Override + public void println(String s) { + print(s); + println(); + } +} diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/TsWriter.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/TsWriter.java index 908036de76..72b61a6cbe 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/TsWriter.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/TsWriter.java @@ -8,9 +8,6 @@ import java.io.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** - * proposed alternative which does not seem to be covered by any unit tests - */ public class TsWriter { // matches strings in the form of @@MY_var_123@@ private static final Pattern VAR = Pattern.compile("@@([a-zA-Z0-9_]+?)@@"); @@ -18,7 +15,7 @@ public class TsWriter { private static final Pattern OPTIONAL_LINE = Pattern.compile("@@if_([a-zA-Z0-9_]+)"); public void writeTunerstudio(ParseState parser, String inputFile, String outputFile) throws IOException { - PrintStream ps = new PrintStream(new FileOutputStream(outputFile)); + PrintStream ps = new PrintStreamAlwaysUnix(new FileOutputStream(outputFile)); writeTunerstudio(parser, inputFile, ps); ps.close(); } diff --git a/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/LayoutTest.java b/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/LayoutTest.java index 27b28b518b..f2fdf9bb60 100644 --- a/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/LayoutTest.java +++ b/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/LayoutTest.java @@ -5,14 +5,16 @@ import org.junit.Test; import java.io.IOException; +import static com.rusefi.test.newParse.NewParseHelper.parseToOutputChannels; import static com.rusefi.test.newParse.NewParseHelper.parseToTs; +import static org.junit.Assert.assertEquals; public class LayoutTest { @Test public void singleField() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "int8_t xyz;comment;\"units\", 1, 2, 3, 4, 5\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 4\n" + @@ -21,15 +23,20 @@ public class LayoutTest { "; unused 3 bytes at offset 1\n" + "; total TS size = 4\n" + "[SettingContextHelp]\n" + - "\txyz = \"comment\"\n", ts); + "\txyz = \"comment\"\n", parseToTs(input)); + + Assert.assertEquals( + "xyz = scalar, S08, 0, \"units\", 1, 2\n" + + "; total TS size = 4\n" + , parseToOutputChannels(input)); } @Test public void twoFieldsSameSize() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "int32_t abc;;\"\", 1, 2, 3, 4, 5\n" + "int32_t xyz;;\"\", 6, 7, 8, 9, 10\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 8\n" + @@ -37,15 +44,20 @@ public class LayoutTest { "abc = scalar, S32, 0, \"\", 1, 2, 3, 4, 5\n" + "xyz = scalar, S32, 4, \"\", 6, 7, 8, 9, 10\n" + "; total TS size = 8\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "abc = scalar, S32, 0, \"\", 1, 2\n" + + "xyz = scalar, S32, 4, \"\", 6, 7\n" + + "; total TS size = 8\n", parseToOutputChannels(input)); } @Test public void twoFieldsBigThenSmall() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "int32_t abc;;\"\", 1, 2, 3, 4, 5\n" + "int8_t xyz;;\"\", 6, 7, 8, 9, 10\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 8\n" + @@ -54,15 +66,20 @@ public class LayoutTest { "xyz = scalar, S08, 4, \"\", 6, 7, 8, 9, 10\n" + "; unused 3 bytes at offset 5\n" + "; total TS size = 8\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "abc = scalar, S32, 0, \"\", 1, 2\n" + + "xyz = scalar, S08, 4, \"\", 6, 7\n" + + "; total TS size = 8\n", parseToOutputChannels(input)); } @Test public void twoFieldsSmallThenBig() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "int8_t abc;;\"\", 1, 2, 3, 4, 5\n" + "int32_t xyz;;\"\", 6, 7, 8, 9, 10\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 8\n" + @@ -71,16 +88,21 @@ public class LayoutTest { "; unused 3 bytes at offset 1\n" + "xyz = scalar, S32, 4, \"\", 6, 7, 8, 9, 10\n" + "; total TS size = 8\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "abc = scalar, S08, 0, \"\", 1, 2\n" + + "xyz = scalar, S32, 4, \"\", 6, 7\n" + + "; total TS size = 8\n", parseToOutputChannels(input)); } @Test public void threeFieldsSmallInMisalignment() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "int16_t abc\n" + "int8_t def\n" + "int32_t xyz\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 8\n" + @@ -90,15 +112,21 @@ public class LayoutTest { "; unused 1 bytes at offset 3\n" + "xyz = scalar, S32, 4, \"\", 1, 0, 0, 0, 0\n" + "; total TS size = 8\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "abc = scalar, S16, 0, \"\", 1, 0\n" + + "def = scalar, S08, 2, \"\", 1, 0\n" + + "xyz = scalar, S32, 4, \"\", 1, 0\n" + + "; total TS size = 8\n", parseToOutputChannels(input)); } @Test public void twoFieldsArrayThenBig() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "int8_t[10] abc;;\"\", 1, 2, 3, 4, 5\n" + "int32_t xyz;;\"\", 6, 7, 8, 9, 10\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 16\n" + @@ -107,7 +135,21 @@ public class LayoutTest { "; unused 2 bytes at offset 10\n" + "xyz = scalar, S32, 12, \"\", 6, 7, 8, 9, 10\n" + "; total TS size = 16\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "abc1 = scalar, S08, 0, \"\", 1, 2\n" + + "abc2 = scalar, S08, 1, \"\", 1, 2\n" + + "abc3 = scalar, S08, 2, \"\", 1, 2\n" + + "abc4 = scalar, S08, 3, \"\", 1, 2\n" + + "abc5 = scalar, S08, 4, \"\", 1, 2\n" + + "abc6 = scalar, S08, 5, \"\", 1, 2\n" + + "abc7 = scalar, S08, 6, \"\", 1, 2\n" + + "abc8 = scalar, S08, 7, \"\", 1, 2\n" + + "abc9 = scalar, S08, 8, \"\", 1, 2\n" + + "abc10 = scalar, S08, 9, \"\", 1, 2\n" + + "xyz = scalar, S32, 12, \"\", 6, 7\n" + + "; total TS size = 16\n", parseToOutputChannels(input)); } @Test @@ -152,10 +194,9 @@ public class LayoutTest { @Test public void arrayIterate() throws IOException { - String ts = parseToTs( - "struct_no_prefix rootStruct\n" + + String input = "struct_no_prefix rootStruct\n" + "int32_t[4 iterate] myArr\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 16\n" + @@ -165,7 +206,14 @@ public class LayoutTest { "myArr3 = scalar, S32, 8, \"\", 1, 0, 0, 0, 0\n" + "myArr4 = scalar, S32, 12, \"\", 1, 0, 0, 0, 0\n" + "; total TS size = 16\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "myArr1 = scalar, S32, 0, \"\", 1, 0\n" + + "myArr2 = scalar, S32, 4, \"\", 1, 0\n" + + "myArr3 = scalar, S32, 8, \"\", 1, 0\n" + + "myArr4 = scalar, S32, 12, \"\", 1, 0\n" + + "; total TS size = 16\n", parseToOutputChannels(input)); } @Test @@ -214,11 +262,11 @@ public class LayoutTest { @Test public void bits() throws IOException { - String ts = parseToTs("struct_no_prefix myStruct\n" + + String input = "struct_no_prefix myStruct\n" + "bit first\n" + "bit second\n" + "bit withOpt,\"a\",\"b\"\n" + - "end_struct"); + "end_struct"; Assert.assertEquals( "pageSize = 4\n" + @@ -227,6 +275,33 @@ public class LayoutTest { "second = bits, U32, 0, [1:1], \"false\", \"true\"\n" + "withOpt = bits, U32, 0, [2:2], \"b\", \"a\"\n" + "; total TS size = 4\n" + - "[SettingContextHelp]\n", ts); + "[SettingContextHelp]\n", parseToTs(input)); + + Assert.assertEquals( + "first = bits, U32, 0, [0:0]\n" + + "second = bits, U32, 0, [1:1]\n" + + "withOpt = bits, U32, 0, [2:2]\n" + + "; total TS size = 4\n" + , parseToOutputChannels(input)); + } + + @Test + public void bigOutputChannels() throws IOException { + String input = "struct_no_prefix total\n" + + "float afr_type;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" + + "uint8_t afr_typet;@@GAUGE_NAME_FUEL_WALL_CORRECTION@@;\"ms\", 1, 0, 0, 3000, 0\n" + + "bit isForcedInduction;isForcedInduction\\nDoes the vehicle have a turbo or supercharger?\n" + + "bit enableFan1WithAc;+Turn on this fan when AC is on.\n" + + "angle_t m_requested_pump;Computed requested pump \n" + + "float tCharge;speed density\n" + + "end_struct\n"; + + assertEquals("afr_type = scalar, F32, 0, \"ms\", 1, 0\n" + + "afr_typet = scalar, U08, 4, \"ms\", 1, 0\n" + + "isForcedInduction = bits, U32, 8, [0:0]\n" + + "enableFan1WithAc = bits, U32, 8, [1:1]\n" + + "m_requested_pump = scalar, F32, 12, \"\", 1, 0\n" + + "tCharge = scalar, F32, 16, \"\", 1, 0\n" + + "; total TS size = 20\n", parseToOutputChannels(input)); } } diff --git a/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/NewParseHelper.java b/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/NewParseHelper.java index 2f9d07185f..dde7fe38fb 100644 --- a/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/NewParseHelper.java +++ b/java_tools/configuration_definition/src/test/java/com/rusefi/test/newParse/NewParseHelper.java @@ -3,6 +3,8 @@ package com.rusefi.test.newParse; import com.rusefi.RusefiParseErrorStrategy; import com.rusefi.newparse.ParseState; import com.rusefi.newparse.outputs.CStructWriter; +import com.rusefi.newparse.outputs.OutputChannelWriter; +import com.rusefi.newparse.outputs.PrintStreamAlwaysUnix; import com.rusefi.newparse.outputs.TsWriter; import java.io.*; @@ -15,23 +17,6 @@ public class NewParseHelper { return parseState; } - private static class PrintStreamAlwaysUnix extends PrintStream { - public PrintStreamAlwaysUnix(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException { - super(out, autoFlush, encoding); - } - - @Override - public void println() { - print('\n'); - } - - @Override - public void println(String s) { - print(s); - println(); - } - } - public static String parseToTs(String input) throws IOException { ParseState state = parse(input); @@ -47,6 +32,20 @@ public class NewParseHelper { return baos.toString(utf8); } + public static String parseToOutputChannels(String input) throws IOException { + ParseState state = parse(input); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final String utf8 = StandardCharsets.UTF_8.name(); + + PrintStream ps = new PrintStreamAlwaysUnix(baos, true, utf8); + + OutputChannelWriter writer = new OutputChannelWriter(ps); + writer.writeOutputChannels(state, null); + + return baos.toString(utf8); + } + public static String parseToC(String input) throws IOException { ParseState state = parse(input);