fix .logicdata saver (#1484)

Co-authored-by: Andrei <andreikagit@users.noreply.github.com>
This commit is contained in:
andreika-git 2020-06-08 07:57:12 +03:00 committed by GitHub
parent 423e913ad5
commit 0dae581ef7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 58 additions and 40 deletions

View File

@ -13,9 +13,7 @@ import java.util.List;
* Support for Saleae .logicdata format. * Support for Saleae .logicdata format.
* (c) andreika 2020 * (c) andreika 2020
* *
* Jun 6 status: this code mostly works but it does not work completely * Jun 7 status: this code mostly works but it needs more testing
* 1) at some point it looked like file produced by LogicdataStreamFileSandbox was valid but it's again not valid?
* 2) event gaps above 32ms are not supported but those are absolutely required for cranking attempts
* *
* @see LogicdataStreamFileSandbox * @see LogicdataStreamFileSandbox
*/ */
@ -32,6 +30,7 @@ public class LogicdataStreamFile extends StreamFile {
private static final int SUB = 0x54; private static final int SUB = 0x54;
private static final int FLAG_NOTEMPTY = 2; private static final int FLAG_NOTEMPTY = 2;
private static final int FLAG_NOTEMPTY_LONG = 3;
private static final int FLAG_EMPTY = 5; private static final int FLAG_EMPTY = 5;
private static final int LOGIC4 = 0x40FD; private static final int LOGIC4 = 0x40FD;
@ -39,15 +38,19 @@ public class LogicdataStreamFile extends StreamFile {
private static final int [] CHANNEL_FLAGS = { 0x13458b, 0x0000ff, 0x00a0f9, 0x00ffff, 0x00ff00, 0xff0000, 0xf020a0, }; private static final int [] CHANNEL_FLAGS = { 0x13458b, 0x0000ff, 0x00a0f9, 0x00ffff, 0x00ff00, 0xff0000, 0xf020a0, };
private static final long SIGN_FLAG = 0x80000000L;
private static int numChannels = 6; private static int numChannels = 6;
private static int reservedDurationInSamples = 10; private static int reservedDurationInSamples = 10;
private static int realDurationInSamples = 0; private static int realDurationInSamples = 0;
private static int scaledDurationInSamples = 0; private static int scaledDurationInSamples = 0;
private static int int4or5 = 4;
private final String fileName; private final String fileName;
private final List<CompositeEvent> eventsBuffer = new ArrayList<>(); private final List<CompositeEvent> eventsBuffer = new ArrayList<>();
private static final String [] channelNames = { "Primary", "Secondary", "Trg", "Sync", "Coil", "Injector", "Channel 6", "Channel 7" };
public LogicdataStreamFile(String fileName) { public LogicdataStreamFile(String fileName) {
this.fileName = fileName; this.fileName = fileName;
} }
@ -89,9 +92,10 @@ public class LogicdataStreamFile extends StreamFile {
writeChannelDataHeader(); writeChannelDataHeader();
boolean useLongDeltas = false;
// we need to split the combined events into separate channels // we need to split the combined events into separate channels
for (int ch = 0; ch < numChannels; ch++) { for (int ch = 0; ch < numChannels; ch++) {
List<Integer> chDeltas = new ArrayList<>(); List<Long> chDeltas = new ArrayList<>();
int chPrevState = -1; int chPrevState = -1;
int prevTs = 0; int prevTs = 0;
for (CompositeEvent event : events) { for (CompositeEvent event : events) {
@ -102,15 +106,13 @@ public class LogicdataStreamFile extends StreamFile {
chPrevState = chState; chPrevState = chState;
} }
if (chState != chPrevState) { if (chState != chPrevState) {
int delta = ts - prevTs; long delta = ts - prevTs;
if (delta > 0x7fff) { if (delta > 0x7fff) {
// todo: split too long events? useLongDeltas = true;
// this is just 32ms cap between events which is very possible during cranking attempts
throw new IllegalArgumentException("Event too long.");
} }
// encode state // encode state
if (chState == 0) if (chState == 0)
delta |= 0x8000; delta |= SIGN_FLAG;
chDeltas.add(delta); chDeltas.add(delta);
@ -119,7 +121,7 @@ public class LogicdataStreamFile extends StreamFile {
} }
} }
writeChannelData(ch, chDeltas, chPrevState, prevTs); writeChannelData(ch, chDeltas, chPrevState, prevTs, useLongDeltas);
} }
writeChannelDataFooter(); writeChannelDataFooter();
@ -173,16 +175,15 @@ public class LogicdataStreamFile extends StreamFile {
write(BLOCK); write(BLOCK);
int4or5 = (numChannels == 4) ? 4 : 5; writeId(0, 0);
writeId(int4or5, int4or5); write(0);
write(SUB); write(0);
write(0);
} }
private void writeChannelHeader(int ch) throws IOException { private void writeChannelHeader(int ch) throws IOException {
write(0xff); write(0xff);
write(ch); write(ch);
write("Channel " + ch); write(channelNames[ch]);
write(0, 2); write(0, 2);
write(1.0); write(1.0);
write(0); write(0);
@ -233,7 +234,7 @@ public class LogicdataStreamFile extends StreamFile {
write(0, 2); write(0, 2);
write(1); write(1);
write(0, 3); write(0, 3);
writeId(int4or5, 0); writeId(0, 0);
write(BLOCK); write(BLOCK);
write(new int[]{ realDurationInSamples, realDurationInSamples, realDurationInSamples }); write(new int[]{ realDurationInSamples, realDurationInSamples, realDurationInSamples });
@ -265,7 +266,7 @@ public class LogicdataStreamFile extends StreamFile {
write(new int[]{ 1, 0, 1 }); write(new int[]{ 1, 0, 1 });
} }
private void writeChannelData(int ch, List<Integer> chDeltas, int chLastState, int lastRecord) throws IOException { private void writeChannelData(int ch, List<Long> chDeltas, int chLastState, int lastRecord, boolean useLongDeltas) throws IOException {
int numEdges = chDeltas.size(); int numEdges = chDeltas.size();
if (numEdges == 0) if (numEdges == 0)
lastRecord = 0; lastRecord = 0;
@ -280,28 +281,30 @@ public class LogicdataStreamFile extends StreamFile {
write(0); write(0);
write(realDurationInSamples); write(realDurationInSamples);
write(1); write(1);
writeAs(lastRecord, 2); write(lastRecord);
int numSamplesLeft = realDurationInSamples - lastRecord; int numSamplesLeft = realDurationInSamples - lastRecord;
write(numSamplesLeft); write(numSamplesLeft);
write(chLastState); write(chLastState);
if (numEdges == 0) { // empty int chFlag = (numEdges == 0) ? FLAG_EMPTY : (useLongDeltas ? FLAG_NOTEMPTY_LONG : FLAG_NOTEMPTY);
write(FLAG_EMPTY); write(chFlag);
write(0, 30);
return;
}
write(FLAG_NOTEMPTY);
if (ch == 0) { if (ch == 0) {
write(0); write(0);
write(BLOCK); write(BLOCK);
write(0, 11); write(0, 11);
if (useLongDeltas) {
write(BLOCK);
write(0, 6);
}
write(BLOCK); write(BLOCK);
} else { } else {
write(0, 10); write(0, 10);
if (useLongDeltas) {
write(0, 5);
}
} }
write(numEdges); write(numEdges);
@ -310,18 +313,26 @@ public class LogicdataStreamFile extends StreamFile {
write(0); write(0);
write(numEdges); write(numEdges);
writeEdges(chDeltas); writeEdges(chDeltas, useLongDeltas);
if (ch == 0) { if (ch == 0) {
write(BLOCK); write(BLOCK);
write(0, 6); write(0, 6);
if (!useLongDeltas) {
write(BLOCK); write(BLOCK);
write(0, 6); write(0, 6);
}
write(BLOCK); write(BLOCK);
} else { } else {
write(0, 9); write(0, 4);
if (!useLongDeltas) {
write(0, 5);
}
}
if (numEdges == 0) {
write(0, 5);
return;
} }
write(1); write(1);
@ -332,17 +343,24 @@ public class LogicdataStreamFile extends StreamFile {
write(0, 16); write(0, 16);
writeRaw(0xFF, 8); writeRaw(0xFF, 8);
writeRaw(0x02, 1); writeRaw(chFlag, 1);
writeRaw(0x00, 7); writeRaw(0x00, 7);
} }
private void writeEdges(List<Integer> chDeltas) throws IOException { private void writeEdges(List<Long> chDeltas, boolean useLongDeltas) throws IOException {
for (int d : chDeltas) { for (long d : chDeltas) {
stream.write(d & 0xff); // set 16-bit 'sign' flag
stream.write((d >> 8) & 0xff); if (!useLongDeltas && (d & SIGN_FLAG) == SIGN_FLAG)
} d = (d & 0x7fff) | (SIGN_FLAG >> 16);
stream.write(0x00); stream.write((byte)(d & 0xff));
} stream.write((byte)((d >> 8) & 0xff));
if (useLongDeltas) {
stream.write((byte)((d >> 16) & 0xff));
stream.write((byte)((d >> 24) & 0xff));
}
}
stream.write(0x00);
}
private void writeChannelDataFooter() throws IOException { private void writeChannelDataFooter() throws IOException {
write(0, 3); write(0, 3);