improve innovate protocol support

git-svn-id: https://svn2.assembla.com/svn/romraider/trunk@251 38686702-15cf-42e4-a595-3071df8bf5ea
This commit is contained in:
kascade 2009-10-19 12:58:32 +00:00
parent 31826ece0b
commit bf97ee7a01
21 changed files with 294 additions and 604 deletions

View File

@ -33,4 +33,6 @@ public interface SerialConnection {
void close();
String readLine();
int read();
}

View File

@ -84,6 +84,15 @@ public final class SerialConnectionImpl implements SerialConnection {
}
}
public int read() {
try {
return is.read();
} catch (IOException e) {
close();
throw new SerialCommunicationException(e);
}
}
public void read(byte[] bytes) {
try {
is.read(bytes, 0, bytes.length);

View File

@ -37,8 +37,8 @@ public final class SerialConnectionManager implements ConnectionManager {
checkNotNullOrEmpty(portName, "portName");
checkNotNull(connectionProperties, "connectionProperties");
// Use TestSerialConnection for testing!!
// connection = new SerialConnectionImpl(portName, connectionProperties);
connection = new TestSerialConnection(portName, connectionProperties);
connection = new SerialConnectionImpl(portName, connectionProperties);
// connection = new TestSerialConnection(portName, connectionProperties);
}
// Send request and wait for response with known length

View File

@ -153,6 +153,10 @@ final class TestSerialConnection implements SerialConnection {
throw new UnsupportedOperationException();
}
public int read() {
throw new UnsupportedOperationException();
}
private int calculateNumResponseDataBytes() {
return ((request.length - REQUEST_NON_DATA_BYTES) / ADDRESS_SIZE) * DATA_SIZE;
}

View File

@ -1,26 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.generic.serial.io;
public interface InnovateConnection {
byte[] read();
void close();
}

View File

@ -1,132 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.generic.serial.io;
import com.romraider.io.connection.ConnectionProperties;
import com.romraider.io.serial.connection.SerialConnection;
import com.romraider.io.serial.connection.SerialConnectionImpl;
import com.romraider.logger.ecu.exception.SerialCommunicationException;
import static com.romraider.util.ByteUtil.matchOnes;
import static com.romraider.util.ByteUtil.matchZeroes;
import static com.romraider.util.HexUtil.asBytes;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkGreaterThanZero;
import static com.romraider.util.ParamChecker.checkNotNull;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import static com.romraider.util.ThreadUtil.sleep;
import org.apache.log4j.Logger;
import static org.apache.log4j.Logger.getLogger;
import java.io.IOException;
import static java.lang.Math.min;
import static java.lang.System.arraycopy;
import static java.lang.System.currentTimeMillis;
public final class InnovateConnectionImpl implements InnovateConnection {
private static final Logger LOGGER = getLogger(InnovateConnectionImpl.class);
private static final byte[] INNOVATE_HEADER = asBytes("0xB280");
private final SerialConnection connection;
private final int responseLength;
private final long sendTimeout;
private final String device;
public InnovateConnectionImpl(String device, String portName, ConnectionProperties connectionProperties, int responseLength) {
checkNotNullOrEmpty(device, "device");
checkNotNullOrEmpty(portName, "portName");
checkNotNull(connectionProperties, "connectionProperties");
checkGreaterThanZero(responseLength, "responseLength");
this.device = device;
this.sendTimeout = connectionProperties.getSendTimeout();
this.responseLength = responseLength;
connection = new SerialConnectionImpl(portName, connectionProperties);
}
// FIX - YIKES!!
public byte[] read() {
try {
connection.readStaleData();
byte[] response = new byte[responseLength];
int bufferLength = responseLength + INNOVATE_HEADER.length - 1;
long start = currentTimeMillis();
while (currentTimeMillis() - start <= sendTimeout) {
sleep(1);
int available = connection.available();
if (available < bufferLength) continue;
byte[] buffer = new byte[bufferLength];
connection.read(buffer);
LOGGER.trace(device + " input: " + asHex(buffer));
int responseBeginIndex = 0;
int bufferBeginIndex = findHeader(buffer);
if (bufferBeginIndex < 0) {
bufferBeginIndex = findLm1(buffer);
if (bufferBeginIndex < 0) continue;
LOGGER.trace(device + ": v1 protocol found - appending header...");
arraycopy(INNOVATE_HEADER, 0, response, 0, INNOVATE_HEADER.length);
responseBeginIndex = INNOVATE_HEADER.length;
}
int tailLength = responseLength - responseBeginIndex;
arraycopy(buffer, bufferBeginIndex, response, responseBeginIndex, min(tailLength, (buffer.length - bufferBeginIndex)));
int remainderLength = tailLength - (buffer.length - bufferBeginIndex);
if (remainderLength > 0) {
byte[] remainder = remainder(remainderLength, start);
if (remainder.length == 0) continue;
arraycopy(remainder, 0, response, responseLength - remainderLength, remainderLength);
}
LOGGER.trace(device + " Response: " + asHex(response));
return response;
}
LOGGER.warn(device + " Response [read timeout]");
return new byte[0];
} catch (Exception e) {
close();
throw new SerialCommunicationException(e);
}
}
private byte[] remainder(int remainderLength, long start) throws IOException {
while (currentTimeMillis() - start <= sendTimeout) {
sleep(1);
int available = connection.available();
if (available >= remainderLength) {
byte[] remainder = new byte[remainderLength];
connection.read(remainder);
return remainder;
}
}
return new byte[0];
}
public void close() {
connection.close();
}
private int findHeader(byte[] bytes) {
for (int i = 0; i < bytes.length - 1; i++) {
if (matchOnes(bytes[i], 178) && matchOnes(bytes[i + 1], 128)) return i;
}
return -1;
}
private int findLm1(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
if (matchOnes(bytes[i], 128) && matchZeroes(bytes[i], 34)) return i;
}
return -1;
}
}

View File

@ -19,6 +19,173 @@
package com.romraider.logger.innovate.generic.serial.io;
public interface InnovateRunner extends Runnable {
void stop();
import com.romraider.io.connection.ConnectionProperties;
import com.romraider.io.serial.connection.SerialConnection;
import com.romraider.io.serial.connection.SerialConnectionImpl;
import com.romraider.logger.innovate.generic.mts.plugin.DataListener;
import static com.romraider.util.ByteUtil.matchOnes;
import static com.romraider.util.ByteUtil.matchZeroes;
import static com.romraider.util.HexUtil.asHex;
import com.romraider.util.Stoppable;
import static com.romraider.util.ThreadUtil.sleep;
import org.apache.log4j.Logger;
import static org.apache.log4j.Logger.getLogger;
import static java.lang.System.arraycopy;
public final class InnovateRunner implements Stoppable {
private static final Logger LOGGER = getLogger(InnovateRunner.class);
private static final double MAX_AFR = 20.33;
private final SerialConnection connection;
private final DataListener listener;
private final String device;
private boolean stop;
public InnovateRunner(String device, String port, DataListener listener) {
this.connection = serialConnection(port);
// LC-1 & LM-2
// this.connection = new TestInnovateConnection("13036B00000000000000000000B2874313036B00000000000000000000B28743");
// LM-1
// this.connection = new TestInnovateConnection("8113037C1E66012600720049003B003B");
this.listener = listener;
this.device = device;
}
public void run() {
try {
while (!stop) {
byte b0 = nextByte();
if (isHeaderHighByte(b0)) {
byte b1 = nextByte();
if (isHeaderLowByte(b1)) {
int numWords = numWords(b0, b1);
byte[] bytes = new byte[numWords * 2];
connection.read(bytes);
LOGGER.trace(device + " response: " + packet(b0, b1, bytes));
process(bytes);
} else {
LOGGER.trace(device + " discarded: " + hex(b1));
}
} else if (isLm1HighByte(b0)) {
byte b1 = nextByte();
if (isLm1LowByte(b1)) {
byte[] rest = new byte[14];
connection.read(rest);
byte[] bytes = new byte[16];
bytes[0] = b0;
bytes[1] = b1;
arraycopy(rest, 0, bytes, 2, rest.length);
LOGGER.trace(device + " response: " + asHex(bytes));
process(bytes);
} else {
LOGGER.trace(device + " discarded: " + hex(b1));
}
} else {
LOGGER.trace(device + " discarded: " + hex(b0));
}
}
} finally {
connection.close();
}
}
private void process(byte[] bytes) {
if (isError(bytes)) {
double error = -1d * getLambda(bytes);
LOGGER.error(device + " error: " + error);
listener.setData(error);
} else if (isOk(bytes)) {
double afr = getAfr(bytes);
LOGGER.trace(device + " AFR: " + afr);
listener.setData(afr > MAX_AFR ? MAX_AFR : afr);
}
}
public void stop() {
stop = true;
}
private SerialConnectionImpl serialConnection(String port) {
ConnectionProperties properties = new InnovateConnectionProperties();
return new SerialConnectionImpl(port, properties);
}
private void waitForBytes(int numBytes) {
while (!stop && connection.available() < numBytes) {
sleep(2L);
}
}
private byte nextByte() {
waitForBytes(1);
return (byte) connection.read();
}
// 1x11xx1x
private boolean isHeaderHighByte(byte b) {
return matchOnes(b, 178);
}
// 1xxxxxxx
private boolean isHeaderLowByte(byte b) {
return matchOnes(b, 128);
}
// 1x0xxx0x
private boolean isLm1HighByte(byte b) {
return matchOnes(b, 128) && matchZeroes(b, 34);
}
// 0xxxxxxx
private boolean isLm1LowByte(byte b) {
return matchZeroes(b, 128);
}
private double getAfr(byte[] bytes) {
return (getLambda(bytes) + 500) * getAf(bytes) / 10000.0;
}
private int getAf(byte[] bytes) {
return ((bytes[0] & 1) << 7) | bytes[1];
}
// xxx000xx
private boolean isOk(byte[] bytes) {
return matchZeroes(bytes[0], 28);
}
// xxx110xx
private boolean isError(byte[] bytes) {
return matchOnes(bytes[0], 24) && matchZeroes(bytes[0], 4);
}
// 01xxxxxx 0xxxxxxx
private int getLambda(byte[] bytes) {
return ((bytes[2] & 63) << 7) | bytes[3];
}
private int numWords(byte b0, byte b1) {
int result = 0;
if (matchOnes(b0, 1)) result |= 128;
if (matchOnes(b1, 64)) result |= 64;
if (matchOnes(b1, 32)) result |= 32;
if (matchOnes(b1, 16)) result |= 16;
if (matchOnes(b1, 8)) result |= 8;
if (matchOnes(b1, 4)) result |= 4;
if (matchOnes(b1, 2)) result |= 2;
if (matchOnes(b1, 1)) result |= 1;
return result;
}
private String packet(byte b0, byte b1, byte[] bytes) {
byte[] result = new byte[bytes.length + 2];
result[0] = b0;
result[1] = b1;
arraycopy(bytes, 0, result, 2, bytes.length);
return asHex(result);
}
// FIX - Push this on to HexUtil
private String hex(byte b) {
return asHex(new byte[]{b});
}
}

View File

@ -1,49 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.generic.serial.io;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettings;
import com.romraider.logger.innovate.generic.serial.plugin.RawDataListener;
public final class InnovateRunnerImpl implements InnovateRunner {
private final InnovateConnection connection;
private final RawDataListener listener;
private boolean stop;
public InnovateRunnerImpl(String device, InnovateSettings innovateSettings, RawDataListener listener, int responseLength) {
connection = new InnovateConnectionImpl(device, innovateSettings.getPort(), new InnovateConnectionProperties(), responseLength);
this.listener = listener;
}
public void run() {
try {
while (!stop) {
byte[] bytes = connection.read();
listener.setBytes(bytes);
}
} finally {
connection.close();
}
}
public void stop() {
stop = true;
}
}

View File

@ -0,0 +1,71 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.generic.serial.io;
import com.romraider.io.serial.connection.SerialConnection;
import static com.romraider.util.HexUtil.asBytes;
public final class TestInnovateConnection implements SerialConnection {
private final byte[] source;
private int i;
public TestInnovateConnection(String hex) {
this.source = asBytes(hex);
}
public void write(byte[] bytes) {
throw new UnsupportedOperationException();
}
public int available() {
return source.length;
}
public void read(byte[] bytes) {
for (int j = 0; j < bytes.length; j++) {
bytes[j] = source[(i + j) % source.length];
}
i = (i + bytes.length);
if (i >= source.length) i %= source.length;
}
public byte[] readAvailable() {
byte[] result = new byte[available()];
read(result);
return result;
}
public void readStaleData() {
throw new UnsupportedOperationException();
}
public void close() {
}
public String readLine() {
throw new UnsupportedOperationException();
}
public int read() {
byte[] result = new byte[1];
read(result);
return result[0];
}
}

View File

@ -1,26 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.generic.serial.plugin;
public interface InnovateSettings {
void setPort(String port);
String getPort();
}

View File

@ -1,32 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.generic.serial.plugin;
public final class InnovateSettingsImpl implements InnovateSettings {
private String port;
public void setPort(String port) {
this.port = port;
}
public String getPort() {
return port;
}
}

View File

@ -1,89 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.lc1.serial.plugin;
import com.romraider.logger.innovate.generic.serial.plugin.DataConvertor;
import static com.romraider.util.ByteUtil.matchOnes;
import static com.romraider.util.ByteUtil.matchZeroes;
import static com.romraider.util.HexUtil.asHex;
import org.apache.log4j.Logger;
public final class Lc1DataConvertor implements DataConvertor {
private static final Logger LOGGER = Logger.getLogger(Lc1DataConvertor.class);
private static final double MAX_AFR = 20.33;
public double convert(byte[] bytes) {
/*
Example bytes: 10110010 10000010 01000011 00010011 00010111 00101111
*/
LOGGER.trace("Converting LC-1 bytes: " + asHex(bytes));
if (isLc1(bytes) && isHeaderValid(bytes)) {
if (isError(bytes)) {
int error = -1 * getLambda(bytes);
LOGGER.error("LC-1 error: " + asHex(bytes) + " --> " + error);
return error;
}
if (isOk(bytes)) {
double afr = getAfr(bytes);
LOGGER.trace("LC-1 AFR: " + afr);
return afr > MAX_AFR ? MAX_AFR : afr;
}
// out of range value seen on overrun...
LOGGER.trace("LC-1 response out of range (overrun?): " + asHex(bytes));
return MAX_AFR;
}
LOGGER.error("LC-1 unrecognized response: " + asHex(bytes));
return 0;
}
private double getAfr(byte[] bytes) {
return (getLambda(bytes) + 500) * getAf(bytes) / 10000.0;
}
private int getAf(byte[] bytes) {
return ((bytes[2] & 1) << 7) | bytes[3];
}
// 010xxx1x
private boolean isLc1(byte[] bytes) {
return bytes.length >= 6 && matchOnes(bytes[2], 66) && matchZeroes(bytes[2], 160);
}
// 1x11xx1x 1xxxxxxx
private boolean isHeaderValid(byte[] bytes) {
return matchOnes(bytes[0], 178) && matchOnes(bytes[1], 128);
}
// 0100001x or 0100011x
private boolean isOk(byte[] bytes) {
if (matchOnes(bytes[2], 66) && matchZeroes(bytes[2], 188)) return true;
return matchOnes(bytes[2], 70) && matchZeroes(bytes[2], 184);
}
// 0101101x
private boolean isError(byte[] bytes) {
return matchOnes(bytes[2], 90) && matchZeroes(bytes[2], 164);
}
// 01xxxxxx 0xxxxxxx
private int getLambda(byte[] bytes) {
return ((bytes[4] & 63) << 7) | bytes[5];
}
}

View File

@ -20,12 +20,10 @@
package com.romraider.logger.innovate.lc1.serial.plugin;
import com.romraider.logger.ecu.external.ExternalDataItem;
import com.romraider.logger.innovate.generic.serial.plugin.DataConvertor;
import com.romraider.logger.innovate.generic.serial.plugin.RawDataListener;
import com.romraider.logger.innovate.generic.mts.plugin.DataListener;
public final class Lc1DataItem implements ExternalDataItem, RawDataListener {
private final DataConvertor convertor = new Lc1DataConvertor();
private byte[] bytes;
public final class Lc1DataItem implements ExternalDataItem, DataListener {
private double data;
public String getName() {
return "Innovate LC-1";
@ -40,11 +38,10 @@ public final class Lc1DataItem implements ExternalDataItem, RawDataListener {
}
public double getData() {
if (bytes == null) return 0.0;
return convertor.convert(bytes);
return data;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
public void setData(double data) {
this.data = data;
}
}

View File

@ -23,25 +23,22 @@ import com.romraider.logger.ecu.EcuLogger;
import com.romraider.logger.ecu.external.ExternalDataItem;
import com.romraider.logger.ecu.external.ExternalDataSource;
import com.romraider.logger.innovate.generic.serial.io.InnovateRunner;
import com.romraider.logger.innovate.generic.serial.io.InnovateRunnerImpl;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettings;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettingsImpl;
import static com.romraider.util.ThreadUtil.runAsDaemon;
import javax.swing.Action;
import static java.util.Arrays.asList;
import java.util.List;
public final class Lc1DataSource implements ExternalDataSource {
private InnovateSettings settings = new InnovateSettingsImpl();
private Lc1DataItem dataItem = new Lc1DataItem();
private InnovateRunner runner;
private String port;
public String getName() {
return "Innovate LC-1";
}
public String getVersion() {
return "0.02";
return "0.03";
}
public List<? extends ExternalDataItem> getDataItems() {
@ -53,15 +50,15 @@ public final class Lc1DataSource implements ExternalDataSource {
}
public void setPort(String port) {
settings.setPort(port);
this.port = port;
}
public String getPort() {
return settings.getPort();
return port;
}
public void connect() {
runner = new InnovateRunnerImpl("LC-1", settings, dataItem, 6);
runner = new InnovateRunner("LC-1", port, dataItem);
runAsDaemon(runner);
}

View File

@ -1,101 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.lm1.serial.plugin;
import com.romraider.logger.innovate.generic.serial.plugin.DataConvertor;
import static com.romraider.util.ByteUtil.matchOnes;
import static com.romraider.util.ByteUtil.matchZeroes;
import static com.romraider.util.HexUtil.asBytes;
import static com.romraider.util.HexUtil.asHex;
import org.apache.log4j.Logger;
//TODO: Remove dupe with Lc1DataConvertor
public final class Lm1DataConvertor implements DataConvertor {
private static final Logger LOGGER = Logger.getLogger(Lm1DataConvertor.class);
private static final double MAX_AFR = 20.33;
public double convert(byte[] bytes) {
LOGGER.trace("Converting LM-1 bytes: " + asHex(bytes));
if (isLm1(bytes) && isHeaderValid(bytes)) {
if (isError(bytes)) {
int error = -1 * getLambda(bytes);
LOGGER.error("LM-1 error: " + asHex(bytes) + " --> " + error);
return error;
}
if (isOk(bytes)) {
double afr = getAfr(bytes);
LOGGER.trace("LM-1 AFR: " + afr);
return afr > MAX_AFR ? MAX_AFR : afr;
}
// out of range value seen on overrun...
LOGGER.trace("LM-1 response out of range (overrun?): " + asHex(bytes));
return MAX_AFR;
}
LOGGER.error("LM-1 unrecognized response: " + asHex(bytes));
return 0;
}
private double getAfr(byte[] bytes) {
return (getLambda(bytes) + 500) * getAf(bytes) / 10000.0;
}
private int getAf(byte[] bytes) {
return ((bytes[2] & 1) << 7) | bytes[3];
}
// 1x0xxx0x
private boolean isLm1(byte[] bytes) {
return bytes.length >= 6 && matchOnes(bytes[2], 128) && matchZeroes(bytes[2], 34);
}
// 1x11xx1x 1xxxxxxx
private boolean isHeaderValid(byte[] bytes) {
return matchOnes(bytes[0], 178) && matchOnes(bytes[1], 128);
}
// 1x00000x or 1x00010x
private boolean isOk(byte[] bytes) {
if (matchOnes(bytes[2], 128) && matchZeroes(bytes[2], 62)) return true;
return matchOnes(bytes[2], 132) && matchZeroes(bytes[2], 58);
}
// xxx001xx
private boolean isOneTenth(byte[] bytes) {
return matchOnes(bytes[2], 4) && matchZeroes(bytes[2], 24);
}
// 1x01100x
private boolean isError(byte[] bytes) {
return matchOnes(bytes[2], 152) && matchZeroes(bytes[2], 38);
}
// 00xxxxxx 0xxxxxxx
private int getLambda(byte[] bytes) {
return (bytes[4] << 7) | bytes[5];
}
public static void main(String[] args) {
byte[] bytes = asBytes("B280851301371E04004C003A002800260034");
// byte[] bytes = asBytes("0xB2808113036F1E650124007000470039003A");
DataConvertor convertor = new Lm1DataConvertor();
double result = convertor.convert(bytes);
System.out.println("result = " + result);
}
}

View File

@ -20,12 +20,10 @@
package com.romraider.logger.innovate.lm1.serial.plugin;
import com.romraider.logger.ecu.external.ExternalDataItem;
import com.romraider.logger.innovate.generic.serial.plugin.DataConvertor;
import com.romraider.logger.innovate.generic.serial.plugin.RawDataListener;
import com.romraider.logger.innovate.generic.mts.plugin.DataListener;
public final class Lm1DataItem implements ExternalDataItem, RawDataListener {
private final DataConvertor convertor = new Lm1DataConvertor();
private byte[] bytes;
public final class Lm1DataItem implements ExternalDataItem, DataListener {
private double data;
public String getName() {
return "Innovate LM-1";
@ -40,11 +38,10 @@ public final class Lm1DataItem implements ExternalDataItem, RawDataListener {
}
public double getData() {
if (bytes == null) return 0.0;
return convertor.convert(bytes);
return data;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
public void setData(double data) {
this.data = data;
}
}

View File

@ -23,25 +23,22 @@ import com.romraider.logger.ecu.EcuLogger;
import com.romraider.logger.ecu.external.ExternalDataItem;
import com.romraider.logger.ecu.external.ExternalDataSource;
import com.romraider.logger.innovate.generic.serial.io.InnovateRunner;
import com.romraider.logger.innovate.generic.serial.io.InnovateRunnerImpl;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettings;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettingsImpl;
import static com.romraider.util.ThreadUtil.runAsDaemon;
import javax.swing.Action;
import static java.util.Arrays.asList;
import java.util.List;
public final class Lm1DataSource implements ExternalDataSource {
private InnovateSettings settings = new InnovateSettingsImpl();
private Lm1DataItem dataItem = new Lm1DataItem();
private InnovateRunner runner;
private String port;
public String getName() {
return "Innovate LM-1";
}
public String getVersion() {
return "0.01";
return "0.02";
}
public List<? extends ExternalDataItem> getDataItems() {
@ -53,15 +50,15 @@ public final class Lm1DataSource implements ExternalDataSource {
}
public void setPort(String port) {
settings.setPort(port);
this.port = port;
}
public String getPort() {
return settings.getPort();
return port;
}
public void connect() {
runner = new InnovateRunnerImpl("LM-1", settings, dataItem, 18);
runner = new InnovateRunner("LM-1", port, dataItem);
runAsDaemon(runner);
}

View File

@ -1,94 +0,0 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2009 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.innovate.lm2.serial.plugin;
import com.romraider.logger.innovate.generic.serial.plugin.DataConvertor;
import static com.romraider.util.ByteUtil.matchOnes;
import static com.romraider.util.ByteUtil.matchZeroes;
import static com.romraider.util.HexUtil.asBytes;
import static com.romraider.util.HexUtil.asHex;
import org.apache.log4j.Logger;
//TODO: Remove dupe with Lc1DataConvertor
public final class Lm2SerialDataConvertor implements DataConvertor {
private static final Logger LOGGER = Logger.getLogger(Lm2SerialDataConvertor.class);
private static final double MAX_AFR = 20.33;
public double convert(byte[] bytes) {
LOGGER.trace("Converting LM-2 bytes: " + asHex(bytes));
if (isLm2(bytes) && isHeaderValid(bytes)) {
if (isError(bytes)) {
int error = -1 * getLambda(bytes);
LOGGER.error("LM-2 error: " + asHex(bytes) + " --> " + error);
return error;
}
if (isOk(bytes)) {
double afr = getAfr(bytes);
LOGGER.trace("LM-2 AFR: " + afr);
return afr > MAX_AFR ? MAX_AFR : afr;
}
// out of range value seen on overrun...
LOGGER.trace("LM-2 response out of range (overrun?): " + asHex(bytes));
return MAX_AFR;
}
LOGGER.error("LM-2 unrecognized response: " + asHex(bytes));
return 0;
}
private double getAfr(byte[] bytes) {
return (getLambda(bytes) + 500) * getAf(bytes) / 10000.0;
}
private int getAf(byte[] bytes) {
return ((bytes[2] & 1) << 7) | bytes[3];
}
// 1x0xxx0x
private boolean isLm2(byte[] bytes) {
return bytes.length >= 6 && matchOnes(bytes[2], 128) && matchZeroes(bytes[2], 34);
}
// 1x11xx1x 1xxxxxxx
private boolean isHeaderValid(byte[] bytes) {
return matchOnes(bytes[0], 178) && matchOnes(bytes[1], 128);
}
// 1x00000x
private boolean isOk(byte[] bytes) {
return matchOnes(bytes[2], 128) && matchZeroes(bytes[2], 62);
}
// 1x01100x
private boolean isError(byte[] bytes) {
return matchOnes(bytes[2], 152) && matchZeroes(bytes[2], 38);
}
// 00xxxxxx 0xxxxxxx
private int getLambda(byte[] bytes) {
return (bytes[4] << 7) | bytes[5];
}
public static void main(String[] args) {
byte[] bytes = asBytes("0xB2808113036F1E650124007000470039003A");
DataConvertor convertor = new Lm2SerialDataConvertor();
double result = convertor.convert(bytes);
System.out.println("result = " + result);
}
}

View File

@ -20,12 +20,10 @@
package com.romraider.logger.innovate.lm2.serial.plugin;
import com.romraider.logger.ecu.external.ExternalDataItem;
import com.romraider.logger.innovate.generic.serial.plugin.DataConvertor;
import com.romraider.logger.innovate.generic.serial.plugin.RawDataListener;
import com.romraider.logger.innovate.generic.mts.plugin.DataListener;
public final class Lm2SerialDataItem implements ExternalDataItem, RawDataListener {
private final DataConvertor convertor = new Lm2SerialDataConvertor();
private byte[] bytes;
public final class Lm2SerialDataItem implements ExternalDataItem, DataListener {
private double data;
public String getName() {
return "Innovate LM-2 [serial]";
@ -40,11 +38,10 @@ public final class Lm2SerialDataItem implements ExternalDataItem, RawDataListene
}
public double getData() {
if (bytes == null) return 0.0;
return convertor.convert(bytes);
return data;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
public void setData(double data) {
this.data = data;
}
}

View File

@ -23,25 +23,22 @@ import com.romraider.logger.ecu.EcuLogger;
import com.romraider.logger.ecu.external.ExternalDataItem;
import com.romraider.logger.ecu.external.ExternalDataSource;
import com.romraider.logger.innovate.generic.serial.io.InnovateRunner;
import com.romraider.logger.innovate.generic.serial.io.InnovateRunnerImpl;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettings;
import com.romraider.logger.innovate.generic.serial.plugin.InnovateSettingsImpl;
import static com.romraider.util.ThreadUtil.runAsDaemon;
import javax.swing.Action;
import static java.util.Arrays.asList;
import java.util.List;
public final class Lm2SerialDataSource implements ExternalDataSource {
private InnovateSettings settings = new InnovateSettingsImpl();
private Lm2SerialDataItem dataItem = new Lm2SerialDataItem();
private InnovateRunner runner;
private String port;
public String getName() {
return "Innovate LM-2 [serial]";
}
public String getVersion() {
return "0.01";
return "0.02";
}
public List<? extends ExternalDataItem> getDataItems() {
@ -53,15 +50,15 @@ public final class Lm2SerialDataSource implements ExternalDataSource {
}
public void setPort(String port) {
settings.setPort(port);
this.port = port;
}
public String getPort() {
return settings.getPort();
return port;
}
public void connect() {
runner = new InnovateRunnerImpl("LM-2", settings, dataItem, 18);
runner = new InnovateRunner("LM-2", port, dataItem);
runAsDaemon(runner);
}

View File

@ -53,6 +53,10 @@ public final class TestPlxConnection implements SerialConnection {
throw new UnsupportedOperationException();
}
public int read() {
throw new UnsupportedOperationException();
}
public void close() {
index = 0;
}