Annotations in C++ code to produce formulas in rusEfi console #807

This commit is contained in:
rusefi 2019-06-18 23:23:30 -04:00
parent 9cbbf72031
commit 13fefc6245
19 changed files with 279 additions and 72 deletions

View File

@ -39,6 +39,6 @@
#define DISPLAY_TEXT(x)
#define DISPLAY_SENSOR(x) {}
#define DISPLAY_IF(x) {}
#define DISPLAY_IF(x) x
#endif /* CONTROLLERS_CORE_COMMON_HEADERS_H_ */

View File

@ -37,7 +37,7 @@ float getTCharge(int rpm, float tps, float coolantTemp, float airTemp DECLARE_EN
}
if ((engine->engineState./*DISPLAY_IF*/isTChargeAirModel = (CONFIG(tChargeMode) == TCHARGE_MODE_AIR_INTERP))) {
if ((engine->engineState.DISPLAY_IF(isTChargeAirModel) = (CONFIG(tChargeMode) == TCHARGE_MODE_AIR_INTERP))) {
const floatms_t gramsPerMsToKgPerHour = (3600.0f * 1000.0f) / 1000.0f;
// We're actually using an 'old' airMass calculated for the previous cycle, but it's ok, we're not having any self-excitaton issues
floatms_t airMassForEngine = engine->engineState./***display*/airMass * CONFIG(specs.cylindersCount);
@ -45,20 +45,29 @@ float getTCharge(int rpm, float tps, float coolantTemp, float airTemp DECLARE_EN
// And if the engine is stopped (0 rpm), then airFlow is also zero (avoiding NaN division)
floatms_t airFlow = (rpm == 0) ? 0 : airMassForEngine * gramsPerMsToKgPerHour / getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX);
// just interpolate between user-specified min and max coefs, based on the max airFlow value
engine->engineState.Tcharge_coff = interpolateClamped(0.0, CONFIG(tChargeAirCoefMin), CONFIG(tChargeAirFlowMax), CONFIG(tChargeAirCoefMax), airFlow);
DISPLAY_TEXT(interpolate_Air_Flow)
engine->engineState.DISPLAY_FIELD(airFlow) = airFlow;
DISPLAY_TEXT(Between)
engine->engineState.Tcharge_coff = interpolateClamped(0.0,
DISPLAY_TEXT(tChargeAirCoefMin) CONFIG(DISPLAY_CONFIG(tChargeAirCoefMin)),
DISPLAY_TEXT(tChargeAirFlowMax) CONFIG(DISPLAY_CONFIG(tChargeAirFlowMax)),
DISPLAY_TEXT(tChargeAirCoefMax) CONFIG(DISPLAY_CONFIG(tChargeAirCoefMax)), airFlow);
// save it for console output (instead of MAF massAirFlow)
engine->engineState.airFlow = airFlow;
} else/* DISPLAY_ELSE */ {
// TCHARGE_MODE_RPM_TPS
DISPLAY_TEXT("interpolate(")
DISPLAY_TEXT(interpolate_RPM)
DISPLAY_SENSOR(RPM)
DISPLAY_TEXT(and_TPS)
DISPLAY_SENSOR(TPS)
float minRpmKcurrentTPS = interpolateMsg("minRpm", tpMin, CONFIG(DISPLAY_CONFIG(tChargeMinRpmMinTps)), tpMax,
CONFIG(DISPLAY_CONFIG(tChargeMinRpmMaxTps)), tps);
DISPLAY_TEXT(EOL)
DISPLAY_TEXT(Between)
float minRpmKcurrentTPS = interpolateMsg("minRpm", tpMin,
DISPLAY_TEXT(tChargeMinRpmMinTps) CONFIG(DISPLAY_CONFIG(tChargeMinRpmMinTps)), tpMax, DISPLAY_TEXT(EOL)
DISPLAY_TEXT(tChargeMinRpmMaxTps) CONFIG(DISPLAY_CONFIG(tChargeMinRpmMaxTps)), tps);
float maxRpmKcurrentTPS = interpolateMsg("maxRpm", tpMin, CONFIG(DISPLAY_CONFIG(tChargeMaxRpmMinTps)), tpMax,
CONFIG(DISPLAY_CONFIG(tChargeMaxRpmMaxTps)), tps);
DISPLAY_TEXT(")")
//ISPLAY_TEXT()
engine->engineState.Tcharge_coff = interpolateMsg("Kcurr", rpmMin, minRpmKcurrentTPS, rpmMax, maxRpmKcurrentTPS, rpm);
/* DISPLAY_ENDIF */

View File

@ -27,3 +27,9 @@ java -DSystemOut.name=gen_config2 ^
com.rusefi.ldmp.LiveDocsMetaParser ^
controllers/sensors/tps.cpp ^
"../"
java -DSystemOut.name=gen_config2 ^
-cp ../java_tools/ConfigDefinition.jar ^
com.rusefi.ldmp.LiveDocsMetaParser ^
controllers/math/speed_density.cpp ^
"../"

View File

@ -3,7 +3,9 @@ package com.rusefi.ui.livedocs;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.config.generated.Fields;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.rusefi.binaryprotocol.BinaryProtocolCommands.COMMAND_GET_STRUCT;
@ -17,14 +19,14 @@ import static com.rusefi.binaryprotocol.IoHelper.swap16;
public enum LiveDocsRegistry {
INSTANCE;
private final Map<Integer, LiveDocHolder> liveDocs = new HashMap<>();
private final List<LiveDocHolder> liveDocs = new ArrayList<>();
public void register(LiveDocHolder holder) {
liveDocs.put(holder.getId(), holder);
liveDocs.add(holder);
}
public void refresh(BinaryProtocol binaryProtocol) {
for (LiveDocHolder h : liveDocs.values()) {
for (LiveDocHolder h : liveDocs) {
boolean visible = h.isVisible();
System.out.println(h + ": " + visible);
if (visible) {

View File

@ -188,7 +188,10 @@ public class Field {
Objects.requireNonNull(ci);
Number value;
ByteBuffer wrapped = ci.getByteBuffer(getOffset(), type.getStorageSize());
if (type == INT) {
if (bitOffset != NO_BIT_OFFSET) {
int packed = wrapped.getInt();
value = (packed >> bitOffset) & 1;
} else if (type == INT) {
value = wrapped.getInt();
} else if (type == INT16) {
value = wrapped.getShort();

View File

@ -0,0 +1,35 @@
package com.rusefi.ldmp.generated;
import com.rusefi.ldmp.*;
public class SpeedDensityMeta {
public static final Request[] CONTENT = new Request[]{
new IfRequest("isTChargeAirModel",
new Request[]{
new TextRequest("interpolate_Air_Flow"),
new FieldRequest("airFlow"),
new TextRequest("Between"),
new TextRequest("tChargeAirCoefMin"),
new ConfigRequest("tChargeAirCoefMin"),
new TextRequest("tChargeAirFlowMax"),
new ConfigRequest("tChargeAirFlowMax"),
new TextRequest("tChargeAirCoefMax"),
new ConfigRequest("tChargeAirCoefMax"),
},
new Request[]{
new TextRequest("interpolate_RPM"),
new SensorRequest("RPM"),
new TextRequest("and_TPS"),
new SensorRequest("TPS"),
new TextRequest("EOL"),
new TextRequest("Between"),
new TextRequest("tChargeMinRpmMinTps"),
new ConfigRequest("tChargeMinRpmMinTps"),
new TextRequest("EOL"),
new TextRequest("tChargeMinRpmMaxTps"),
new ConfigRequest("tChargeMinRpmMaxTps"),
new ConfigRequest("tChargeMaxRpmMinTps"),
new ConfigRequest("tChargeMaxRpmMaxTps"),
}),
};
}

View File

@ -4,19 +4,14 @@ import com.opensr5.ConfigurationImage;
import com.rusefi.FileLog;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.binaryprotocol.BinaryProtocolHolder;
import com.rusefi.config.generated.EngineState;
import com.rusefi.config.generated.Fields;
import com.rusefi.config.generated.ThermistorState;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.ldmp.generated.ThermistorsMeta;
import com.rusefi.ldmp.generated.TpsMeta;
import com.rusefi.ui.config.ConfigField;
import com.rusefi.ui.livedocs.LiveDocPanel;
import com.rusefi.ui.util.UiUtils;
import com.rusefi.ui.widgets.IntGaugeLabel;
import org.jetbrains.annotations.NotNull;
import org.putgemin.VerticalFlowLayout;
import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;
@ -43,20 +38,11 @@ public class FormulasPane {
private final JPanel centerProxy = new JPanel(new BorderLayout());
private boolean isPaused;
private JPanel liveDocs = new JPanel(new VerticalFlowLayout());
private JPanel liveDocs = LiveDocPanel.createLiveDocumentationPanel();
public FormulasPane() {
content.add(centerProxy, BorderLayout.CENTER);
liveDocs.add(LiveDocPanel.getPanel("Coolant Sensor", "CLT", Fields.LDS_CLT_INDEX,
ThermistorState.VALUES, ThermistorsMeta.CONTENT));
liveDocs.add(LiveDocPanel.getPanel("Intake Air Sensor", "IAT", Fields.LDS_IAT_INDEX,
ThermistorState.VALUES, ThermistorsMeta.CONTENT));
liveDocs.add(LiveDocPanel.getPanel("Throttle Position Sensor", "", Fields.LDS_ENGINE_STATE_INDEX,
EngineState.VALUES, TpsMeta.CONTENT));
centerProxy.add(new JLabel("Waiting for data..."), BorderLayout.CENTER);
JButton saveImage = UiUtils.createSaveImageButton();

View File

@ -0,0 +1,44 @@
package com.rusefi.ui.livedocs;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class ActionPanel {
List<RefreshActions> actionsList = new ArrayList<>();
private final JPanel panel = new JPanel(new MigLayout());
private JPanel currentLinePanel;
public ActionPanel(String title) {
panel.setBorder(BorderFactory.createTitledBorder(title));
}
public ActionPanel(JPanel result, List<RefreshActions> combined) {
panel.add(result);
actionsList.addAll(combined);
}
public JPanel getPanel() {
return panel;
}
public void newLine() {
initIfNeeded();
currentLinePanel = null;
}
private void initIfNeeded() {
if (currentLinePanel == null) {
currentLinePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
panel.add(currentLinePanel, "wrap");
}
}
public void addControl(JComponent component) {
initIfNeeded();
currentLinePanel.add(component);
}
}

View File

@ -3,28 +3,30 @@ package com.rusefi.ui.livedocs;
import com.opensr5.ConfigurationImage;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.config.Field;
import com.rusefi.config.generated.EngineState;
import com.rusefi.config.generated.Fields;
import com.rusefi.ldmp.ConfigRequest;
import com.rusefi.ldmp.FieldRequest;
import com.rusefi.ldmp.Request;
import com.rusefi.ldmp.TextRequest;
import net.miginfocom.swing.MigLayout;
import com.rusefi.config.generated.ThermistorState;
import com.rusefi.ldmp.*;
import com.rusefi.ldmp.generated.SpeedDensityMeta;
import com.rusefi.ldmp.generated.ThermistorsMeta;
import com.rusefi.ldmp.generated.TpsMeta;
import com.rusefi.ui.livedocs.controls.Toolbox;
import org.jetbrains.annotations.NotNull;
import org.putgemin.VerticalFlowLayout;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class LiveDocPanel {
@NotNull
public static JPanel getPanel(String title, String instancePrefix, final int id, Field[] values, Request[] content) {
JPanel panel = new JPanel(new MigLayout());
panel.setBorder(BorderFactory.createTitledBorder(title));
List<RefreshActions> actions = createComponents(panel, content, values, instancePrefix);
ActionPanel ap = createComponents(title, content, values, instancePrefix);
JPanel panel = ap.getPanel();
LiveDocHolder holder = new LiveDocHolder(id, actions, values) {
LiveDocHolder holder = new LiveDocHolder(id, ap.actionsList, values) {
@Override
public boolean isVisible() {
boolean isVisible = !panel.getVisibleRect().isEmpty();
@ -41,22 +43,23 @@ public class LiveDocPanel {
return c.isVisible() && (parent == null || isRecursivelyVisible(parent));
}
private static List<RefreshActions> createComponents(JPanel panel, Request[] content, Field[] values, String instancePrefix) {
List<RefreshActions> actionsList = new ArrayList<>();
private static ActionPanel createComponents(String title, Request[] content, Field[] values, String instancePrefix) {
ActionPanel result = new ActionPanel(title);
for (Request r : content) {
if (r instanceof TextRequest) {
TextRequest request = (TextRequest) r;
if (request.isEol()) {
panel.add(new JLabel(), "wrap");
result.newLine();
} else {
panel.add(new JLabel(request.getValue().replaceAll("_", " ")));
result.addControl(new JLabel(request.getValue().replaceAll("_", " ")));
}
} else if (r instanceof FieldRequest) {
FieldRequest request = (FieldRequest) r;
Field field = Field.findField(values, "", request.getField());
JLabel label = new JLabel(field.getName());
panel.add(label);
actionsList.add(new RefreshActions() {
JLabel label = new JLabel("*");
result.addControl(label);
result.actionsList.add(new RefreshActions() {
@Override
public void refresh(BinaryProtocol bp, byte[] response) {
Number fieldValue = field.getValue(new ConfigurationImage(response));
@ -68,20 +71,90 @@ public class LiveDocPanel {
ConfigRequest request = (ConfigRequest) r;
Field field = Field.findField(Fields.VALUES, instancePrefix, request.getField());
JLabel label = new JLabel(field.getName());
actionsList.add(new RefreshActions() {
JLabel label = new JLabel("*");
result.actionsList.add(new RefreshActions() {
@Override
public void refresh(BinaryProtocol bp, byte[] response) {
String value = field.getAnyValue(bp.getController()).toString();
label.setText(value);
}
});
panel.add(label);
result.addControl(label);
} else if (r instanceof SensorRequest) {
SensorRequest request = (SensorRequest) r;
result.addControl(new JLabel("*"));
} else if (r instanceof IfRequest) {
IfRequest request = (IfRequest) r;
ActionPanel panel = createIfRequestPanel(request, values);
result.actionsList.addAll(panel.actionsList);
result.addControl(panel.getPanel());
} else {
throw new UnsupportedOperationException(r.toString());
}
}
return actionsList;
return result;
}
private static ActionPanel createIfRequestPanel(IfRequest request, Field[] values) {
Field conditionField = Field.findField(values, "", request.getVariable());
JPanel result = new JPanel(new VerticalFlowLayout());
result.add(new JLabel(request.getVariable()));
ActionPanel trueAP = createComponents("", request.trueBlock.toArray(new Request[0]), values, "");
ActionPanel falseAP = createComponents("", request.falseBlock.toArray(new Request[0]), values, "");
result.add(trueAP.getPanel());
result.add(falseAP.getPanel());
List<RefreshActions> combined = new ArrayList<>(trueAP.actionsList);
combined.addAll(falseAP.actionsList);
combined.add(new RefreshActions() {
@Override
public void refresh(BinaryProtocol bp, byte[] response) {
int value = (int) conditionField.getValue(new ConfigurationImage(response));
JPanel active;
JPanel passive;
if (value == 1) {
active = trueAP.getPanel();
passive = falseAP.getPanel();
} else {
active = falseAP.getPanel();
passive = trueAP.getPanel();
}
active.setBorder(BorderFactory.createLineBorder(Color.green));
passive.setBorder(BorderFactory.createLineBorder(Color.red));
Toolbox.setEnabledRecursive(active, true);
Toolbox.setEnabledRecursive(passive, true);
}
});
return new ActionPanel(result, combined);
}
@NotNull
public static JPanel createLiveDocumentationPanel() {
JPanel liveDocs = new JPanel(new VerticalFlowLayout());
liveDocs.add(getPanel("Coolant Sensor", "CLT", Fields.LDS_CLT_INDEX,
ThermistorState.VALUES, ThermistorsMeta.CONTENT));
liveDocs.add(getPanel("Intake Air Sensor", "IAT", Fields.LDS_IAT_INDEX,
ThermistorState.VALUES, ThermistorsMeta.CONTENT));
liveDocs.add(getPanel("Throttle Position Sensor", "", Fields.LDS_ENGINE_STATE_INDEX,
EngineState.VALUES, TpsMeta.CONTENT));
liveDocs.add(getPanel("tCharge", "", Fields.LDS_ENGINE_STATE_INDEX,
EngineState.VALUES, SpeedDensityMeta.CONTENT));
return liveDocs;
}
}

View File

@ -66,9 +66,9 @@ public class LiveDocsSandbox {
}
@NotNull
private static JPanel wrapWithOffset(JPanel panel) {
public static JPanel wrapWithOffset(JPanel panel) {
JPanel topWrapped = new JPanel(new FlowLayout());
topWrapped.add(new JLabel("x"));
topWrapped.add(new JLabel(" "));
topWrapped.add(panel);
return topWrapped;
}

View File

@ -2,7 +2,7 @@
<configuration default="false" name="LiveDocsMetaParser" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="com.rusefi.ldmp.LiveDocsMetaParser" />
<module name="configuration_definition" />
<option name="PROGRAM_PARAMETERS" value="&quot;../../firmware/controllers/sensors/thermistors.cpp&quot;" />
<option name="PROGRAM_PARAMETERS" value="&quot;../../firmware/controllers/math/speed_density.cpp&quot; &quot;../../&quot;" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.rusefi.ldmp.*" />

View File

@ -40,6 +40,6 @@ public class ConfigRequest extends Request {
@Override
public String getJavaCode() {
return withSimpleParameter("\"" + field + "\"");
return withSimpleParameter(quoteString(field));
}
}

View File

@ -35,6 +35,7 @@ public class FieldRequest extends Request {
@Override
public String getJavaCode() {
return withSimpleParameter("\"" + field + "\"");
return withSimpleParameter(quoteString(field));
}
}

View File

@ -1,8 +1,11 @@
package com.rusefi.ldmp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.rusefi.ConfigDefinition.EOL;
public class IfRequest extends Request {
private final String variable;
public List<Request> trueBlock = new ArrayList<>();
@ -12,6 +15,12 @@ public class IfRequest extends Request {
this.variable = variable;
}
public IfRequest(String variable, Request[] trueBlock, Request[] falseBlock) {
this(variable);
this.trueBlock.addAll(Arrays.asList(trueBlock));
this.falseBlock.addAll(Arrays.asList(falseBlock));
}
@Override
public String toString() {
return "IfRequest{" +
@ -24,4 +33,23 @@ public class IfRequest extends Request {
public String getVariable() {
return variable;
}
@Override
public String getJavaCode() {
String result = Request.GLOBAL_PREFIX;
Request.GLOBAL_PREFIX = Request.GLOBAL_PREFIX + "\t";
result += "new IfRequest(" + quoteString(variable) + "," + EOL +
Request.GLOBAL_PREFIX + "new Request[]{" + EOL +
Request.printList(trueBlock) +
"}," + EOL +
Request.GLOBAL_PREFIX + "new Request[]{" + EOL +
Request.printList(falseBlock) +
"})," + EOL;
Request.GLOBAL_PREFIX = Request.GLOBAL_PREFIX.substring(1);
return result;
}
}

View File

@ -8,10 +8,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.*;
import java.util.stream.Stream;
import static com.rusefi.ConfigDefinition.EOL;
@ -33,6 +30,8 @@ public class LiveDocsMetaParser {
}
public static void main(String[] args) throws IOException {
if (args.length != 2)
throw new IllegalArgumentException("Two arguments expected but " + Arrays.toString(args));
String fileName = args[0];
String destinationPath = args[1];
SystemOut.println(fileName);
@ -128,16 +127,17 @@ public class LiveDocsMetaParser {
"public class " + className + " {" + EOL +
"\tpublic static final Request[] CONTENT = new Request[]{" + EOL);
for (Request request : r) {
java.append(request.getJavaCode());
}
java.append(Request.printList(r));
java.append("\t};" + EOL +
"}");
return java.toString();
}
private static String toProperCase(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
}
public static String getClassName(String cppSourceName) {
int lastDotIndex = cppSourceName.lastIndexOf('.');
if (lastDotIndex != -1)
@ -146,7 +146,11 @@ public class LiveDocsMetaParser {
if (lastDotIndex != -1)
cppSourceName = cppSourceName.substring(lastSlashIndex + 1);
return Character.toUpperCase(cppSourceName.charAt(0)) + cppSourceName.substring(1) + "Meta";
String[] parts = cppSourceName.split("_");
String camelCaseString = "";
for (String part : parts) {
camelCaseString = camelCaseString + toProperCase(part);
}
return camelCaseString + "Meta";
}
}

View File

@ -1,13 +1,26 @@
package com.rusefi.ldmp;
import java.util.List;
import static com.rusefi.ConfigDefinition.EOL;
public class Request {
public String getJavaCode() {
return withSimpleParameter("");
public abstract class Request {
static String GLOBAL_PREFIX = "\t\t\t";
static String printList(List<Request> r) {
StringBuilder java = new StringBuilder();
for (Request request : r)
java.append(request.getJavaCode());
return java.toString();
}
public abstract String getJavaCode();
protected String withSimpleParameter(String parameter) {
return "\t\t\tnew " + getClass().getSimpleName() + "(" + parameter + ")," + EOL;
return GLOBAL_PREFIX + "new " + getClass().getSimpleName() + "(" + parameter + ")," + EOL;
}
protected String quoteString(String variable) {
return "\"" + variable + "\"";
}
}

View File

@ -2,8 +2,6 @@ package com.rusefi.ldmp;
import java.util.Objects;
import static com.rusefi.ConfigDefinition.EOL;
public class SensorRequest extends Request {
private final String value;
@ -11,6 +9,10 @@ public class SensorRequest extends Request {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public String toString() {
return "SensorRequest{" +
@ -33,6 +35,6 @@ public class SensorRequest extends Request {
@Override
public String getJavaCode() {
return "/*sens*/" + EOL;
return withSimpleParameter(quoteString(value));
}
}

View File

@ -41,6 +41,6 @@ public class TextRequest extends Request {
@Override
public String getJavaCode() {
return withSimpleParameter("\"" + value + "\"");
return withSimpleParameter(quoteString(value));
}
}

View File

@ -11,6 +11,7 @@ public class LiveDocsMetaParserTest {
@Test
public void getClassName() {
assertEquals("TpsMeta", LiveDocsMetaParser.getClassName("controllers/sensors/tps.cpp"));
assertEquals("SpeedDensityMeta", LiveDocsMetaParser.getClassName("speed_density.cpp"));
}
@Test
@ -52,7 +53,7 @@ public class LiveDocsMetaParserTest {
"public class xx {\n" +
"\tpublic static final Request[] CONTENT = new Request[]{\n" +
"\t\t\tnew TextRequest(\"interpolate\"),\n" +
"/*sens*/\n" +
"\t\t\tnew SensorRequest(\"RPM\"),\n" +
"\t\t\tnew TextRequest(\"TCHARGE_MODE_RPM_TPS\"),\n" +
"\t\t\tnew ConfigRequest(\"tChargeMinRpmMinTps\"),\n" +
"\t};\n" +