Lua script editor in console (#2699)
* stub * implement reset * console * just use the console command * cleanup * s * s * ui * write in chunks * fix write * tab size, script read * parse script properly * put lua script in flash, tiny for now * generated fields
This commit is contained in:
parent
c7f3c17c75
commit
b373c03db8
|
@ -1072,6 +1072,8 @@ static void setDefaultEngineConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||||
// set_fsio_expression 1 "rpm > fsio_setting(1)"
|
// set_fsio_expression 1 "rpm > fsio_setting(1)"
|
||||||
setFsio(0, GPIO_UNASSIGNED, RPM_ABOVE_USER_SETTING_1 PASS_CONFIG_PARAMETER_SUFFIX);
|
setFsio(0, GPIO_UNASSIGNED, RPM_ABOVE_USER_SETTING_1 PASS_CONFIG_PARAMETER_SUFFIX);
|
||||||
#endif /* EFI_FSIO */
|
#endif /* EFI_FSIO */
|
||||||
|
|
||||||
|
strncpy(config->luaScript, "function onTick()\nend", efi::size(config->luaScript));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -81,6 +81,8 @@ typedef float percent_t;
|
||||||
|
|
||||||
typedef void (*Void)(void);
|
typedef void (*Void)(void);
|
||||||
|
|
||||||
|
typedef char lua_script_t[LUA_SCRIPT_SIZE];
|
||||||
|
|
||||||
typedef char error_message_t[ERROR_BUFFER_SIZE];
|
typedef char error_message_t[ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
typedef char vehicle_info_t[VEHICLE_INFO_SIZE];
|
typedef char vehicle_info_t[VEHICLE_INFO_SIZE];
|
||||||
|
|
|
@ -234,9 +234,7 @@ static bool runOneLua() {
|
||||||
// Reset default tick rate
|
// Reset default tick rate
|
||||||
luaTickPeriodMs = 100;
|
luaTickPeriodMs = 100;
|
||||||
|
|
||||||
auto scriptStr = "function onTick() end";
|
if (!loadScript(ls, config->luaScript)) {
|
||||||
|
|
||||||
if (!loadScript(ls, scriptStr)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1592,8 +1592,9 @@ fsio_table_8x8_u8t vvtTable2;
|
||||||
float[FSIO_TABLE_8] vvtTable2LoadBins;;"L", 1, 0, 0.0, 255, 0
|
float[FSIO_TABLE_8] vvtTable2LoadBins;;"L", 1, 0, 0.0, 255, 0
|
||||||
float[FSIO_TABLE_8] vvtTable2RpmBins;RPM is float and not integer in order to use unified methods for interpolation;"RPM", 1, 0, 0.0, 25500.0, 2
|
float[FSIO_TABLE_8] vvtTable2RpmBins;RPM is float and not integer in order to use unified methods for interpolation;"RPM", 1, 0, 0.0, 25500.0, 2
|
||||||
|
|
||||||
|
#define LUA_SCRIPT_SIZE 256
|
||||||
uint8_t[256] unused15136;;"units", 1, 0, -20, 100, 0
|
custom lua_script_t @@LUA_SCRIPT_SIZE@@ string, ASCII, @OFFSET@, @@LUA_SCRIPT_SIZE@@
|
||||||
|
lua_script_t luaScript;
|
||||||
|
|
||||||
ignition_table_t ignitionTable;
|
ignition_table_t ignitionTable;
|
||||||
float[IGN_LOAD_COUNT] ignitionLoadBins;;"Load", 1, 0.0, 0, 500.0, 2
|
float[IGN_LOAD_COUNT] ignitionLoadBins;;"Load", 1, 0.0, 0, 500.0, 2
|
||||||
|
|
|
@ -324,7 +324,7 @@ public class BinaryProtocol {
|
||||||
byte[] newBytes = newVersion.getRange(range.first, size);
|
byte[] newBytes = newVersion.getRange(range.first, size);
|
||||||
log.info("new " + Arrays.toString(newBytes));
|
log.info("new " + Arrays.toString(newBytes));
|
||||||
|
|
||||||
writeData(newVersion.getContent(), range.first, size);
|
writeData(newVersion.getContent(), 0, range.first, size);
|
||||||
|
|
||||||
offset = range.second;
|
offset = range.second;
|
||||||
}
|
}
|
||||||
|
@ -489,15 +489,15 @@ public class BinaryProtocol {
|
||||||
Runtime.getRuntime().removeShutdownHook(hook);
|
Runtime.getRuntime().removeShutdownHook(hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeData(byte[] content, Integer offset, int size) {
|
public void writeData(byte[] content, int contentOffset, int ecuOffset, int size) {
|
||||||
isBurnPending = true;
|
isBurnPending = true;
|
||||||
|
|
||||||
byte packet[] = new byte[5 + size];
|
byte packet[] = new byte[5 + size];
|
||||||
packet[0] = Fields.TS_CHUNK_WRITE_COMMAND;
|
packet[0] = Fields.TS_CHUNK_WRITE_COMMAND;
|
||||||
putShort(packet, 1, swap16(offset));
|
putShort(packet, 1, swap16(ecuOffset));
|
||||||
putShort(packet, 3, swap16(size));
|
putShort(packet, 3, swap16(size));
|
||||||
|
|
||||||
System.arraycopy(content, offset, packet, 7, size);
|
System.arraycopy(content, contentOffset, packet, 5, size);
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
while (!isClosed && (System.currentTimeMillis() - start < Timeouts.BINARY_IO_TIMEOUT)) {
|
while (!isClosed && (System.currentTimeMillis() - start < Timeouts.BINARY_IO_TIMEOUT)) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.rusefi.config.generated;
|
package com.rusefi.config.generated;
|
||||||
|
|
||||||
// this file was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon May 17 09:41:25 UTC 2021
|
// this file was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon May 17 14:39:09 PDT 2021
|
||||||
|
|
||||||
// by class com.rusefi.output.FileJavaFieldsConsumer
|
// by class com.rusefi.output.FileJavaFieldsConsumer
|
||||||
import com.rusefi.config.*;
|
import com.rusefi.config.*;
|
||||||
|
@ -1036,6 +1036,8 @@ public class Fields {
|
||||||
public static final int lowPressureFuel_value2_offset = 3324;
|
public static final int lowPressureFuel_value2_offset = 3324;
|
||||||
public static final int lps25BaroSensorScl_offset = 1458;
|
public static final int lps25BaroSensorScl_offset = 1458;
|
||||||
public static final int lps25BaroSensorSda_offset = 1459;
|
public static final int lps25BaroSensorSda_offset = 1459;
|
||||||
|
public static final int LUA_SCRIPT_SIZE = 256;
|
||||||
|
public static final int luaScript_offset = 16032;
|
||||||
public static final int MAF_DECODING_COUNT = 256;
|
public static final int MAF_DECODING_COUNT = 256;
|
||||||
public static final int mafAdcChannel_offset = 543;
|
public static final int mafAdcChannel_offset = 543;
|
||||||
public static final int mafDecoding_offset = 10784;
|
public static final int mafDecoding_offset = 10784;
|
||||||
|
@ -1210,7 +1212,7 @@ public class Fields {
|
||||||
public static final int servoOutputPins8_offset = 3147;
|
public static final int servoOutputPins8_offset = 3147;
|
||||||
public static final int showHumanReadableWarning_offset = 976;
|
public static final int showHumanReadableWarning_offset = 976;
|
||||||
public static final int showSdCardWarning_offset = 76;
|
public static final int showSdCardWarning_offset = 76;
|
||||||
public static final int SIGNATURE_HASH = 1539247760;
|
public static final int SIGNATURE_HASH = 1304382715;
|
||||||
public static final int silentTriggerError_offset = 1464;
|
public static final int silentTriggerError_offset = 1464;
|
||||||
public static final int slowAdcAlpha_offset = 2088;
|
public static final int slowAdcAlpha_offset = 2088;
|
||||||
public static final int sparkDwellRpmBins_offset = 332;
|
public static final int sparkDwellRpmBins_offset = 332;
|
||||||
|
@ -1494,7 +1496,7 @@ public class Fields {
|
||||||
public static final char TS_SD_R_COMMAND = 'r';
|
public static final char TS_SD_R_COMMAND = 'r';
|
||||||
public static final char TS_SD_W_COMMAND = 'w';
|
public static final char TS_SD_W_COMMAND = 'w';
|
||||||
public static final char TS_SET_LOGGER_SWITCH = 'l';
|
public static final char TS_SET_LOGGER_SWITCH = 'l';
|
||||||
public static final String TS_SIGNATURE = "rusEFI 2021.05.17.all.1539247760";
|
public static final String TS_SIGNATURE = "rusEFI 2021.05.17.all.1304382715";
|
||||||
public static final char TS_SINGLE_WRITE_COMMAND = 'W';
|
public static final char TS_SINGLE_WRITE_COMMAND = 'W';
|
||||||
public static final int TT_TT_1_16 = 50;
|
public static final int TT_TT_1_16 = 50;
|
||||||
public static final int TT_TT_2JZ_1_12 = 29;
|
public static final int TT_TT_2JZ_1_12 = 29;
|
||||||
|
@ -1556,7 +1558,6 @@ public class Fields {
|
||||||
public static final int unused1476b20_offset = 1476;
|
public static final int unused1476b20_offset = 1476;
|
||||||
public static final int unused1476b3_offset = 1476;
|
public static final int unused1476b3_offset = 1476;
|
||||||
public static final int unused1476b8_offset = 1476;
|
public static final int unused1476b8_offset = 1476;
|
||||||
public static final int unused15136_offset = 16032;
|
|
||||||
public static final int unused1708_offset = 1708;
|
public static final int unused1708_offset = 1708;
|
||||||
public static final int unused1756_offset = 1756;
|
public static final int unused1756_offset = 1756;
|
||||||
public static final int unused2260_offset = 2260;
|
public static final int unused2260_offset = 2260;
|
||||||
|
@ -2781,6 +2782,7 @@ public class Fields {
|
||||||
public static final Field MAPESTIMATETABLE = Field.create("MAPESTIMATETABLE", 15200, FieldType.INT);
|
public static final Field MAPESTIMATETABLE = Field.create("MAPESTIMATETABLE", 15200, FieldType.INT);
|
||||||
public static final Field VVTTABLE1 = Field.create("VVTTABLE1", 15776, FieldType.INT);
|
public static final Field VVTTABLE1 = Field.create("VVTTABLE1", 15776, FieldType.INT);
|
||||||
public static final Field VVTTABLE2 = Field.create("VVTTABLE2", 15904, FieldType.INT);
|
public static final Field VVTTABLE2 = Field.create("VVTTABLE2", 15904, FieldType.INT);
|
||||||
|
public static final Field LUASCRIPT = Field.create("LUASCRIPT", 16032, 256, FieldType.STRING);
|
||||||
public static final Field IGNITIONTABLE = Field.create("IGNITIONTABLE", 16288, FieldType.INT);
|
public static final Field IGNITIONTABLE = Field.create("IGNITIONTABLE", 16288, FieldType.INT);
|
||||||
public static final Field VETABLE = Field.create("VETABLE", 17440, FieldType.INT);
|
public static final Field VETABLE = Field.create("VETABLE", 17440, FieldType.INT);
|
||||||
public static final Field LAMBDATABLE = Field.create("LAMBDATABLE", 18592, FieldType.INT);
|
public static final Field LAMBDATABLE = Field.create("LAMBDATABLE", 18592, FieldType.INT);
|
||||||
|
@ -3844,6 +3846,7 @@ public class Fields {
|
||||||
MAPESTIMATETABLE,
|
MAPESTIMATETABLE,
|
||||||
VVTTABLE1,
|
VVTTABLE1,
|
||||||
VVTTABLE2,
|
VVTTABLE2,
|
||||||
|
LUASCRIPT,
|
||||||
IGNITIONTABLE,
|
IGNITIONTABLE,
|
||||||
VETABLE,
|
VETABLE,
|
||||||
LAMBDATABLE,
|
LAMBDATABLE,
|
||||||
|
|
|
@ -17,6 +17,7 @@ import com.rusefi.ui.console.MainFrame;
|
||||||
import com.rusefi.ui.console.TabbedPanel;
|
import com.rusefi.ui.console.TabbedPanel;
|
||||||
import com.rusefi.ui.engine.EngineSnifferPanel;
|
import com.rusefi.ui.engine.EngineSnifferPanel;
|
||||||
import com.rusefi.ui.logview.LogViewer;
|
import com.rusefi.ui.logview.LogViewer;
|
||||||
|
import com.rusefi.ui.lua.LuaScriptPanel;
|
||||||
import com.rusefi.ui.util.DefaultExceptionHandler;
|
import com.rusefi.ui.util.DefaultExceptionHandler;
|
||||||
import com.rusefi.ui.util.JustOneInstance;
|
import com.rusefi.ui.util.JustOneInstance;
|
||||||
|
|
||||||
|
@ -108,6 +109,11 @@ public class ConsoleUI {
|
||||||
tabbedPane.addTab("Presets", new PresetsPane(uiContext).getContent());
|
tabbedPane.addTab("Presets", new PresetsPane(uiContext).getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!linkManager.isLogViewer()) {
|
||||||
|
LuaScriptPanel luaScriptPanel = new LuaScriptPanel(uiContext, getConfig().getRoot().getChild("lua"));
|
||||||
|
tabbedPaneAdd("Lua Scripting", luaScriptPanel.getPanel(), luaScriptPanel.getTabSelectedListener());
|
||||||
|
}
|
||||||
|
|
||||||
tabbedPaneAdd("Engine Sniffer", engineSnifferPanel.getPanel(), engineSnifferPanel.getTabSelectedListener());
|
tabbedPaneAdd("Engine Sniffer", engineSnifferPanel.getPanel(), engineSnifferPanel.getTabSelectedListener());
|
||||||
|
|
||||||
if (!linkManager.isLogViewer()) {
|
if (!linkManager.isLogViewer()) {
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package com.rusefi.ui.lua;
|
||||||
|
|
||||||
|
import com.opensr5.ConfigurationImage;
|
||||||
|
import com.rusefi.FixedCommandControl;
|
||||||
|
import com.rusefi.binaryprotocol.BinaryProtocol;
|
||||||
|
import com.rusefi.config.generated.Fields;
|
||||||
|
import com.rusefi.ui.MessagesPanel;
|
||||||
|
import com.rusefi.ui.UIContext;
|
||||||
|
import com.rusefi.ui.storage.Node;
|
||||||
|
import com.rusefi.ui.widgets.AnyCommand;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class LuaScriptPanel {
|
||||||
|
private final UIContext context;
|
||||||
|
private final JPanel mainPanel = new JPanel(new BorderLayout());
|
||||||
|
private final AnyCommand command;
|
||||||
|
private final JTextArea scriptText;
|
||||||
|
|
||||||
|
public LuaScriptPanel(UIContext context, Node config) {
|
||||||
|
this.context = context;
|
||||||
|
this.command = AnyCommand.createField(context, config, true, true);
|
||||||
|
|
||||||
|
// Upper panel: command entry, etc
|
||||||
|
JPanel upperPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
|
||||||
|
|
||||||
|
JButton readButton = new JButton("Read from ECU");
|
||||||
|
JButton writeButton = new JButton("Write to ECU");
|
||||||
|
JButton resetButton = new JButton("Reset/Reload Lua");
|
||||||
|
|
||||||
|
readButton.addActionListener(e -> read());
|
||||||
|
writeButton.addActionListener(e -> write());
|
||||||
|
resetButton.addActionListener(e -> resetLua());
|
||||||
|
|
||||||
|
upperPanel.add(readButton);
|
||||||
|
upperPanel.add(writeButton);
|
||||||
|
upperPanel.add(resetButton);
|
||||||
|
upperPanel.add(this.command.getContent());
|
||||||
|
|
||||||
|
// Center panel - script editor and log
|
||||||
|
JPanel scriptPanel = new JPanel(new BorderLayout());
|
||||||
|
this.scriptText = new JTextArea();
|
||||||
|
this.scriptText.setTabSize(2);
|
||||||
|
scriptPanel.add(this.scriptText, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
//centerPanel.add(, BorderLayout.WEST);
|
||||||
|
JPanel messagesPanel = new JPanel(new BorderLayout());
|
||||||
|
MessagesPanel mp = new MessagesPanel(null);
|
||||||
|
messagesPanel.add(BorderLayout.NORTH, mp.getButtonPanel());
|
||||||
|
messagesPanel.add(BorderLayout.CENTER, mp.getMessagesScroll());
|
||||||
|
|
||||||
|
JSplitPane centerPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scriptPanel, messagesPanel);
|
||||||
|
|
||||||
|
this.mainPanel.add(upperPanel, BorderLayout.NORTH);
|
||||||
|
this.mainPanel.add(centerPanel, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getPanel() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionListener getTabSelectedListener() {
|
||||||
|
return new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (command != null)
|
||||||
|
command.requestFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void read() {
|
||||||
|
BinaryProtocol bp = this.context.getLinkManager().getCurrentStreamState();
|
||||||
|
|
||||||
|
if (bp == null) {
|
||||||
|
// TODO: Handle missing ECU
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationImage image = bp.getControllerConfiguration();
|
||||||
|
ByteBuffer luaScriptBuffer = image.getByteBuffer(Fields.luaScript_offset, Fields.LUA_SCRIPT_SIZE);
|
||||||
|
|
||||||
|
byte scriptArr[] = new byte[Fields.LUA_SCRIPT_SIZE];
|
||||||
|
luaScriptBuffer.get(scriptArr);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
// Find the null terminator
|
||||||
|
for (i = 0; i < scriptArr.length && scriptArr[i] != 0; i++) ;
|
||||||
|
scriptText.setText(new String(scriptArr, 0, i, Charset.forName("ASCII")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void write() {
|
||||||
|
BinaryProtocol bp = this.context.getLinkManager().getCurrentStreamState();
|
||||||
|
|
||||||
|
String script = scriptText.getText();
|
||||||
|
|
||||||
|
byte paddedScript[] = new byte[Fields.LUA_SCRIPT_SIZE];
|
||||||
|
byte scriptBytes[] = script.getBytes(StandardCharsets.US_ASCII);
|
||||||
|
System.arraycopy(scriptBytes, 0, paddedScript, 0, scriptBytes.length);
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
int remaining;
|
||||||
|
|
||||||
|
do {
|
||||||
|
remaining = paddedScript.length - idx;
|
||||||
|
int thisWrite = remaining > Fields.BLOCKING_FACTOR ? Fields.BLOCKING_FACTOR : remaining;
|
||||||
|
|
||||||
|
bp.writeData(paddedScript, idx, Fields.luaScript_offset + idx, thisWrite);
|
||||||
|
|
||||||
|
idx += thisWrite;
|
||||||
|
|
||||||
|
remaining -= thisWrite;
|
||||||
|
} while (remaining > 0);
|
||||||
|
|
||||||
|
bp.burn();
|
||||||
|
|
||||||
|
// Burning doesn't reload lua script, so we have to do it manually
|
||||||
|
resetLua();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetLua() {
|
||||||
|
this.context.getCommandQueue().write("luareset");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue