diff --git a/firmware/console/binary/tunerstudio.cpp b/firmware/console/binary/tunerstudio.cpp index b19c417813..f10a73a031 100644 --- a/firmware/console/binary/tunerstudio.cpp +++ b/firmware/console/binary/tunerstudio.cpp @@ -474,6 +474,7 @@ static bool isKnownCommand(char command) { || command == TS_GET_FILE_RANGE || command == TS_SET_LOGGER_SWITCH || command == TS_GET_LOGGER_GET_BUFFER + || command == TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY || command == TS_GET_TEXT || command == TS_CRC_CHECK_COMMAND || command == TS_GET_FIRMWARE_VERSION @@ -841,17 +842,28 @@ int tunerStudioHandleCrcCommand(ts_channel_s *tsChannel, char *data, int incomin break; case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY: + { + EnableToothLoggerIfNotEnabled(); const uint8_t* const buffer = GetToothLoggerBuffer().Buffer; const uint8_t* const start = buffer + COMPOSITE_PACKET_SIZE * transmitted; int currentEnd = getCompositeRecordCount(); + // set debug_mode 40 + if (engineConfiguration->debugMode == DBG_40) { + tsOutputChannels.debugIntField1 = currentEnd; + tsOutputChannels.debugIntField2 = transmitted; + + } + if (currentEnd > transmitted) { // more normal case - tail after head sr5SendResponse(tsChannel, TS_CRC, start, COMPOSITE_PACKET_SIZE * (currentEnd - transmitted)); transmitted = currentEnd; + } else if (currentEnd == transmitted) { + sr5SendResponse(tsChannel, TS_CRC, start, 0); } else { // we are here if tail of buffer has reached the end of buffer and re-started from the start of buffer // sending end of the buffer, next transmission would take care of the rest diff --git a/java_console/inifile/src/com/opensr5/ini/field/EnumIniField.java b/java_console/inifile/src/com/opensr5/ini/field/EnumIniField.java index 4909a6bb94..9ce42f10fc 100644 --- a/java_console/inifile/src/com/opensr5/ini/field/EnumIniField.java +++ b/java_console/inifile/src/com/opensr5/ini/field/EnumIniField.java @@ -46,6 +46,10 @@ public class EnumIniField extends IniField { return enums.get(ordinal); } + public static boolean getBit(int ordinal, int bitPosition) { + return getBitRange(ordinal, bitPosition, 0) == 1; + } + public static int getBitRange(int ordinal, int bitPosition, int bitSize) { ordinal = ordinal >> bitPosition; ordinal = ordinal & ((1 << (bitSize + 1)) - 1); diff --git a/java_console/inifile/src/com/opensr5/ini/test/IniFileReaderTest.java b/java_console/inifile/src/com/opensr5/ini/test/IniFileReaderTest.java index 9fd769537e..ec5d2a5a38 100644 --- a/java_console/inifile/src/com/opensr5/ini/test/IniFileReaderTest.java +++ b/java_console/inifile/src/com/opensr5/ini/test/IniFileReaderTest.java @@ -108,9 +108,9 @@ public class IniFileReaderTest { assertEquals(0, EnumIniField.getBitRange(4, 0, 1)); assertEquals(3, EnumIniField.getBitRange(7, 0, 1)); - assertEquals(1, EnumIniField.getBitRange(0xff, 0, 0)); + assertEquals(true, EnumIniField.getBit(0xff, 0)); - assertEquals(1, EnumIniField.getBitRange(0xf0, 4, 0)); + assertEquals(true, EnumIniField.getBit(0xf0, 4)); assertEquals(2, EnumIniField.getBitRange(0xf0, 3, 1)); } diff --git a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java index 9b6d027290..89be55b1c1 100644 --- a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java +++ b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java @@ -7,6 +7,8 @@ import com.opensr5.io.DataListener; import com.rusefi.ConfigurationImageDiff; import com.rusefi.FileLog; import com.rusefi.Timeouts; +import com.rusefi.composite.CompositeEvent; +import com.rusefi.composite.CompositeParser; import com.rusefi.config.generated.Fields; import com.rusefi.core.Pair; import com.rusefi.core.Sensor; @@ -18,10 +20,12 @@ import jssc.SerialPortException; import org.jetbrains.annotations.Nullable; import java.io.EOFException; +import java.io.FileWriter; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -148,6 +152,7 @@ public class BinaryProtocol implements BinaryProtocolCommands { public void run() { if (requestOutputChannels()) ConnectionWatchdog.onDataArrived(); +// getComposite(); String text = requestPendingMessages(); if (text != null) listener.onDataArrived((text + "\r\n").getBytes()); @@ -446,15 +451,22 @@ public class BinaryProtocol implements BinaryProtocolCommands { } } - public void getComposite() throws IOException { + public void getComposite() { if (isClosed) return; byte packet[] = new byte[1]; packet[0] = Fields.TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY; -// executeCommand() - + byte[] response = executeCommand(packet, "composite log", true); + if (checkResponseCode(response, RESPONSE_OK)) { + List events = CompositeParser.parse(response); + try { + CompositeParser.writeVCD(events, new FileWriter("rusEFI.vcd")); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } } public boolean requestOutputChannels() { diff --git a/java_console/models/src/com/rusefi/composite/CompositeEvent.java b/java_console/models/src/com/rusefi/composite/CompositeEvent.java new file mode 100644 index 0000000000..af347f138a --- /dev/null +++ b/java_console/models/src/com/rusefi/composite/CompositeEvent.java @@ -0,0 +1,37 @@ +package com.rusefi.composite; + +public class CompositeEvent { + private final int timestamp; + private final boolean primaryTrigger; + private final boolean secondaryTrigger; + private final boolean trg; + private final boolean sync; + + public CompositeEvent(int timestamp, boolean primaryTrigger, boolean secondaryTrigger, boolean trg, boolean sync) { + this.timestamp = timestamp; + this.primaryTrigger = primaryTrigger; + this.secondaryTrigger = secondaryTrigger; + this.trg = trg; + this.sync = sync; + } + + public int getTimestamp() { + return timestamp; + } + + public int isPrimaryTriggerAsInt() { + return primaryTrigger ? 1 : 0; + } + + public int isSecondaryTriggerAsInt() { + return secondaryTrigger ? 1 : 0; + } + + public int isSyncAsInt() { + return sync ? 1 : 0; + } + + public int isTrgAsInt() { + return trg ? 1 : 0; + } +} diff --git a/java_console/models/src/com/rusefi/composite/CompositeParser.java b/java_console/models/src/com/rusefi/composite/CompositeParser.java new file mode 100644 index 0000000000..ac0e0f7bce --- /dev/null +++ b/java_console/models/src/com/rusefi/composite/CompositeParser.java @@ -0,0 +1,85 @@ +package com.rusefi.composite; + +import com.opensr5.ini.field.EnumIniField; +import com.rusefi.config.generated.Fields; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class CompositeParser { + + public static final String TAG_PRIMARY = "t"; + public static final String TAG_SECONDARY = "s"; + public static final String TAG_TRG = "r"; + public static final String TAG_SYNC = "y"; + + public static List parse(byte[] response) { + ByteBuffer byteBuffer = ByteBuffer.wrap(response); + byteBuffer.order(ByteOrder.BIG_ENDIAN); + System.out.println("Got composite " + response.length); + int ptr = 1; + + List events = new ArrayList<>(); + + while (ptr + Fields.COMPOSITE_PACKET_SIZE <= response.length) { + + int timestamp = byteBuffer.getInt(ptr); + byte flags = byteBuffer.get(ptr + 4); + System.out.println(timestamp + " " + flags); + + boolean primaryTrigger = EnumIniField.getBit(flags, 0); + boolean secondaryTrigger = EnumIniField.getBit(flags, 1); + boolean trg = EnumIniField.getBit(flags, 2); + boolean sync = EnumIniField.getBit(flags, 3); + + ptr += Fields.COMPOSITE_PACKET_SIZE; + + events.add(new CompositeEvent(timestamp, primaryTrigger, secondaryTrigger, trg, sync)); + } + return events; + } + + /** + * https://en.wikipedia.org/wiki/Value_change_dump + */ + public static void writeVCD(List events, Writer writer, Date date) throws IOException { + writer.write("$date\n"); + writer.write("\t" + date + "\n"); + writer.write("$end\n" + + "$version\n" + + " 1.0\n" + + "$end\n" + + "$timescale\n" + + " 1ps\n" + + "$end\n" + + "$scope module test $end\n" + + "$var wire 1 " + TAG_PRIMARY + " PRI_TRG $end\n" + + "$var wire 1 " + TAG_SECONDARY + " SEC_TRG $end\n" + + "$var wire 1 " + TAG_TRG + " TRG $end\n" + + "$var wire 1 " + TAG_SYNC + " SYNC $end\n" + + "$upscope $end\n" + + "$enddefinitions $end\n" + + "$dumpvars\n"); + + for (CompositeEvent event : events) { + writer.write("#" + event.getTimestamp() + "\n"); + writer.write(event.isPrimaryTriggerAsInt() + TAG_PRIMARY + "\n"); + writer.write(event.isSecondaryTriggerAsInt() + TAG_SECONDARY + "\n"); + writer.write(event.isTrgAsInt() + TAG_TRG + "\n"); + writer.write(event.isSyncAsInt() + TAG_SYNC + "\n"); + + } + writer.flush(); + } + + public static void writeVCD(List events, FileWriter fileWriter) throws IOException { + writeVCD(events, fileWriter, new Date()); + } +} diff --git a/java_console/models/src/com/rusefi/composite/test/CompositeParserTest.java b/java_console/models/src/com/rusefi/composite/test/CompositeParserTest.java new file mode 100644 index 0000000000..e53295a03f --- /dev/null +++ b/java_console/models/src/com/rusefi/composite/test/CompositeParserTest.java @@ -0,0 +1,23 @@ +package com.rusefi.composite.test; + +import com.rusefi.composite.CompositeEvent; +import com.rusefi.composite.CompositeParser; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Date; +import java.util.List; + +public class CompositeParserTest { + @Test + public void testParseAndExportToVCD() throws IOException { + byte[] input = {0, 1, 110, -101, 53, 58, 1, 110, -86, -43, 42, 1, 110, -78, 14, 10, 1, 110, -74, -67, 8, 1, 110, -23, -30, 9, 1}; + + List events = CompositeParser.parse(input); + + StringWriter writer = new StringWriter(); + //FileWriter writer = new FileWriter("rusEFI.vcd"); + CompositeParser.writeVCD(events, writer, new Date(1590847552574L)); + } +}