can-log-tools/reader/src/main/java/com/rusefi/can/analysis/CounterScanner.java

181 lines
5.9 KiB
Java
Raw Normal View History

2022-11-12 20:00:51 -08:00
package com.rusefi.can.analysis;
import com.rusefi.can.CANPacket;
2023-10-21 20:07:51 -07:00
import org.yaml.snakeyaml.Yaml;
2022-11-12 20:00:51 -08:00
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-10-22 20:13:55 -07:00
public static final String COUNTERS_YAML = "counters.yaml";
2023-10-21 20:07:51 -07:00
public static void scanForCounters(String reportDestinationFolder, List<CANPacket> packets) throws IOException {
2023-07-30 16:52:39 -07:00
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-10-21 20:07:51 -07:00
Yaml yaml = new Yaml();
2023-11-08 16:53:33 -08:00
Map<Integer, Map<Integer, Integer>> map = new TreeMap<>();
2023-10-21 20:07:51 -07:00
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);
2023-10-21 20:07:51 -07:00
Map<Integer, Integer> lengthByStartIndex = map.computeIfAbsent(counterWithWidth.getStart().getSid(), integer -> new HashMap<>());
lengthByStartIndex.put(counterWithWidth.getStart().getTotalBitIndex(), counterWithWidth.getTotalNumberOfBits());
2022-11-14 18:17:52 -08:00
}
2023-10-22 20:13:55 -07:00
String yamlCountersReportFileName = reportDestinationFolder + File.separator + COUNTERS_YAML;
2023-10-21 20:07:51 -07:00
System.out.println("Writing report to " + yamlCountersReportFileName);
yaml.dump(map, new FileWriter(yamlCountersReportFileName));
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;
}
2023-10-21 20:07:51 -07:00
public int getTotalBitIndex() {
2023-10-22 20:13:55 -07:00
return byteId.byteIndex * 8 + bitIndex;
2023-10-21 20:07:51 -07:00
}
2022-11-12 20:00:51 -08:00
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-10-22 20:13:55 -07:00
return byteId.byteIndex;
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
}
}
}