tune via CAN #3361

only trivial refactoring
This commit is contained in:
rusefillc 2021-12-04 20:10:30 -05:00
parent 399888f795
commit d186e4153e
4 changed files with 66 additions and 72 deletions

View File

@ -40,6 +40,7 @@ public class ControllerConnectorState {
port = PortDetector.autoDetectSerial(null).getSerialPort(); port = PortDetector.autoDetectSerial(null).getSerialPort();
if (port == null) if (port == null)
throw new IllegalStateException("ECU serial not detected"); throw new IllegalStateException("ECU serial not detected");
System.out.println("Auto-connected to " + port);
} }
IoUtil.realHardwareConnect(linkManager, port); IoUtil.realHardwareConnect(linkManager, port);

View File

@ -2,6 +2,7 @@ package com.rusefi.io.can;
import com.devexperts.logging.Logging; import com.devexperts.logging.Logging;
import com.opensr5.io.DataListener; import com.opensr5.io.DataListener;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.IoStream; import com.rusefi.io.IoStream;
import com.rusefi.io.serial.SerialIoStream; import com.rusefi.io.serial.SerialIoStream;
import com.rusefi.io.tcp.BinaryProtocolProxy; import com.rusefi.io.tcp.BinaryProtocolProxy;
@ -10,7 +11,6 @@ import com.rusefi.io.tcp.TcpConnector;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -29,62 +29,13 @@ public class Elm327Connector implements Closeable {
private final Object lock = new Object(); private final Object lock = new Object();
// these should match the defines in the firmware private IoStream stream = null;
private final static int CAN_SERIAL_TX_ID = 0x100;
private final static int CAN_SERIAL_RX_ID = 0x102;
private final static int ISO_TP_FRAME_SINGLE = 0;
private final static int ISO_TP_FRAME_FIRST = 1;
private final static int ISO_TP_FRAME_CONSECUTIVE = 2;
private final static int ISO_TP_FRAME_FLOW_CONTROL = 3;
private IoStream stream = null;
private String partialLine = ""; private String partialLine = "";
private final List<String> completeLines = new ArrayList<>(); private final List<String> completeLines = new ArrayList<>();
private boolean isCommandMode = false; private boolean isCommandMode = false;
private Elm327IoStream elmStream; private Elm327IoStream elmStream;
// CAN multiframe decoder state
static class CanDecoder {
public int waitingForNumBytes = 0;
public int waitingForFrameIndex = 0;
public byte [] decodePacket(byte [] data) throws Exception {
int frameType = (data[0] >> 4) & 0xf;
int numBytesAvailable, frameIdx;
int dataOffset;
switch (frameType) {
case ISO_TP_FRAME_SINGLE:
numBytesAvailable = data[0] & 0xf;
dataOffset = 1;
this.waitingForNumBytes = 0;
break;
case ISO_TP_FRAME_FIRST:
this.waitingForNumBytes = ((data[0] & 0xf) << 8) | data[1];
this.waitingForFrameIndex = 1;
numBytesAvailable = Math.min(this.waitingForNumBytes, 6);
dataOffset = 2;
break;
case ISO_TP_FRAME_CONSECUTIVE:
frameIdx = data[0] & 0xf;
if (this.waitingForNumBytes < 0 || this.waitingForFrameIndex != frameIdx) {
throw new Exception("ISO_TP_FRAME_CONSECUTIVE: That's an abnormal situation, and we probably should react?");
}
this.waitingForFrameIndex = (this.waitingForFrameIndex + 1) & 0xf;
numBytesAvailable = Math.min(this.waitingForNumBytes, 7);
dataOffset = 1;
break;
case ISO_TP_FRAME_FLOW_CONTROL:
throw new Exception("ISO_TP_FRAME_FLOW_CONTROL: should we just ignore the FC frame?");
default:
throw new Exception("Unknown frame type");
}
return Arrays.copyOfRange(data, dataOffset, dataOffset + numBytesAvailable);
}
}
public static boolean checkConnection(String serialPort, IoStream stream) { public static boolean checkConnection(String serialPort, IoStream stream) {
Elm327Connector con = new Elm327Connector(); Elm327Connector con = new Elm327Connector();
boolean found = con.initConnection(serialPort, stream); boolean found = con.initConnection(serialPort, stream);
@ -107,16 +58,16 @@ public class Elm327Connector implements Closeable {
sendCommand("ATSP6", "OK"); sendCommand("ATSP6", "OK");
// set rx ID // set rx ID
sendCommand("ATCF " + Integer.toHexString(CAN_SERIAL_RX_ID), "OK"); sendCommand("ATCF " + Integer.toHexString(Fields.CAN_SERIAL_RX_ID), "OK");
// rx ID mask = "all bits set" // rx ID mask = "all bits set"
sendCommand("ATCM FFF", "OK"); sendCommand("ATCM FFF", "OK");
// set tx ID // set tx ID
sendCommand("ATSH " + Integer.toHexString(CAN_SERIAL_TX_ID), "OK"); sendCommand("ATSH " + Integer.toHexString(Fields.CAN_SERIAL_TX_ID), "OK");
// set FC tx ID (should match our tx ID) // set FC tx ID (should match our tx ID)
sendCommand("ATFCSH " + Integer.toHexString(CAN_SERIAL_TX_ID), "OK"); sendCommand("ATFCSH " + Integer.toHexString(Fields.CAN_SERIAL_TX_ID), "OK");
// set FC data // set FC data
sendCommand("ATFCSD 30 00 00", "OK"); sendCommand("ATFCSD 30 00 00", "OK");
// use custom FC ID & data // use custom FC ID & data
@ -183,13 +134,13 @@ public class Elm327Connector implements Closeable {
// 1 frame // 1 frame
if (bytes.length <= 7) { if (bytes.length <= 7) {
sendFrame((ISO_TP_FRAME_SINGLE << 4) | bytes.length, bytes, 0, bytes.length); sendCanFrame((IsoTpCanDecoder.ISO_TP_FRAME_SINGLE << 4) | bytes.length, bytes, 0, bytes.length);
return; return;
} }
// multiple frames // multiple frames
// send the first header frame // send the first header frame
sendFrame((ISO_TP_FRAME_FIRST << 4) | ((bytes.length >> 8) & 0x0f), bytes.length & 0xff, bytes, 0, 6); sendCanFrame((IsoTpCanDecoder.ISO_TP_FRAME_FIRST << 4) | ((bytes.length >> 8) & 0x0f), bytes.length & 0xff, bytes, 0, 6);
// get a flow control frame // get a flow control frame
receiveData(); receiveData();
@ -199,7 +150,7 @@ public class Elm327Connector implements Closeable {
while (remaining > 0) { while (remaining > 0) {
int len = Math.min(remaining, 7); int len = Math.min(remaining, 7);
// send the consecutive frames // send the consecutive frames
sendFrame((ISO_TP_FRAME_CONSECUTIVE << 4) | ((idx++) & 0x0f), bytes, offset, len); sendCanFrame((IsoTpCanDecoder.ISO_TP_FRAME_CONSECUTIVE << 4) | ((idx++) & 0x0f), bytes, offset, len);
offset += len; offset += len;
remaining -= len; remaining -= len;
} }
@ -259,15 +210,15 @@ public class Elm327Connector implements Closeable {
return null; return null;
} }
private void sendFrame(int hdr0, byte [] data, int offset, int len) { private void sendCanFrame(int hdr0, byte [] data, int offset, int len) {
sendData(new byte[] { (byte)hdr0 }, data, offset, len); sendCanData(new byte[] { (byte)hdr0 }, data, offset, len);
} }
private void sendFrame(int hdr0, int hdr1, byte [] data, int offset, int len) { private void sendCanFrame(int hdr0, int hdr1, byte [] data, int offset, int len) {
sendData(new byte[] { (byte)hdr0, (byte)hdr1 }, data, offset, len); sendCanData(new byte[] { (byte)hdr0, (byte)hdr1 }, data, offset, len);
} }
private void sendData(byte [] hdr, byte [] data, int offset, int len) { private void sendCanData(byte [] hdr, byte [] data, int offset, int len) {
//log.info("--------sendData offset="+Integer.toString(offset) + " len=" + Integer.toString(len) + "hdr.len=" + Integer.toString(hdr.length)); //log.info("--------sendData offset="+Integer.toString(offset) + " len=" + Integer.toString(len) + "hdr.len=" + Integer.toString(hdr.length));
len += hdr.length; len += hdr.length;
@ -336,19 +287,15 @@ public class Elm327Connector implements Closeable {
byte [] canPacket = HexUtil.asBytes(line); byte [] canPacket = HexUtil.asBytes(line);
try { try {
elmStream.processCanPacket(canPacket); elmStream.processCanPacket(canPacket);
} catch (Exception ignore) { } catch (Exception e) {
// todo: ? System.out.println("ELM327: Error processing " + line);
} }
} }
private boolean startNetworkConnector(int controllerPort) { private boolean startNetworkConnector(int controllerPort) {
try { try {
elmStream = new Elm327IoStream(this, "elm327Stream"); elmStream = new Elm327IoStream(this, "elm327Stream");
BinaryProtocolProxy.createProxy(elmStream, controllerPort, new BinaryProtocolProxy.ClientApplicationActivityListener() { BinaryProtocolProxy.createProxy(elmStream, controllerPort, BinaryProtocolProxy.ClientApplicationActivityListener.VOID);
@Override
public void onActivity() {
}
});
} catch (IOException ignore) { } catch (IOException ignore) {
return false; return false;
} }

View File

@ -3,9 +3,7 @@ package com.rusefi.io.can;
import com.opensr5.io.DataListener; import com.opensr5.io.DataListener;
import com.rusefi.binaryprotocol.IncomingDataBuffer; import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.binaryprotocol.IoHelper; import com.rusefi.binaryprotocol.IoHelper;
import com.rusefi.io.ByteReader;
import com.rusefi.io.serial.AbstractIoStream; import com.rusefi.io.serial.AbstractIoStream;
import com.rusefi.shared.FileUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.*; import java.io.*;
@ -29,7 +27,7 @@ public class Elm327IoStream extends AbstractIoStream {
private final static boolean sendShortPacketsInOneFrame = true; private final static boolean sendShortPacketsInOneFrame = true;
private final static boolean receiveShortPacketsInOneFrame = false; private final static boolean receiveShortPacketsInOneFrame = false;
private Elm327Connector.CanDecoder canDecoder = new Elm327Connector.CanDecoder(); private IsoTpCanDecoder canDecoder = new IsoTpCanDecoder();
public Elm327IoStream(Elm327Connector con, String loggingPrefix) throws IOException { public Elm327IoStream(Elm327Connector con, String loggingPrefix) throws IOException {

View File

@ -0,0 +1,48 @@
package com.rusefi.io.can;
import java.util.Arrays;
// CAN multiframe decoder state
class IsoTpCanDecoder {
private final static int ISO_TP_FRAME_FLOW_CONTROL = 3;
final static int ISO_TP_FRAME_SINGLE = 0;
final static int ISO_TP_FRAME_FIRST = 1;
final static int ISO_TP_FRAME_CONSECUTIVE = 2;
public int waitingForNumBytes = 0;
public int waitingForFrameIndex = 0;
public byte[] decodePacket(byte[] data) throws Exception {
int frameType = (data[0] >> 4) & 0xf;
int numBytesAvailable, frameIdx;
int dataOffset;
switch (frameType) {
case ISO_TP_FRAME_SINGLE:
numBytesAvailable = data[0] & 0xf;
dataOffset = 1;
this.waitingForNumBytes = 0;
break;
case ISO_TP_FRAME_FIRST:
this.waitingForNumBytes = ((data[0] & 0xf) << 8) | data[1];
this.waitingForFrameIndex = 1;
numBytesAvailable = Math.min(this.waitingForNumBytes, 6);
dataOffset = 2;
break;
case ISO_TP_FRAME_CONSECUTIVE:
frameIdx = data[0] & 0xf;
if (this.waitingForNumBytes < 0 || this.waitingForFrameIndex != frameIdx) {
throw new Exception("ISO_TP_FRAME_CONSECUTIVE: That's an abnormal situation, and we probably should react?");
}
this.waitingForFrameIndex = (this.waitingForFrameIndex + 1) & 0xf;
numBytesAvailable = Math.min(this.waitingForNumBytes, 7);
dataOffset = 1;
break;
case ISO_TP_FRAME_FLOW_CONTROL:
throw new Exception("ISO_TP_FRAME_FLOW_CONTROL: should we just ignore the FC frame?");
default:
throw new Exception("Unknown frame type");
}
return Arrays.copyOfRange(data, dataOffset, dataOffset + numBytesAvailable);
}
}