mirror of https://github.com/rusefi/RomRaider.git
Merge branch 'RomRaider:master' into ncs_conv
This commit is contained in:
commit
be340e84d7
|
@ -9,3 +9,4 @@ FASTK = {0} Fast-K:
|
|||
CANBUS = {0} CAN bus:
|
||||
EXTERNALS = Externals:
|
||||
QUERYSTATS = {0}[ {1,number,0.00} queries/sec, {2,number,0.00} sec/query ]
|
||||
STOPPING = Stopping ...
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2012 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -22,11 +22,43 @@ package com.romraider.io.connection;
|
|||
import com.romraider.logger.ecu.comms.manager.PollingState;
|
||||
|
||||
public interface ConnectionManager {
|
||||
/**
|
||||
* Use the open method when communications to a Module requires a
|
||||
* StartCommunication sequence, such as Five Baud or Fast Init.
|
||||
* Include the StopCommunication sequence in the open so that
|
||||
* if something fails, the stop sequence is pre-loaded for use.
|
||||
* @param start - the byte sequence used to start comms
|
||||
* @param stop - the byte sequence used to stop comss
|
||||
*/
|
||||
void open(byte[] start, byte[] stop);
|
||||
|
||||
/**
|
||||
* Use this send method to send a request to a Module and return the
|
||||
* Module's reply in response. Polling state can be slow or fast as
|
||||
* provided by the PollingState parameter.
|
||||
* @param request - the bytes to send to the Module
|
||||
* @param response - a byte array sized to contain the Module's response
|
||||
* @param pollState - polling state, State_0 (slow) or State_1 (fast)
|
||||
*/
|
||||
void send(byte[] request, byte[] response, PollingState pollState);
|
||||
|
||||
/**
|
||||
* Use this send method to send bytes to a Module and return the
|
||||
* Module's reply.
|
||||
* @param bytes - the bytes to send to the Module
|
||||
* @return A byte array of the Module's response, variable sized
|
||||
*/
|
||||
byte[] send(byte[] bytes);
|
||||
|
||||
/**
|
||||
* Use this method to clear the communications line of any erroneous data.
|
||||
* It can be called before closing off communications to clear buffers
|
||||
* of stale data, or when changing polling modes.
|
||||
*/
|
||||
void clearLine();
|
||||
|
||||
/**
|
||||
* Use this method to close communications with the Module.
|
||||
*/
|
||||
void close();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -60,6 +60,10 @@ public final class ElmConnectionManager implements ConnectionManager {
|
|||
// readTimeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(byte[] start, byte[] stop) {
|
||||
}
|
||||
|
||||
public int getCurrentProtocolMode() {
|
||||
return elmMode;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2018 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -46,16 +46,28 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
private byte[] lastResponse;
|
||||
private long timeout;
|
||||
private boolean commsStarted;
|
||||
private final byte[] startReq = {
|
||||
(byte) 0x81, (byte) 0x10, (byte) 0xFC, (byte) 0x81, (byte) 0x0E};
|
||||
private final byte[] stopReq = {
|
||||
(byte) 0x81, (byte) 0x10, (byte) 0xFC, (byte) 0x82, (byte) 0x0F};
|
||||
private PollingState.State currentPollState;
|
||||
private ConnectionProperties connectionProperties;
|
||||
private String library;
|
||||
private byte[] startRequest;
|
||||
private byte[] stopRequest;
|
||||
|
||||
public J2534ConnectionISO14230(ConnectionProperties connectionProperties, String library) {
|
||||
checkNotNull(connectionProperties, "connectionProperties");
|
||||
checkNotNull(library, "library");
|
||||
deviceId = -1;
|
||||
commsStarted = false;
|
||||
this.connectionProperties = connectionProperties;
|
||||
timeout = (long)connectionProperties.getConnectTimeout();
|
||||
this.library = library;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(byte[] start, byte[] stop) {
|
||||
checkNotNull(start, "start");
|
||||
checkNotNull(stop, "stop");
|
||||
startRequest = start;
|
||||
stopRequest = stop;
|
||||
initJ2534(connectionProperties, library);
|
||||
LOGGER.info("J2534/ISO14230 connection initialised");
|
||||
}
|
||||
|
@ -65,7 +77,7 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
checkNotNull(request, "request");
|
||||
checkNotNull(response, "response");
|
||||
checkNotNull(pollState, "pollState");
|
||||
|
||||
|
||||
if (pollState.getCurrentState() == PollingState.State.STATE_0 &&
|
||||
pollState.getLastState() == PollingState.State.STATE_1) {
|
||||
clearLine();
|
||||
|
@ -90,6 +102,7 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
pollState.setNewQuery(true);
|
||||
}
|
||||
}
|
||||
currentPollState = pollState.getCurrentState();
|
||||
}
|
||||
|
||||
// Send request and wait specified time for response with unknown length
|
||||
|
@ -101,13 +114,17 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
|
||||
public void clearLine() {
|
||||
boolean repeat = true;
|
||||
if (currentPollState == PollingState.State.STATE_0) {
|
||||
// Slow poll, no need to send break and clear the line
|
||||
return;
|
||||
}
|
||||
while (repeat) {
|
||||
LOGGER.debug("J2534/ISO14230 sending line break");
|
||||
int p3_min = getP3Min();
|
||||
setP3Min(2);
|
||||
api.writeMsg(
|
||||
channelId,
|
||||
stopReq,
|
||||
stopRequest,
|
||||
0L,
|
||||
TxFlags.WAIT_P3_MIN_ONLY);
|
||||
setP3Min(p3_min);
|
||||
|
@ -129,6 +146,7 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
} while (!empty && i <= 3);
|
||||
}
|
||||
try {
|
||||
// if we are clearing the line due to a comms error, re-init to continue logging
|
||||
fastInit();
|
||||
}
|
||||
catch (J2534Exception e) {
|
||||
|
@ -172,7 +190,6 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
"J2534/ISO14230 connection success: deviceId:%d, channelId:%d, msgId:%d, baud:%d",
|
||||
deviceId, channelId, msgId, connectionProperties.getBaudRate()));
|
||||
fastInit();
|
||||
commsStarted = true;
|
||||
} catch (Exception e) {
|
||||
LOGGER.debug(String.format(
|
||||
"J2534/ISO14230 exception: deviceId:%d, channelId:%d, msgId:%d",
|
||||
|
@ -250,14 +267,15 @@ public final class J2534ConnectionISO14230 implements ConnectionManager {
|
|||
}
|
||||
|
||||
private void fastInit() {
|
||||
final byte[] timing = api.fastInit(channelId, startReq);
|
||||
final byte[] timing = api.fastInit(channelId, startRequest);
|
||||
LOGGER.debug(String.format(
|
||||
"J2534/ISO14230 Fast Init: deviceId:%d, channelId:%d, timing:%s",
|
||||
deviceId, channelId, asHex(timing)));
|
||||
commsStarted = true;
|
||||
}
|
||||
|
||||
private void stopComms() {
|
||||
final byte[] response = send(stopReq);
|
||||
final byte[] response = send(stopRequest);
|
||||
LOGGER.debug(String.format("Stop comms Response = %s", asHex(response)));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2014 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -19,6 +19,7 @@
|
|||
|
||||
package com.romraider.io.j2534.api;
|
||||
|
||||
import static com.romraider.util.HexUtil.asHex;
|
||||
import static com.romraider.util.ParamChecker.checkNotNull;
|
||||
import static org.apache.log4j.Logger.getLogger;
|
||||
|
||||
|
@ -39,6 +40,7 @@ public final class J2534ConnectionISO15765 implements ConnectionManager {
|
|||
private int deviceId;
|
||||
private int msgId;
|
||||
private final long timeout;
|
||||
private byte[] stopRequest;
|
||||
|
||||
public J2534ConnectionISO15765(
|
||||
ConnectionProperties connectionProperties,
|
||||
|
@ -50,6 +52,19 @@ public final class J2534ConnectionISO15765 implements ConnectionManager {
|
|||
LOGGER.info("J2534/ISO15765 connection initialized");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(byte[] start, byte[] stop) {
|
||||
checkNotNull(start, "start");
|
||||
checkNotNull(start, "stop");
|
||||
this.stopRequest = stop;
|
||||
LOGGER.debug(String.format("Start Diagnostics Request ---> %s",
|
||||
asHex(start)));
|
||||
api.writeMsg(channelId, start, timeout, TxFlags.ISO15765_FRAME_PAD);
|
||||
final byte[] response = api.readMsg(channelId, 1, timeout);
|
||||
LOGGER.debug(String.format("Start Diagnostics Response <--- %s",
|
||||
asHex(response)));
|
||||
}
|
||||
|
||||
// Send request and wait for response with known length
|
||||
@Override
|
||||
public void send(byte[] request, byte[] response, PollingState pollState) {
|
||||
|
@ -79,6 +94,12 @@ public final class J2534ConnectionISO15765 implements ConnectionManager {
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
LOGGER.debug(String.format("Stop Diagnostics Request ---> %s",
|
||||
asHex(stopRequest)));
|
||||
api.writeMsg(channelId, stopRequest, timeout, TxFlags.ISO15765_FRAME_PAD);
|
||||
final byte[] response = api.readMsg(channelId, 1, timeout);
|
||||
LOGGER.debug(String.format("Stop Diagnostics Response <--- %s",
|
||||
asHex(response)));
|
||||
stopFcFilter();
|
||||
disconnectChannel();
|
||||
closeDevice();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2018 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -55,6 +55,10 @@ public final class J2534ConnectionISO9141 implements ConnectionManager {
|
|||
LOGGER.info("J2534/ISO9141 connection initialised");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(byte[] start, byte[] stop) {
|
||||
}
|
||||
|
||||
// Send request and wait for response with known length
|
||||
public void send(byte[] request, byte[] response, PollingState pollState) {
|
||||
checkNotNull(request, "request");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2018 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -22,6 +22,9 @@ package com.romraider.io.j2534.api;
|
|||
import static com.romraider.util.HexUtil.asHex;
|
||||
import static com.romraider.util.LogManager.initDebugLogging;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.romraider.io.j2534.api.J2534Impl.Config;
|
||||
import com.romraider.io.j2534.api.J2534Impl.Flag;
|
||||
import com.romraider.io.j2534.api.J2534Impl.Protocol;
|
||||
|
@ -55,23 +58,76 @@ public class TestJ2534 {
|
|||
|
||||
int msgId = api.startPassMsgFilter(channelId, (byte) 0x00, (byte) 0x00);
|
||||
try {
|
||||
List<byte[]> msgs = new ArrayList<byte[]>();
|
||||
byte[] ecuInit = null;
|
||||
if (protocol.equalsIgnoreCase("ssm")) {
|
||||
ecuInit = new byte[]{
|
||||
(byte) 0x80, (byte) 0x10, (byte) 0xF0,
|
||||
(byte) 0x01, (byte) 0xBF, (byte) 0x40};
|
||||
msgs.add(ecuInit);
|
||||
}
|
||||
else if (protocol.equalsIgnoreCase("ds2")) {
|
||||
ecuInit = new byte[]{
|
||||
(byte) 0x12, (byte) 0x04, (byte) 0x00,
|
||||
(byte) 0x16};
|
||||
byte[] engine = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x03, (byte) 0x1F};
|
||||
byte[] swtch = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x04, (byte) 0x18};
|
||||
byte[] lambda = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x91, (byte) 0x8D};
|
||||
byte[] adapt = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x92, (byte) 0x8E};
|
||||
byte[] corr = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x93, (byte) 0x8F};
|
||||
byte[] cat = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x94, (byte) 0x88};
|
||||
byte[] status = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0x95, (byte) 0x89};
|
||||
byte[] close = new byte[]{
|
||||
(byte) 0x12, (byte) 0x05, (byte) 0x0B,
|
||||
(byte) 0xFF, (byte) 0xE3};
|
||||
byte[] _0C = new byte[]{
|
||||
(byte) 0x12, (byte) 0x04, (byte) 0x0C,
|
||||
(byte) 0x1A};
|
||||
byte[] _0D = new byte[]{
|
||||
(byte) 0x12, (byte) 0x04, (byte) 0x0D,
|
||||
(byte) 0x1B};
|
||||
byte[] _25 = new byte[]{
|
||||
(byte) 0x12, (byte) 0x04, (byte) 0x25,
|
||||
(byte) 0x33};
|
||||
byte[] _53 = new byte[]{
|
||||
(byte) 0x12, (byte) 0x04, (byte) 0x53,
|
||||
(byte) 0x45};
|
||||
msgs.add(ecuInit);
|
||||
msgs.add(engine);
|
||||
msgs.add(swtch);
|
||||
msgs.add(lambda);
|
||||
msgs.add(adapt);
|
||||
msgs.add(corr);
|
||||
msgs.add(cat);
|
||||
msgs.add(status);
|
||||
msgs.add(close);
|
||||
msgs.add(_0C);
|
||||
msgs.add(_0D);
|
||||
msgs.add(_25);
|
||||
msgs.add(_53);
|
||||
}
|
||||
|
||||
api.writeMsg(channelId, ecuInit, 55L, TxFlags.NO_FLAGS);
|
||||
System.out.println("Request = " + asHex(ecuInit));
|
||||
for (byte[] msg : msgs) {
|
||||
api.writeMsg(channelId, msg, 55L, TxFlags.NO_FLAGS);
|
||||
System.out.println("Request = " + asHex(msg));
|
||||
|
||||
byte[] response = api.readMsg(channelId, 1, 2000L);
|
||||
System.out.println("Response = " + asHex(response));
|
||||
byte[] response = api.readMsg(channelId, 500L);
|
||||
System.out.println("Response = " + asHex(response));
|
||||
}
|
||||
|
||||
} finally {
|
||||
api.stopMsgFilter(channelId, msgId);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -19,6 +19,8 @@
|
|||
|
||||
package com.romraider.io.protocol;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.romraider.logger.ecu.comms.manager.PollingState;
|
||||
import com.romraider.logger.ecu.definition.Module;
|
||||
|
||||
|
@ -29,7 +31,7 @@ public interface ProtocolNCS extends Protocol {
|
|||
|
||||
byte[] constructReadSidPidRequest(Module module, byte sid, byte[][] pid);
|
||||
|
||||
byte[] constructLoadAddressRequest(byte[][] addresses);
|
||||
byte[] constructLoadAddressRequest(Map<byte[], Integer> queryMap);
|
||||
|
||||
void validateLoadAddressResponse(byte[] response);
|
||||
|
||||
|
@ -39,4 +41,12 @@ public interface ProtocolNCS extends Protocol {
|
|||
PollingState pollState);
|
||||
|
||||
byte[] constructEcuIdRequest(Module module);
|
||||
|
||||
byte[] constructEcuStopRequest(Module module);
|
||||
|
||||
byte[] constructStartDiagRequest(Module module);
|
||||
|
||||
byte[] constructElevatedDiagRequest(Module module);
|
||||
|
||||
byte[] constructReadMemoryRequest(Module module, byte[][] address, int numBytes);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -28,6 +28,7 @@ import static java.lang.System.arraycopy;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.romraider.io.protocol.Protocol;
|
||||
|
@ -48,6 +49,21 @@ public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
|||
return protocol.constructEcuFastInitRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructStartDiagRequest(Module module) {
|
||||
return protocol.constructStartDiagRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructElevatedDiagRequest(Module module) {
|
||||
return protocol.constructElevatedDiagRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuStopRequest(Module module) {
|
||||
return protocol.constructEcuStopRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuInitRequest(Module module) {
|
||||
return protocol.constructEcuInitRequest(module);
|
||||
|
@ -91,6 +107,17 @@ public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
|||
convertToByteAddresses(filteredQueries));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadMemoryRequest(Module module,
|
||||
Collection<EcuQuery> queries, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadMemoryResponse(int requestSize, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateLoadAddressResponse(byte[] response) {
|
||||
protocol.validateLoadAddressResponse(response);
|
||||
|
@ -170,6 +197,10 @@ public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processReadMemoryResponses(Collection<EcuQuery> queries, byte[] response) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol getProtocol() {
|
||||
return protocol;
|
||||
|
@ -189,7 +220,8 @@ public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
|||
protocol.checkValidWriteResponse(data, response);
|
||||
}
|
||||
|
||||
private Collection<EcuQuery> filterDuplicates(Collection<EcuQuery> queries) {
|
||||
@Override
|
||||
public Collection<EcuQuery> filterDuplicates(Collection<EcuQuery> queries) {
|
||||
Collection<EcuQuery> filteredQueries = new ArrayList<EcuQuery>();
|
||||
for (EcuQuery query : queries) {
|
||||
if (!filteredQueries.contains(query)) {
|
||||
|
@ -199,13 +231,8 @@ public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
|||
return filteredQueries;
|
||||
}
|
||||
|
||||
private byte[][] convertToByteAddresses(Collection<EcuQuery> queries) {
|
||||
int byteCount = 0;
|
||||
for (EcuQuery query : queries) {
|
||||
byteCount += query.getAddresses().length;
|
||||
}
|
||||
byte[][] addresses = new byte[byteCount][];
|
||||
int i = 0;
|
||||
private Map<byte[], Integer> convertToByteAddresses(Collection<EcuQuery> queries) {
|
||||
final Map<byte[], Integer> queryMap = new LinkedHashMap<byte[], Integer>();
|
||||
for (EcuQuery query : queries) {
|
||||
byte[] bytes = query.getBytes();
|
||||
int addrCount = query.getAddresses().length;
|
||||
|
@ -213,9 +240,9 @@ public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
|||
for (int j = 0; j < addrCount; j++) {
|
||||
final byte[] addr = new byte[addrLen];
|
||||
arraycopy(bytes, j * addrLen, addr, 0, addr.length);
|
||||
addresses[i++] = addr;
|
||||
queryMap.put(addr, 1);
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
return queryMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -26,6 +26,7 @@ import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import com.romraider.io.connection.ConnectionProperties;
|
||||
import com.romraider.io.connection.KwpConnectionProperties;
|
||||
|
@ -53,6 +54,8 @@ public final class NCSProtocol implements ProtocolNCS {
|
|||
public static final byte WRITE_ADDRESS_RESPONSE = (byte) 0xF8;
|
||||
public static final byte FASTINIT_COMMAND = (byte) 0x81;
|
||||
public static final byte FASTINIT_RESPONSE = (byte) 0xC1;
|
||||
public static final byte STOP_COMMAND = (byte) 0x82;
|
||||
public static final byte STOP_RESPONSE = (byte) 0xC2;
|
||||
public static final byte ECU_ID_SID = (byte) 0x1A;
|
||||
public static final byte OPTION_81 = (byte) 0x81;
|
||||
public static final byte FIELD_TYPE_01 = (byte) 0x01;
|
||||
|
@ -69,6 +72,7 @@ public final class NCSProtocol implements ProtocolNCS {
|
|||
public static final int ADDRESS_SIZE = 3;
|
||||
public static Module module;
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuFastInitRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
|
@ -77,6 +81,27 @@ public final class NCSProtocol implements ProtocolNCS {
|
|||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuStopRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
final byte[] request = buildRequest(
|
||||
STOP_COMMAND, false, new byte[]{});
|
||||
return request;
|
||||
}
|
||||
|
||||
// not implemented
|
||||
@Override
|
||||
public byte[] constructStartDiagRequest(Module module) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// not implemented
|
||||
@Override
|
||||
public byte[] constructElevatedDiagRequest(Module module) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// not implemented
|
||||
@Override
|
||||
public byte[] constructEcuInitRequest(Module module) {
|
||||
|
@ -133,12 +158,27 @@ public final class NCSProtocol implements ProtocolNCS {
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructLoadAddressRequest(byte[][] addresses) {
|
||||
checkNotNullOrEmpty(addresses, "addresses");
|
||||
//TODO: not yet implemented
|
||||
public byte[] constructReadMemoryRequest(Module module, byte[][] address,
|
||||
int numBytes) {
|
||||
|
||||
throw new UnsupportedProtocolException(
|
||||
"Read memory command is not supported on for address: " +
|
||||
asHex(address[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructLoadAddressRequest(Map<byte[], Integer> queries) {
|
||||
checkNotNullOrEmpty(queries, "queries");
|
||||
// short header - false, length encoded into lower 5 bits of first byte
|
||||
// 0x8Len 0x10 0xFC 0xac 0x81 fld_typ address1 [[fld_typ address2] ... [fld_typ addressN]] checksum
|
||||
// short header - true
|
||||
// Len 0xac 0x81 fld_typ address1 [[fld_typ address2] ... [fld_typ addressN]] checksum
|
||||
byte [][] addresses = new byte[queries.size()][];
|
||||
int i = 0;
|
||||
for (byte [] query : queries.keySet()) {
|
||||
addresses[i++] = query;
|
||||
}
|
||||
return buildLoadAddrRequest(true, addresses);
|
||||
}
|
||||
|
||||
|
@ -201,6 +241,7 @@ public final class NCSProtocol implements ProtocolNCS {
|
|||
|
||||
@Override
|
||||
//TODO: not yet implemented
|
||||
// maybe use: Service $11 - Module reset
|
||||
public byte[] constructEcuResetRequest(Module module, int resetCode) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
|
@ -375,7 +416,7 @@ public final class NCSProtocol implements ProtocolNCS {
|
|||
if (tmp[0] == (byte) 0xFF) {
|
||||
bb.write(FIELD_TYPE_83);
|
||||
bb.write((byte) 0xFF);
|
||||
bb.write(tmp);
|
||||
bb.write(tmp, 0, 3);
|
||||
}
|
||||
else { //assume a short length ROM address
|
||||
bb.write(FIELD_TYPE_83);
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.io.protocol.ncs.iso15765;
|
||||
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.RESPONSE_NON_DATA_BYTES;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSResponseProcessor.extractResponseData;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSResponseProcessor.filterRequestFromResponse;
|
||||
import static com.romraider.util.HexUtil.hexToInt;
|
||||
import static com.romraider.util.ParamChecker.checkNotNull;
|
||||
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
|
||||
import static java.lang.System.arraycopy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.romraider.io.protocol.Protocol;
|
||||
import com.romraider.io.protocol.ProtocolNCS;
|
||||
import com.romraider.logger.ecu.comms.io.protocol.LoggerProtocolNCS;
|
||||
import com.romraider.logger.ecu.comms.manager.PollingState;
|
||||
import com.romraider.logger.ecu.comms.query.EcuInit;
|
||||
import com.romraider.logger.ecu.comms.query.EcuInitCallback;
|
||||
import com.romraider.logger.ecu.comms.query.EcuQuery;
|
||||
import com.romraider.logger.ecu.comms.query.EcuQueryData;
|
||||
import com.romraider.logger.ecu.definition.Module;
|
||||
|
||||
public final class NCSLoggerProtocol implements LoggerProtocolNCS {
|
||||
private final ProtocolNCS protocol = new NCSProtocol();
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuFastInitRequest(Module module) {
|
||||
return protocol.constructEcuFastInitRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructStartDiagRequest(Module module) {
|
||||
return protocol.constructStartDiagRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructElevatedDiagRequest(Module module) {
|
||||
return protocol.constructElevatedDiagRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuInitRequest(Module module) {
|
||||
return protocol.constructEcuInitRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuStopRequest(Module module) {
|
||||
return protocol.constructEcuStopRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuIdRequest(Module module) {
|
||||
return protocol.constructEcuIdRequest(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuResetRequest(Module module, int resetCode) {
|
||||
return protocol.constructEcuResetRequest(module, resetCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadAddressRequest(Module module,
|
||||
Collection<EcuQuery> queries) {
|
||||
return protocol.constructReadAddressRequest(
|
||||
module, convertToByteAddresses(queries));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadAddressRequest(
|
||||
Module module, Collection<EcuQuery> queries, PollingState pollState) {
|
||||
return protocol.constructReadAddressRequest(
|
||||
module, new byte[0][0], pollState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadSidPidRequest(Module module, byte sid, byte[] pid) {
|
||||
final byte[][] request = new byte[1][pid.length];
|
||||
arraycopy(pid, 0, request[0], 0, pid.length);
|
||||
return protocol.constructReadSidPidRequest(module, sid, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructLoadAddressRequest(Collection<EcuQuery> queries) {
|
||||
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
|
||||
// convert to address and data length
|
||||
return protocol.constructLoadAddressRequest(
|
||||
convertToByteAddressAndLen(filteredQueries));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadMemoryRequest(Module module,
|
||||
Collection<EcuQuery> queries, int length) {
|
||||
|
||||
return protocol.constructReadMemoryRequest(
|
||||
module, convertToByteAddresses(queries), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadMemoryResponse(int requestSize, int length) {
|
||||
return new byte[RESPONSE_NON_DATA_BYTES + requestSize + length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateLoadAddressResponse(byte[] response) {
|
||||
protocol.validateLoadAddressResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadAddressResponse(
|
||||
Collection<EcuQuery> queries, PollingState pollState) {
|
||||
|
||||
checkNotNullOrEmpty(queries, "queries");
|
||||
int numBytes = 7;
|
||||
if (pollState.isFastPoll()) {
|
||||
numBytes = 6;
|
||||
}
|
||||
// CAN addr
|
||||
// one byte - Response sid
|
||||
// one byte - Response pid
|
||||
// one byte - option
|
||||
// variable bytes of data defined for pid
|
||||
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
|
||||
for (EcuQuery ecuQuery : filteredQueries) {
|
||||
//numBytes += ecuQuery.getBytes().length;
|
||||
numBytes += EcuQueryData.getDataLength(ecuQuery);
|
||||
}
|
||||
return new byte[(numBytes)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] preprocessResponse(
|
||||
byte[] request, byte[] response, PollingState pollState) {
|
||||
|
||||
return filterRequestFromResponse(request, response, pollState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEcuInitResponse(EcuInitCallback callback, byte[] response) {
|
||||
checkNotNull(callback, "callback");
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
EcuInit ecuInit = protocol.parseEcuInitResponse(response);
|
||||
callback.callback(ecuInit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] processEcuIdResponse(byte[] response) {
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
return protocol.parseResponseData(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] processReadSidPidResponse(byte[] response) {
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
return protocol.checkValidSidPidResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEcuResetResponse(byte[] response) {
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
protocol.checkValidEcuResetResponse(response);
|
||||
}
|
||||
|
||||
// processes the response bytes and sets individual responses on corresponding query objects
|
||||
@Override
|
||||
public void processReadAddressResponses(
|
||||
Collection<EcuQuery> queries, byte[] response, PollingState pollState) {
|
||||
|
||||
checkNotNullOrEmpty(queries, "queries");
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
final byte[] responseData = extractResponseData(response);
|
||||
final Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
|
||||
final Map<String, byte[]> addressResults = new HashMap<String, byte[]>();
|
||||
int i = 0;
|
||||
for (EcuQuery filteredQuery : filteredQueries) {
|
||||
final int dataLength = EcuQueryData.getDataLength(filteredQuery);
|
||||
final byte[] data = new byte[dataLength];
|
||||
arraycopy(responseData, i, data, 0, dataLength);
|
||||
addressResults.put(filteredQuery.getHex(), data);
|
||||
i += dataLength;
|
||||
}
|
||||
for (EcuQuery query : queries) {
|
||||
query.setResponse(addressResults.get(query.getHex()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the response bytes and set individual response on corresponding
|
||||
* query objects.
|
||||
* The response data is based on the lowest EcuData address and the length
|
||||
* is the result of the difference between the highest and lowest address.
|
||||
* The index into the response array is based in the lowest address.
|
||||
**/
|
||||
public void processReadMemoryResponses(
|
||||
Collection<EcuQuery> queries, byte[] response) {
|
||||
|
||||
checkNotNullOrEmpty(queries, "queries");
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
final byte[] responseData = extractResponseData(response);
|
||||
final Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
|
||||
final Map<String, byte[]> addressResults = new HashMap<String, byte[]>();
|
||||
|
||||
int lowestAddress = Integer.MAX_VALUE;
|
||||
for (EcuQuery filteredQuery : filteredQueries) {
|
||||
final int address = hexToInt(filteredQuery.getAddresses()[0]);
|
||||
if (address < lowestAddress) {
|
||||
lowestAddress = address;
|
||||
}
|
||||
}
|
||||
|
||||
int srcPos = 0;
|
||||
for (EcuQuery filteredQuery : filteredQueries) {
|
||||
int dataTypeLength = EcuQueryData.getDataLength(filteredQuery);
|
||||
final byte[] bytes = new byte[dataTypeLength];
|
||||
final int address = hexToInt(filteredQuery.getAddresses()[0]);
|
||||
srcPos = address - lowestAddress;
|
||||
arraycopy(responseData, srcPos, bytes, 0, bytes.length);
|
||||
addressResults.put(filteredQuery.getHex(), bytes);
|
||||
}
|
||||
|
||||
for (EcuQuery query : queries) {
|
||||
query.setResponse(addressResults.get(query.getHex()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Protocol getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructWriteAddressRequest(
|
||||
Module module, byte[] writeAddress, byte value) {
|
||||
|
||||
return protocol.constructWriteAddressRequest(module, writeAddress, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWriteResponse(byte[] data, byte[] response) {
|
||||
checkNotNullOrEmpty(data, "data");
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
protocol.checkValidWriteResponse(data, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EcuQuery> filterDuplicates(Collection<EcuQuery> queries) {
|
||||
Collection<EcuQuery> filteredQueries = new ArrayList<EcuQuery>();
|
||||
for (EcuQuery query : queries) {
|
||||
if (!filteredQueries.contains(query)) {
|
||||
filteredQueries.add(query);
|
||||
}
|
||||
}
|
||||
return filteredQueries;
|
||||
}
|
||||
|
||||
private byte[][] convertToByteAddresses(Collection<EcuQuery> queries) {
|
||||
int byteCount = 0;
|
||||
for (EcuQuery query : queries) {
|
||||
byteCount += query.getAddresses().length;
|
||||
}
|
||||
byte[][] addresses = new byte[byteCount][];
|
||||
int i = 0;
|
||||
for (EcuQuery query : queries) {
|
||||
byte[] bytes = query.getBytes();
|
||||
int addrCount = query.getAddresses().length;
|
||||
int addrLen = bytes.length / addrCount;
|
||||
for (int j = 0; j < addrCount; j++) {
|
||||
final byte[] addr = new byte[addrLen];
|
||||
arraycopy(bytes, j * addrLen, addr, 0, addr.length);
|
||||
addresses[i++] = addr;
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private Map<byte[], Integer> convertToByteAddressAndLen(Collection<EcuQuery> queries) {
|
||||
final Map<byte[], Integer> queryMap = new LinkedHashMap<byte[], Integer>();
|
||||
for (EcuQuery query : queries) {
|
||||
queryMap.put(query.getBytes(), EcuQueryData.getDataLength(query));
|
||||
}
|
||||
return queryMap;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.io.protocol.ncs.iso15765;
|
||||
|
||||
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 java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import com.romraider.io.connection.ConnectionProperties;
|
||||
import com.romraider.io.connection.KwpConnectionProperties;
|
||||
import com.romraider.io.protocol.ProtocolNCS;
|
||||
import com.romraider.io.protocol.ncs.iso15765.NCSResponseProcessor;
|
||||
import com.romraider.io.protocol.ncs.iso15765.NCSProtocol;
|
||||
import com.romraider.logger.ecu.comms.manager.PollingState;
|
||||
import com.romraider.logger.ecu.comms.query.EcuInit;
|
||||
import com.romraider.logger.ecu.comms.query.NCSEcuInit;
|
||||
import com.romraider.logger.ecu.definition.Module;
|
||||
import com.romraider.logger.ecu.exception.InvalidResponseException;
|
||||
import com.romraider.logger.ecu.exception.UnsupportedProtocolException;
|
||||
|
||||
public final class NCSProtocol implements ProtocolNCS {
|
||||
private final ByteArrayOutputStream bb = new ByteArrayOutputStream(255);
|
||||
public static final byte READ_MEMORY_PADDING = (byte) 0x00;
|
||||
public static final byte READ_MEMORY_COMMAND = (byte) 0x23;
|
||||
public static final byte READ_MEMORY_RESPONSE = (byte) 0x63;
|
||||
public static final byte LOAD_ADDRESS_COMMAND = (byte) 0x2C;
|
||||
public static final byte DDLOCID = (byte) 0xE0;
|
||||
public static final byte LOAD_ADDRESS_RESPONSE = (byte) 0x6C;
|
||||
public static final byte READ_LOAD_COMMAND = (byte) 0x21;
|
||||
public static final byte READ_LOAD_RESPONSE = (byte) 0x61;
|
||||
public static final byte ECU_INIT_COMMAND = (byte) 0x10;
|
||||
public static final byte ECU_INIT_RESPONSE = (byte) 0x50;
|
||||
public static final byte ECU_ID_SID = (byte) 0x21;
|
||||
public static final byte ECU_ID_CMD = (byte) 0x10;
|
||||
public static final byte FIELD_TYPE_01 = (byte) 0x01;
|
||||
public static final byte FIELD_TYPE_02 = (byte) 0x02;
|
||||
public static final byte FIELD_TYPE_03 = (byte) 0x03;
|
||||
public static final byte SID_21 = (byte) 0x21;
|
||||
public static final byte SID_22 = (byte) 0x22;
|
||||
public static final byte ECU_ID_SID_RESPONSE = (byte) 0x50;
|
||||
public static final byte READ_SID_21_RESPONSE = (byte) 0x61;
|
||||
public static final byte READ_SID_GRP_RESPONSE = (byte) 0x62;
|
||||
public static final byte ECU_RESET_COMMAND = (byte) 0x04;
|
||||
public static final byte ECU_RESET_RESPONSE = (byte) 0x44;
|
||||
public static final byte NCS_NRC = (byte) 0x7F;
|
||||
public static final int RESPONSE_NON_DATA_BYTES = 4;
|
||||
public static final int ADDRESS_SIZE = 4;
|
||||
public static Module module;
|
||||
|
||||
// not implemented
|
||||
@Override
|
||||
public byte[] constructEcuFastInitRequest(Module module) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuStopRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
// 000007E01081
|
||||
final byte[] request = buildRequest(
|
||||
ECU_INIT_COMMAND, false, new byte[]{(byte) 0x81});
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuInitRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
// 000007E010C0
|
||||
final byte[] request = buildRequest(
|
||||
ECU_INIT_COMMAND, false, new byte[]{(byte) 0xC0});
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructStartDiagRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
// 000007E010C0
|
||||
final byte[] request = buildRequest(
|
||||
ECU_INIT_COMMAND, false, new byte[]{(byte) 0xC0});
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructElevatedDiagRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
// 000007E010FB
|
||||
final byte[] request = buildRequest(
|
||||
ECU_INIT_COMMAND, false, new byte[]{(byte) 0xFB});
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructEcuIdRequest(Module module) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
// 000007E02110
|
||||
final byte[] request = buildRequest(
|
||||
ECU_ID_SID, false, new byte[]{ECU_ID_CMD});
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadSidPidRequest(Module module, byte sid, byte[][] pid) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
final byte[] request = buildRequest(sid, false, pid);
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
//TODO: not yet implemented
|
||||
public byte[] constructWriteMemoryRequest(
|
||||
Module module, byte[] address, byte[] values) {
|
||||
|
||||
throw new UnsupportedProtocolException(
|
||||
"Write memory command is not supported on for address: " +
|
||||
asHex(address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructWriteAddressRequest(
|
||||
Module module, byte[] address, byte value) {
|
||||
|
||||
throw new UnsupportedProtocolException(
|
||||
"Write Address command is not supported on for address: " +
|
||||
asHex(address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadMemoryRequest(Module module, byte[] address,
|
||||
int numBytes) {
|
||||
NCSProtocol.module = module;
|
||||
// 000007E023 4-byte_address 2-byte_numBytes
|
||||
final byte[] frame = new byte[6];
|
||||
if (address[0] == -1) {
|
||||
frame[0] = (byte) 0xFF;
|
||||
}
|
||||
System.arraycopy(address, 0, frame, 4-address.length, address.length);
|
||||
frame[5] = (byte) numBytes;
|
||||
return buildRequest(READ_MEMORY_COMMAND, false, frame, new byte[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadMemoryRequest(
|
||||
Module module, byte[][] address, int numBytes) {
|
||||
checkNotNull(module, "module");
|
||||
checkNotNullOrEmpty(address, "address");
|
||||
checkGreaterThanZero(numBytes, "numBytes");
|
||||
return constructReadMemoryRequest(module, address[0],
|
||||
numBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructLoadAddressRequest(Map<byte[], Integer> queryMap) {
|
||||
checkNotNullOrEmpty(queryMap, "queryMap");
|
||||
// ID 0x2C 0xE0 DEFMODE ... DEFMODE ... DEFMODE ...
|
||||
return buildLoadAddrRequest(queryMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadAddressRequest(Module module, byte[][] addresses) {
|
||||
// read addresses
|
||||
// addr sid pid
|
||||
return buildSidPidRequest(addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] constructReadAddressRequest(Module module, byte[][] bs,
|
||||
PollingState pollState) {
|
||||
return buildRequest(
|
||||
READ_LOAD_COMMAND, false, new byte[]{(byte) 0xE0});
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] preprocessResponse(
|
||||
byte[] request, byte[] response, PollingState pollState) {
|
||||
return NCSResponseProcessor.filterRequestFromResponse(
|
||||
request, response, pollState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] parseResponseData(byte[] processedResponse) {
|
||||
checkNotNullOrEmpty(processedResponse, "processedResponse");
|
||||
return NCSResponseProcessor.extractResponseData(processedResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValidEcuInitResponse(byte[] processedResponse) {
|
||||
checkNotNullOrEmpty(processedResponse, "processedResponse");
|
||||
NCSResponseProcessor.validateResponse(processedResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcuInit parseEcuInitResponse(byte[] processedResponse) {
|
||||
checkNotNullOrEmpty(processedResponse, "processedResponse");
|
||||
//final byte[] ecuInitBytes = parseResponseData(processedResponse);
|
||||
return new NCSEcuInit(processedResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateLoadAddressResponse(byte[] response) {
|
||||
checkNotNullOrEmpty(response, "addressLoadResponse");
|
||||
NCSResponseProcessor.validateResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
//TODO: not yet implemented
|
||||
// maybe use: Service $11 with 0x80 - module reset
|
||||
public byte[] constructEcuResetRequest(Module module, int resetCode) {
|
||||
checkNotNull(module, "module");
|
||||
NCSProtocol.module = module;
|
||||
return buildRequest((byte) 0, false, new byte[]{ECU_RESET_COMMAND});
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] checkValidSidPidResponse(byte[] response) {
|
||||
checkNotNullOrEmpty(response, "SidPidResponse");
|
||||
return NCSResponseProcessor.extractResponseData(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
//TODO: not yet implemented
|
||||
public void checkValidEcuResetResponse(byte[] processedResponse) {
|
||||
checkNotNullOrEmpty(processedResponse, "processedResponse");
|
||||
byte responseType = processedResponse[4];
|
||||
if (responseType != ECU_RESET_RESPONSE) {
|
||||
throw new InvalidResponseException(
|
||||
"Unexpected OBD Reset response: " +
|
||||
asHex(processedResponse));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValidWriteResponse(byte[] data, byte[] processedResponse) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionProperties getDefaultConnectionProperties() {
|
||||
return new KwpConnectionProperties() {
|
||||
|
||||
public int getBaudRate() {
|
||||
return 500000;
|
||||
}
|
||||
|
||||
public void setBaudRate(int b) {
|
||||
|
||||
}
|
||||
|
||||
public int getDataBits() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int getStopBits() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getParity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getConnectTimeout() {
|
||||
return 2000;
|
||||
}
|
||||
|
||||
public int getSendTimeout() {
|
||||
return 255;
|
||||
}
|
||||
|
||||
public int getP1Max() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getP3Min() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
public int getP4Min() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private byte[] buildRequest(
|
||||
byte command,
|
||||
boolean padContent,
|
||||
byte[]... content) {
|
||||
|
||||
bb.reset();
|
||||
try {
|
||||
bb.write(module.getTester());
|
||||
bb.write(command);
|
||||
if (padContent) {
|
||||
bb.write(READ_MEMORY_PADDING);
|
||||
}
|
||||
for (byte[] tmp : content) {
|
||||
bb.write(tmp);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bb.toByteArray();
|
||||
}
|
||||
|
||||
private final byte[] buildSidPidRequest(byte[]... content) {
|
||||
|
||||
bb.reset();
|
||||
try {
|
||||
bb.write(module.getTester());
|
||||
for (byte[] tmp : content) {
|
||||
bb.write(tmp);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bb.toByteArray();
|
||||
}
|
||||
|
||||
private final byte[] buildLoadAddrRequest(Map<byte[], Integer> queryMap) {
|
||||
|
||||
int PIDYDLID = 1;
|
||||
byte[] request = new byte[0];
|
||||
try {
|
||||
bb.reset();
|
||||
bb.write(module.getTester());
|
||||
bb.write(LOAD_ADDRESS_COMMAND);
|
||||
bb.write(DDLOCID);
|
||||
for (byte[] tmp : queryMap.keySet()) {
|
||||
if (tmp[0] == SID_22) {
|
||||
bb.write(FIELD_TYPE_02); //definitionMode
|
||||
bb.write(PIDYDLID++); //positionIn
|
||||
bb.write(queryMap.get(tmp)); //size
|
||||
bb.write(tmp, 1, tmp.length - 1);//CID
|
||||
bb.write(1); //positionInRecord
|
||||
continue;
|
||||
}
|
||||
else if (tmp[0] == (byte) 0xFF) {
|
||||
bb.write(FIELD_TYPE_03); //definitionMode
|
||||
bb.write(PIDYDLID++); //positionIn
|
||||
bb.write(queryMap.get(tmp));//size (could be 1, 2 or 4)
|
||||
bb.write((byte) 0xFF); //RAM addr high byte
|
||||
bb.write(tmp, 0, 3); //RAM addr
|
||||
}
|
||||
}
|
||||
request = bb.toByteArray();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.io.protocol.ncs.iso15765;
|
||||
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.module;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.ECU_INIT_RESPONSE;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.ECU_ID_SID_RESPONSE;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.READ_SID_21_RESPONSE;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.NCS_NRC;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.READ_SID_GRP_RESPONSE;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.READ_MEMORY_RESPONSE;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.RESPONSE_NON_DATA_BYTES;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.LOAD_ADDRESS_RESPONSE;
|
||||
import static com.romraider.io.protocol.ncs.iso15765.NCSProtocol.READ_LOAD_RESPONSE;
|
||||
import static com.romraider.util.ByteUtil.asUnsignedInt;
|
||||
import static com.romraider.util.HexUtil.asHex;
|
||||
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
|
||||
|
||||
import com.romraider.logger.ecu.comms.manager.PollingState;
|
||||
import com.romraider.logger.ecu.exception.InvalidResponseException;
|
||||
|
||||
public final class NCSResponseProcessor {
|
||||
|
||||
private NCSResponseProcessor() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final static byte[] filterRequestFromResponse(
|
||||
byte[] request, byte[] response, PollingState pollState) {
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
// If J2534 device Loopback is off, the request is filtered out by J2534 device
|
||||
// and only the response is present
|
||||
return response;
|
||||
}
|
||||
|
||||
public static void validateResponse(byte[] response) {
|
||||
assertTrue(response.length > RESPONSE_NON_DATA_BYTES, "Invalid response length");
|
||||
assertEquals(module.getAddress(), response, "Invalid " +
|
||||
module.getName() + " id");
|
||||
if (response[4] == NCS_NRC) {
|
||||
assertNrc(NCS_NRC, response[4], response[5], response[6], "Request type not supported");
|
||||
}
|
||||
assertOneOf(new byte[]{ECU_INIT_RESPONSE, ECU_ID_SID_RESPONSE,
|
||||
READ_SID_21_RESPONSE, READ_SID_GRP_RESPONSE,
|
||||
READ_MEMORY_RESPONSE, LOAD_ADDRESS_RESPONSE,
|
||||
READ_LOAD_RESPONSE}, response[4], "Invalid response code");
|
||||
}
|
||||
|
||||
public static byte[] extractResponseData(byte[] response) {
|
||||
checkNotNullOrEmpty(response, "response");
|
||||
// 0x00 0x00 0x07 0xe0 response_command response_data
|
||||
validateResponse(response);
|
||||
int nonDataLength = 0;
|
||||
byte[] data = new byte[]{};
|
||||
if (response[4] == ECU_ID_SID_RESPONSE) {
|
||||
nonDataLength = RESPONSE_NON_DATA_BYTES;
|
||||
}
|
||||
else if (response[4] == READ_SID_21_RESPONSE) {
|
||||
nonDataLength = RESPONSE_NON_DATA_BYTES + 2;
|
||||
}
|
||||
else if (response[4] == READ_SID_GRP_RESPONSE) {
|
||||
nonDataLength = RESPONSE_NON_DATA_BYTES + 3;
|
||||
}
|
||||
else if (response[4] == READ_MEMORY_RESPONSE) {
|
||||
nonDataLength = RESPONSE_NON_DATA_BYTES + 1;
|
||||
}
|
||||
else if (response[4] == LOAD_ADDRESS_RESPONSE) {
|
||||
nonDataLength = RESPONSE_NON_DATA_BYTES + 2;
|
||||
}
|
||||
else if (response[4] == READ_LOAD_RESPONSE) {
|
||||
nonDataLength = RESPONSE_NON_DATA_BYTES + 2;
|
||||
}
|
||||
data = new byte[response.length - nonDataLength];
|
||||
System.arraycopy(response, nonDataLength, data, 0, data.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
private final static void assertTrue(boolean condition, String msg) {
|
||||
if (!condition) {
|
||||
throw new InvalidResponseException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private final static void assertNrc(
|
||||
byte expected, byte actual, byte command, byte code, String msg) {
|
||||
|
||||
if (actual == expected) {
|
||||
String ec = "unsupported.";
|
||||
if (code == 0x10) {
|
||||
ec = "general reject no specific reason.";
|
||||
}
|
||||
if (code == 0x11) {
|
||||
ec = "mode not supported.";
|
||||
}
|
||||
if (code == 0x12) {
|
||||
ec = "request sub-function is not supported or invalid format.";
|
||||
}
|
||||
if (code == 0x13) {
|
||||
ec = "invalid format or length.";
|
||||
}
|
||||
if (code == 0x21) {
|
||||
ec = "busy, repeat request.";
|
||||
}
|
||||
if (code == 0x22) {
|
||||
ec = "conditions not correct or request sequence error.";
|
||||
}
|
||||
throw new InvalidResponseException(String.format(
|
||||
"%s. Command: %s, %s",
|
||||
msg, asHex(command), ec));
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertEquals(byte[] expected, byte[] actual, String msg) {
|
||||
final byte[] idBytes = new byte[4];
|
||||
System.arraycopy(actual, 0, idBytes, 0, 4);
|
||||
final int idExpected = asUnsignedInt(expected);
|
||||
final int idActual = asUnsignedInt(idBytes);
|
||||
if (idActual != idExpected) {
|
||||
throw new InvalidResponseException(msg + ". Expected: " + asHex(expected) + ". Actual: " + asHex(idBytes) + ".");
|
||||
}
|
||||
}
|
||||
|
||||
private final static void assertOneOf(
|
||||
byte[] validOptions, byte actual, String msg) {
|
||||
|
||||
for (byte option : validOptions) {
|
||||
if (option == actual) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < validOptions.length; i++) {
|
||||
if (i > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(asHex(validOptions[i]));
|
||||
}
|
||||
throw new InvalidResponseException(String.format(
|
||||
"%s. Expected one of [%s]. Actual: %s.",
|
||||
msg, builder.toString(), asHex(actual)));
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2016 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -53,6 +53,10 @@ public final class SerialConnectionManager implements ConnectionManager {
|
|||
//connection = new TestSerialConnection2(portName, connectionProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(byte[] start, byte[] stop) {
|
||||
}
|
||||
|
||||
// Send request and wait for response with known length
|
||||
@Override
|
||||
public void send(byte[] request, byte[] response, PollingState pollState) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -64,6 +64,10 @@ public final class DS2LoggerConnection implements LoggerConnection {
|
|||
settings.getTransportProtocol());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Module module) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ecuReset(Module module, int resetCode) {
|
||||
byte[] request = protocol.constructEcuResetRequest(module, resetCode);
|
||||
|
@ -121,7 +125,7 @@ public final class DS2LoggerConnection implements LoggerConnection {
|
|||
}
|
||||
// read data starting at address [00 SG HI LO NN] NN - number of bytes<249
|
||||
else if (groupTest.startsWith("0x060x00")) {
|
||||
final EcuQueryRangeTest range = new EcuQueryRangeTest(querySet);
|
||||
final EcuQueryRangeTest range = new EcuQueryRangeTest(querySet, 128);
|
||||
final Collection<EcuQuery> newQuery = range.validate();
|
||||
int length = range.getLength();
|
||||
if (newQuery != null && length > 0) {
|
||||
|
@ -162,7 +166,9 @@ public final class DS2LoggerConnection implements LoggerConnection {
|
|||
|| groupTest.startsWith("0x0b0x04")
|
||||
|| groupTest.startsWith("0x0b0x91")
|
||||
|| groupTest.startsWith("0x0b0x92")
|
||||
|| groupTest.startsWith("0x0b0x93")) {
|
||||
|| groupTest.startsWith("0x0b0x93")
|
||||
|| groupTest.startsWith("0x0b0x94")
|
||||
|| groupTest.startsWith("0x0b0x95")) {
|
||||
|
||||
request = protocol.constructReadGroupRequest(
|
||||
module, group);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -54,7 +54,11 @@ public final class ELMOBDLoggerConnection implements LoggerConnection {
|
|||
}
|
||||
|
||||
@Override
|
||||
//ToDo
|
||||
public void open(Module module) {
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO:
|
||||
public void ecuReset(Module module, int resetCode) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2015 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -28,15 +28,52 @@ import java.util.Collection;
|
|||
import java.util.Map;
|
||||
|
||||
public interface LoggerConnection {
|
||||
|
||||
/**
|
||||
* Use the open method when communications to a Module requires a
|
||||
* StartCommunication sequence, such as Five Baud or Fast Init.
|
||||
* @param module - the Module to open
|
||||
*/
|
||||
void open(Module module);
|
||||
|
||||
/**
|
||||
* Use this method to reset the module.
|
||||
* @param module - the Module to reset
|
||||
* @param resetCode - the reset procedure to activate
|
||||
*/
|
||||
void ecuReset(Module module, int resetCode);
|
||||
|
||||
/**
|
||||
* Use this method to get the identity the Module communicating with.
|
||||
* @param callback - callback which will identify the Module
|
||||
* @param module - the Module to identify
|
||||
*/
|
||||
void ecuInit(EcuInitCallback callback, Module module);
|
||||
|
||||
/**
|
||||
* Use this method to query the Module for the parameters included as queries.
|
||||
* @param queries - the Collection of EcuQuery items
|
||||
* @param module - the Module to query
|
||||
* @param pollState - the PollingState to use
|
||||
*/
|
||||
void sendAddressReads(Collection<EcuQuery> queries, Module module, PollingState pollState);
|
||||
|
||||
|
||||
/**
|
||||
* Use this method to clear the communications line of any erroneous data.
|
||||
* It can be called before closing off communications to clear buffers
|
||||
* of stale data, or when changing polling modes.
|
||||
*/
|
||||
void clearLine();
|
||||
|
||||
/**
|
||||
* Use this method to close communications with the Module.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Use this method to write to a Module.
|
||||
* @param writeQueries - a Map of EcuQuery items to write
|
||||
* @param module - the Module to write to
|
||||
*/
|
||||
void sendAddressWrites(Map<EcuQuery, byte[]> writeQueries, Module module);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -24,6 +24,7 @@ import static com.romraider.util.ParamChecker.checkNotNull;
|
|||
import static com.romraider.util.ThreadUtil.sleep;
|
||||
import static org.apache.log4j.Logger.getLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
@ -40,6 +41,8 @@ import com.romraider.logger.ecu.comms.manager.PollingState;
|
|||
import com.romraider.logger.ecu.comms.manager.PollingStateImpl;
|
||||
import com.romraider.logger.ecu.comms.query.EcuInitCallback;
|
||||
import com.romraider.logger.ecu.comms.query.EcuQuery;
|
||||
import com.romraider.logger.ecu.comms.query.EcuQueryData;
|
||||
import com.romraider.logger.ecu.comms.query.EcuQueryRangeTest;
|
||||
import com.romraider.logger.ecu.definition.Module;
|
||||
import com.romraider.logger.ecu.exception.SerialCommunicationException;
|
||||
|
||||
|
@ -50,14 +53,21 @@ public final class NCSLoggerConnection implements LoggerConnection {
|
|||
private final LoggerProtocolNCS protocol;
|
||||
private final ConnectionManager manager;
|
||||
private int queryCount;
|
||||
private final Settings settings = SettingsManager.getSettings();
|
||||
private final Collection<EcuQuery> scQuery = new ArrayList<EcuQuery>();
|
||||
private final Collection<EcuQuery> ramQuery = new ArrayList<EcuQuery>();
|
||||
private boolean commsStarted;
|
||||
private boolean elevatedDiag;
|
||||
|
||||
|
||||
public NCSLoggerConnection(ConnectionManager manager) {
|
||||
checkNotNull(manager, "manager");
|
||||
this.manager = manager;
|
||||
final Settings settings = SettingsManager.getSettings();
|
||||
this.protocol = (LoggerProtocolNCS) ProtocolFactory.getProtocol(
|
||||
settings.getLoggerProtocol(),
|
||||
settings.getTransportProtocol());
|
||||
commsStarted = false;
|
||||
elevatedDiag = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,13 +86,17 @@ public final class NCSLoggerConnection implements LoggerConnection {
|
|||
|
||||
@Override
|
||||
// Build an init string similar to the SSM version so the logger definition
|
||||
// can reference supported parameters with ecubyte/bit attributes.
|
||||
// can reference supported parameters using ecubyte/bit attributes.
|
||||
public void ecuInit(EcuInitCallback callback, Module module) {
|
||||
// ConnectionManger must have completed a fastInit to start comms
|
||||
if (!commsStarted) open(module);
|
||||
final byte[] initResponse = new byte[422];
|
||||
byte[] request = protocol.constructEcuIdRequest(module);
|
||||
byte[] request;
|
||||
byte[] response;
|
||||
request = protocol.constructEcuIdRequest(module);
|
||||
LOGGER.debug(String.format("%s ID Request ---> %s",
|
||||
module, asHex(request)));
|
||||
byte[] response = manager.send(request);
|
||||
response = manager.send(request);
|
||||
LOGGER.debug(String.format("%s ID Raw Response <--- %s",
|
||||
module, asHex(response)));
|
||||
response = protocol.processEcuIdResponse(response);
|
||||
|
@ -120,7 +134,7 @@ public final class NCSLoggerConnection implements LoggerConnection {
|
|||
}
|
||||
sid = (byte) 0x22;
|
||||
final byte[] highBytes = {
|
||||
(byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14,
|
||||
(byte) 0x11, (byte) 0x12, (byte) 0x13,
|
||||
(byte) 0x15};
|
||||
for (byte hb : highBytes) {
|
||||
if (hb == (byte) 0x13) { // Supported Switch PIDs
|
||||
|
@ -211,48 +225,21 @@ public final class NCSLoggerConnection implements LoggerConnection {
|
|||
Module module,
|
||||
PollingState pollState) {
|
||||
|
||||
if (queries.size() != queryCount
|
||||
|| pollState.isNewQuery()) {
|
||||
// max data bytes 63 when length encoded into format byte
|
||||
int dataLength = 0;
|
||||
for (EcuQuery query : queries) {
|
||||
for (final String address : query.getAddresses()) {
|
||||
dataLength += calcLength(address);
|
||||
}
|
||||
}
|
||||
// if length is too big then notify user to un-select some parameters
|
||||
if (dataLength > 61) {
|
||||
throw new SerialCommunicationException(
|
||||
rb.getString("TOOLARGE"));
|
||||
}
|
||||
final byte[] request = protocol.constructLoadAddressRequest(queries);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
// ConnectionManger must have completed a fastInit to start comms
|
||||
if (!commsStarted) open(module);
|
||||
|
||||
byte[] response = new byte[4]; // short header response
|
||||
if ((request[0] & (byte)0x80) == (byte)0x80) {
|
||||
response = new byte[6]; // long header response
|
||||
}
|
||||
manager.send(request, response, pollState);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address response <--- %s",
|
||||
pollState.getCurrentState(), module, asHex(response)));
|
||||
protocol.validateLoadAddressResponse(response);
|
||||
queryCount = queries.size();
|
||||
// CAN Slow poll, read each parameter in a separate query, inefficient
|
||||
if (settings.isCanBus() && !pollState.isFastPoll()) {
|
||||
doSlowCanQueries(queries, module, pollState);
|
||||
}
|
||||
final byte[] request = protocol.constructReadAddressRequest(
|
||||
module, queries, pollState);
|
||||
if (pollState.getCurrentState() == PollingState.State.STATE_0) {
|
||||
LOGGER.debug(String.format("Mode:%s %s Read request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
pollState.setLastState(PollingState.State.STATE_0);
|
||||
// Use CAN UDS 2C to load parameters and then request to read all loaded
|
||||
else if (settings.isCanBus() && pollState.isFastPoll()) {
|
||||
doFastCanQueries(queries, module, pollState);
|
||||
}
|
||||
// if not CAN do k-line queries
|
||||
else {
|
||||
doKlineQueries(queries, module, pollState);
|
||||
}
|
||||
final byte[] response = protocol.constructReadAddressResponse(
|
||||
queries, pollState);
|
||||
manager.send(request, response, pollState);
|
||||
LOGGER.debug(String.format("Mode:%s %s Read response <--- %s",
|
||||
pollState.getCurrentState(), module, asHex(response)));
|
||||
protocol.processReadAddressResponses(
|
||||
queries, response, pollState);
|
||||
}
|
||||
|
||||
public void clearQueryCount() {
|
||||
|
@ -265,8 +252,23 @@ public final class NCSLoggerConnection implements LoggerConnection {
|
|||
manager.clearLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Module module) {
|
||||
// For k-line, get the fast init sequence and stop command, then open
|
||||
// the connection via the ConnectionManager
|
||||
byte[] start = protocol.constructEcuFastInitRequest(module);
|
||||
byte[] stop = protocol.constructEcuStopRequest(module);
|
||||
// For CAN, start a standard diagnostics session
|
||||
if (settings.isCanBus()) {
|
||||
start = protocol.constructStartDiagRequest(module);
|
||||
}
|
||||
manager.open(start, stop);
|
||||
commsStarted = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
commsStarted = false;
|
||||
clearQueryCount();
|
||||
manager.close();
|
||||
}
|
||||
|
@ -284,4 +286,243 @@ public final class NCSLoggerConnection implements LoggerConnection {
|
|||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
private void doKlineQueries(
|
||||
Collection<EcuQuery> queries,
|
||||
Module module,
|
||||
PollingState pollState) {
|
||||
|
||||
// k-line max data bytes is 63 when length encoded into format byte
|
||||
if (queries.size() != queryCount
|
||||
|| pollState.isNewQuery()) {
|
||||
int dataLength = 0;
|
||||
for (EcuQuery query : queries) {
|
||||
for (final String address : query.getAddresses()) {
|
||||
dataLength += calcLength(address);
|
||||
}
|
||||
}
|
||||
// if length is too big then notify user to un-select some parameters
|
||||
if (dataLength > 61) {
|
||||
throw new SerialCommunicationException(
|
||||
rb.getString("TOOLARGE"));
|
||||
}
|
||||
}
|
||||
|
||||
if (queries.size() != queryCount
|
||||
|| pollState.isNewQuery()) {
|
||||
final byte[] request = protocol.constructLoadAddressRequest(queries);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
|
||||
byte[] response = new byte[4]; // short header response
|
||||
if ((request[0] & (byte)0x80) == (byte)0x80) {
|
||||
response = new byte[6]; // long header response
|
||||
}
|
||||
protocol.validateLoadAddressResponse(
|
||||
sendRcv(module, request, response, pollState));
|
||||
queryCount = queries.size();
|
||||
}
|
||||
final byte[] request = protocol.constructReadAddressRequest(
|
||||
module, queries, pollState);
|
||||
if (pollState.getCurrentState() == PollingState.State.STATE_0) {
|
||||
LOGGER.debug(String.format("Mode:%s %s Read request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
pollState.setLastState(PollingState.State.STATE_0);
|
||||
}
|
||||
final byte[] response = protocol.constructReadAddressResponse(
|
||||
queries, pollState);
|
||||
protocol.processReadAddressResponses(
|
||||
queries,
|
||||
sendRcv(module, request, response, pollState),
|
||||
pollState);
|
||||
}
|
||||
|
||||
/**
|
||||
* SID/CID can't be combined with reading memory addresses direct,
|
||||
* so we need to load and read each group separately.
|
||||
* The queries are divided into and added to the class attributes scQuery
|
||||
* and ramQuery collections.
|
||||
* @param queries - the collection of queries to evaluate and split
|
||||
*/
|
||||
private void splitSidFromRamQueries(Collection<EcuQuery> queries) {
|
||||
scQuery.clear();
|
||||
ramQuery.clear();
|
||||
for (EcuQuery query : queries) {
|
||||
final String[] addresses = query.getAddresses();
|
||||
for (final String address : addresses) {
|
||||
if (address.startsWith("0x22")) { // SID&CID
|
||||
scQuery.add(query);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ramQuery.add(query);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doSlowCanQueries(
|
||||
Collection<EcuQuery> queries,
|
||||
Module module,
|
||||
PollingState pollState) {
|
||||
|
||||
splitSidFromRamQueries(queries);
|
||||
byte[] request;
|
||||
byte[] response;
|
||||
if (!scQuery.isEmpty()) {
|
||||
final Collection<EcuQuery> sidQuery = new ArrayList<EcuQuery>();
|
||||
for (EcuQuery query : scQuery) {
|
||||
// for each query in the collection create a new collection with one item
|
||||
sidQuery.clear();
|
||||
sidQuery.add(query);
|
||||
if (elevatedDiag) {
|
||||
request = protocol.constructStartDiagRequest(module);
|
||||
LOGGER.debug(String.format("%s Standard Diagnostics Request ---> %s",
|
||||
module, asHex(request)));
|
||||
response = manager.send(request);
|
||||
LOGGER.debug(String.format("%s Standard Diagnostics Response <--- %s",
|
||||
module, asHex(response)));
|
||||
elevatedDiag = false;
|
||||
}
|
||||
request = protocol.constructReadAddressRequest(
|
||||
module, sidQuery);
|
||||
response = new byte[0];
|
||||
LOGGER.debug(module + " CAN Request ---> " + asHex(request));
|
||||
response = protocol.constructReadAddressResponse(
|
||||
sidQuery, pollState);
|
||||
protocol.processReadAddressResponses(
|
||||
sidQuery,
|
||||
sendRcv(module, request, response, pollState),
|
||||
pollState);
|
||||
}
|
||||
}
|
||||
// if query address is not an SID, elevate diag session and
|
||||
// switch to SID 23 using readMemoryRequest
|
||||
if (!ramQuery.isEmpty()) {
|
||||
if (!elevatedDiag) {
|
||||
request = protocol.constructElevatedDiagRequest(module);
|
||||
LOGGER.debug(String.format("%s Elevated Diagnostics Request ---> %s",
|
||||
module, asHex(request)));
|
||||
response = manager.send(request);
|
||||
LOGGER.debug(String.format("%s Elevated Diagnostics Response <--- %s",
|
||||
module, asHex(response)));
|
||||
elevatedDiag = true;
|
||||
}
|
||||
// Inspect the address of each query to determine if a single query
|
||||
// with a start address and byte length can be substituted as opposed
|
||||
// to querying each address separately.
|
||||
final EcuQueryRangeTest range = new EcuQueryRangeTest(ramQuery, 63);
|
||||
final Collection<EcuQuery> newQuery = range.validate();
|
||||
int length = range.getLength();
|
||||
if (newQuery != null && length > 0) {
|
||||
request = protocol.constructReadMemoryRequest(module, newQuery, length);
|
||||
LOGGER.debug(module + " CAN $23 Request ---> " + asHex(request));
|
||||
response = protocol.constructReadMemoryResponse(1, length);
|
||||
protocol.processReadMemoryResponses(
|
||||
ramQuery,
|
||||
sendRcv(module, request, response, pollState));
|
||||
}
|
||||
else {
|
||||
// for each query in the collection create a new collection with one item
|
||||
for (EcuQuery query : ramQuery) {
|
||||
newQuery.clear();
|
||||
newQuery.add(query);
|
||||
request = protocol.constructReadMemoryRequest(
|
||||
module, newQuery, EcuQueryData.getDataLength(query));
|
||||
LOGGER.debug(String.format("Mode:%s %s Memory request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
response = protocol.constructReadMemoryResponse(1,
|
||||
EcuQueryData.getDataLength(query));
|
||||
protocol.processReadMemoryResponses(
|
||||
newQuery,
|
||||
sendRcv(module, request, response, pollState));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doFastCanQueries (
|
||||
Collection<EcuQuery> queries,
|
||||
Module module,
|
||||
PollingState pollState) {
|
||||
|
||||
// When parameter selection changes or there are RAM parameters present
|
||||
// load and read the SID/CID parameters separate from the RAM parameters
|
||||
if (queries.size() != queryCount
|
||||
|| pollState.isNewQuery()) {
|
||||
|
||||
splitSidFromRamQueries(queries);
|
||||
queryCount = queries.size();
|
||||
pollState.setNewQuery(true);
|
||||
}
|
||||
|
||||
byte[] request;
|
||||
byte[] response;
|
||||
if (!scQuery.isEmpty()) { // SID/CID queries
|
||||
if (pollState.isNewQuery() || !ramQuery.isEmpty()) {
|
||||
request = protocol.constructLoadAddressRequest(scQuery);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
// CAN max is 99 bytes
|
||||
if (request.length > 99) {
|
||||
throw new SerialCommunicationException(
|
||||
rb.getString("TOOLARGE"));
|
||||
}
|
||||
response = manager.send(request);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address response <--- %s",
|
||||
pollState.getCurrentState(), module, asHex(response)));
|
||||
protocol.validateLoadAddressResponse(response);
|
||||
}
|
||||
request = protocol.constructReadAddressRequest(
|
||||
module, scQuery, pollState);
|
||||
response = protocol.constructReadAddressResponse(
|
||||
scQuery, pollState);
|
||||
protocol.processReadAddressResponses(
|
||||
scQuery,
|
||||
sendRcv(module, request, response, pollState),
|
||||
pollState);
|
||||
}
|
||||
// When parameter selection changes or there are SID CID parameters present
|
||||
// load and read the RAM parameters separate from the SID CID parameters
|
||||
if (!ramQuery.isEmpty()) { // RAM queries
|
||||
if (pollState.isNewQuery() || !scQuery.isEmpty()) {
|
||||
request = protocol.constructLoadAddressRequest(ramQuery);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address request ---> %s",
|
||||
pollState.getCurrentState(), module, asHex(request)));
|
||||
// CAN max is 99 bytes
|
||||
if (request.length > 99) {
|
||||
throw new SerialCommunicationException(
|
||||
rb.getString("TOOLARGE"));
|
||||
}
|
||||
response = manager.send(request);
|
||||
LOGGER.debug(String.format("Mode:%s %s Load address response <--- %s",
|
||||
pollState.getCurrentState(), module, asHex(response)));
|
||||
protocol.validateLoadAddressResponse(response);
|
||||
pollState.setFastPoll(true);
|
||||
}
|
||||
request = protocol.constructReadAddressRequest(
|
||||
module, ramQuery, pollState);
|
||||
response = protocol.constructReadAddressResponse(
|
||||
ramQuery, pollState);
|
||||
protocol.processReadAddressResponses(
|
||||
ramQuery,
|
||||
sendRcv(module, request, response, pollState),
|
||||
pollState);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] sendRcv(
|
||||
Module module, byte[] request,
|
||||
byte[] response, PollingState pollState) {
|
||||
|
||||
manager.send(request, response, pollState);
|
||||
LOGGER.trace(module + " Read Raw Response <--- " + asHex(response));
|
||||
final byte[] processedResponse = protocol.preprocessResponse(
|
||||
request, response, pollState);
|
||||
LOGGER.debug("Mode:" + pollState.getCurrentState() + " " +
|
||||
module + " Response <--- " + asHex(processedResponse));
|
||||
return processedResponse;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -53,6 +53,10 @@ public final class OBDLoggerConnection implements LoggerConnection {
|
|||
this.protocol = (LoggerProtocolOBD) ProtocolFactory.getProtocol(settings.getLoggerProtocol(), settings.getTransportProtocol());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Module module) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ecuReset(Module module, int resetCode) {
|
||||
byte[] request = protocol.constructEcuResetRequest(module, resetCode);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2015 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -58,6 +58,10 @@ public final class SSMLoggerConnection implements LoggerConnection {
|
|||
settings.getTransportProtocol());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Module module) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ecuReset(Module module, int resetCode) {
|
||||
byte[] request = protocol.constructEcuResetRequest(module, resetCode);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -44,4 +44,18 @@ public interface LoggerProtocolNCS extends LoggerProtocol {
|
|||
byte[] constructEcuIdRequest(Module module);
|
||||
|
||||
byte[] processEcuIdResponse(byte[] response);
|
||||
|
||||
byte[] constructEcuStopRequest(Module module);
|
||||
|
||||
byte[] constructStartDiagRequest(Module module);
|
||||
|
||||
byte[] constructElevatedDiagRequest(Module module);
|
||||
|
||||
Collection<EcuQuery> filterDuplicates(Collection<EcuQuery> queries);
|
||||
|
||||
byte[] constructReadMemoryRequest(Module module, Collection<EcuQuery> queries, int length);
|
||||
|
||||
byte[] constructReadMemoryResponse(int requestSize, int length);
|
||||
|
||||
void processReadMemoryResponses(Collection<EcuQuery> queries, byte[] response);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2019 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -149,12 +149,17 @@ public final class DS2LearningTableValues extends SwingWorker<Void, Void>
|
|||
try {
|
||||
Collection<EcuQuery> queries = buildLearningQueries();
|
||||
|
||||
LOGGER.info("Retrieving vehicle info & A/F values ...");
|
||||
connection.sendAddressReads(
|
||||
queries,
|
||||
settings.getDestinationTarget(),
|
||||
new PollingStateImpl());
|
||||
LOGGER.info("Current vehicle info & A/F values retrieved.");
|
||||
try {
|
||||
LOGGER.info("Retrieving vehicle info & A/F values ...");
|
||||
connection.sendAddressReads(
|
||||
queries,
|
||||
settings.getDestinationTarget(),
|
||||
new PollingStateImpl());
|
||||
LOGGER.info("Current vehicle info & A/F values retrieved.");
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.error(message + " Error retrieving values", e);
|
||||
}
|
||||
|
||||
Collections.sort(
|
||||
(List<EcuQuery>)queries, new ParameterIdComparator());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2019 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -57,8 +57,6 @@ import com.romraider.logger.ecu.comms.query.EcuQuery;
|
|||
import com.romraider.logger.ecu.comms.query.EcuQueryImpl;
|
||||
import com.romraider.logger.ecu.definition.EcuData;
|
||||
import com.romraider.logger.ecu.definition.EcuDefinition;
|
||||
import com.romraider.logger.ecu.definition.Module;
|
||||
import com.romraider.logger.ecu.definition.Transport;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuDefinitionDocumentLoader;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuDefinitionInheritanceList;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuTableDefinitionHandler;
|
||||
|
@ -140,13 +138,6 @@ public final class NCSLearningTableValues extends SwingWorker<Void, Void>
|
|||
document = EcuDefinitionDocumentLoader.getDocument(ecuDef);
|
||||
}
|
||||
|
||||
final String transport = settings.getTransportProtocol();
|
||||
final Module module = settings.getDestinationTarget();
|
||||
if (settings.isCanBus()) {
|
||||
settings.setTransportProtocol("ISO14230");
|
||||
final Module ecuModule = getModule("ECU");
|
||||
settings.setDestinationTarget(ecuModule);
|
||||
}
|
||||
final boolean logging = logger.isLogging();
|
||||
if (logging) logger.stopLogging();
|
||||
|
||||
|
@ -361,8 +352,8 @@ public final class NCSLearningTableValues extends SwingWorker<Void, Void>
|
|||
}
|
||||
finally {
|
||||
connection.close();
|
||||
settings.setTransportProtocol(transport);
|
||||
settings.setDestinationTarget(module);
|
||||
// settings.setTransportProtocol(transport);
|
||||
// settings.setDestinationTarget(module);
|
||||
if (logging) logger.startLogging();
|
||||
}
|
||||
}
|
||||
|
@ -549,37 +540,6 @@ public final class NCSLearningTableValues extends SwingWorker<Void, Void>
|
|||
return ranges.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Transport based on its String ID.
|
||||
*/
|
||||
private Transport getTransportById(String id) {
|
||||
for (Transport transport : getTransportMap().keySet()) {
|
||||
if (transport.getId().equalsIgnoreCase(id))
|
||||
return transport;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Map of Transport and associated Modules for the current protocol.
|
||||
*/
|
||||
private Map<Transport, Collection<Module>> getTransportMap() {
|
||||
return logger.getProtocolList().get(settings.getLoggerProtocol());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Module based on its String name.
|
||||
*/
|
||||
private Module getModule(String name) {
|
||||
final Collection<Module> modules = getTransportMap().get(
|
||||
getTransportById(settings.getTransportProtocol()));
|
||||
for (Module module: modules) {
|
||||
if (module.getName().equalsIgnoreCase(name))
|
||||
return module;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load ECU def table names from a user customized properties file.
|
||||
* The file will replace the Class defined names if it is present.
|
||||
|
|
|
@ -330,7 +330,9 @@ public final class QueryManagerImpl implements QueryManager {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
messageListener.reportError(e);
|
||||
sleep(500L);
|
||||
} finally {
|
||||
messageListener.reportMessage(rb.getString("STOPPING"));
|
||||
txManager.stop();
|
||||
pollState.setCurrentState(PollingState.State.STATE_0);
|
||||
pollState.setNewQuery(true);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2012 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -21,11 +21,28 @@ package com.romraider.logger.ecu.comms.query;
|
|||
|
||||
public interface EcuQuery extends Query {
|
||||
|
||||
/**
|
||||
* Return a list of Strings, each entry in the list is an address of this
|
||||
* query. For byte data there's only one address in the list, for word
|
||||
* data there are two addresses in the list, for Dword there are four
|
||||
* addresses in the list.
|
||||
*/
|
||||
String[] getAddresses();
|
||||
|
||||
/**
|
||||
* Return a byte array made up from all of the addresses for this query.
|
||||
*/
|
||||
byte[] getBytes();
|
||||
|
||||
/**
|
||||
* Return a String made up from all of the addresses for this query in hex
|
||||
* format.
|
||||
*/
|
||||
String getHex();
|
||||
|
||||
/**
|
||||
* Set the byte array that represents the response data for the query.
|
||||
* @param bytes
|
||||
*/
|
||||
void setResponse(byte[] bytes);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2015 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -27,16 +27,40 @@ import com.romraider.logger.ecu.definition.LoggerData;
|
|||
*/
|
||||
public final class EcuQueryData {
|
||||
|
||||
/**
|
||||
* Return the length for an ECU Query item. The larger of either the
|
||||
* number of addresses or the length defined by the data storagetype.
|
||||
* @param ecuQuery - the ECU query to evaluate
|
||||
* @return the length of the data type
|
||||
*/
|
||||
public final static int getDataLength(EcuQuery ecuQuery) {
|
||||
return getDataLength(ecuQuery.getLoggerData());
|
||||
// A query has its data length encoded in the definition using either
|
||||
// the length="#" attribute of an address element or, by the
|
||||
// storagetype="?" attribute in a conversion element.
|
||||
final int addressLength = ecuQuery.getAddresses().length;
|
||||
int dataTypeLength = getDataLength(ecuQuery.getLoggerData());
|
||||
if (addressLength > dataTypeLength) {
|
||||
dataTypeLength = addressLength;
|
||||
}
|
||||
return dataTypeLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length for an Logger Data item.
|
||||
* @param loggerData - the Logger Data to evaluate
|
||||
* @return the length of the data type
|
||||
*/
|
||||
public final static int getDataLength(LoggerData loggerData) {
|
||||
final String dataType =
|
||||
loggerData.getSelectedConvertor().getDataType().toLowerCase();
|
||||
return getDataLength(dataType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length for a Data type, int8, uint8, int16, etc.
|
||||
* @param dataType - the Data type string to evaluate
|
||||
* @return the length of the data type
|
||||
*/
|
||||
public final static int getDataLength(String dataType) {
|
||||
int dataLength = 1;
|
||||
if (dataType.contains("int16")) {
|
||||
|
@ -48,6 +72,4 @@ public final class EcuQueryData {
|
|||
}
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
private EcuQueryData() {}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2015 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -19,6 +19,8 @@
|
|||
|
||||
package com.romraider.logger.ecu.comms.query;
|
||||
|
||||
import static com.romraider.util.HexUtil.hexToInt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -35,10 +37,18 @@ public final class EcuQueryRangeTest {
|
|||
Logger.getLogger(EcuQueryRangeTest.class);
|
||||
private final Collection<EcuQuery> queries;
|
||||
private int datalength;
|
||||
private int maxLength;
|
||||
|
||||
|
||||
public EcuQueryRangeTest(Collection<EcuQuery> queries) {
|
||||
/**
|
||||
* Initialize the class with a collection of queries and the maximum
|
||||
* distance between the lowest and highest allowed.
|
||||
* @param queries - collection of queries
|
||||
* @param maxLength - the maximum data length
|
||||
*/
|
||||
public EcuQueryRangeTest(Collection<EcuQuery> queries, int maxLength) {
|
||||
this.queries = queries;
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,28 +68,30 @@ public final class EcuQueryRangeTest {
|
|||
int lowestAddress = Integer.MAX_VALUE;
|
||||
int highestAddress = 0;
|
||||
for (EcuQuery query : queryList) {
|
||||
int dataSize = EcuQueryData.getDataLength(query);
|
||||
final int address = Integer.parseInt(query.getHex(), 16);
|
||||
if (address < lowestAddress) {
|
||||
lowestAddress = address;
|
||||
newQuery.clear();
|
||||
newQuery.add(query);
|
||||
final int dataTypeLength = EcuQueryData.getDataLength(query);
|
||||
for (int i = 0; i < dataTypeLength; i++) {
|
||||
int address = hexToInt(query.getAddresses()[0]) + i;
|
||||
if (address < lowestAddress) {
|
||||
lowestAddress = address;
|
||||
newQuery.clear();
|
||||
newQuery.add(query);
|
||||
}
|
||||
if (address > highestAddress) {
|
||||
highestAddress = address;
|
||||
}
|
||||
LOGGER.trace(
|
||||
String.format(
|
||||
"addr:%d size:%d lowest:%d highest:%d",
|
||||
address, highestAddress - lowestAddress + 1,
|
||||
lowestAddress, highestAddress));
|
||||
}
|
||||
if (address > highestAddress) {
|
||||
highestAddress = address + dataSize - 1;
|
||||
}
|
||||
LOGGER.trace(
|
||||
String.format(
|
||||
"addr:%d size:%d lowest:%d highest:%d",
|
||||
address, dataSize, lowestAddress, highestAddress));
|
||||
}
|
||||
datalength = highestAddress - lowestAddress;
|
||||
if (datalength <= 128) {
|
||||
datalength ++;
|
||||
return newQuery;
|
||||
datalength = highestAddress - lowestAddress + 1;
|
||||
if (datalength > maxLength) {
|
||||
datalength = 0;
|
||||
newQuery.clear();
|
||||
}
|
||||
datalength = 0;
|
||||
return null;
|
||||
return newQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,24 +36,24 @@ import com.romraider.util.SettingsManager;
|
|||
import com.romraider.xml.RomAttributeParser;
|
||||
|
||||
public class DataCell implements Serializable {
|
||||
private static final long serialVersionUID = 1111479947434817639L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DataCell.class);
|
||||
|
||||
private static final long serialVersionUID = 1111479947434817639L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DataCell.class);
|
||||
|
||||
//View we need to keep up to date
|
||||
private DataCellView view = null;
|
||||
private Table table;
|
||||
|
||||
|
||||
//This sounds like a View property, but the manipulations
|
||||
//functions depend on this, so its better to put it here
|
||||
private boolean isSelected = false;
|
||||
|
||||
|
||||
private double binValue = 0.0;
|
||||
private double originalValue = 0.0;
|
||||
private double compareToValue = 0.0;
|
||||
private String liveValue = Settings.BLANK;
|
||||
private String staticText = null;
|
||||
private Rom rom;
|
||||
|
||||
|
||||
//Index within table
|
||||
private int index;
|
||||
|
||||
|
@ -73,24 +73,24 @@ public class DataCell implements Serializable {
|
|||
public DataCell(Table table, int index, Rom rom) {
|
||||
this(table, rom);
|
||||
this.index = index;
|
||||
|
||||
updateBinValueFromMemory();
|
||||
|
||||
updateBinValueFromMemory();
|
||||
this.originalValue = this.binValue;
|
||||
registerDataCell(this);
|
||||
}
|
||||
|
||||
|
||||
public void setTable(Table t) {
|
||||
this.table = t;
|
||||
this.table = t;
|
||||
}
|
||||
|
||||
|
||||
public void setRom(Rom rom) {
|
||||
this.rom = rom;
|
||||
this.rom = rom;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getBinary() {
|
||||
return rom.getBinary();
|
||||
return rom.getBinary();
|
||||
}
|
||||
|
||||
|
||||
private double getValueFromMemory(int index) {
|
||||
double dataValue = 0.0;
|
||||
byte[] input = getBinary();
|
||||
|
@ -99,8 +99,8 @@ public class DataCell implements Serializable {
|
|||
int ramOffset = table.getRamOffset();
|
||||
int storageAddress = table.getStorageAddress();
|
||||
boolean signed = table.isSignedData();
|
||||
|
||||
|
||||
|
||||
|
||||
// populate data cells
|
||||
if (storageType == Settings.STORAGE_TYPE_FLOAT) { //float storage type
|
||||
byte[] byteValue = new byte[4];
|
||||
|
@ -111,7 +111,7 @@ public class DataCell implements Serializable {
|
|||
dataValue = RomAttributeParser.byteToFloat(byteValue, table.getEndian(), table.getMemModelEndian());
|
||||
|
||||
} else if (storageType == Settings.STORAGE_TYPE_MOVI20 ||
|
||||
storageType == Settings.STORAGE_TYPE_MOVI20S) { // when data is in MOVI20 instruction
|
||||
storageType == Settings.STORAGE_TYPE_MOVI20S) { // when data is in MOVI20 instruction
|
||||
dataValue = RomAttributeParser.parseByteValue(input,
|
||||
endian,
|
||||
storageAddress + index * 3 - ramOffset,
|
||||
|
@ -119,78 +119,78 @@ public class DataCell implements Serializable {
|
|||
signed);
|
||||
|
||||
} else { // integer storage type
|
||||
if(table.getBitMask() == 0) {
|
||||
dataValue = RomAttributeParser.parseByteValue(input,
|
||||
endian, storageAddress + index * storageType - ramOffset,
|
||||
storageType, signed);
|
||||
}
|
||||
else {
|
||||
dataValue = RomAttributeParser.parseByteValueMasked(input, endian,
|
||||
storageAddress + index * storageType - ramOffset,
|
||||
storageType, signed, table.getBitMask());
|
||||
}
|
||||
if(table.getBitMask() == 0) {
|
||||
dataValue = RomAttributeParser.parseByteValue(input,
|
||||
endian, storageAddress + index * storageType - ramOffset,
|
||||
storageType, signed);
|
||||
}
|
||||
else {
|
||||
dataValue = RomAttributeParser.parseByteValueMasked(input, endian,
|
||||
storageAddress + index * storageType - ramOffset,
|
||||
storageType, signed, table.getBitMask());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return dataValue;
|
||||
}
|
||||
|
||||
private double getValueFromMemory() {
|
||||
if (table.getDataLayout() == Table.DataLayout.BOSCH_SUBTRACT) {
|
||||
|
||||
//Bosch Motronic subtract method
|
||||
double dataValue = Math.pow(2, 8 * table.getStorageType());
|
||||
|
||||
for (int j = table.data.length - 1; j >= index; j--) {
|
||||
dataValue -= getValueFromMemory(j);
|
||||
}
|
||||
|
||||
return dataValue;
|
||||
}
|
||||
else {
|
||||
|
||||
private double getValueFromMemory() {
|
||||
if (table.getDataLayout() == Table.DataLayout.BOSCH_SUBTRACT) {
|
||||
|
||||
//Bosch Motronic subtract method
|
||||
double dataValue = Math.pow(2, 8 * table.getStorageType());
|
||||
|
||||
for (int j = table.data.length - 1; j >= index; j--) {
|
||||
dataValue -= getValueFromMemory(j);
|
||||
}
|
||||
|
||||
return dataValue;
|
||||
}
|
||||
else {
|
||||
return getValueFromMemory(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveBinValueInFile() {
|
||||
if (table.getName().contains("Checksum Fix")) return;
|
||||
|
||||
|
||||
public void saveBinValueInFile() {
|
||||
if (table.getName().contains("Checksum Fix")) return;
|
||||
|
||||
byte[] binData = getBinary();
|
||||
int userLevel = table.getUserLevel();
|
||||
int storageType = table.getStorageType();
|
||||
int userLevel = table.getUserLevel();
|
||||
int storageType = table.getStorageType();
|
||||
Endian endian = table.getEndian();
|
||||
int ramOffset = table.getRamOffset();
|
||||
int storageAddress = table.getStorageAddress();
|
||||
boolean isBoschSubtract = table.getDataLayout() == Table.DataLayout.BOSCH_SUBTRACT;
|
||||
|
||||
double crossedValue = 0;
|
||||
|
||||
|
||||
double crossedValue = 0;
|
||||
|
||||
//Do reverse cross referencing in for Bosch Subtract Axis array
|
||||
if(isBoschSubtract) {
|
||||
for (int i = table.data.length - 1; i >=index ; i--) {
|
||||
if(i == index)
|
||||
crossedValue -= table.data[i].getBinValue();
|
||||
else if(i == table.data.length - 1)
|
||||
crossedValue = Math.pow(2, 8 * storageType) - getValueFromMemory(i);
|
||||
else {
|
||||
crossedValue -= getValueFromMemory(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (userLevel <= getSettings().getUserLevel() && (userLevel < 5 || getSettings().isSaveDebugTables()) ) {
|
||||
if(isBoschSubtract) {
|
||||
for (int i = table.data.length - 1; i >=index ; i--) {
|
||||
if(i == index)
|
||||
crossedValue -= table.data[i].getBinValue();
|
||||
else if(i == table.data.length - 1)
|
||||
crossedValue = Math.pow(2, 8 * storageType) - getValueFromMemory(i);
|
||||
else {
|
||||
crossedValue -= getValueFromMemory(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (userLevel <= getSettings().getUserLevel() && (userLevel < 5 || getSettings().isSaveDebugTables()) ) {
|
||||
// determine output byte values
|
||||
byte[] output;
|
||||
int mask = table.getBitMask();
|
||||
|
||||
int mask = table.getBitMask();
|
||||
|
||||
if (storageType != Settings.STORAGE_TYPE_FLOAT) {
|
||||
int finalValue = 0;
|
||||
|
||||
int finalValue = 0;
|
||||
|
||||
// convert byte values
|
||||
if(table.isStaticDataTable() && storageType > 0) {
|
||||
LOGGER.warn("Static data table: " + table.toString() + ", storageType: "+storageType);
|
||||
|
||||
try {
|
||||
finalValue = Integer.parseInt(getStaticText());
|
||||
LOGGER.warn("Static data table: " + table.toString() + ", storageType: "+storageType);
|
||||
|
||||
try {
|
||||
finalValue = Integer.parseInt(getStaticText());
|
||||
} catch (NumberFormatException ex) {
|
||||
LOGGER.error("Error parsing static data table value: " + getStaticText(), ex);
|
||||
LOGGER.error("Validate the table definition storageType and data value.");
|
||||
|
@ -200,143 +200,143 @@ public class DataCell implements Serializable {
|
|||
// Do not save the value.
|
||||
//LOGGER.debug("The static data table value will not be saved.");
|
||||
return;
|
||||
} else {
|
||||
finalValue = (int) (isBoschSubtract ? crossedValue : getBinValue());
|
||||
} else {
|
||||
finalValue = (int) (isBoschSubtract ? crossedValue : getBinValue());
|
||||
}
|
||||
|
||||
if(mask != 0) {
|
||||
// Shift left again
|
||||
finalValue = finalValue << ByteUtil.firstOneOfMask(mask);
|
||||
}
|
||||
|
||||
|
||||
if(mask != 0) {
|
||||
// Shift left again
|
||||
finalValue = finalValue << ByteUtil.firstOneOfMask(mask);
|
||||
}
|
||||
|
||||
output = RomAttributeParser.parseIntegerValue(finalValue, endian, storageType);
|
||||
|
||||
|
||||
int byteLength = storageType;
|
||||
if (storageType == Settings.STORAGE_TYPE_MOVI20 ||
|
||||
storageType == Settings.STORAGE_TYPE_MOVI20S) { // when data is in MOVI20 instruction
|
||||
byteLength = 3;
|
||||
storageType == Settings.STORAGE_TYPE_MOVI20S) { // when data is in MOVI20 instruction
|
||||
byteLength = 3;
|
||||
}
|
||||
|
||||
|
||||
//If mask enabled, only change bits within the mask
|
||||
if(mask != 0) {
|
||||
int tempBitMask = 0;
|
||||
|
||||
for (int z = 0; z < byteLength; z++) { // insert into file
|
||||
|
||||
tempBitMask = mask;
|
||||
|
||||
//Trim mask depending on byte, from left to right
|
||||
tempBitMask = (tempBitMask & (0xFF << 8 * (byteLength - 1 - z))) >> 8*(byteLength - 1 - z);
|
||||
|
||||
// Delete old bits
|
||||
binData[index * byteLength + z + storageAddress - ramOffset] &= ~tempBitMask;
|
||||
|
||||
// Overwrite
|
||||
binData[index * byteLength + z + storageAddress - ramOffset] |= output[z];
|
||||
}
|
||||
int tempBitMask = 0;
|
||||
|
||||
for (int z = 0; z < byteLength; z++) { // insert into file
|
||||
|
||||
tempBitMask = mask;
|
||||
|
||||
//Trim mask depending on byte, from left to right
|
||||
tempBitMask = (tempBitMask & (0xFF << 8 * (byteLength - 1 - z))) >> 8*(byteLength - 1 - z);
|
||||
|
||||
// Delete old bits
|
||||
binData[index * byteLength + z + storageAddress - ramOffset] &= ~tempBitMask;
|
||||
|
||||
// Overwrite
|
||||
binData[index * byteLength + z + storageAddress - ramOffset] |= output[z];
|
||||
}
|
||||
}
|
||||
//No Masking
|
||||
else {
|
||||
for (int z = 0; z < byteLength; z++) { // insert into file
|
||||
binData[index * byteLength + z + storageAddress - ramOffset] = output[z];
|
||||
}
|
||||
for (int z = 0; z < byteLength; z++) { // insert into file
|
||||
binData[index * byteLength + z + storageAddress - ramOffset] = output[z];
|
||||
}
|
||||
}
|
||||
|
||||
} else { // float
|
||||
// convert byte values
|
||||
output = RomAttributeParser.floatToByte((float) getBinValue(), endian, table.getMemModelEndian());
|
||||
|
||||
|
||||
for (int z = 0; z < 4; z++) { // insert in to file
|
||||
binData[index * 4 + z + storageAddress - ramOffset] = output[z];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//On the Bosch substract model, we need to update all previous cells, because they depend on our value
|
||||
if(isBoschSubtract && index > 0) table.data[index-1].saveBinValueInFile();
|
||||
|
||||
checkForDataUpdates();
|
||||
|
||||
checkForDataUpdates();
|
||||
}
|
||||
|
||||
|
||||
public void registerDataCell(DataCell cell) {
|
||||
|
||||
int memoryIndex = getMemoryStartAddress(cell);
|
||||
|
||||
if (rom.byteCellMapping.containsKey(memoryIndex))
|
||||
{
|
||||
rom.byteCellMapping.get(memoryIndex).add(cell);
|
||||
}
|
||||
else {
|
||||
LinkedList<DataCell> l = new LinkedList<DataCell>();
|
||||
l.add(cell);
|
||||
rom.byteCellMapping.put(memoryIndex, l);
|
||||
}
|
||||
|
||||
int memoryIndex = getMemoryStartAddress(cell);
|
||||
|
||||
if (rom.byteCellMapping.containsKey(memoryIndex))
|
||||
{
|
||||
rom.byteCellMapping.get(memoryIndex).add(cell);
|
||||
}
|
||||
else {
|
||||
LinkedList<DataCell> l = new LinkedList<DataCell>();
|
||||
l.add(cell);
|
||||
rom.byteCellMapping.put(memoryIndex, l);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkForDataUpdates() {
|
||||
int memoryIndex = getMemoryStartAddress(this);
|
||||
|
||||
if (rom.byteCellMapping.containsKey(memoryIndex)){
|
||||
for(DataCell c : rom.byteCellMapping.get(memoryIndex)) {
|
||||
c.updateBinValueFromMemory();
|
||||
}
|
||||
}
|
||||
|
||||
public void checkForDataUpdates() {
|
||||
int memoryIndex = getMemoryStartAddress(this);
|
||||
|
||||
if (rom.byteCellMapping.containsKey(memoryIndex)){
|
||||
for(DataCell c : rom.byteCellMapping.get(memoryIndex)) {
|
||||
c.updateBinValueFromMemory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static int getMemoryStartAddress(DataCell cell) {
|
||||
Table t = cell.getTable();
|
||||
return t.getStorageAddress() + cell.getIndexInTable() * t.getStorageType() - t.getRamOffset();
|
||||
Table t = cell.getTable();
|
||||
return t.getStorageAddress() + cell.getIndexInTable() * t.getStorageType() - t.getRamOffset();
|
||||
}
|
||||
|
||||
|
||||
public Settings getSettings()
|
||||
{
|
||||
return SettingsManager.getSettings();
|
||||
}
|
||||
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
if(!table.isStaticDataTable() && this.isSelected != selected) {
|
||||
this.isSelected = selected;
|
||||
|
||||
|
||||
if(view!=null) {
|
||||
ECUEditorManager.getECUEditor().getTableToolBar().updateTableToolBar(table);
|
||||
view.drawCell();
|
||||
ECUEditorManager.getECUEditor().getTableToolBar().updateTableToolBar(table);
|
||||
view.drawCell();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isSelected() {
|
||||
return isSelected;
|
||||
return isSelected;
|
||||
}
|
||||
public void updateBinValueFromMemory() {
|
||||
this.binValue = getValueFromMemory();
|
||||
updateView();
|
||||
this.binValue = getValueFromMemory();
|
||||
updateView();
|
||||
}
|
||||
|
||||
|
||||
public void setDataView(DataCellView v) {
|
||||
view = v;
|
||||
view = v;
|
||||
}
|
||||
|
||||
|
||||
public int getIndexInTable() {
|
||||
return index;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
private void updateView() {
|
||||
if(view != null)
|
||||
view.drawCell();
|
||||
if(view != null)
|
||||
view.drawCell();
|
||||
}
|
||||
|
||||
|
||||
public Table getTable() {
|
||||
return this.table;
|
||||
return this.table;
|
||||
}
|
||||
|
||||
|
||||
public String getStaticText() {
|
||||
return staticText;
|
||||
return staticText;
|
||||
}
|
||||
|
||||
|
||||
public String getLiveValue() {
|
||||
return this.liveValue;
|
||||
}
|
||||
|
||||
|
||||
public void setLiveDataTraceValue(String liveValue) {
|
||||
if(this.liveValue != liveValue) {
|
||||
this.liveValue = liveValue;
|
||||
|
@ -347,18 +347,18 @@ public class DataCell implements Serializable {
|
|||
public double getBinValue() {
|
||||
return binValue;
|
||||
}
|
||||
|
||||
|
||||
public double getOriginalValue() {
|
||||
return originalValue;
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
|
||||
public double getCompareToValue() {
|
||||
return compareToValue;
|
||||
return compareToValue;
|
||||
}
|
||||
|
||||
|
||||
public double getRealValue() {
|
||||
if(table.getCurrentScale() == null) return binValue;
|
||||
|
||||
if(table.getCurrentScale() == null) return binValue;
|
||||
|
||||
return JEPUtil.evaluate(table.getCurrentScale().getExpression(), binValue);
|
||||
}
|
||||
|
||||
|
@ -408,9 +408,9 @@ public class DataCell implements Serializable {
|
|||
if(binValue == newBinValue || table.locked || table.getName().contains("Checksum Fix")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (table.userLevel > getSettings().getUserLevel())
|
||||
throw new UserLevelException(table.userLevel);
|
||||
|
||||
if (table.userLevel > getSettings().getUserLevel())
|
||||
throw new UserLevelException(table.userLevel);
|
||||
|
||||
double checkedValue = newBinValue;
|
||||
|
||||
|
@ -493,20 +493,21 @@ public class DataCell implements Serializable {
|
|||
this.compareToValue = compareCell.originalValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void multiply(double factor) throws UserLevelException {
|
||||
if(table.getCurrentScale().getName().equals("Raw Value"))
|
||||
setBinValue(binValue * factor);
|
||||
|
||||
public void multiply(double factor) throws UserLevelException {
|
||||
if(table.getCurrentScale().getCategory().equals("Raw Value"))
|
||||
setBinValue(binValue * factor);
|
||||
else {
|
||||
String newValue = (getRealValue() * factor) + "";
|
||||
|
||||
//We need to convert from dot to comma, in the case of EU Format. This is because getRealValue to String has dot notation.
|
||||
|
||||
//We need to convert from dot to comma, in the case of EU Format.
|
||||
// This is because getRealValue to String has dot notation.
|
||||
if(NumberUtil.getSeperator() == ',') newValue = newValue.replace('.', ',');
|
||||
|
||||
setRealValue(newValue);
|
||||
|
||||
setRealValue(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if(other == null) {
|
||||
|
|
|
@ -29,6 +29,7 @@ public class Scale implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = 5836610685159474795L;
|
||||
|
||||
private String category = "Raw Value";
|
||||
private String name = "Raw Value";
|
||||
private String unit = "raw value";
|
||||
private String expression = "x";
|
||||
|
@ -41,31 +42,37 @@ public class Scale implements Serializable {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "\n ---- Scale ----" +
|
||||
"\n Name: " + getName() +
|
||||
"\n Expression: " + getExpression() +
|
||||
"\n Byte Expression: " + getByteExpression() +
|
||||
"\n Unit: " + getUnit() +
|
||||
"\n Format: " + getFormat() +
|
||||
"\n Coarse Increment: " + getCoarseIncrement() +
|
||||
"\n Fine Increment: " + getFineIncrement() +
|
||||
"\n Min: " + getMin() +
|
||||
"\n Max: " + getMax() +
|
||||
"\n ---- End Scale ----\n";
|
||||
return "\n ---- Scale ----" +
|
||||
"\n Category: " + getCategory() +
|
||||
"\n Name: " + getName() +
|
||||
"\n Expression: " + getExpression() +
|
||||
"\n Byte Expression: " + getByteExpression() +
|
||||
"\n Unit: " + getUnit() +
|
||||
"\n Format: " + getFormat() +
|
||||
"\n Coarse Increment: " + getCoarseIncrement() +
|
||||
"\n Fine Increment: " + getFineIncrement() +
|
||||
"\n Min: " + getMin() +
|
||||
"\n Max: " + getMax() +
|
||||
"\n ---- End Scale ----\n";
|
||||
}
|
||||
|
||||
|
||||
public boolean validate() {
|
||||
if(expression.equals("x") && byteExpression.equals("x")) return true;
|
||||
|
||||
if(expression.equals("x") && byteExpression.equals("x")) return true;
|
||||
|
||||
double startValue = 5;
|
||||
double toReal = JEPUtil.evaluate(getExpression(), startValue); // convert real world value of "5"
|
||||
// convert real world value of "5"
|
||||
double toReal = JEPUtil.evaluate(getExpression(), startValue);
|
||||
double endValue = JEPUtil.evaluate(getByteExpression(), toReal);
|
||||
|
||||
// if real to byte doesn't equal 5, report conflict
|
||||
if (Math.abs(endValue - startValue) > .001) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
@ -128,6 +135,22 @@ public class Scale implements Serializable {
|
|||
this.fineIncrement = fineIncrement;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>category</b> is used to group like scalings, such as Metric,
|
||||
* Imperial, etc. (case insensitive).<br>
|
||||
* This is the value shown in the Table Tool bar scaling selection list.
|
||||
* @return <b>category</b> name
|
||||
*/
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>name</b> is defined in a scalingbase element (case insensitive).<br>
|
||||
* <b>name</b> is used by the base attribute in a scaling element definition
|
||||
* to inherit from a scalingbase.
|
||||
* @return <b>name</b> as defined in scalingbase
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -169,11 +192,26 @@ public class Scale implements Serializable {
|
|||
|
||||
Scale otherScale = (Scale)other;
|
||||
|
||||
if( (null == this.getCategory() && null == otherScale.getCategory())
|
||||
|| (this.getCategory().isEmpty() && otherScale.getCategory().isEmpty()) )
|
||||
{
|
||||
;// Skip Category compare if Category is null or empty.
|
||||
} else
|
||||
{
|
||||
if(!this.getCategory().equalsIgnoreCase(otherScale.getCategory()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( (null == this.getName() && null == otherScale.getName())
|
||||
|| (this.getName().isEmpty() && otherScale.getName().isEmpty()) ) {
|
||||
|| (this.getName().isEmpty() && otherScale.getName().isEmpty()) )
|
||||
{
|
||||
;// Skip name compare if name is null or empty.
|
||||
} else {
|
||||
if(!this.getName().equalsIgnoreCase(otherScale.getName())) {
|
||||
} else
|
||||
{
|
||||
if(!this.getName().equalsIgnoreCase(otherScale.getName()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -223,4 +261,4 @@ public class Scale implements Serializable {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,31 +41,31 @@ public abstract class Table implements Serializable {
|
|||
|
||||
protected TableView tableView;
|
||||
protected TableFrame tableFrame;
|
||||
|
||||
|
||||
protected String name;
|
||||
protected String category = "Other";
|
||||
protected String description = Settings.BLANK;
|
||||
protected Vector<Scale> scales = new Vector<Scale>();
|
||||
protected Scale curScale;
|
||||
protected PresetManager presetManager;
|
||||
|
||||
|
||||
protected int storageAddress;
|
||||
protected int storageType;
|
||||
protected boolean signed;
|
||||
protected Settings.Endian endian = Settings.Endian.BIG;
|
||||
protected boolean flip;
|
||||
|
||||
protected DataLayout dataLayout = DataLayout.DEFAULT; //DataCell Ordering
|
||||
|
||||
protected DataLayout dataLayout = DataLayout.DEFAULT; //DataCell Ordering
|
||||
protected DataCell[] data = new DataCell[1];
|
||||
|
||||
|
||||
protected boolean beforeRam = false;
|
||||
protected int ramOffset = 0;
|
||||
|
||||
|
||||
protected int userLevel = 0;
|
||||
protected boolean locked = false;
|
||||
protected String logParam = Settings.BLANK;
|
||||
private int bitMask = 0;
|
||||
|
||||
private int bitMask = 0;
|
||||
|
||||
protected double minAllowedBin = 0.0;
|
||||
protected double maxAllowedBin = 0.0;
|
||||
|
||||
|
@ -75,39 +75,39 @@ public abstract class Table implements Serializable {
|
|||
protected double maxCompare = 0.0;
|
||||
protected double minCompare = 0.0;
|
||||
|
||||
protected boolean staticDataTable = false;
|
||||
protected boolean staticDataTable = false;
|
||||
private Table compareTable = null;
|
||||
protected Settings.DataType compareValueType = Settings.DataType.BIN;
|
||||
|
||||
|
||||
public enum DataLayout {
|
||||
DEFAULT,
|
||||
BOSCH_SUBTRACT
|
||||
DEFAULT,
|
||||
BOSCH_SUBTRACT
|
||||
}
|
||||
|
||||
|
||||
public void setTableView(TableView v) {
|
||||
this.tableView = v;
|
||||
this.tableView = v;
|
||||
}
|
||||
|
||||
|
||||
public TableView getTableView() {
|
||||
return this.tableView;
|
||||
return this.tableView;
|
||||
}
|
||||
|
||||
|
||||
public void setTableFrame(TableFrame v) {
|
||||
this.tableFrame = v;
|
||||
this.tableFrame = v;
|
||||
}
|
||||
|
||||
|
||||
public TableFrame getTableFrame() {
|
||||
return this.tableFrame;
|
||||
return this.tableFrame;
|
||||
}
|
||||
|
||||
|
||||
public DataCell[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public void addStaticDataCell(String s) {
|
||||
setStaticDataTable(true);
|
||||
DataCell c = new DataCell(this, s, null);
|
||||
|
||||
setStaticDataTable(true);
|
||||
DataCell c = new DataCell(this, s, null);
|
||||
|
||||
for(int i = 0; i < data.length; i++) {
|
||||
if(data[i] == null) {
|
||||
data[i] = c;
|
||||
|
@ -115,36 +115,36 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Cleans up all references to avoid data leaks
|
||||
public void clearData() {
|
||||
if(data != null) {
|
||||
for(int i=0;i<getDataSize();i++) {
|
||||
if(data[i]!=null) {
|
||||
data[i].setTable(null);
|
||||
data[i].setRom(null);
|
||||
data[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
data = null;
|
||||
}
|
||||
if(data != null) {
|
||||
for(int i=0;i<getDataSize();i++) {
|
||||
if(data[i]!=null) {
|
||||
data[i].setTable(null);
|
||||
data[i].setRom(null);
|
||||
data[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setData(DataCell[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
public int getRamOffset() {
|
||||
return this.ramOffset;
|
||||
return this.ramOffset;
|
||||
}
|
||||
|
||||
|
||||
public void populateTable(Rom rom) throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
|
||||
if(isStaticDataTable()) return;
|
||||
|
||||
validateScaling();
|
||||
|
||||
// temporarily remove lock;
|
||||
if(isStaticDataTable()) return;
|
||||
|
||||
validateScaling();
|
||||
|
||||
// temporarily remove lock;
|
||||
boolean tempLock = locked;
|
||||
locked = false;
|
||||
|
||||
|
@ -152,16 +152,16 @@ public abstract class Table implements Serializable {
|
|||
this.ramOffset = rom.getRomID().getRamOffset();
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
data[i] = new DataCell(this, i, rom);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
data[i] = new DataCell(this, i, rom);
|
||||
}
|
||||
|
||||
// reset locked status
|
||||
locked = tempLock;
|
||||
calcCellRanges();
|
||||
|
||||
//Add Raw Scale
|
||||
addScale(new Scale());
|
||||
|
||||
//Add Raw Scale
|
||||
addScale(new Scale());
|
||||
}
|
||||
|
||||
public abstract TableType getType();
|
||||
|
@ -175,7 +175,7 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
category = category.trim().replace(" //", "//").replace("// ", "//");
|
||||
category = category.trim().replace(" //", "//").replace("// ", "//");
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
|
@ -186,21 +186,21 @@ public abstract class Table implements Serializable {
|
|||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Gets called by toolbar
|
||||
public void updateIncrementDecrementValues(double fineInc, double courseInc) {
|
||||
this.curScale.setCoarseIncrement(courseInc);
|
||||
this.curScale.setFineIncrement(fineInc);
|
||||
public void updateIncrementDecrementValues(double fineInc, double courseInc) {
|
||||
this.curScale.setCoarseIncrement(courseInc);
|
||||
this.curScale.setFineIncrement(fineInc);
|
||||
}
|
||||
|
||||
|
||||
public Scale getCurrentScale() {
|
||||
return this.curScale;
|
||||
}
|
||||
|
||||
public Scale getScale(String scaleName) throws NameNotFoundException {
|
||||
for (Scale scale : scales) {
|
||||
if (scale.getName().equalsIgnoreCase(scaleName)) {
|
||||
if (scale.getCategory().equalsIgnoreCase(scaleName)) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ public abstract class Table implements Serializable {
|
|||
public void addScale(Scale scale) {
|
||||
// look for scale, replace or add new
|
||||
for (int i = 0; i < scales.size(); i++) {
|
||||
if (scales.get(i).getName().equalsIgnoreCase(scale.getName())) {
|
||||
if (scales.get(i).getCategory().equalsIgnoreCase(scale.getCategory())) {
|
||||
scales.remove(i);
|
||||
break;
|
||||
}
|
||||
|
@ -224,12 +224,12 @@ public abstract class Table implements Serializable {
|
|||
if(null == curScale) {
|
||||
this.curScale = scale;
|
||||
}
|
||||
|
||||
if(SettingsManager.getSettings().getDefaultScale().equalsIgnoreCase(scale.getName())) {
|
||||
|
||||
if(SettingsManager.getSettings().getDefaultScale().equalsIgnoreCase(scale.getCategory())) {
|
||||
this.curScale = scale;
|
||||
}
|
||||
else if("Default".equalsIgnoreCase(scale.getName())) {
|
||||
this.curScale = scale;
|
||||
else if("Default".equalsIgnoreCase(scale.getCategory())) {
|
||||
this.curScale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ public abstract class Table implements Serializable {
|
|||
public String getLogParam() {
|
||||
return logParam;
|
||||
}
|
||||
|
||||
|
||||
public String getLogParamString() {
|
||||
return getName()+ ":" + getLogParam();
|
||||
}
|
||||
|
@ -312,21 +312,21 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(String n) {
|
||||
this.name = n;
|
||||
this.name = n;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public StringBuffer getTableAsString() {
|
||||
StringBuffer output = new StringBuffer(Settings.BLANK);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
|
||||
if(data[i]!= null)
|
||||
output.append(NumberUtil.stringValue(data[i].getRealValue()));
|
||||
output.append(NumberUtil.stringValue(data[i].getRealValue()));
|
||||
|
||||
if (i < data.length - 1) {
|
||||
output.append(Settings.TAB);
|
||||
|
@ -334,7 +334,7 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
//Faster version of equals where data doesnt matter (yet)
|
||||
public boolean equalsWithoutData(Object other) {
|
||||
try {
|
||||
|
@ -351,46 +351,46 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
|
||||
Table otherTable = (Table)other;
|
||||
|
||||
|
||||
if(storageAddress != otherTable.storageAddress) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(!this.name.equals(otherTable.name)) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(this.data.length != otherTable.data.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.bitMask != otherTable.bitMask) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.bitMask != otherTable.bitMask) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch(Exception ex) {
|
||||
// TODO: Log Exception.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
try {
|
||||
boolean withoutData = equalsWithoutData(other);
|
||||
if(!withoutData) return false;
|
||||
|
||||
|
||||
Table otherTable = (Table)other;
|
||||
|
||||
|
||||
// Compare Bin Values
|
||||
for(int i=0 ; i < this.data.length ; i++) {
|
||||
if(! this.data[i].equals(otherTable.data[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
} catch(Exception ex) {
|
||||
// TODO: Log Exception.
|
||||
|
@ -414,7 +414,7 @@ public abstract class Table implements Serializable {
|
|||
return JEPUtil.evaluate(getCurrentScale().getExpression(), getMinAllowedBin());
|
||||
}
|
||||
|
||||
protected void calcValueRange() {
|
||||
protected void calcValueRange() {
|
||||
if (getStorageType() != Settings.STORAGE_TYPE_FLOAT) {
|
||||
if (isSignedData()) {
|
||||
switch (getStorageType()) {
|
||||
|
@ -441,15 +441,15 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if(bitMask == 0) {
|
||||
maxAllowedBin = (Math.pow(256, getStorageType()) - 1);
|
||||
}
|
||||
else {
|
||||
maxAllowedBin =(int)(Math.pow(2,ByteUtil.lengthOfMask(bitMask)) - 1);
|
||||
}
|
||||
|
||||
minAllowedBin = 0.0;
|
||||
|
||||
if(bitMask == 0) {
|
||||
maxAllowedBin = (Math.pow(256, getStorageType()) - 1);
|
||||
}
|
||||
else {
|
||||
maxAllowedBin =(int)(Math.pow(2,ByteUtil.lengthOfMask(bitMask)) - 1);
|
||||
}
|
||||
|
||||
minAllowedBin = 0.0;
|
||||
}
|
||||
} else {
|
||||
maxAllowedBin = Float.MAX_VALUE;
|
||||
|
@ -463,37 +463,37 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
|
||||
public void calcCellRanges() {
|
||||
if(data.length > 0) {
|
||||
double binMax = data[0].getBinValue();
|
||||
double binMin = data[0].getBinValue();
|
||||
|
||||
double compareMax = data[0].getCompareValue();
|
||||
double compareMin = data[0].getCompareValue();
|
||||
|
||||
for(DataCell cell : data) {
|
||||
|
||||
// Calc bin
|
||||
if(binMax < cell.getBinValue()) {
|
||||
binMax = cell.getBinValue();
|
||||
}
|
||||
if(binMin > cell.getBinValue()) {
|
||||
binMin = cell.getBinValue();
|
||||
}
|
||||
|
||||
// Calc compare
|
||||
double compareValue = cell.getCompareValue();
|
||||
if(compareMax < compareValue) {
|
||||
compareMax = compareValue;
|
||||
}
|
||||
if(compareMin > compareValue) {
|
||||
compareMin = compareValue;
|
||||
}
|
||||
}
|
||||
setMaxBin(binMax);
|
||||
setMinBin(binMin);
|
||||
setMaxCompare(compareMax);
|
||||
setMinCompare(compareMin);
|
||||
}
|
||||
if(data.length > 0) {
|
||||
double binMax = data[0].getBinValue();
|
||||
double binMin = data[0].getBinValue();
|
||||
|
||||
double compareMax = data[0].getCompareValue();
|
||||
double compareMin = data[0].getCompareValue();
|
||||
|
||||
for(DataCell cell : data) {
|
||||
|
||||
// Calc bin
|
||||
if(binMax < cell.getBinValue()) {
|
||||
binMax = cell.getBinValue();
|
||||
}
|
||||
if(binMin > cell.getBinValue()) {
|
||||
binMin = cell.getBinValue();
|
||||
}
|
||||
|
||||
// Calc compare
|
||||
double compareValue = cell.getCompareValue();
|
||||
if(compareMax < compareValue) {
|
||||
compareMax = compareValue;
|
||||
}
|
||||
if(compareMin > compareValue) {
|
||||
compareMin = compareValue;
|
||||
}
|
||||
}
|
||||
setMaxBin(binMax);
|
||||
setMinBin(binMin);
|
||||
setMaxCompare(compareMax);
|
||||
setMinCompare(compareMin);
|
||||
}
|
||||
}
|
||||
|
||||
public double getMaxBin() {
|
||||
|
@ -559,14 +559,14 @@ public abstract class Table implements Serializable {
|
|||
cell.undo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
abstract public byte[] saveFile(byte[] binData);
|
||||
|
||||
|
||||
public void setValues(String name, String value) {
|
||||
if(presetManager == null) presetManager = new PresetManager(this);
|
||||
presetManager.setValues(name, value);
|
||||
if(presetManager == null) presetManager = new PresetManager(this);
|
||||
presetManager.setValues(name, value);
|
||||
}
|
||||
|
||||
|
||||
public boolean isBeforeRam() {
|
||||
return beforeRam;
|
||||
}
|
||||
|
@ -574,46 +574,46 @@ public abstract class Table implements Serializable {
|
|||
public void setBeforeRam(boolean beforeRam) {
|
||||
this.beforeRam = beforeRam;
|
||||
}
|
||||
|
||||
|
||||
public void setDataLayout(String s) {
|
||||
if(s.trim().equalsIgnoreCase("bosch_subtract")) {
|
||||
setDataLayout(DataLayout.BOSCH_SUBTRACT);
|
||||
}
|
||||
else {
|
||||
setDataLayout(DataLayout.DEFAULT);
|
||||
}
|
||||
if(s.trim().equalsIgnoreCase("bosch_subtract")) {
|
||||
setDataLayout(DataLayout.BOSCH_SUBTRACT);
|
||||
}
|
||||
else {
|
||||
setDataLayout(DataLayout.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setDataLayout(DataLayout m) {
|
||||
this.dataLayout = m;
|
||||
}
|
||||
|
||||
|
||||
public DataLayout getDataLayout() {
|
||||
return this.dataLayout;
|
||||
}
|
||||
|
||||
public void setStringMask(String stringMask) {
|
||||
int mask = ByteUtil.parseUnsignedInt(stringMask, 16);
|
||||
setBitMask(mask);
|
||||
}
|
||||
|
||||
public void setBitMask(int mask) {
|
||||
if(mask == 0) return;
|
||||
|
||||
//Clamp mask to max size
|
||||
bitMask = (int) Math.min(mask, Math.pow(2,getStorageType()*8)-1);
|
||||
calcValueRange();
|
||||
}
|
||||
|
||||
public int getBitMask() {
|
||||
return bitMask;
|
||||
}
|
||||
|
||||
public void setStringMask(String stringMask) {
|
||||
int mask = ByteUtil.parseUnsignedInt(stringMask, 16);
|
||||
setBitMask(mask);
|
||||
}
|
||||
|
||||
public void setBitMask(int mask) {
|
||||
if(mask == 0) return;
|
||||
|
||||
//Clamp mask to max size
|
||||
bitMask = (int) Math.min(mask, Math.pow(2,getStorageType()*8)-1);
|
||||
calcValueRange();
|
||||
}
|
||||
|
||||
public int getBitMask() {
|
||||
return bitMask;
|
||||
}
|
||||
|
||||
public void validateScaling() {
|
||||
if (getType() != TableType.SWITCH) {
|
||||
if (getType() != TableType.SWITCH) {
|
||||
for(Scale scale : scales) {
|
||||
if (!scale.validate()) {
|
||||
TableView.showBadScalePopup(this, scale);
|
||||
TableView.showBadScalePopup(this, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -639,32 +639,32 @@ public abstract class Table implements Serializable {
|
|||
calcCellRanges();
|
||||
if(tableView != null) tableView.drawTable();
|
||||
}
|
||||
|
||||
|
||||
public void clearSelection() {
|
||||
if(data!=null) {
|
||||
for (DataCell cell : data) {
|
||||
if(data!=null) {
|
||||
for (DataCell cell : data) {
|
||||
cell.setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void selectCellAt(int y) {
|
||||
if(y >= 0 && y < data.length) {
|
||||
clearSelection();
|
||||
data[y].setSelected(true);
|
||||
if(tableView!=null) tableView.highlightBeginY = y;
|
||||
if(tableView!=null) tableView.highlightBeginY = y;
|
||||
}
|
||||
}
|
||||
|
||||
public void selectCellAtWithoutClear(int y) {
|
||||
if(y >= 0 && y < data.length) {
|
||||
data[y].setSelected(true);
|
||||
if(tableView!=null)tableView.highlightBeginY = y;
|
||||
if(tableView!=null)tableView.highlightBeginY = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void verticalInterpolate() throws UserLevelException{
|
||||
horizontalInterpolate();
|
||||
horizontalInterpolate();
|
||||
}
|
||||
|
||||
public void horizontalInterpolate() throws UserLevelException {
|
||||
|
@ -679,38 +679,38 @@ public abstract class Table implements Serializable {
|
|||
coords[1] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (coords[1] - coords[0] > 1) {
|
||||
double y1, y2;
|
||||
y1 = tableData[coords[0]].getBinValue();
|
||||
y2 = tableData[coords[1]].getBinValue();
|
||||
for (int i = coords[0] + 1; i < coords[1]; ++i) {
|
||||
float p = (float)((i - coords[0]))/(coords[1] - coords[0]);
|
||||
float p = (float)((i - coords[0]))/(coords[1] - coords[0]);
|
||||
data[i].setBinValue((y2*p)+(y1 *(1-p)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void interpolate() throws UserLevelException {
|
||||
horizontalInterpolate();
|
||||
}
|
||||
|
||||
|
||||
public double linearInterpolation(double x, double x1, double x2, double y1, double y2) {
|
||||
return (x1 == x2) ? 0.0 : (y1 + (x - x1) * (y2 - y1) / (x2 - x1));
|
||||
}
|
||||
|
||||
|
||||
public void increment(double increment) throws UserLevelException {
|
||||
for (DataCell cell : data) {
|
||||
if (cell.isSelected()) {
|
||||
cell.increment(increment);
|
||||
}
|
||||
}
|
||||
for (DataCell cell : data) {
|
||||
if (cell.isSelected()) {
|
||||
cell.increment(increment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void multiply(double factor) throws UserLevelException{
|
||||
for (DataCell cell : data) {
|
||||
if (cell.isSelected()) {
|
||||
cell.multiply(factor);
|
||||
public void multiply(double factor) throws UserLevelException{
|
||||
for (DataCell cell : data) {
|
||||
if (cell.isSelected()) {
|
||||
cell.multiply(factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -724,7 +724,7 @@ public abstract class Table implements Serializable {
|
|||
}
|
||||
|
||||
public abstract boolean isLiveDataSupported();
|
||||
|
||||
|
||||
public int getUserLevel() {
|
||||
return userLevel;
|
||||
}
|
||||
|
@ -737,10 +737,10 @@ public abstract class Table implements Serializable {
|
|||
userLevel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void setScaleByName(String scaleName) throws NameNotFoundException {
|
||||
|
||||
public void setScaleByCategory(String scaleName) throws NameNotFoundException {
|
||||
for(Scale scale : scales) {
|
||||
if(scale.getName().equalsIgnoreCase(scaleName)) {
|
||||
if(scale.getCategory().equalsIgnoreCase(scaleName)) {
|
||||
Scale currentScale = getCurrentScale();
|
||||
if(currentScale == null || !currentScale.equals(scale)) {
|
||||
this.setCurrentScale(scale);
|
||||
|
@ -754,10 +754,10 @@ public abstract class Table implements Serializable {
|
|||
|
||||
public void setCurrentScale(Scale curScale) {
|
||||
this.curScale = curScale;
|
||||
|
||||
|
||||
if(tableView!=null) {
|
||||
tableView.drawTable();
|
||||
}
|
||||
tableView.drawTable();
|
||||
}
|
||||
}
|
||||
|
||||
public Settings getSettings()
|
||||
|
@ -781,13 +781,13 @@ public abstract class Table implements Serializable {
|
|||
|
||||
public void setCompareTable(Table compareTable) {
|
||||
this.compareTable = compareTable;
|
||||
|
||||
|
||||
if(tableView!= null)tableView.drawTable();
|
||||
}
|
||||
|
||||
public void setCompareValueType(Settings.DataType compareValueType) {
|
||||
this.compareValueType = compareValueType;
|
||||
|
||||
|
||||
if(tableView!= null)tableView.drawTable();
|
||||
}
|
||||
|
||||
|
@ -797,7 +797,7 @@ public abstract class Table implements Serializable {
|
|||
|
||||
public void colorCells() {
|
||||
calcCellRanges();
|
||||
|
||||
|
||||
if(tableView!=null)tableView.drawTable();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class Table2D extends Table {
|
|||
public Table1D getAxis() {
|
||||
return axis;
|
||||
}
|
||||
|
||||
|
||||
public void setAxis(Table1D axis) {
|
||||
this.axis = axis;
|
||||
axis.setAxisParent(this);
|
||||
|
@ -45,15 +45,15 @@ public class Table2D extends Table {
|
|||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " (2D)";// + axis;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearData() {
|
||||
super.clearData();
|
||||
axis.clearData();
|
||||
axis=null;
|
||||
super.clearData();
|
||||
axis.clearData();
|
||||
axis=null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void populateCompareValues(Table otherTable) {
|
||||
if(null == otherTable || !(otherTable instanceof Table2D)) {
|
||||
|
@ -77,7 +77,7 @@ public class Table2D extends Table {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void populateTable(Rom rom) throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
|
||||
public void populateTable(Rom rom) throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
|
||||
axis.populateTable(rom);
|
||||
super.populateTable(rom);
|
||||
}
|
||||
|
@ -94,10 +94,10 @@ public class Table2D extends Table {
|
|||
super.undoAll();
|
||||
axis.undoAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] saveFile(byte[] binData) {
|
||||
public byte[] saveFile(byte[] binData) {
|
||||
return binData;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ public class Table2D extends Table {
|
|||
sb.append(getName()+ ":" + getLogParam());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isLiveDataSupported() {
|
||||
return !isNullOrEmpty(axis.getLogParam());
|
||||
|
@ -118,7 +118,7 @@ public class Table2D extends Table {
|
|||
public boolean isButtonSelected() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setCompareValueType(Settings.DataType compareValueType) {
|
||||
super.setCompareValueType(compareValueType);
|
||||
|
@ -129,50 +129,50 @@ public class Table2D extends Table {
|
|||
public void setCurrentScale(Scale curScale) {
|
||||
if(SettingsManager.getSettings().isScaleHeadersAndData() && !axis.isStaticDataTable()) {
|
||||
try {
|
||||
this.axis.setScaleByName(curScale.getName());
|
||||
this.axis.setScaleByCategory(curScale.getCategory());
|
||||
} catch (NameNotFoundException e) {
|
||||
try {
|
||||
this.axis.setScaleByName(SettingsManager.getSettings().getDefaultScale());
|
||||
this.axis.setScaleByCategory(SettingsManager.getSettings().getDefaultScale());
|
||||
} catch (NameNotFoundException e1) {
|
||||
try {
|
||||
this.axis.setScaleByName("Default");
|
||||
try {
|
||||
this.axis.setScaleByCategory("Default");
|
||||
} catch (NameNotFoundException e2) {
|
||||
e2.printStackTrace();
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.curScale = curScale;
|
||||
|
||||
|
||||
if(tableView != null) tableView.drawTable();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearSelection() {
|
||||
if(axis!=null)
|
||||
axis.clearSelection();
|
||||
|
||||
if(axis!=null)
|
||||
axis.clearSelection();
|
||||
|
||||
super.clearSelection();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setRealValue(String realValue) throws UserLevelException {
|
||||
super.setRealValue(realValue);
|
||||
axis.setRealValue(realValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void increment(double increment) throws UserLevelException {
|
||||
super.increment(increment);
|
||||
axis.increment(increment);
|
||||
super.increment(increment);
|
||||
axis.increment(increment);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void multiply(double factor) throws UserLevelException{
|
||||
super.multiply(factor);
|
||||
axis.multiply(factor);
|
||||
public void multiply(double factor) throws UserLevelException{
|
||||
super.multiply(factor);
|
||||
axis.multiply(factor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void interpolate() throws UserLevelException {
|
||||
super.interpolate();
|
||||
|
@ -213,7 +213,7 @@ public class Table2D extends Table {
|
|||
// Interpolate x axis in case the x axis in selected.
|
||||
this.getAxis().horizontalInterpolate();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public StringBuffer getTableAsString() {
|
||||
StringBuffer output = new StringBuffer(Settings.BLANK);
|
||||
|
@ -273,5 +273,5 @@ public class Table2D extends Table {
|
|||
// TODO: Log Exception.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,11 +42,11 @@ public class Table3D extends Table {
|
|||
public TableType getType() {
|
||||
return Table.TableType.TABLE_3D;
|
||||
}
|
||||
|
||||
|
||||
public Table3DView getTableView() {
|
||||
return (Table3DView) tableView;
|
||||
return (Table3DView) tableView;
|
||||
}
|
||||
|
||||
|
||||
public Table1D getXAxis() {
|
||||
return xAxis;
|
||||
}
|
||||
|
@ -104,24 +104,24 @@ public class Table3D extends Table {
|
|||
public int getSizeY() {
|
||||
return data[0].length;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearData() {
|
||||
for(DataCell[] column : data) {
|
||||
for(DataCell cell : column) {
|
||||
cell.setTable(null);
|
||||
cell.setRom(null);
|
||||
cell.setTable(null);
|
||||
cell.setRom(null);
|
||||
}
|
||||
}
|
||||
|
||||
xAxis.clearData();
|
||||
yAxis.clearData();
|
||||
|
||||
data = null;
|
||||
xAxis=null;
|
||||
yAxis=null;
|
||||
|
||||
xAxis.clearData();
|
||||
yAxis.clearData();
|
||||
|
||||
data = null;
|
||||
xAxis=null;
|
||||
yAxis=null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public StringBuffer getTableAsString() {
|
||||
StringBuffer output = new StringBuffer(Settings.BLANK);
|
||||
|
@ -135,8 +135,8 @@ public class Table3D extends Table {
|
|||
|
||||
for (int x = 0; x < getSizeX(); x++) {
|
||||
|
||||
output.append(NumberUtil.stringValue(data[x][y].getRealValue()));
|
||||
|
||||
output.append(NumberUtil.stringValue(data[x][y].getRealValue()));
|
||||
|
||||
if (x < getSizeX() - 1) {
|
||||
output.append(Settings.TAB);
|
||||
}
|
||||
|
@ -152,9 +152,9 @@ public class Table3D extends Table {
|
|||
|
||||
@Override
|
||||
public void populateTable(Rom rom) throws NullPointerException, ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
|
||||
validateScaling();
|
||||
|
||||
// fill first empty cell
|
||||
validateScaling();
|
||||
|
||||
// fill first empty cell
|
||||
if (!beforeRam) {
|
||||
this.ramOffset = rom.getRomID().getRamOffset();
|
||||
}
|
||||
|
@ -192,11 +192,11 @@ public class Table3D extends Table {
|
|||
}
|
||||
|
||||
// reset locked status
|
||||
locked = tempLock;
|
||||
locked = tempLock;
|
||||
calcCellRanges();
|
||||
|
||||
//Add Raw Scale
|
||||
addScale(new Scale());
|
||||
|
||||
//Add Raw Scale
|
||||
addScale(new Scale());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -301,7 +301,7 @@ public class Table3D extends Table {
|
|||
|
||||
@Override
|
||||
public byte[] saveFile(byte[] binData) {
|
||||
return binData;
|
||||
return binData;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -330,81 +330,81 @@ public class Table3D extends Table {
|
|||
if(SettingsManager.getSettings().isScaleHeadersAndData()) {
|
||||
if(!xAxis.isStaticDataTable()) {
|
||||
try {
|
||||
this.xAxis.setScaleByName(curScale.getName());
|
||||
this.xAxis.setScaleByCategory(curScale.getCategory());
|
||||
} catch (NameNotFoundException e) {
|
||||
try {
|
||||
this.xAxis.setScaleByName(SettingsManager.getSettings().getDefaultScale());
|
||||
this.xAxis.setScaleByCategory(SettingsManager.getSettings().getDefaultScale());
|
||||
} catch (NameNotFoundException e1) {
|
||||
try {
|
||||
this.xAxis.setScaleByName("Default");
|
||||
try {
|
||||
this.xAxis.setScaleByCategory("Default");
|
||||
} catch (NameNotFoundException e2) {
|
||||
e2.printStackTrace();
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!yAxis.isStaticDataTable()) {
|
||||
try {
|
||||
this.yAxis.setScaleByName(curScale.getName());
|
||||
this.yAxis.setScaleByCategory(curScale.getCategory());
|
||||
} catch (NameNotFoundException e) {
|
||||
try {
|
||||
this.yAxis.setScaleByName(SettingsManager.getSettings().getDefaultScale());
|
||||
this.yAxis.setScaleByCategory(SettingsManager.getSettings().getDefaultScale());
|
||||
} catch (NameNotFoundException e1) {
|
||||
try {
|
||||
this.yAxis.setScaleByName("Default");
|
||||
try {
|
||||
this.yAxis.setScaleByCategory("Default");
|
||||
} catch (NameNotFoundException e2) {
|
||||
e2.printStackTrace();
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.curScale = curScale;
|
||||
|
||||
this.curScale = curScale;
|
||||
if(tableView!=null) tableView.drawTable();
|
||||
}
|
||||
|
||||
|
||||
private void setHighlightXY(int x, int y) {
|
||||
if(tableView!=null) {
|
||||
tableView.highlightBeginX = x;
|
||||
tableView.highlightBeginY = y;
|
||||
tableView.highlightBeginX = x;
|
||||
tableView.highlightBeginY = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void deSelectCellAt(int x, int y) {
|
||||
clearSelection();
|
||||
data[x][y].setSelected(false);
|
||||
setHighlightXY(x,y);
|
||||
}
|
||||
|
||||
|
||||
public void selectCellAt(int x, int y) {
|
||||
clearSelection();
|
||||
data[x][y].setSelected(true);
|
||||
setHighlightXY(x,y);
|
||||
}
|
||||
|
||||
|
||||
public void selectCellAtWithoutClear(int x, int y) {
|
||||
data[x][y].setSelected(true);
|
||||
setHighlightXY(x,y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearSelection() {
|
||||
if(xAxis!=null)
|
||||
xAxis.clearSelection();
|
||||
|
||||
if(yAxis!=null)
|
||||
yAxis.clearSelection();
|
||||
|
||||
if(data!=null) {
|
||||
for (int x = 0; x < getSizeX(); x++) {
|
||||
for (int y = 0; y < getSizeY(); y++) {
|
||||
data[x][y].setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(xAxis!=null)
|
||||
xAxis.clearSelection();
|
||||
|
||||
if(yAxis!=null)
|
||||
yAxis.clearSelection();
|
||||
|
||||
if(data!=null) {
|
||||
for (int x = 0; x < getSizeX(); x++) {
|
||||
for (int y = 0; y < getSizeY(); y++) {
|
||||
data[x][y].setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void increment(double increment) throws UserLevelException {
|
||||
for (int x = 0; x < getSizeX(); x++) {
|
||||
|
@ -420,13 +420,13 @@ public class Table3D extends Table {
|
|||
public void multiply(double factor) throws UserLevelException {
|
||||
for (int x = 0; x < getSizeX(); x++) {
|
||||
for (int y = 0; y < getSizeY(); y++) {
|
||||
if (data[x][y].isSelected()) {
|
||||
data[x][y].multiply(factor);
|
||||
if (data[x][y].isSelected()) {
|
||||
data[x][y].multiply(factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setRealValue(String realValue) throws UserLevelException {
|
||||
for(DataCell[] column : data) {
|
||||
|
@ -439,7 +439,7 @@ public class Table3D extends Table {
|
|||
xAxis.setRealValue(realValue);
|
||||
yAxis.setRealValue(realValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void verticalInterpolate() throws UserLevelException {
|
||||
int[] coords = { getSizeX(), getSizeY(), 0, 0};
|
||||
|
@ -519,7 +519,7 @@ public class Table3D extends Table {
|
|||
verticalInterpolate();
|
||||
horizontalInterpolate();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getLogParamString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -587,5 +587,3 @@ public class Table3D extends Table {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.
|
||||
*
|
||||
* Encoding and decoding routines based on:
|
||||
* https://github.com/fenugrec/nissutils/blob/master/cli_utils/
|
||||
*/
|
||||
|
||||
package com.romraider.maps.checksum;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.romraider.util.HexUtil;
|
||||
|
||||
/**
|
||||
* This class contains functions to encode and decoded data as well as
|
||||
* calculate its CRC in Nissan fashion.
|
||||
*/
|
||||
public final class NcsCoDec {
|
||||
|
||||
public NcsCoDec() {
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given inBuf, decode the data with the supplied code
|
||||
* and return the decoded data
|
||||
*/
|
||||
public final byte[] nisDecode(ByteBuffer inBuf, int code) {
|
||||
final ByteBuffer outBuf = ByteBuffer.allocate(inBuf.capacity()).order(ByteOrder.BIG_ENDIAN);
|
||||
inBuf.rewind();
|
||||
while (inBuf.hasRemaining()) {
|
||||
outBuf.putInt(decode(inBuf.getInt(), code));
|
||||
}
|
||||
return outBuf.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given inBuf, encode the data with the supplied code
|
||||
* and return the encoded data
|
||||
*/
|
||||
public final byte[] nisEncode(ByteBuffer inBuf, int code) {
|
||||
final ByteBuffer outBuf = ByteBuffer.allocate(inBuf.capacity()).order(ByteOrder.BIG_ENDIAN);
|
||||
inBuf.rewind();
|
||||
while (inBuf.hasRemaining()) {
|
||||
outBuf.putInt(encode(inBuf.getInt(), code));
|
||||
}
|
||||
return outBuf.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given encoded data, decode the data with the supplied code
|
||||
* and return decoded data
|
||||
*/
|
||||
// https://github.com/fenugrec/nissutils/blob/master/cli_utils/nislib.c#dec1
|
||||
private final int decode(int data, int code) {
|
||||
final int dH = data >>> 16;
|
||||
final int dL = data & 0xFFFF;
|
||||
final int cH = code >>> 16;
|
||||
final int cL = code & 0xFFFF;
|
||||
final int kL = mess2(dH, dL, cL);
|
||||
final int kH = mess1(dL, kL, cH);
|
||||
return (kH << 16) | kL;
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given data, encode the data with the supplied code
|
||||
* and return the encoded data
|
||||
*/
|
||||
// https://github.com/fenugrec/nissutils/blob/master/cli_utils/nislib.c#enc1
|
||||
private final int encode(int data, int code) {
|
||||
final int dH = data >>> 16;
|
||||
final int dL = data & 0xFFFF;
|
||||
final int cH = code >>> 16;
|
||||
final int cL = code & 0xFFFF;
|
||||
final int kL = mess1(dH, dL, cH);
|
||||
final int kH = mess2(dL, kL, cL);
|
||||
return (kH << 16 | kL);
|
||||
}
|
||||
|
||||
// https://github.com/fenugrec/nissutils/blob/master/cli_utils/nislib.c#mess1
|
||||
private final int mess1(int a, int b, int x) {
|
||||
final int var0 = (x + b) & 0xFFFF;
|
||||
final int var1 = var0 << 2;
|
||||
final int var2 = var1 >>> 16;
|
||||
final int var3 = var2 + var0 + var1 - 1;
|
||||
return (var3 ^ a) & 0xFFFF;
|
||||
}
|
||||
|
||||
// https://github.com/fenugrec/nissutils/blob/master/cli_utils/nislib.c#mess2
|
||||
private final int mess2(int a, int b, int x) {
|
||||
final int var0 = (x + b) & 0xFFFF;
|
||||
final int var1 = var0 << 1;
|
||||
final int var2 = ((var1 >>> 16) + var0 + var1 - 1) & 0xFFFF;
|
||||
final int var3 = var2 << 4;
|
||||
final int var4 = var3 + (var3 >>> 16);
|
||||
return (a ^ var4 ^ var2) & 0xFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given data, calculate the 16 bit CRC.
|
||||
*/
|
||||
// sub_15CC in 1ZN67A
|
||||
public final short calcCrc(byte[] data) {
|
||||
int r6;
|
||||
int r5;
|
||||
int crc = 0xffff;
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
r5 = data[i];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
r6 = crc & 1;
|
||||
crc = crc >>> 1;
|
||||
if(r6 != (r5 & 1)) {
|
||||
crc = crc ^ 0x8408;
|
||||
}
|
||||
r5 = r5 >> 1;
|
||||
}
|
||||
}
|
||||
return (short) crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the NisCoDec functions
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
final NcsCoDec codec = new NcsCoDec();
|
||||
String bin_text = "FFFF22E4000115F8000116A000011724000117C80002B9C4E00180F884F820088B1B62F0E7EC9625D91426209623656062637205645C60430274901D7501655C029C760560530624D20D420B75019013D60C029C9011A0040624E4AC644CB18BE5127F204F266EF66DF66CF66BF66AF6000B69F697B481050848035EFFFF22E4";
|
||||
byte[] bin = HexUtil.asBytes(bin_text);
|
||||
final int scode = 0xC2C0823F;
|
||||
ByteBuffer data = ByteBuffer.allocate(bin.length).order(ByteOrder.BIG_ENDIAN).put(bin);
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
short crc = codec.calcCrc(dataEncoded);
|
||||
short invert = (short) ~crc;
|
||||
short le = (short) (((invert << 8) | ((invert & 0xffff) >>> 8)) & 0xffff);
|
||||
final byte[] crcCheck = new byte[dataEncoded.length + 2];
|
||||
System.arraycopy(dataEncoded, 0, crcCheck, 0, dataEncoded.length);
|
||||
crcCheck[crcCheck.length - 2] = (byte) (invert & 0xff);
|
||||
crcCheck[crcCheck.length - 1] = (byte) ((invert & 0xffff) >>> 8);
|
||||
short residue = codec.calcCrc(crcCheck);
|
||||
System.out.println(String.format(
|
||||
"Encode Test:%nbin data: %s%nscode: %08X%nencoded: %s%nCRC (D10D): %04X%n~CRC (2EF2): %04X%n" +
|
||||
"little-endian ~CRC (F22E): %04X%nresidue: %04X",
|
||||
HexUtil.asHex(bin), scode, HexUtil.asHex(dataEncoded), crc, invert, le,
|
||||
residue));
|
||||
String text = "34830000003030303030303041060431434D43375150443430310000000000000000005230303030434F4E332B0619022000005CAD04";
|
||||
byte[] hex = HexUtil.asBytes(text);
|
||||
residue = codec.calcCrc(hex);
|
||||
System.out.println(String.format("%s%nCRC: %04X%n~CRC: %04X",
|
||||
HexUtil.asHex(hex), residue, (short)~residue));
|
||||
text = "348300000030FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9BC";
|
||||
hex = HexUtil.asBytes(text);
|
||||
residue = codec.calcCrc(hex);
|
||||
System.out.println(String.format("%s%nCRC: %04X%n~CRC: %04X",
|
||||
HexUtil.asHex(hex), residue, (short)~residue));
|
||||
data.rewind();
|
||||
data = ByteBuffer.allocate(dataEncoded.length).order(ByteOrder.BIG_ENDIAN).put(dataEncoded);
|
||||
byte[] dataDecoded = codec.nisDecode(data, scode);
|
||||
System.out.println(String.format("Decoded Data: %s",
|
||||
HexUtil.asHex(dataDecoded)));
|
||||
if(bin_text.equalsIgnoreCase(HexUtil.asHex(dataDecoded))) {
|
||||
System.out.println("Decoded data matches input data");
|
||||
}
|
||||
else {
|
||||
System.out.println("DATA DOES NOT MATCH !!!");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2014 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -28,42 +28,44 @@ import com.romraider.maps.Scale;
|
|||
public final class ScalesTableModel extends DefaultTableModel {
|
||||
private static final long serialVersionUID = -5967359776053559125L;
|
||||
private static final String[] colNames = {
|
||||
"Name", "Expression", "Byte Expression",
|
||||
"Category", "Name", "Expression", "Byte Expression",
|
||||
"Unit", "Format", "Coarse", "Fine", "Min", "Max"};
|
||||
private Vector<Scale> scales;
|
||||
|
||||
|
||||
@Override
|
||||
public final int getColumnCount() {
|
||||
return colNames.length;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final String getColumnName(int column) {
|
||||
return colNames[column].toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Object getValueAt(int row, int column) {
|
||||
if (null != scales) {
|
||||
final Scale scale = scales.get(row);
|
||||
switch (column) {
|
||||
case 0:
|
||||
return scale.getCategory();
|
||||
case 1:
|
||||
return scale.getName();
|
||||
case 1:
|
||||
case 2:
|
||||
return scale.getExpression();
|
||||
case 2:
|
||||
return scale.getByteExpression();
|
||||
case 3:
|
||||
return scale.getByteExpression();
|
||||
case 4:
|
||||
return scale.getUnit();
|
||||
case 4:
|
||||
case 5:
|
||||
return scale.getFormat();
|
||||
case 5:
|
||||
return scale.getCoarseIncrement();
|
||||
case 6:
|
||||
return scale.getCoarseIncrement();
|
||||
case 7:
|
||||
return scale.getFineIncrement();
|
||||
case 7:
|
||||
case 8:
|
||||
return scale.getMin();
|
||||
case 8:
|
||||
case 9:
|
||||
return scale.getMax();
|
||||
default:
|
||||
return null;
|
||||
|
@ -73,12 +75,12 @@ public final class ScalesTableModel extends DefaultTableModel {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getRowCount() {
|
||||
return (null != scales) ? scales.size() : 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Class<? extends Object> getColumnClass(int column) {
|
||||
return getValueAt(0, column).getClass();
|
||||
|
@ -88,7 +90,7 @@ public final class ScalesTableModel extends DefaultTableModel {
|
|||
public final boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public final void setScalesList(Vector<Scale> scales) {
|
||||
this.scales = scales;
|
||||
}
|
||||
|
|
|
@ -233,12 +233,12 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
} catch (PropertyVetoException ex) {
|
||||
}
|
||||
frame.requestFocusInWindow();
|
||||
|
||||
|
||||
try {
|
||||
setValue(frame.getTable());
|
||||
} catch (UserLevelException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
setValue(frame.getTable());
|
||||
} catch (UserLevelException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -312,47 +312,47 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
}
|
||||
|
||||
public void updateTableToolBar() {
|
||||
Table t = getTable();
|
||||
|
||||
if(t != null)
|
||||
this.updateTableToolBar(t);
|
||||
Table t = getTable();
|
||||
|
||||
if(t != null)
|
||||
this.updateTableToolBar(t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void saveFineCourseValuesInTable(Table t) {
|
||||
if(t == null || t.getCurrentScale() == null) return;
|
||||
|
||||
double incCoarse = 0;
|
||||
double incFine = 0;
|
||||
|
||||
try {
|
||||
//Commit the value which was typed (if field still has focus)
|
||||
incrementByCoarse.commitEdit();
|
||||
incrementByFine.commitEdit();
|
||||
|
||||
incCoarse = Double.parseDouble(String.valueOf(incrementByCoarse.getValue()));
|
||||
incFine = Double.parseDouble(String.valueOf(incrementByFine.getValue()));
|
||||
}
|
||||
//Current value in the inc/dec field are not valid
|
||||
catch(ParseException e) {
|
||||
return;
|
||||
}
|
||||
//Should not happen since ParseException would happen before that
|
||||
catch(NumberFormatException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Save current inc/dec values in table before we switch
|
||||
if(incCoarse!=0 && incFine != 0) {
|
||||
t.updateIncrementDecrementValues(incFine,incCoarse);
|
||||
}
|
||||
|
||||
if(t == null || t.getCurrentScale() == null) return;
|
||||
|
||||
double incCoarse = 0;
|
||||
double incFine = 0;
|
||||
|
||||
try {
|
||||
//Commit the value which was typed (if field still has focus)
|
||||
incrementByCoarse.commitEdit();
|
||||
incrementByFine.commitEdit();
|
||||
|
||||
incCoarse = Double.parseDouble(String.valueOf(incrementByCoarse.getValue()));
|
||||
incFine = Double.parseDouble(String.valueOf(incrementByFine.getValue()));
|
||||
}
|
||||
//Current value in the inc/dec field are not valid
|
||||
catch(ParseException e) {
|
||||
return;
|
||||
}
|
||||
//Should not happen since ParseException would happen before that
|
||||
catch(NumberFormatException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Save current inc/dec values in table before we switch
|
||||
if(incCoarse!=0 && incFine != 0) {
|
||||
t.updateIncrementDecrementValues(incFine,incCoarse);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void updateTableToolBar(Table selectedTable) {
|
||||
//Select the parent Table always instead?
|
||||
//if(selectedTable instanceof Table1D)selectedTable = ((Table1D)selectedTable).getAxisParent();
|
||||
|
||||
//Select the parent Table always instead?
|
||||
//if(selectedTable instanceof Table1D)selectedTable = ((Table1D)selectedTable).getAxisParent();
|
||||
|
||||
if(selectedTable == null && this.selectedTable == null) {
|
||||
// Skip if the table is the same to avoid multiple updates
|
||||
return;
|
||||
|
@ -365,7 +365,7 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
|
||||
|
||||
//Save the current inc/dec values in the table
|
||||
saveFineCourseValuesInTable(this.selectedTable);
|
||||
saveFineCourseValuesInTable(this.selectedTable);
|
||||
this.selectedTable = selectedTable;
|
||||
|
||||
setBorder(toolbarBorder);
|
||||
|
@ -388,7 +388,7 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
{
|
||||
this.scaleSelection.setSelectedItem("Default");
|
||||
} else {
|
||||
this.scaleSelection.setSelectedItem(selectedTable.getCurrentScale().getName());
|
||||
this.scaleSelection.setSelectedItem(selectedTable.getCurrentScale().getCategory());
|
||||
}
|
||||
|
||||
toggleTableToolBar(selectedTable);
|
||||
|
@ -513,7 +513,7 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
scaleSelection.removeAllItems();
|
||||
|
||||
for (Scale scale : scales) {
|
||||
scaleSelection.addItem(scale.getName());
|
||||
scaleSelection.addItem(scale.getCategory());
|
||||
}
|
||||
|
||||
// and put it back
|
||||
|
@ -528,28 +528,28 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
return;
|
||||
}
|
||||
try {
|
||||
if (e.getSource() == incrementCoarse) {
|
||||
incrementCoarse(curTable);
|
||||
} else if (e.getSource() == decrementCoarse) {
|
||||
decrementCoarse(curTable);
|
||||
} else if (e.getSource() == enable3d) {
|
||||
enable3d(curTable);
|
||||
} else if (e.getSource() == incrementFine) {
|
||||
incrementFine(curTable);
|
||||
} else if (e.getSource() == decrementFine) {
|
||||
decrementFine(curTable);
|
||||
} else if (e.getSource() == multiply) {
|
||||
multiply(curTable);
|
||||
} else if (e.getSource() == setValue) {
|
||||
setValue(curTable);
|
||||
} else if (e.getSource() == colorCells) {
|
||||
colorCells(curTable);
|
||||
} else if (e.getSource() == refreshCompare) {
|
||||
refreshCompare(curTable);
|
||||
}
|
||||
if (e.getSource() == incrementCoarse) {
|
||||
incrementCoarse(curTable);
|
||||
} else if (e.getSource() == decrementCoarse) {
|
||||
decrementCoarse(curTable);
|
||||
} else if (e.getSource() == enable3d) {
|
||||
enable3d(curTable);
|
||||
} else if (e.getSource() == incrementFine) {
|
||||
incrementFine(curTable);
|
||||
} else if (e.getSource() == decrementFine) {
|
||||
decrementFine(curTable);
|
||||
} else if (e.getSource() == multiply) {
|
||||
multiply(curTable);
|
||||
} else if (e.getSource() == setValue) {
|
||||
setValue(curTable);
|
||||
} else if (e.getSource() == colorCells) {
|
||||
colorCells(curTable);
|
||||
} else if (e.getSource() == refreshCompare) {
|
||||
refreshCompare(curTable);
|
||||
}
|
||||
}
|
||||
catch(UserLevelException ex) {
|
||||
TableView.showInvalidUserLevelPopup(ex);
|
||||
TableView.showInvalidUserLevelPopup(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -771,7 +771,7 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
if (e.getSource() == scaleSelection) {
|
||||
// scale changed
|
||||
try {
|
||||
curTable.setScaleByName((String)scaleSelection.getSelectedItem());
|
||||
curTable.setScaleByCategory((String)scaleSelection.getSelectedItem());
|
||||
updateToolbarIncrementDecrementValues();
|
||||
} catch (NameNotFoundException e1) {
|
||||
e1.printStackTrace();
|
||||
|
@ -818,10 +818,10 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
|
||||
//Set the value
|
||||
try {
|
||||
table3d.setRealValue(String.valueOf(value));
|
||||
} catch (UserLevelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
table3d.setRealValue(String.valueOf(value));
|
||||
} catch (UserLevelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -846,4 +846,4 @@ public class TableToolBar extends JToolBar implements MouseListener, ItemListene
|
|||
public Table getSelectedTable() {
|
||||
return this.selectedTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2020 RomRaider.com
|
||||
* Copyright (C) 2006-2021 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
|
||||
|
@ -28,6 +28,7 @@ import java.io.FileInputStream;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
|
@ -38,6 +39,8 @@ import com.romraider.xml.DOMSettingsUnmarshaller;
|
|||
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
|
||||
|
||||
public class SettingsManager {
|
||||
private static final Logger LOGGER =
|
||||
Logger.getLogger(SettingsManager.class);
|
||||
private static final ResourceBundle rb = new ResourceUtil().getBundle(
|
||||
SettingsManager.class.getName());
|
||||
private static final String SETTINGS_FILE = "/settings.xml";
|
||||
|
@ -73,6 +76,7 @@ public class SettingsManager {
|
|||
sf = new File(USER_HOME + SETTINGS_FILE);
|
||||
settingsFileIn = new FileInputStream(sf);
|
||||
}
|
||||
LOGGER.info("Loaded settings from file: " + settingsDir.replace("\\", "/") + SETTINGS_FILE);
|
||||
|
||||
final InputSource src = new InputSource(settingsFileIn);
|
||||
final DOMSettingsUnmarshaller domUms = new DOMSettingsUnmarshaller();
|
||||
|
|
|
@ -51,16 +51,16 @@ import com.romraider.util.SettingsManager;
|
|||
|
||||
public class TableScaleUnmarshaller {
|
||||
private static final Logger LOGGER = Logger.getLogger(TableScaleUnmarshaller.class);
|
||||
private final Map<String, Integer> tableNames = new HashMap<String, Integer>();
|
||||
private final Map<String, Integer> tableNames = new HashMap<String, Integer>();
|
||||
private final List<Scale> scales = new ArrayList<Scale>();
|
||||
private String memModelEndian = null;
|
||||
|
||||
|
||||
public void setMemModelEndian(String endian) {
|
||||
memModelEndian = endian;
|
||||
memModelEndian = endian;
|
||||
}
|
||||
|
||||
|
||||
public void unmarshallBaseScales(Node rootNode) {
|
||||
NodeList nodes = rootNode.getChildNodes();
|
||||
NodeList nodes = rootNode.getChildNodes();
|
||||
Node n;
|
||||
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
|
@ -68,336 +68,346 @@ public class TableScaleUnmarshaller {
|
|||
|
||||
if (n.getNodeType() == ELEMENT_NODE
|
||||
&& n.getNodeName().equalsIgnoreCase("scalingbase")) {
|
||||
scales.add(unmarshallScale(n, new Scale()));
|
||||
unmarshallScale(n, new Scale());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Table unmarshallTable(Node tableNode, Table table, Rom rom)
|
||||
throws XMLParseException, TableIsOmittedException, Exception {
|
||||
|
||||
if (unmarshallAttribute(tableNode, "omit", "false").equalsIgnoreCase(
|
||||
"true")) { // remove table if omitted
|
||||
throw new TableIsOmittedException();
|
||||
}
|
||||
|
||||
if (!unmarshallAttribute(tableNode, "base", "none").equalsIgnoreCase(
|
||||
"none")) { // copy base table for inheritance
|
||||
try {
|
||||
table = (Table) ObjectCloner
|
||||
.deepCopy(rom.getTableByName(unmarshallAttribute(tableNode,
|
||||
"base", "none")));
|
||||
public Table unmarshallTable(Node tableNode, Table table, Rom rom)
|
||||
throws XMLParseException, TableIsOmittedException, Exception {
|
||||
|
||||
} catch (TableNotFoundException ex) { /* table not found, do nothing */
|
||||
if (unmarshallAttribute(tableNode, "omit", "false").equalsIgnoreCase(
|
||||
"true")) { // remove table if omitted
|
||||
throw new TableIsOmittedException();
|
||||
}
|
||||
|
||||
} catch (InvalidTableNameException ex) { // Table name is invalid, do nothing.
|
||||
if (!unmarshallAttribute(tableNode, "base", "none").equalsIgnoreCase(
|
||||
"none")) { // copy base table for inheritance
|
||||
try {
|
||||
table = (Table) ObjectCloner
|
||||
.deepCopy(rom.getTableByName(unmarshallAttribute(tableNode,
|
||||
"base", "none")));
|
||||
|
||||
} catch (NullPointerException ex) {
|
||||
JOptionPane.showMessageDialog(ECUEditorManager.getECUEditor(),
|
||||
new DebugPanel(ex, SettingsManager.getSettings().getSupportURL()), "Exception",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
} catch (TableNotFoundException ex) { /* table not found, do nothing */
|
||||
|
||||
if (table == null) {
|
||||
// create new instance (otherwise it
|
||||
// is inherited)
|
||||
final String tn = unmarshallAttribute(tableNode, "name", "unknown");
|
||||
final String type = unmarshallAttribute(tableNode, "type", "none");
|
||||
} catch (InvalidTableNameException ex) { // Table name is invalid, do nothing.
|
||||
|
||||
if (tableNames.containsKey(tn) || type.contains("xis")) {
|
||||
if (type.equalsIgnoreCase("3D")) {
|
||||
table = new Table3D();
|
||||
} catch (NullPointerException ex) {
|
||||
JOptionPane.showMessageDialog(ECUEditorManager.getECUEditor(),
|
||||
new DebugPanel(ex, SettingsManager.getSettings().getSupportURL()), "Exception",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (type.equalsIgnoreCase("2D")) {
|
||||
table = new Table2D();
|
||||
if (table == null) {
|
||||
// create new instance (otherwise it is inherited)
|
||||
final String tn = unmarshallAttribute(tableNode, "name", "unknown");
|
||||
final String type = unmarshallAttribute(tableNode, "type", "none");
|
||||
|
||||
} else if (type.equalsIgnoreCase("1D")) {
|
||||
table = new Table1D(Table.TableType.TABLE_1D);
|
||||
if (tableNames.containsKey(tn) || type.contains("xis")) {
|
||||
if (type.equalsIgnoreCase("3D")) {
|
||||
table = new Table3D();
|
||||
|
||||
} else if (type.equalsIgnoreCase("X Axis")
|
||||
|| type.equalsIgnoreCase("Static X Axis")) {
|
||||
table = new Table1D(Table.TableType.X_AXIS);
|
||||
} else if (type.equalsIgnoreCase("2D")) {
|
||||
table = new Table2D();
|
||||
|
||||
} else if (type.equalsIgnoreCase("Y Axis")
|
||||
|| type.equalsIgnoreCase("Static Y Axis")) {
|
||||
table = new Table1D(Table.TableType.Y_AXIS);
|
||||
} else if (type.equalsIgnoreCase("Switch")) {
|
||||
table = new TableSwitch();
|
||||
} else if (type.equalsIgnoreCase("1D")) {
|
||||
table = new Table1D(Table.TableType.TABLE_1D);
|
||||
|
||||
} else if (type.equalsIgnoreCase("BitwiseSwitch")) {
|
||||
table = new TableBitwiseSwitch();
|
||||
}
|
||||
else if(type.equalsIgnoreCase("none")){
|
||||
throw new XMLParseException("Table type unspecified for "
|
||||
+ tableNode.getAttributes().getNamedItem("name"));
|
||||
}
|
||||
else {
|
||||
throw new XMLParseException("Table type " + type + " unknown for "
|
||||
+ tableNode.getAttributes().getNamedItem("name"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
} else if (type.equalsIgnoreCase("X Axis")
|
||||
|| type.equalsIgnoreCase("Static X Axis")) {
|
||||
table = new Table1D(Table.TableType.X_AXIS);
|
||||
|
||||
// unmarshall table attributes
|
||||
final String tn = unmarshallAttribute(tableNode, "name", table.getName());
|
||||
table.setName(tn);
|
||||
if (unmarshallAttribute(tableNode, "beforeram", "false")
|
||||
.equalsIgnoreCase("true")) {
|
||||
table.setBeforeRam(true);
|
||||
}
|
||||
|
||||
|
||||
table.setDataLayout(unmarshallAttribute(tableNode, "dataLayout", ""));
|
||||
table.setCategory(unmarshallAttribute(tableNode, "category",
|
||||
table.getCategory()));
|
||||
if (table.getStorageType() < 1) {
|
||||
table.setSignedData(RomAttributeParser
|
||||
.parseStorageDataSign(unmarshallAttribute(tableNode,
|
||||
"storagetype",
|
||||
String.valueOf(table.getStorageType()))));
|
||||
}
|
||||
table.setStorageType(RomAttributeParser
|
||||
.parseStorageType(unmarshallAttribute(tableNode, "storagetype",
|
||||
String.valueOf(table.getStorageType()))));
|
||||
if (memModelEndian == null) {
|
||||
table.setEndian(RomAttributeParser.parseEndian(unmarshallAttribute(
|
||||
tableNode, "endian", table.getEndian().getMarshallingString())));
|
||||
}
|
||||
else {
|
||||
final Settings.Endian endian = memModelEndian.equalsIgnoreCase("little") ? Settings.Endian.LITTLE : Settings.Endian.BIG;
|
||||
table.setMemModelEndian(endian);
|
||||
table.setEndian(endian);
|
||||
}
|
||||
if (tableNames.containsKey(tn)) {
|
||||
table.setStorageAddress(tableNames.get(tn));
|
||||
}
|
||||
else {
|
||||
table.setStorageAddress(RomAttributeParser
|
||||
.parseHexString(unmarshallAttribute(tableNode,
|
||||
"storageaddress",
|
||||
String.valueOf(table.getStorageAddress()))));
|
||||
}
|
||||
|
||||
table.setDescription(unmarshallAttribute(tableNode, "description",
|
||||
table.getDescription()));
|
||||
table.setDataSize(unmarshallAttribute(tableNode, "sizey",
|
||||
unmarshallAttribute(tableNode, "sizex", table.getDataSize())));
|
||||
table.setFlip(unmarshallAttribute(tableNode, "flipy",
|
||||
unmarshallAttribute(tableNode, "flipx", table.getFlip())));
|
||||
table.setUserLevel(unmarshallAttribute(tableNode, "userlevel",
|
||||
table.getUserLevel()));
|
||||
table.setLocked(unmarshallAttribute(tableNode, "locked",
|
||||
table.isLocked()));
|
||||
table.setLogParam(unmarshallAttribute(tableNode, "logparam",
|
||||
table.getLogParam()));
|
||||
table.setStringMask(
|
||||
unmarshallAttribute(tableNode, "mask", "0"));
|
||||
} else if (type.equalsIgnoreCase("Y Axis")
|
||||
|| type.equalsIgnoreCase("Static Y Axis")) {
|
||||
table = new Table1D(Table.TableType.Y_AXIS);
|
||||
} else if (type.equalsIgnoreCase("Switch")) {
|
||||
table = new TableSwitch();
|
||||
|
||||
if (table.getType() == Table.TableType.TABLE_3D) {
|
||||
((Table3D) table).setSwapXY(unmarshallAttribute(tableNode,
|
||||
"swapxy", ((Table3D) table).getSwapXY()));
|
||||
((Table3D) table).setFlipX(unmarshallAttribute(tableNode, "flipx",
|
||||
((Table3D) table).getFlipX()));
|
||||
((Table3D) table).setFlipY(unmarshallAttribute(tableNode, "flipy",
|
||||
((Table3D) table).getFlipY()));
|
||||
((Table3D) table).setSizeX(unmarshallAttribute(tableNode, "sizex",
|
||||
((Table3D) table).getSizeX()));
|
||||
((Table3D) table).setSizeY(unmarshallAttribute(tableNode, "sizey",
|
||||
((Table3D) table).getSizeY()));
|
||||
}
|
||||
|
||||
Node n;
|
||||
NodeList nodes = tableNode.getChildNodes();
|
||||
} else if (type.equalsIgnoreCase("BitwiseSwitch")) {
|
||||
table = new TableBitwiseSwitch();
|
||||
}
|
||||
else if(type.equalsIgnoreCase("none")){
|
||||
throw new XMLParseException("Table type unspecified for "
|
||||
+ tableNode.getAttributes().getNamedItem("name"));
|
||||
}
|
||||
else {
|
||||
throw new XMLParseException("Table type " + type + " unknown for "
|
||||
+ tableNode.getAttributes().getNamedItem("name"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
n = nodes.item(i);
|
||||
// unmarshall table attributes
|
||||
final String tn = unmarshallAttribute(tableNode, "name", table.getName());
|
||||
table.setName(tn);
|
||||
if (unmarshallAttribute(tableNode, "beforeram", "false")
|
||||
.equalsIgnoreCase("true")) {
|
||||
table.setBeforeRam(true);
|
||||
}
|
||||
|
||||
if (n.getNodeType() == ELEMENT_NODE) {
|
||||
if (n.getNodeName().equalsIgnoreCase("table")) {
|
||||
table.setDataLayout(unmarshallAttribute(tableNode, "dataLayout", ""));
|
||||
table.setCategory(unmarshallAttribute(tableNode, "category",
|
||||
table.getCategory()));
|
||||
if (table.getStorageType() < 1) {
|
||||
table.setSignedData(RomAttributeParser
|
||||
.parseStorageDataSign(unmarshallAttribute(tableNode,
|
||||
"storagetype",
|
||||
String.valueOf(table.getStorageType()))));
|
||||
}
|
||||
table.setStorageType(RomAttributeParser
|
||||
.parseStorageType(unmarshallAttribute(tableNode, "storagetype",
|
||||
String.valueOf(table.getStorageType()))));
|
||||
if (memModelEndian == null) {
|
||||
table.setEndian(RomAttributeParser.parseEndian(unmarshallAttribute(
|
||||
tableNode, "endian", table.getEndian().getMarshallingString())));
|
||||
}
|
||||
else {
|
||||
final Settings.Endian endian = memModelEndian.equalsIgnoreCase("little") ? Settings.Endian.LITTLE : Settings.Endian.BIG;
|
||||
table.setMemModelEndian(endian);
|
||||
table.setEndian(endian);
|
||||
}
|
||||
if (tableNames.containsKey(tn)) {
|
||||
table.setStorageAddress(tableNames.get(tn));
|
||||
}
|
||||
else {
|
||||
table.setStorageAddress(RomAttributeParser
|
||||
.parseHexString(unmarshallAttribute(tableNode,
|
||||
"storageaddress",
|
||||
String.valueOf(table.getStorageAddress()))));
|
||||
}
|
||||
|
||||
if (table.getType() == Table.TableType.TABLE_2D) { // if table is 2D,
|
||||
// parse axis
|
||||
table.setDescription(unmarshallAttribute(tableNode, "description",
|
||||
table.getDescription()));
|
||||
table.setDataSize(unmarshallAttribute(tableNode, "sizey",
|
||||
unmarshallAttribute(tableNode, "sizex", table.getDataSize())));
|
||||
table.setFlip(unmarshallAttribute(tableNode, "flipy",
|
||||
unmarshallAttribute(tableNode, "flipx", table.getFlip())));
|
||||
table.setUserLevel(unmarshallAttribute(tableNode, "userlevel",
|
||||
table.getUserLevel()));
|
||||
table.setLocked(unmarshallAttribute(tableNode, "locked",
|
||||
table.isLocked()));
|
||||
table.setLogParam(unmarshallAttribute(tableNode, "logparam",
|
||||
table.getLogParam()));
|
||||
table.setStringMask(
|
||||
unmarshallAttribute(tableNode, "mask", "0"));
|
||||
|
||||
if (RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n, "type",
|
||||
"unknown")) == Table.TableType.Y_AXIS
|
||||
|| RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n,
|
||||
"type", "unknown")) == Table.TableType.X_AXIS) {
|
||||
if (table.getType() == Table.TableType.TABLE_3D) {
|
||||
((Table3D) table).setSwapXY(unmarshallAttribute(tableNode,
|
||||
"swapxy", ((Table3D) table).getSwapXY()));
|
||||
((Table3D) table).setFlipX(unmarshallAttribute(tableNode, "flipx",
|
||||
((Table3D) table).getFlipX()));
|
||||
((Table3D) table).setFlipY(unmarshallAttribute(tableNode, "flipy",
|
||||
((Table3D) table).getFlipY()));
|
||||
((Table3D) table).setSizeX(unmarshallAttribute(tableNode, "sizex",
|
||||
((Table3D) table).getSizeX()));
|
||||
((Table3D) table).setSizeY(unmarshallAttribute(tableNode, "sizey",
|
||||
((Table3D) table).getSizeY()));
|
||||
}
|
||||
|
||||
Table1D tempTable = (Table1D) unmarshallTable(n,
|
||||
((Table2D) table).getAxis(), rom);
|
||||
if (tempTable.getDataSize() != table.getDataSize()) {
|
||||
tempTable.setDataSize(table.getDataSize());
|
||||
}
|
||||
tempTable.setData(((Table2D) table).getAxis().getData());
|
||||
((Table2D) table).setAxis(tempTable);
|
||||
|
||||
Node n;
|
||||
NodeList nodes = tableNode.getChildNodes();
|
||||
|
||||
}
|
||||
} else if (table.getType() == Table.TableType.TABLE_3D) { // if table
|
||||
// is 3D,
|
||||
// populate
|
||||
// xAxis
|
||||
if (RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n, "type",
|
||||
"unknown")) == Table.TableType.X_AXIS) {
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
n = nodes.item(i);
|
||||
|
||||
Table1D tempTable = (Table1D) unmarshallTable(n,
|
||||
((Table3D) table).getXAxis(), rom);
|
||||
if (tempTable.getDataSize() != ((Table3D) table)
|
||||
.getSizeX()) {
|
||||
tempTable.setDataSize(((Table3D) table)
|
||||
.getSizeX());
|
||||
}
|
||||
tempTable.setData(((Table3D) table).getXAxis().getData());
|
||||
((Table3D) table).setXAxis(tempTable);
|
||||
|
||||
if (n.getNodeType() == ELEMENT_NODE) {
|
||||
if (n.getNodeName().equalsIgnoreCase("table")) {
|
||||
|
||||
} else if (RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n, "type",
|
||||
"unknown")) == Table.TableType.Y_AXIS) {
|
||||
if (table.getType() == Table.TableType.TABLE_2D) { // if table is 2D,
|
||||
// parse axis
|
||||
if (RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n, "type",
|
||||
"unknown")) == Table.TableType.Y_AXIS
|
||||
|| RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n,
|
||||
"type", "unknown")) == Table.TableType.X_AXIS) {
|
||||
|
||||
Table1D tempTable = (Table1D) unmarshallTable(n,
|
||||
((Table3D) table).getYAxis(), rom);
|
||||
if (tempTable.getDataSize() != ((Table3D) table)
|
||||
.getSizeY()) {
|
||||
tempTable.setDataSize(((Table3D) table)
|
||||
.getSizeY());
|
||||
}
|
||||
tempTable.setData(((Table3D) table).getYAxis().getData());
|
||||
((Table3D) table).setYAxis(tempTable);
|
||||
}
|
||||
}
|
||||
Table1D tempTable = (Table1D) unmarshallTable(n,
|
||||
((Table2D) table).getAxis(), rom);
|
||||
if (tempTable.getDataSize() != table.getDataSize()) {
|
||||
tempTable.setDataSize(table.getDataSize());
|
||||
}
|
||||
tempTable.setData(((Table2D) table).getAxis().getData());
|
||||
((Table2D) table).setAxis(tempTable);
|
||||
}
|
||||
|
||||
} else if (n.getNodeName().equalsIgnoreCase("scaling")) {
|
||||
// check whether scale already exists. if so, modify, else
|
||||
// use new instance
|
||||
Scale baseScale = table.getScale(unmarshallAttribute(n,"name", "Default"));
|
||||
table.addScale(unmarshallScale(n, baseScale));
|
||||
} else if (table.getType() == Table.TableType.TABLE_3D) { // if table
|
||||
// is 3D,
|
||||
// populate
|
||||
// xAxis
|
||||
if (RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n, "type",
|
||||
"unknown")) == Table.TableType.X_AXIS) {
|
||||
|
||||
} else if (n.getNodeName().equalsIgnoreCase("data")) {
|
||||
// parse and add data to table
|
||||
if(table instanceof Table1D) {
|
||||
((Table1D)table).addStaticDataCell(unmarshallText(n));
|
||||
} else {
|
||||
// Why would this happen. Static should only be for axis.
|
||||
LOGGER.error("Error adding static data cell.");
|
||||
}
|
||||
Table1D tempTable = (Table1D) unmarshallTable(n,
|
||||
((Table3D) table).getXAxis(), rom);
|
||||
if (tempTable.getDataSize() != ((Table3D) table)
|
||||
.getSizeX()) {
|
||||
tempTable.setDataSize(((Table3D) table)
|
||||
.getSizeX());
|
||||
}
|
||||
tempTable.setData(((Table3D) table).getXAxis().getData());
|
||||
((Table3D) table).setXAxis(tempTable);
|
||||
|
||||
} else if (n.getNodeName().equalsIgnoreCase("description")) {
|
||||
table.setDescription(unmarshallText(n));
|
||||
} else if (RomAttributeParser
|
||||
.parseTableType(unmarshallAttribute(n, "type",
|
||||
"unknown")) == Table.TableType.Y_AXIS) {
|
||||
|
||||
} else if (n.getNodeName().equalsIgnoreCase("state")) {
|
||||
table.setValues(
|
||||
unmarshallAttribute(n, "name", ""),
|
||||
unmarshallAttribute(n, "data", "0"));
|
||||
} else if (n.getNodeName().equalsIgnoreCase("bit")) {
|
||||
table.setValues(
|
||||
unmarshallAttribute(n, "name", ""),
|
||||
unmarshallAttribute(n, "position", "0"));
|
||||
|
||||
} else { /* unexpected element in Table (skip) */
|
||||
}
|
||||
} else { /* unexpected node-type in Table (skip) */
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list of table names to be used as a filter on the inherited
|
||||
* tables to reduce unnecessary table object creation.
|
||||
* @param nodes - the NodeList to filter
|
||||
* @throws XMLParseException
|
||||
* @throws TableIsOmittedException
|
||||
* @throws Exception
|
||||
*/
|
||||
public void filterFoundRomTables (NodeList nodes) {
|
||||
Node n;
|
||||
Table1D tempTable = (Table1D) unmarshallTable(n,
|
||||
((Table3D) table).getYAxis(), rom);
|
||||
if (tempTable.getDataSize() != ((Table3D) table)
|
||||
.getSizeY()) {
|
||||
tempTable.setDataSize(((Table3D) table)
|
||||
.getSizeY());
|
||||
}
|
||||
tempTable.setData(((Table3D) table).getYAxis().getData());
|
||||
((Table3D) table).setYAxis(tempTable);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
n = nodes.item(i);
|
||||
if (n.getNodeType() == ELEMENT_NODE
|
||||
&& n.getNodeName().equalsIgnoreCase("table")) {
|
||||
} else if (n.getNodeName().equalsIgnoreCase("scaling")) {
|
||||
// check whether scale already exists. if so, modify, else
|
||||
// use new instance
|
||||
Scale baseScale = table.getScale(unmarshallAttribute(n, "category", "Default"));
|
||||
table.addScale(unmarshallScale(n, baseScale));
|
||||
|
||||
final String name = unmarshallAttribute(n, "name", "unknown");
|
||||
final int address = RomAttributeParser
|
||||
.parseHexString(unmarshallAttribute(n,
|
||||
"storageaddress", "-1"));
|
||||
} else if (n.getNodeName().equalsIgnoreCase("data")) {
|
||||
// parse and add data to table
|
||||
if(table instanceof Table1D) {
|
||||
((Table1D)table).addStaticDataCell(unmarshallText(n));
|
||||
} else {
|
||||
// Why would this happen. Static should only be for axis.
|
||||
LOGGER.error("Error adding static data cell.");
|
||||
}
|
||||
|
||||
if (unmarshallAttribute(n, "omit", "false").equalsIgnoreCase(
|
||||
"true")) {
|
||||
return;
|
||||
}
|
||||
} else if (n.getNodeName().equalsIgnoreCase("description")) {
|
||||
table.setDescription(unmarshallText(n));
|
||||
|
||||
if (!tableNames.containsKey(name) && address >= 0) {
|
||||
tableNames.put(name, address);
|
||||
}
|
||||
else if (tableNames.containsKey(name)) {
|
||||
if (tableNames.get(name) < 1 && address >= 0) {
|
||||
tableNames.put(name, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Scale unmarshallScale(Node scaleNode, Scale scale) {
|
||||
} else if (n.getNodeName().equalsIgnoreCase("state")) {
|
||||
table.setValues(
|
||||
unmarshallAttribute(n, "name", ""),
|
||||
unmarshallAttribute(n, "data", "0"));
|
||||
} else if (n.getNodeName().equalsIgnoreCase("bit")) {
|
||||
table.setValues(
|
||||
unmarshallAttribute(n, "name", ""),
|
||||
unmarshallAttribute(n, "position", "0"));
|
||||
|
||||
// look for base scale first
|
||||
String base = unmarshallAttribute(scaleNode, "base", "none");
|
||||
if (!base.equalsIgnoreCase("none")) {
|
||||
for (Scale scaleItem : scales) {
|
||||
} else { /* unexpected element in Table (skip) */
|
||||
}
|
||||
} else { /* unexpected node-type in Table (skip) */
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
// check whether name matches base and set scale if so
|
||||
if (scaleItem.getName().equalsIgnoreCase(base)) {
|
||||
try {
|
||||
scale = (Scale) ObjectCloner.deepCopy(scaleItem);
|
||||
/**
|
||||
* Create a list of table names to be used as a filter on the inherited
|
||||
* tables to reduce unnecessary table object creation.
|
||||
* @param nodes - the NodeList to filter
|
||||
* @throws XMLParseException
|
||||
* @throws TableIsOmittedException
|
||||
* @throws Exception
|
||||
*/
|
||||
public void filterFoundRomTables (NodeList nodes) {
|
||||
Node n;
|
||||
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
ECUEditorManager.getECUEditor(),
|
||||
new DebugPanel(ex, SettingsManager.getSettings()
|
||||
.getSupportURL()), "Exception",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Name should always be set to Default even if missing
|
||||
scale.setName(unmarshallAttribute(scaleNode, "name", "Default"));
|
||||
|
||||
|
||||
//Iterate over available attributes
|
||||
for(int i=0; i < scaleNode.getAttributes().getLength(); i++) {
|
||||
Node attr = scaleNode.getAttributes().item(i);
|
||||
String name = attr.getNodeName();
|
||||
String value = attr.getNodeValue();
|
||||
|
||||
if(name.equalsIgnoreCase("units"))scale.setUnit(value);
|
||||
else if(name.equalsIgnoreCase("expression")) scale.setExpression(value);
|
||||
else if(name.equalsIgnoreCase("to_byte")) scale.setByteExpression(value);
|
||||
else if(name.equalsIgnoreCase("format")) scale.setFormat(value);
|
||||
else if(name.equalsIgnoreCase("max")) scale.setMax(Double.parseDouble(value));
|
||||
else if(name.equalsIgnoreCase("min")) scale.setMin(Double.parseDouble(value));
|
||||
else if(name.equalsIgnoreCase("coarseincrement") || name.equalsIgnoreCase("increment"))
|
||||
scale.setCoarseIncrement(Double.parseDouble(value));
|
||||
else if(name.equalsIgnoreCase("fineincrement")) scale.setFineIncrement(Double.parseDouble(value));
|
||||
}
|
||||
|
||||
for (Scale s : scales) {
|
||||
if (s.equals(scale)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
scales.add(scale);
|
||||
return scale;
|
||||
}
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
n = nodes.item(i);
|
||||
if (n.getNodeType() == ELEMENT_NODE
|
||||
&& n.getNodeName().equalsIgnoreCase("table")) {
|
||||
|
||||
final String name = unmarshallAttribute(n, "name", "unknown");
|
||||
final int address = RomAttributeParser
|
||||
.parseHexString(unmarshallAttribute(n,
|
||||
"storageaddress", "-1"));
|
||||
|
||||
if (unmarshallAttribute(n, "omit", "false").equalsIgnoreCase(
|
||||
"true")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tableNames.containsKey(name) && address >= 0) {
|
||||
tableNames.put(name, address);
|
||||
}
|
||||
else if (tableNames.containsKey(name)) {
|
||||
if (tableNames.get(name) < 1 && address >= 0) {
|
||||
tableNames.put(name, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Scale unmarshallScale(Node scaleNode, Scale scale) {
|
||||
|
||||
// look for base scaling attribute first
|
||||
String base = unmarshallAttribute(scaleNode, "base", "none");
|
||||
if (!base.equalsIgnoreCase("none")) {
|
||||
// check whether base value matches the name of a an existing
|
||||
// scalingbase, if so, inherit from scalingbase
|
||||
for (Scale scaleItem : scales) {
|
||||
if (scaleItem.getName().equalsIgnoreCase(base)) {
|
||||
try {
|
||||
scale = (Scale) ObjectCloner.deepCopy(scaleItem);
|
||||
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
ECUEditorManager.getECUEditor(),
|
||||
new DebugPanel(ex, SettingsManager.getSettings()
|
||||
.getSupportURL()), "Exception",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set Category to Default if missing or not inherited from scalingbase
|
||||
if (base.equalsIgnoreCase("none")) {
|
||||
scale.setCategory(unmarshallAttribute(scaleNode, "category", "Default"));
|
||||
}
|
||||
|
||||
// Set scaling name, if a scaling has no name attribute (scaling is
|
||||
// defined in a table element), try and use the units value as its
|
||||
// name, otherwise use none
|
||||
if (!scale.getCategory().equalsIgnoreCase("Raw Value") &&
|
||||
scale.getName().equalsIgnoreCase("Raw Value")) {
|
||||
scale.setName(unmarshallAttribute(scaleNode, "name",
|
||||
unmarshallAttribute(scaleNode, "units", "none")));
|
||||
}
|
||||
|
||||
// Iterate over other available attributes
|
||||
for(int i=0; i < scaleNode.getAttributes().getLength(); i++) {
|
||||
Node attr = scaleNode.getAttributes().item(i);
|
||||
String name = attr.getNodeName();
|
||||
String value = attr.getNodeValue();
|
||||
|
||||
if(name.equalsIgnoreCase("units"))scale.setUnit(value);
|
||||
else if(name.equalsIgnoreCase("expression")) scale.setExpression(value);
|
||||
else if(name.equalsIgnoreCase("to_byte")) scale.setByteExpression(value);
|
||||
else if(name.equalsIgnoreCase("format")) scale.setFormat(value);
|
||||
else if(name.equalsIgnoreCase("max")) scale.setMax(Double.parseDouble(value));
|
||||
else if(name.equalsIgnoreCase("min")) scale.setMin(Double.parseDouble(value));
|
||||
else if(name.equalsIgnoreCase("coarseincrement") || name.equalsIgnoreCase("increment"))
|
||||
scale.setCoarseIncrement(Double.parseDouble(value));
|
||||
else if(name.equalsIgnoreCase("fineincrement")) scale.setFineIncrement(Double.parseDouble(value));
|
||||
}
|
||||
|
||||
for (Scale s : scales) {
|
||||
if (s.equals(scale)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
scales.add(scale);
|
||||
return scale;
|
||||
}
|
||||
|
||||
// for unit testing
|
||||
public List<Scale> getScales() {
|
||||
return scales;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<roms>
|
||||
<rom>
|
||||
<romid>
|
||||
<xmlid>32BITBASE</xmlid>
|
||||
<market>USDM</market>
|
||||
<make>Subaru</make>
|
||||
<model>Impreza</model>
|
||||
<submodel>STi</submodel>
|
||||
<transmission>MT</transmission>
|
||||
<filesize>512kb</filesize>
|
||||
<memmodel>SH7055</memmodel>
|
||||
<flashmethod>sti04</flashmethod>
|
||||
</romid>
|
||||
<table type="2D" name="A/F Learning #1 Airflow Ranges" category="Fueling - AF Correction / Learning" storagetype="float" endian="little" sizey="3" userlevel="4">
|
||||
<scaling units="Mass Airflow (g/s)" expression="x" to_byte="x" format="0.00" fineincrement=".1" coarseincrement="1" />
|
||||
<table type="Static Y Axis" name="A/F Learning Store/Apply Ranges" sizey="3">
|
||||
<data> Max Range A / Min Range B </data>
|
||||
<data> Max Range B / Min Range C </data>
|
||||
<data> Max Range C / Min Range D </data>
|
||||
</table>
|
||||
<description>These are the airflow ranges in which the different long-term fuel trims are calculated in closed loop and applied to the same airflow ranges for both closed loop and open loop.</description>
|
||||
</table>
|
||||
<table type="2D" name="A/F Learning Airflow Ranges" category="Fueling - AF Correction / Learning" storagetype="float" endian="little" sizey="3" userlevel="4">
|
||||
<scaling units="Mass Airflow (g/s)" expression="x" to_byte="x" format="0.00" fineincrement=".1" coarseincrement="1" />
|
||||
<table type="Static Y Axis" name="A/F Learning #1 and #2 Store/Apply Ranges" sizey="3">
|
||||
<data> Max Range A / Min Range B </data>
|
||||
<data> Max Range B / Min Range C </data>
|
||||
<data> Max Range C / Min Range D </data>
|
||||
</table>
|
||||
<description>These are the airflow ranges in which the different long-term fuel trims are calculated in closed loop and applied to the same airflow ranges for both closed loop and open loop.</description>
|
||||
</table>
|
||||
</rom>
|
||||
<rom base="32BITBASE">
|
||||
<romid>
|
||||
<xmlid>A2WC510N</xmlid>
|
||||
<internalidaddress>2000</internalidaddress>
|
||||
<internalidstring>A2WC510N</internalidstring>
|
||||
<ecuid>2F12785206</ecuid>
|
||||
<year>05</year>
|
||||
<market>USDM</market>
|
||||
<make>Subaru</make>
|
||||
<model>Legacy</model>
|
||||
<submodel>GT</submodel>
|
||||
<transmission>MT</transmission>
|
||||
<memmodel>SH7058</memmodel>
|
||||
<flashmethod>sti05</flashmethod>
|
||||
<filesize>1024kb</filesize>
|
||||
</romid>
|
||||
<table name="A/F Learning #1 Airflow Ranges" storageaddress="0xC7078" />
|
||||
</rom>
|
||||
<rom base="A2WC510N">
|
||||
<romid>
|
||||
<xmlid>A2WC510S</xmlid>
|
||||
<internalidaddress>2000</internalidaddress>
|
||||
<internalidstring>A2WC510S</internalidstring>
|
||||
<ecuid>2F12795206</ecuid>
|
||||
<year>05</year>
|
||||
<market>USDM</market>
|
||||
<make>Subaru</make>
|
||||
<model>Outback</model>
|
||||
<submodel>XT</submodel>
|
||||
<transmission>MT</transmission>
|
||||
<memmodel>SH7058</memmodel>
|
||||
<flashmethod>sti05</flashmethod>
|
||||
<filesize>1024kb</filesize>
|
||||
</romid>
|
||||
</rom>
|
||||
</roms>
|
|
@ -0,0 +1,87 @@
|
|||
<!-- demonstrate scalingbase use and <table base= inheritance -->
|
||||
|
||||
<roms>
|
||||
<scalingbase category="Standard" name="BoostTarget_psirelativesealevel" units="Boost Target (psi relative sea level)" expression="(x-760)*.01933677" to_byte="(x/.01933677)+760" format="0.00" fineincrement=".01" coarseincrement=".5" />
|
||||
<scalingbase name="rpm" units="RPM" expression="x" to_byte="x" format="#" fineincrement="50" coarseincrement="100" />
|
||||
<scalingbase name="targetboostcomppercent" expression="(x*.78125)-100" to_byte="(x+100)/.78125" format="0.0" fineincrement=".4" coarseincrement="1" />
|
||||
<scalingbase name="WastegateDutyCycle_%" units="Wastegate Duty Cycle (%)" expression="x*.00390625" to_byte="x/.00390625" format="0.0" fineincrement=".2" coarseincrement="1" min="0.1" max="99.9"/>
|
||||
<scalingbase category="Metric" name="BoostTarget_barabsolute" units="Boost Target (bar absolute)" expression="x*.001333224" to_byte="x/.001333224" format="#0.000" fineincrement=".01" coarseincrement=".1" />
|
||||
|
||||
<rom>
|
||||
<romid>
|
||||
<xmlid>32BITBASE</xmlid>
|
||||
<market>USDM</market>
|
||||
<make>Subaru</make>
|
||||
<model>Impreza</model>
|
||||
<submodel>STi</submodel>
|
||||
<transmission>MT</transmission>
|
||||
<filesize>512kb</filesize>
|
||||
<memmodel>SH7055</memmodel>
|
||||
<flashmethod>sti04</flashmethod>
|
||||
</romid>
|
||||
<table type="3D" name="Target Boost A" category="Boost Control - Target" storagetype="uint16" endian="big" sizex="8" sizey="12" userlevel="1" logparam="E52">
|
||||
<scaling base="BoostTarget_barabsolute"/>
|
||||
<scaling base="BoostTarget_psirelativesealevel"/>
|
||||
<table type="X Axis" name="Throttle Plate Opening Angle" storagetype="float" endian="little" logparam="E38">
|
||||
<scaling units="%" expression="x/.84" to_byte="x*.84" format="0.0" fineincrement=".3" coarseincrement="1" />
|
||||
</table>
|
||||
<table type="Y Axis" name="Engine Speed" storagetype="float" endian="little" logparam="P8">
|
||||
<scaling base="rpm"/>
|
||||
</table>
|
||||
<description>This map contains the desired boost targets. Boost compensation tables can impact the final boost target.</description>
|
||||
</table>
|
||||
<table base="Target Boost A" name="Target Boost B">
|
||||
<description>Inherited Target Boost A</description>
|
||||
</table>
|
||||
<table type="3D" name="Initial Wastegate Duty A" category="Boost Control - Wastegate" storagetype="uint16" endian="big" sizex="8" sizey="12" userlevel="1" logparam="P36">
|
||||
<scaling base="WastegateDutyCycle_%" />
|
||||
<table type="X Axis" name="Throttle Plate Opening Angle" storagetype="float" endian="little" logparam="E38">
|
||||
<scaling units="%" expression="x/.84" to_byte="x*.84" format="0.0" fineincrement=".3" coarseincrement="1" />
|
||||
</table>
|
||||
<table type="Y Axis" name="Engine Speed" storagetype="float" endian="little" logparam="P8">
|
||||
<scaling base="rpm"/>
|
||||
</table>
|
||||
<description>These are the starting values for wastegate duty. Wastegate compensation tables are applied to initial and max wastegate duty values.</description>
|
||||
</table>
|
||||
<table type="3D" name="CL Fueling Target Compensation A (ECT)" category="Fueling - Closed Loop" storagetype="uint16" endian="big" sizex="16" sizey="3" userlevel="4">
|
||||
<scaling units="Estimated Air/Fuel Ratio Points (Additive)" expression="(-x*.000224304213)+7.350001" to_byte="(x-7.350001)/-.000224304213" format="0.000" fineincrement=".01" coarseincrement=".1" />
|
||||
<table type="X Axis" name="Coolant Temperature" storagetype="float" endian="little" logparam="P2">
|
||||
<scaling category="Metric" units="Degrees C" expression="x" to_byte="x" format="#" fineincrement="1" coarseincrement="5" />
|
||||
<scaling category="Standard" units="Degrees F" expression="(x*1.8)+32" to_byte="(x-32)/1.8" format="#" fineincrement="1" coarseincrement="5" />
|
||||
</table>
|
||||
<table type="Y Axis" name="Engine Load" storagetype="float" endian="little" logparam="E32">
|
||||
<scaling units="g/rev" expression="x" to_byte="x" format="0.00" fineincrement=".01" coarseincrement=".1" />
|
||||
</table>
|
||||
<description>This is the compensation to the closed loop base fueling target based on coolant temp. Other compensations (some undefined), are also applied.</description>
|
||||
</table>
|
||||
</rom>
|
||||
<rom base="32BITBASE">
|
||||
<romid>
|
||||
<xmlid>A2WC522S</xmlid>
|
||||
<internalidaddress>2000</internalidaddress>
|
||||
<internalidstring>A2WC522S</internalidstring>
|
||||
<ecuid>2F12795606</ecuid>
|
||||
<year>05</year>
|
||||
<market>USDM</market>
|
||||
<make>Subaru</make>
|
||||
<model>Outback</model>
|
||||
<submodel>XT</submodel>
|
||||
<transmission>MT</transmission>
|
||||
<memmodel>SH7058</memmodel>
|
||||
<flashmethod>sti05</flashmethod>
|
||||
<filesize>1024kb</filesize>
|
||||
</romid>
|
||||
<table name="Target Boost A" storageaddress="0xC11D4">
|
||||
<table type="X Axis" storageaddress="0xC1184" />
|
||||
<table type="Y Axis" storageaddress="0xC11A4" />
|
||||
</table>
|
||||
<table name="Target Boost B" storageaddress="0xC12E4">
|
||||
<table type="X Axis" storageaddress="0xC1294" />
|
||||
<table type="Y Axis" storageaddress="0xC12B4" />
|
||||
</table>
|
||||
<table name="Initial Wastegate Duty A" storageaddress="0xC0BC0" sizey="11">
|
||||
<table type="X Axis" storageaddress="0xC0B74" />
|
||||
<table type="Y Axis" storageaddress="0xC0B94" />
|
||||
</table>
|
||||
</rom>
|
||||
</roms>
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.ecu.comms.learning.EcuDefinitionInheritance;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import com.romraider.logger.ecu.comms.learning.tableaxis.SSMTableAxisQueryParameterSet;
|
||||
import com.romraider.logger.ecu.comms.query.EcuQuery;
|
||||
import com.romraider.logger.ecu.definition.EcuDefinition;
|
||||
import com.romraider.logger.ecu.definition.EcuDefinitionImpl;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuDefinitionDocumentLoader;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuDefinitionInheritanceList;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuTableDefinitionHandler;
|
||||
|
||||
|
||||
public class EcuDefinitionInheritanceTest {
|
||||
|
||||
/** Test the address manipulation needed to convert the def table
|
||||
* address to the linear RAM read address.
|
||||
*/
|
||||
@Test
|
||||
public void testAddress() {
|
||||
List<String> AF_TABLE_NAMES = Arrays.asList(
|
||||
"A/F Learning #1 Airflow Ranges",
|
||||
"A/F Learning #1 Airflow Ranges ",
|
||||
"A/F Learning Airflow Ranges");
|
||||
Collection<EcuQuery> queries = new ArrayList<EcuQuery>();
|
||||
EcuDefinition ecuDef = new EcuDefinitionImpl("2F12795206", "A2WC510S",
|
||||
"05 outback xt", "A2WC510N", new File("src/test/definitions/LearningAirflowRanges.xml"));
|
||||
Document document = EcuDefinitionDocumentLoader.getDocument(ecuDef);
|
||||
queries = getTableAxisRanges(document, ecuDef, AF_TABLE_NAMES);
|
||||
assertEquals(3, queries.size());
|
||||
for (EcuQuery query : queries) {
|
||||
System.out.println(query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the table axis values from the ECU definition. First try the
|
||||
* 4-cyl table names, if still empty try the 6-cyl table name.
|
||||
*/
|
||||
private final List<EcuQuery> getTableAxisRanges(
|
||||
Document document,
|
||||
EcuDefinition ecuDef,
|
||||
List<String> tableNames) {
|
||||
|
||||
List<EcuQuery> tableAxis = new ArrayList<EcuQuery>();
|
||||
for (String tableName : tableNames) {
|
||||
tableAxis = loadTable(document, ecuDef, tableName);
|
||||
if (!tableAxis.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tableAxis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a List of EcuQueries to retrieve the axis and scaling of a table.
|
||||
* A table is found when the storageaddress parameter has been identified.
|
||||
*/
|
||||
private final List<EcuQuery> loadTable(
|
||||
Document document,
|
||||
EcuDefinition ecuDef,
|
||||
String tableName) {
|
||||
|
||||
final List<Node> inheritanceList =
|
||||
EcuDefinitionInheritanceList.getInheritanceList(document, ecuDef);
|
||||
final Map<String, String> tableMap =
|
||||
EcuTableDefinitionHandler.getTableDefinition(
|
||||
document,
|
||||
inheritanceList,
|
||||
tableName);
|
||||
List<EcuQuery> tableAxisQuery = new ArrayList<EcuQuery>();
|
||||
if (tableMap.containsKey("storageaddress")) {
|
||||
tableAxisQuery = SSMTableAxisQueryParameterSet.build(
|
||||
tableMap.get("storageaddress"),
|
||||
tableMap.get("storagetype"),
|
||||
tableMap.get("expression"),
|
||||
tableMap.get("units"),
|
||||
tableMap.get("sizey")
|
||||
);
|
||||
}
|
||||
return tableAxisQuery;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.maps.checksum;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.romraider.util.HexUtil;
|
||||
|
||||
public class NcsCoDecTest {
|
||||
final NcsCoDec codec = new NcsCoDec();
|
||||
final String text = "FFFF22E4000115F8000116A000011724000117C80002B9C4E00180F884F820088B1B62F0E7EC9625D91426209623656062637205645C60430274901D7501655C029C760560530624D20D420B75019013D60C029C9011A0040624E4AC644CB18BE5127F204F266EF66DF66CF66BF66AF6000B69F697B481050848035EFFFF22E4";
|
||||
final byte[] bin = HexUtil.asBytes(text);
|
||||
final int scode = 0xC2C0823F;
|
||||
final ByteBuffer data = ByteBuffer.allocate(bin.length).order(ByteOrder.BIG_ENDIAN).put(bin);
|
||||
final String encoded = "118283C9B4953B9B63A23EE3EE224177089344AB4C466E96F606B2997EDEE9129E7B377498905B95D0C75576E88B5EBCBB0065BB03DFCB5279839C252FADBD8A8C1119449FBD8C25107BC5FB5961EB1E7FA50CC2A0BF7DC5B2414339FD0B213B321AAC721891B7AB6F0A837B0D088F7B185ADF86263BC56DBAB2D6D0118283C9";
|
||||
|
||||
@Test
|
||||
public final void testEncodeData() {
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
assertEquals(encoded, HexUtil.asHex(dataEncoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testEncodedDataCrc() {
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
assertEquals((short) 0xD10D, (short) codec.calcCrc(dataEncoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testBitwiseComplementCrc() {
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
assertEquals((short) 0x2EF2, (short) ~codec.calcCrc(dataEncoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testBitwiseComplementCrcLitteEndian() {
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
short bcCrc = (short) ~codec.calcCrc(dataEncoded);
|
||||
short le = (short) (((bcCrc << 8) | ((bcCrc & 0xffff) >>> 8)) & 0xffff);
|
||||
assertEquals((short) 0xF22E, le);
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testResidue() {
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
short bcCrc = (short) ~codec.calcCrc(dataEncoded);
|
||||
final byte[] crcCheck = new byte[dataEncoded.length + 2];
|
||||
System.arraycopy(dataEncoded, 0, crcCheck, 0, dataEncoded.length);
|
||||
crcCheck[crcCheck.length - 2] = (byte) (bcCrc & 0xff);
|
||||
crcCheck[crcCheck.length - 1] = (byte) ((bcCrc & 0xffff) >>> 8);
|
||||
assertEquals((short) 0xF0B8, (short) codec.calcCrc(crcCheck));
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testDecodeData() {
|
||||
final byte[] dataEncoded = codec.nisEncode(data, scode);
|
||||
final ByteBuffer bb = ByteBuffer.allocate(dataEncoded.length)
|
||||
.order(ByteOrder.BIG_ENDIAN).put(dataEncoded);
|
||||
final byte[] data = codec.nisDecode(bb, scode);
|
||||
assertEquals(text, HexUtil.asHex(data));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* RomRaider Open-Source Tuning, Logging and Reflashing
|
||||
* Copyright (C) 2006-2021 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.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import com.romraider.logger.ecu.definition.EcuDefinition;
|
||||
import com.romraider.logger.ecu.definition.EcuDefinitionImpl;
|
||||
import com.romraider.logger.ecu.definition.xml.EcuDefinitionDocumentLoader;
|
||||
import com.romraider.maps.Scale;
|
||||
|
||||
|
||||
public class TableScaleUnmarshallerTest {
|
||||
private final Document document = getDocument();
|
||||
private final TableScaleUnmarshaller tableScaleHandler = new TableScaleUnmarshaller();
|
||||
|
||||
/** Test creation of scales from XML definition file scalingbase.
|
||||
*/
|
||||
@Test
|
||||
public void testScalingBase() {
|
||||
final List<Scale> expectedScales = buildExpectedScales();
|
||||
tableScaleHandler.unmarshallBaseScales(document.getDocumentElement());
|
||||
final List<Scale> scales = tableScaleHandler.getScales();
|
||||
for (final Scale scale : scales) {
|
||||
System.out.println(scale);
|
||||
}
|
||||
assertEquals(expectedScales.size(), scales.size());
|
||||
for (Scale expectedScale : expectedScales) {
|
||||
assertEquals(true, scales.contains(expectedScale));
|
||||
}
|
||||
}
|
||||
|
||||
private Document getDocument() {
|
||||
final EcuDefinition ecuDef = new EcuDefinitionImpl("2F12795606", "A2WC522S",
|
||||
"05 Outback XT", "32BITBASE", new File("src/test/definitions/scalingbase_test.xml"));
|
||||
final Document document = EcuDefinitionDocumentLoader.getDocument(ecuDef);
|
||||
return document;
|
||||
}
|
||||
|
||||
private List<Scale> buildExpectedScales() {
|
||||
final List<Scale> expectedScales = new ArrayList<Scale>();
|
||||
|
||||
final Scale BoostTarget_barabsolute = new Scale();
|
||||
BoostTarget_barabsolute.setCategory("Metric");
|
||||
BoostTarget_barabsolute.setName("BoostTarget_barabsolute");
|
||||
BoostTarget_barabsolute.setExpression("x*.001333224");
|
||||
BoostTarget_barabsolute.setByteExpression("x/.001333224");
|
||||
BoostTarget_barabsolute.setUnit("Boost Target (bar absolute)");
|
||||
BoostTarget_barabsolute.setFormat("#0.000");
|
||||
BoostTarget_barabsolute.setCoarseIncrement(0.1);
|
||||
BoostTarget_barabsolute.setFineIncrement(0.01);
|
||||
expectedScales.add(BoostTarget_barabsolute);
|
||||
|
||||
final Scale BoostTarget_psirelativesealevel = new Scale();
|
||||
BoostTarget_psirelativesealevel.setCategory("Standard");
|
||||
BoostTarget_psirelativesealevel.setName("BoostTarget_psirelativesealevel");
|
||||
BoostTarget_psirelativesealevel.setExpression("(x-760)*.01933677");
|
||||
BoostTarget_psirelativesealevel.setByteExpression("(x/.01933677)+760");
|
||||
BoostTarget_psirelativesealevel.setUnit("Boost Target (psi relative sea level)");
|
||||
BoostTarget_psirelativesealevel.setFormat("0.00");
|
||||
BoostTarget_psirelativesealevel.setCoarseIncrement(0.5);
|
||||
BoostTarget_psirelativesealevel.setFineIncrement(0.01);
|
||||
expectedScales.add(BoostTarget_psirelativesealevel);
|
||||
|
||||
final Scale rpm = new Scale();
|
||||
rpm.setCategory("Default");
|
||||
rpm.setName("rpm");
|
||||
rpm.setExpression("x");
|
||||
rpm.setByteExpression("x");
|
||||
rpm.setUnit("RPM");
|
||||
rpm.setFormat("#");
|
||||
rpm.setCoarseIncrement(100.0);
|
||||
rpm.setFineIncrement(50.0);
|
||||
expectedScales.add(rpm);
|
||||
|
||||
final Scale targetboostcomppercent = new Scale();
|
||||
targetboostcomppercent.setCategory("Default");
|
||||
targetboostcomppercent.setName("targetboostcomppercent");
|
||||
targetboostcomppercent.setExpression("(x*.78125)-100");
|
||||
targetboostcomppercent.setByteExpression("(x+100)/.78125");
|
||||
targetboostcomppercent.setUnit("raw value");
|
||||
targetboostcomppercent.setFormat("0.0");
|
||||
targetboostcomppercent.setCoarseIncrement(1.0);
|
||||
targetboostcomppercent.setFineIncrement(0.4);
|
||||
expectedScales.add(targetboostcomppercent);
|
||||
|
||||
final Scale WastegateDutyCycle_ = new Scale();
|
||||
WastegateDutyCycle_.setCategory("Default");
|
||||
WastegateDutyCycle_.setName("WastegateDutyCycle_%");
|
||||
WastegateDutyCycle_.setExpression("x*.00390625");
|
||||
WastegateDutyCycle_.setByteExpression("x/.00390625");
|
||||
WastegateDutyCycle_.setUnit("Wastegate Duty Cycle (%)");
|
||||
WastegateDutyCycle_.setFormat("0.0");
|
||||
WastegateDutyCycle_.setCoarseIncrement(1.0);
|
||||
WastegateDutyCycle_.setFineIncrement(0.2);
|
||||
WastegateDutyCycle_.setMin(0.1);
|
||||
WastegateDutyCycle_.setMax(99.9);
|
||||
expectedScales.add(WastegateDutyCycle_);
|
||||
|
||||
return expectedScales;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue