2022-11-12 20:00:51 -08:00
|
|
|
package com.rusefi.can.analysis;
|
|
|
|
|
|
|
|
import com.rusefi.can.CANPacket;
|
|
|
|
|
2023-07-30 16:52:39 -07:00
|
|
|
import java.io.*;
|
2022-11-12 20:00:51 -08:00
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
public class CounterScanner {
|
2023-07-30 16:52:39 -07:00
|
|
|
public static void scanForCounters(String reportDestinationFolder, List<CANPacket> packets) throws FileNotFoundException {
|
|
|
|
|
|
|
|
String outputFileName = reportDestinationFolder + File.separator + "counter_report.txt";
|
|
|
|
PrintWriter pw = new PrintWriter(new FileOutputStream(outputFileName));
|
2022-11-12 20:00:51 -08:00
|
|
|
|
|
|
|
Map<BitStateKey, BitState> bitStates = new TreeMap<>();
|
|
|
|
|
|
|
|
for (CANPacket packet : packets) {
|
|
|
|
for (int byteIndex = 0; byteIndex < packet.getData().length; byteIndex++) {
|
|
|
|
byte byteValue = packet.getData()[byteIndex];
|
|
|
|
|
|
|
|
for (int bitIndex = 0; bitIndex < 8; bitIndex++) {
|
|
|
|
|
|
|
|
int bitValue = byteValue >> bitIndex & 1;
|
|
|
|
|
|
|
|
BitStateKey key = new BitStateKey(packet.getId(), byteIndex, bitIndex);
|
|
|
|
|
|
|
|
BitState state = bitStates.computeIfAbsent(key, o -> new BitState());
|
|
|
|
|
|
|
|
state.handle(bitValue == 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-14 18:17:52 -08:00
|
|
|
|
|
|
|
LinkedHashMap<BitStateKey, Integer> counters = new LinkedHashMap<>();
|
2022-11-12 20:00:51 -08:00
|
|
|
for (Map.Entry<BitStateKey, BitState> e : bitStates.entrySet()) {
|
|
|
|
|
2022-11-12 20:34:27 -08:00
|
|
|
BitState bitState = e.getValue();
|
|
|
|
if (bitState.couldBeCounter()) {
|
|
|
|
BitStateKey key = e.getKey();
|
2023-07-30 16:52:39 -07:00
|
|
|
pw.println("Working: Looks like counter key=" + key + " cycleLength=" + bitState.cycleLength);
|
2022-11-14 18:17:52 -08:00
|
|
|
|
|
|
|
counters.put(key, bitState.cycleLength);
|
2022-11-12 20:34:27 -08:00
|
|
|
}
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
2022-11-14 18:17:52 -08:00
|
|
|
|
2023-07-30 16:52:39 -07:00
|
|
|
pw.println("Scanning...");
|
2022-11-14 18:17:52 -08:00
|
|
|
List<CounterAggregator.CounterWithWidth> countersWithWidth = CounterAggregator.scan(counters);
|
|
|
|
|
2023-07-30 16:52:39 -07:00
|
|
|
pw.println("Here are the founding:");
|
2022-11-14 18:17:52 -08:00
|
|
|
for (CounterAggregator.CounterWithWidth counterWithWidth : countersWithWidth) {
|
2023-07-30 16:52:39 -07:00
|
|
|
pw.println("Found " + counterWithWidth);
|
2022-11-14 18:17:52 -08:00
|
|
|
}
|
2023-07-30 16:52:39 -07:00
|
|
|
pw.close();
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static class BitStateKey implements Comparable {
|
2023-01-01 23:08:45 -08:00
|
|
|
private final ByteRateOfChange.ByteId byteId;
|
2022-11-12 20:00:51 -08:00
|
|
|
private final int bitIndex;
|
|
|
|
|
|
|
|
public BitStateKey(int sid, int byteIndex, int bitIndex) {
|
2023-01-01 23:08:45 -08:00
|
|
|
this.byteId = new ByteRateOfChange.ByteId(sid, byteIndex);
|
2022-11-12 20:00:51 -08:00
|
|
|
this.bitIndex = bitIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getSid() {
|
2023-01-01 23:08:45 -08:00
|
|
|
return byteId.sid;
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public int getByteIndex() {
|
2023-01-01 23:08:45 -08:00
|
|
|
return byteId.index;
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public int getBitIndex() {
|
|
|
|
return bitIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object o) {
|
|
|
|
if (this == o) return true;
|
|
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
|
|
BitStateKey that = (BitStateKey) o;
|
2023-01-01 23:08:45 -08:00
|
|
|
return byteId.equals(that.byteId) && bitIndex == that.bitIndex;
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
2023-01-01 23:08:45 -08:00
|
|
|
return Objects.hash(byteId.hashCode(), bitIndex);
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
2022-11-14 18:17:52 -08:00
|
|
|
return "{" +
|
2023-01-01 23:08:45 -08:00
|
|
|
byteId +
|
2022-11-14 18:17:52 -08:00
|
|
|
", bitIndex " + bitIndex +
|
2022-11-12 20:00:51 -08:00
|
|
|
'}';
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compareTo(Object o) {
|
|
|
|
BitStateKey other = (BitStateKey) o;
|
|
|
|
|
2023-01-01 23:08:45 -08:00
|
|
|
int compareByte = byteId.compareTo(other.byteId);
|
|
|
|
if (compareByte != 0)
|
|
|
|
return compareByte;
|
2022-11-12 20:00:51 -08:00
|
|
|
return bitIndex - other.bitIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static class BitState {
|
2022-11-12 20:34:27 -08:00
|
|
|
int index;
|
|
|
|
int cycleLength;
|
|
|
|
|
|
|
|
public boolean couldBeCounter() {
|
|
|
|
return state == StateMachine.HAPPY_COUNTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum StateMachine {
|
|
|
|
FIRST_VALUE,
|
|
|
|
LOOKING_FOR_FIRST_SWITCHOVER,
|
|
|
|
FOUND_FIRST_SWITCHOVER,
|
|
|
|
HAPPY_COUNTER,
|
|
|
|
NOT_GOOD
|
|
|
|
}
|
|
|
|
|
|
|
|
StateMachine state = StateMachine.FIRST_VALUE;
|
2022-11-12 20:00:51 -08:00
|
|
|
|
|
|
|
boolean previousBitValue;
|
|
|
|
|
|
|
|
public void handle(boolean bitValue) {
|
2022-11-12 20:34:27 -08:00
|
|
|
if (state == StateMachine.NOT_GOOD) {
|
2022-11-12 20:00:51 -08:00
|
|
|
return;
|
2022-11-12 20:34:27 -08:00
|
|
|
} else if (state == StateMachine.FIRST_VALUE) {
|
|
|
|
previousBitValue = bitValue;
|
|
|
|
state = StateMachine.LOOKING_FOR_FIRST_SWITCHOVER;
|
|
|
|
} else if (state == StateMachine.LOOKING_FOR_FIRST_SWITCHOVER) {
|
|
|
|
if (previousBitValue == bitValue)
|
|
|
|
return;
|
|
|
|
previousBitValue = bitValue;
|
|
|
|
state = StateMachine.FOUND_FIRST_SWITCHOVER;
|
|
|
|
} else if (state == StateMachine.FOUND_FIRST_SWITCHOVER) {
|
|
|
|
index++;
|
|
|
|
if (previousBitValue != bitValue) {
|
|
|
|
state = StateMachine.HAPPY_COUNTER;
|
|
|
|
cycleLength = index;
|
|
|
|
previousBitValue = bitValue;
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
} else if (state == StateMachine.HAPPY_COUNTER) {
|
|
|
|
index++;
|
|
|
|
|
|
|
|
if (previousBitValue != bitValue) {
|
|
|
|
if (index != cycleLength)
|
|
|
|
state = StateMachine.NOT_GOOD;
|
|
|
|
previousBitValue = bitValue;
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
throw new IllegalStateException(state.toString());
|
2022-11-12 20:00:51 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|