mirror of https://github.com/rusefi/rusefi-1.git
live data for wastegate and launch control #3588
This commit is contained in:
parent
fcf53fa710
commit
bc2b6b71a8
|
@ -0,0 +1,294 @@
|
||||||
|
/*
|
||||||
|
* @(#)LittleEndianOutputStream.java 1.0.1 99/05/19
|
||||||
|
*
|
||||||
|
* Copyright 1998, 1999 Elliotte Rusty Harold
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.macfaq.io;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A little endian output stream writes primitive Java numbers
|
||||||
|
* and characters to an output stream in a little endian format.
|
||||||
|
* The standard java.io.DataOutputStream class which this class
|
||||||
|
* imitates uses big-endian integers.
|
||||||
|
*
|
||||||
|
* @author Elliotte Rusty Harold
|
||||||
|
* @version 1.0.1, 19 May 1999
|
||||||
|
* @see com.macfaq.io.LittleEndianInputStream
|
||||||
|
* @see java.io.DataOutputStream
|
||||||
|
*/
|
||||||
|
public class LittleEndianOutputStream extends FilterOutputStream {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of bytes written so far to the little endian output stream.
|
||||||
|
*/
|
||||||
|
protected int written;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new little endian output stream and chains it to the
|
||||||
|
* output stream specified by the out argument.
|
||||||
|
*
|
||||||
|
* @param out the underlying output stream.
|
||||||
|
* @see java.io.FilterOutputStream#out
|
||||||
|
*/
|
||||||
|
public LittleEndianOutputStream(OutputStream out) {
|
||||||
|
super(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the specified byte value to the underlying output stream.
|
||||||
|
*
|
||||||
|
* @param b the <code>byte</code> value to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public synchronized void write(int b) throws IOException {
|
||||||
|
out.write(b);
|
||||||
|
written++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes <code>length</code> bytes from the specified byte array
|
||||||
|
* starting at <code>offset</code> to the underlying output stream.
|
||||||
|
*
|
||||||
|
* @param data the data.
|
||||||
|
* @param offset the start offset in the data.
|
||||||
|
* @param length the number of bytes to write.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public synchronized void write(byte[] data, int offset, int length)
|
||||||
|
throws IOException {
|
||||||
|
out.write(data, offset, length);
|
||||||
|
written += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a <code>boolean</code> to the underlying output stream as
|
||||||
|
* a single byte. If the argument is true, the byte value 1 is written.
|
||||||
|
* If the argument is false, the byte value <code>0</code> in written.
|
||||||
|
*
|
||||||
|
* @param b the <code>boolean</code> value to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeBoolean(boolean b) throws IOException {
|
||||||
|
|
||||||
|
if (b) this.write(1);
|
||||||
|
else this.write(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes out a <code>byte</code> to the underlying output stream
|
||||||
|
*
|
||||||
|
* @param b the <code>byte</code> value to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeByte(int b) throws IOException {
|
||||||
|
out.write(b);
|
||||||
|
written++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a two byte <code>short</code> to the underlying output stream in
|
||||||
|
* little endian order, low byte first.
|
||||||
|
*
|
||||||
|
* @param s the <code>short</code> to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeShort(int s) throws IOException {
|
||||||
|
|
||||||
|
out.write(s & 0xFF);
|
||||||
|
out.write((s >>> 8) & 0xFF);
|
||||||
|
written += 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a two byte <code>char</code> to the underlying output stream
|
||||||
|
* in little endian order, low byte first.
|
||||||
|
*
|
||||||
|
* @param c the <code>char</code> value to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeChar(int c) throws IOException {
|
||||||
|
|
||||||
|
out.write(c & 0xFF);
|
||||||
|
out.write((c >>> 8) & 0xFF);
|
||||||
|
written += 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a four-byte <code>int</code> to the underlying output stream
|
||||||
|
* in little endian order, low byte first, high byte last
|
||||||
|
*
|
||||||
|
* @param i the <code>int</code> to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeInt(int i) throws IOException {
|
||||||
|
|
||||||
|
out.write(i & 0xFF);
|
||||||
|
out.write((i >>> 8) & 0xFF);
|
||||||
|
out.write((i >>> 16) & 0xFF);
|
||||||
|
out.write((i >>> 24) & 0xFF);
|
||||||
|
written += 4;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an eight-byte <code>long</code> to the underlying output stream
|
||||||
|
* in little endian order, low byte first, high byte last
|
||||||
|
*
|
||||||
|
* @param l the <code>long</code> to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeLong(long l) throws IOException {
|
||||||
|
|
||||||
|
out.write((int) l & 0xFF);
|
||||||
|
out.write((int) (l >>> 8) & 0xFF);
|
||||||
|
out.write((int) (l >>> 16) & 0xFF);
|
||||||
|
out.write((int) (l >>> 24) & 0xFF);
|
||||||
|
out.write((int) (l >>> 32) & 0xFF);
|
||||||
|
out.write((int) (l >>> 40) & 0xFF);
|
||||||
|
out.write((int) (l >>> 48) & 0xFF);
|
||||||
|
out.write((int) (l >>> 56) & 0xFF);
|
||||||
|
written += 8;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a 4 byte Java float to the underlying output stream in
|
||||||
|
* little endian order.
|
||||||
|
*
|
||||||
|
* @param f the <code>float</code> value to be written.
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public final void writeFloat(float f) throws IOException {
|
||||||
|
|
||||||
|
this.writeInt(Float.floatToIntBits(f));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an 8 byte Java double to the underlying output stream in
|
||||||
|
* little endian order.
|
||||||
|
*
|
||||||
|
* @param d the <code>double</code> value to be written.
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public final void writeDouble(double d) throws IOException {
|
||||||
|
|
||||||
|
this.writeLong(Double.doubleToLongBits(d));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string to the underlying output stream as a sequence of
|
||||||
|
* bytes. Each character is written to the data output stream as
|
||||||
|
* if by the <code>writeByte()</code> method.
|
||||||
|
*
|
||||||
|
* @param s the <code>String</code> value to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
* @see java.io.LittleEndianOutputStream#writeByte(int)
|
||||||
|
* @see java.io.LittleEndianOutputStream#out
|
||||||
|
*/
|
||||||
|
public void writeBytes(String s) throws IOException {
|
||||||
|
|
||||||
|
int length = s.length();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
out.write((byte) s.charAt(i));
|
||||||
|
}
|
||||||
|
written += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string to the underlying output stream as a sequence of
|
||||||
|
* characters. Each character is written to the data output stream as
|
||||||
|
* if by the <code>writeChar</code> method.
|
||||||
|
*
|
||||||
|
* @param s a <code>String</code> value to be written.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
* @see java.io.LittleEndianOutputStream#writeChar(int)
|
||||||
|
* @see java.io.LittleEndianOutputStream#out
|
||||||
|
*/
|
||||||
|
public void writeChars(String s) throws IOException {
|
||||||
|
|
||||||
|
int length = s.length();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
int c = s.charAt(i);
|
||||||
|
out.write(c & 0xFF);
|
||||||
|
out.write((c >>> 8) & 0xFF);
|
||||||
|
}
|
||||||
|
written += length * 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string of no more than 65,535 characters
|
||||||
|
* to the underlying output stream using UTF-8
|
||||||
|
* encoding. This method first writes a two byte short
|
||||||
|
* in <b>big</b> endian order as required by the
|
||||||
|
* UTF-8 specification. This gives the number of bytes in the
|
||||||
|
* UTF-8 encoded version of the string, not the number of characters
|
||||||
|
* in the string. Next each character of the string is written
|
||||||
|
* using the UTF-8 encoding for the character.
|
||||||
|
*
|
||||||
|
* @param s the string to be written.
|
||||||
|
* @exception UTFDataFormatException if the string is longer than
|
||||||
|
* 65,535 characters.
|
||||||
|
* @exception IOException if the underlying stream throws an IOException.
|
||||||
|
*/
|
||||||
|
public void writeUTF(String s) throws IOException {
|
||||||
|
|
||||||
|
int numchars = s.length();
|
||||||
|
int numbytes = 0;
|
||||||
|
|
||||||
|
for (int i = 0 ; i < numchars ; i++) {
|
||||||
|
int c = s.charAt(i);
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) numbytes++;
|
||||||
|
else if (c > 0x07FF) numbytes += 3;
|
||||||
|
else numbytes += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numbytes > 65535) throw new UTFDataFormatException();
|
||||||
|
|
||||||
|
out.write((numbytes >>> 8) & 0xFF);
|
||||||
|
out.write(numbytes & 0xFF);
|
||||||
|
for (int i = 0 ; i < numchars ; i++) {
|
||||||
|
int c = s.charAt(i);
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
out.write(c);
|
||||||
|
}
|
||||||
|
else if (c > 0x07FF) {
|
||||||
|
out.write(0xE0 | ((c >> 12) & 0x0F));
|
||||||
|
out.write(0x80 | ((c >> 6) & 0x3F));
|
||||||
|
out.write(0x80 | (c & 0x3F));
|
||||||
|
written += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.write(0xC0 | ((c >> 6) & 0x1F));
|
||||||
|
out.write(0x80 | (c & 0x3F));
|
||||||
|
written += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
written += numchars + 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes written to this little endian output stream.
|
||||||
|
* (This class is not thread-safe with respect to this method. It is
|
||||||
|
* possible that this number is temporarily less than the actual
|
||||||
|
* number of bytes written.)
|
||||||
|
* @return the value of the <code>written</code> field.
|
||||||
|
* @see java.io.LittleEndianOutputStream#written
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return this.written;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,13 @@
|
||||||
package com.rusefi.config;
|
package com.rusefi.config;
|
||||||
|
|
||||||
|
import com.macfaq.io.LittleEndianOutputStream;
|
||||||
import com.opensr5.ConfigurationImage;
|
import com.opensr5.ConfigurationImage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static com.rusefi.config.FieldType.*;
|
import static com.rusefi.config.FieldType.*;
|
||||||
|
@ -154,6 +158,29 @@ public class Field {
|
||||||
return options[ordinal];
|
return options[ordinal];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setValue(byte[] content, boolean value) {
|
||||||
|
ByteBuffer wrapped = ByteBuffer.wrap(content, 0, content.length);
|
||||||
|
wrapped.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
if (bitOffset != NO_BIT_OFFSET) {
|
||||||
|
int packed = wrapped.getInt();
|
||||||
|
int thisBit = (value ? 1 : 0) << bitOffset;
|
||||||
|
int mask = 1 << bitOffset;
|
||||||
|
int newValue = (packed & ~mask) | thisBit;
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
LittleEndianOutputStream dout = new LittleEndianOutputStream(baos);
|
||||||
|
// wow worst way to modify an integer in byte array? :)
|
||||||
|
try {
|
||||||
|
dout.writeInt(newValue);
|
||||||
|
// dout.flush();
|
||||||
|
byte[] src = baos.toByteArray();
|
||||||
|
System.arraycopy(src, 0, content, getOffset(), 4);
|
||||||
|
baos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* each usage is a potential bug?! we are supposed to have explicit multiplier for each field
|
* each usage is a potential bug?! we are supposed to have explicit multiplier for each field
|
||||||
*/
|
*/
|
||||||
|
@ -196,8 +223,7 @@ public class Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Field create(String name, int offset, FieldType type, int bitOffset) {
|
public static Field create(String name, int offset, FieldType type, int bitOffset) {
|
||||||
Field field = new Field(name, offset, type, bitOffset);
|
return new Field(name, offset, type, bitOffset);
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Field create(String name, int offset, FieldType type, String... options) {
|
public static Field create(String name, int offset, FieldType type, String... options) {
|
||||||
|
@ -210,8 +236,7 @@ public class Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Field create(String name, int offset, FieldType type) {
|
public static Field create(String name, int offset, FieldType type) {
|
||||||
Field field = new Field(name, offset, type);
|
return new Field(name, offset, type);
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStringValue(ConfigurationImage image) {
|
public String getStringValue(ConfigurationImage image) {
|
||||||
|
@ -223,4 +248,8 @@ public class Field {
|
||||||
bb.get(bytes);
|
bb.get(bytes);
|
||||||
return new String(bytes).trim();
|
return new String(bytes).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getBooleanValue(ConfigurationImage ci) {
|
||||||
|
return getValue(ci) != 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
package com.rusefi.config.test;
|
package com.rusefi.config.test;
|
||||||
|
|
||||||
|
import com.opensr5.ConfigurationImage;
|
||||||
import com.rusefi.config.Field;
|
import com.rusefi.config.Field;
|
||||||
import com.rusefi.config.FieldCommandResponse;
|
import com.rusefi.config.FieldCommandResponse;
|
||||||
|
import com.rusefi.config.generated.Fields;
|
||||||
import com.rusefi.core.Pair;
|
import com.rusefi.core.Pair;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
public class FieldTest {
|
public class FieldTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -30,17 +30,39 @@ public class FieldTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrecisionDependingOnScale() {
|
public void setBooleanValue() {
|
||||||
assertEquals("0.12302", Field.niceToString(0.12302, 4));
|
byte[] config = new byte[Fields.persistent_config_s_size];
|
||||||
assertEquals("0.1232", Field.niceToString(0.12317, 3));
|
ConfigurationImage ci = new ConfigurationImage(config);
|
||||||
|
|
||||||
assertEquals("1234567.1", Field.niceToString(1234567.123, 4));
|
assertFalse(Fields.ISFORCEDINDUCTION.getBooleanValue(ci));
|
||||||
assertEquals("10000.0", Field.niceToString(10000.00002, 4));
|
assertFalse(Fields.OVERRIDETRIGGERGAPS.getBooleanValue(ci));
|
||||||
assertEquals("0.002", Field.niceToString(0.002, 4));
|
assertFalse(Fields.ENABLEFAN1WITHAC.getBooleanValue(ci));
|
||||||
assertEquals("12.302", Field.niceToString(12.302, 4));
|
|
||||||
assertEquals("12.302", Field.niceToString(12.302, 3));
|
Fields.OVERRIDETRIGGERGAPS.setValue(config, true);
|
||||||
assertEquals("12.31", Field.niceToString(12.312, 2));
|
|
||||||
assertEquals("123.02", Field.niceToString(123.02, 4));
|
assertFalse(Fields.ISFORCEDINDUCTION.getBooleanValue(ci));
|
||||||
|
assertTrue(Fields.OVERRIDETRIGGERGAPS.getBooleanValue(ci));
|
||||||
|
assertFalse(Fields.ENABLEFAN1WITHAC.getBooleanValue(ci));
|
||||||
|
|
||||||
|
Fields.OVERRIDETRIGGERGAPS.setValue(config, false);
|
||||||
|
|
||||||
|
assertFalse(Fields.ISFORCEDINDUCTION.getBooleanValue(ci));
|
||||||
|
assertFalse(Fields.OVERRIDETRIGGERGAPS.getBooleanValue(ci));
|
||||||
|
assertFalse(Fields.ENABLEFAN1WITHAC.getBooleanValue(ci));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrecisionDependingOnScale() {
|
||||||
|
assertEquals("0.12302", Field.niceToString(0.12302, 4));
|
||||||
|
assertEquals("0.1232", Field.niceToString(0.12317, 3));
|
||||||
|
|
||||||
|
assertEquals("1234567.1", Field.niceToString(1234567.123, 4));
|
||||||
|
assertEquals("10000.0", Field.niceToString(10000.00002, 4));
|
||||||
|
assertEquals("0.002", Field.niceToString(0.002, 4));
|
||||||
|
assertEquals("12.302", Field.niceToString(12.302, 4));
|
||||||
|
assertEquals("12.302", Field.niceToString(12.302, 3));
|
||||||
|
assertEquals("12.31", Field.niceToString(12.312, 2));
|
||||||
|
assertEquals("123.02", Field.niceToString(123.02, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue