rusefi/java_console/ui/src/main/java/com/rusefi/ui/engine/EngineSnifferPanel.java

350 lines
13 KiB
Java
Raw Normal View History

2015-07-10 06:01:56 -07:00
package com.rusefi.ui.engine;
2022-02-12 13:20:38 -08:00
import com.devexperts.logging.Logging;
2015-07-10 06:01:56 -07:00
import com.rusefi.FileLog;
import com.rusefi.config.generated.Fields;
2015-07-10 06:01:56 -07:00
import com.rusefi.core.EngineState;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.ui.*;
import com.rusefi.ui.config.BitConfigField;
import com.rusefi.ui.config.ConfigField;
import com.rusefi.core.preferences.storage.Node;
2016-11-19 09:02:47 -08:00
import com.rusefi.ui.util.URLLabel;
2015-07-10 06:01:56 -07:00
import com.rusefi.ui.util.UiUtils;
import com.rusefi.ui.widgets.AnyCommand;
import com.rusefi.waves.EngineChart;
2016-11-19 09:02:47 -08:00
import com.rusefi.waves.EngineChartParser;
2015-07-10 06:01:56 -07:00
import com.rusefi.waves.EngineReport;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
2022-02-12 13:20:38 -08:00
import static com.devexperts.logging.Logging.getLogging;
2015-07-10 06:01:56 -07:00
/**
* Engine Sniffer control consists of a set of {@link UpDownImage}
* <p/>
* <p/>
* Date: 6/23/13
2020-06-09 17:08:16 -07:00
* Andrey Belomutskiy, (c) 2013-2020
2015-07-10 06:01:56 -07:00
*
* @see EngineSnifferStatusPanel status bar
* @see com.rusefi.ui.test.WavePanelSandbox
*/
public class EngineSnifferPanel {
2022-02-12 13:20:38 -08:00
private static final Logging log = getLogging(EngineSnifferPanel.class);
2015-07-10 06:01:56 -07:00
private static final int EFI_DEFAULT_CHART_SIZE = 180;
2015-07-15 19:02:21 -07:00
public static final Comparator<String> INSTANCE = new ImageOrderComparator();
2015-07-10 06:01:56 -07:00
private static final String HELP_URL = "http://rusefi.com/wiki/index.php?title=Manual:DevConsole#Digital_Chart";
public static final String HELP_TEXT = "Click here for online help";
private final JPanel chartPanel = new JPanel(new BorderLayout());
2017-01-06 04:02:35 -08:00
/**
* chartPanel in the center and warning panel on the bottom
*/
private final JPanel mainPanel = new JPanel(new BorderLayout());
2015-07-10 06:01:56 -07:00
/**
* imageName -> UpDownImage
*/
2015-12-27 17:02:47 -08:00
private final TreeMap<String, UpDownImage> images = new TreeMap<>(INSTANCE);
2015-07-10 06:01:56 -07:00
/**
* this is the panel which displays all {@link UpDownImage} using {@link GridLayout}
*/
private final JPanel imagePanel = new JPanel(new GridLayout(1, 1)) {
@Override
public Dimension getPreferredSize() {
Dimension d = chartPanel.getSize();
Dimension s = super.getPreferredSize();
2022-02-09 22:51:48 -08:00
return new Dimension((int) (d.width * zoomControl.getZoomProvider().getZoomValue()), s.height);
2015-07-10 06:01:56 -07:00
}
};
private final ZoomControl zoomControl = new ZoomControl();
2022-02-09 22:51:48 -08:00
private final EngineSnifferStatusPanel statusPanel = new EngineSnifferStatusPanel();
private final UpDownImage crank = createImage(Fields.PROTOCOL_CRANK1);
2015-07-10 06:01:56 -07:00
private final ChartScrollControl scrollControl;
2017-01-29 06:06:38 -08:00
private AnyCommand command;
2015-07-10 06:01:56 -07:00
private boolean isPaused;
2020-06-25 17:03:48 -07:00
public EngineSnifferPanel(UIContext uiContext, Node config) {
2015-09-20 20:01:32 -07:00
statusPanel.setTimeAxisTranslator(crank.createTranslator());
2015-07-10 06:01:56 -07:00
2016-11-19 09:02:47 -08:00
final JButton pauseButton = UiUtils.createPauseButton();
pauseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setPaused(pauseButton, !isPaused);
}
});
JButton clearButton = UiUtils.createClearButton();
2015-07-10 06:01:56 -07:00
clearButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (UpDownImage image : images.values())
image.setWaveReport(EngineReport.MOCK, null);
2016-11-19 09:02:47 -08:00
setPaused(pauseButton, false);
2015-07-10 06:01:56 -07:00
}
});
JButton saveImageButton = UiUtils.createSaveImageButton();
saveImageButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveImage();
}
});
JPanel upperPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
upperPanel.add(clearButton);
upperPanel.add(saveImageButton);
upperPanel.add(pauseButton);
2020-06-25 17:51:09 -07:00
upperPanel.add(new RpmLabel(uiContext,2).getContent());
2015-07-10 06:01:56 -07:00
2020-06-25 17:51:09 -07:00
if (!uiContext.getLinkManager().isLogViewer()) {
2020-06-25 18:05:06 -07:00
command = AnyCommand.createField(uiContext, config, "chartsize " + EFI_DEFAULT_CHART_SIZE, true, true);
2017-01-29 06:06:38 -08:00
upperPanel.add(command.getContent());
2015-12-14 09:02:21 -08:00
}
2015-07-10 06:01:56 -07:00
upperPanel.add(zoomControl);
2022-02-09 22:51:48 -08:00
scrollControl = ChartRepository.getInstance().createControls(chart -> displayChart(chart));
2020-06-25 17:51:09 -07:00
if (uiContext.getLinkManager().isLogViewer())
2015-07-10 06:01:56 -07:00
upperPanel.add(scrollControl.getContent());
upperPanel.add(new URLLabel(HELP_TEXT, HELP_URL));
JPanel bottomPanel = new JPanel(new BorderLayout());
2015-12-14 09:02:21 -08:00
2020-06-25 17:51:09 -07:00
if (!uiContext.getLinkManager().isLogViewer()) {
2015-12-14 09:02:21 -08:00
JPanel lowerButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
2020-06-25 17:18:02 -07:00
lowerButtons.add(new ConfigField(uiContext, Fields.GLOBALTRIGGERANGLEOFFSET, "Trigger Offset").getContent());
2020-06-25 17:03:48 -07:00
lowerButtons.add(new BitConfigField(uiContext, Fields.VERBOSETRIGGERSYNCHDETAILS, "Verbose trigger Sync").getContent());
2021-12-05 13:22:19 -08:00
lowerButtons.add(new BitConfigField(uiContext, Fields.VERBOSEVVTDECODING, "Verbose VVT Sync").getContent());
lowerButtons.add(new BitConfigField(uiContext, Fields.ENGINESNIFFERFOCUSONINPUTS, "Focus On Inputs").getContent());
2020-06-25 17:18:02 -07:00
lowerButtons.add(new ConfigField(uiContext, Fields.ENGINECHARTSIZE, "Engine Sniffer size").getContent());
2021-03-04 10:42:52 -08:00
lowerButtons.add(new ConfigField(uiContext, Fields.ENGINESNIFFERRPMTHRESHOLD, "RPM threshold").getContent());
lowerButtons.add(new BitConfigField(uiContext, Fields.INVERTPRIMARYTRIGGERSIGNAL, "Invert Primary Input").getContent());
2015-12-14 09:02:21 -08:00
bottomPanel.add(lowerButtons, BorderLayout.NORTH);
}
2015-07-10 06:01:56 -07:00
bottomPanel.add(statusPanel.infoPanel, BorderLayout.SOUTH);
chartPanel.add(upperPanel, BorderLayout.NORTH);
2015-12-27 17:02:47 -08:00
JScrollPane pane = new JScrollPane(imagePanel, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
2015-07-10 06:01:56 -07:00
chartPanel.add(pane, BorderLayout.CENTER);
chartPanel.add(bottomPanel, BorderLayout.SOUTH);
2022-02-09 22:51:48 -08:00
zoomControl.listener = () -> {
System.out.println("onZoomChange");
/**
* We have scroll pane size which depends on zoom, that's a long chain of dependencies
*/
UiUtils.trueLayout(imagePanel.getParent());
2015-07-10 06:01:56 -07:00
};
resetImagePanel();
2020-06-25 20:12:29 -07:00
uiContext.getLinkManager().getEngineState().registerStringValueAction(EngineReport.ENGINE_CHART, new EngineState.ValueCallback<String>() {
2015-07-10 06:01:56 -07:00
@Override
public void onUpdate(String value) {
if (isPaused)
return;
displayChart(value);
}
});
2017-01-06 04:02:35 -08:00
mainPanel.add(chartPanel, BorderLayout.CENTER);
mainPanel.add(new WarningPanel(config).getPanel(config), BorderLayout.SOUTH);
2015-07-10 06:01:56 -07:00
}
2016-11-19 09:02:47 -08:00
private void setPaused(JButton pauseButton, boolean isPaused) {
this.isPaused = isPaused;
UiUtils.setPauseButtonText(pauseButton, this.isPaused);
}
2016-06-04 14:01:42 -07:00
public void setOutpinListener(EngineState engineState) {
engineState.registerStringValueAction(Fields.PROTOCOL_OUTPIN, new EngineState.ValueCallback<String>() {
2016-06-04 14:01:42 -07:00
@Override
public void onUpdate(String value) {
2022-02-09 22:51:48 -08:00
String[] pinInfo = value.split("@");
2016-06-04 14:01:42 -07:00
if (pinInfo.length != 2)
return;
String channel = pinInfo[0];
String pin = pinInfo[1];
UpDownImage image = images.get(channel);
2020-05-25 22:32:17 -07:00
ChannelNaming.INSTANCE.channelName2PhysicalPin.put(channel, pin);
2016-06-04 14:01:42 -07:00
if (image != null)
image.setPhysicalPin(pin);
}
});
}
2015-07-10 06:01:56 -07:00
private void resetImagePanel() {
imagePanel.removeAll();
imagePanel.add(crank);
images.put(Fields.PROTOCOL_CRANK1, crank);
2015-07-10 06:01:56 -07:00
}
public void displayChart(String value) {
2022-02-12 13:16:11 -08:00
EngineChart map = EngineChartParser.unpackToMap(value);
2015-07-10 06:01:56 -07:00
StringBuilder revolutions = map.get(Fields.TOP_DEAD_CENTER_MESSAGE);
2015-07-10 06:01:56 -07:00
statusPanel.setRevolutions(revolutions);
// Create images for any new keys
for (String imageName : map.getMap().keySet()) {
2015-07-10 06:01:56 -07:00
createSecondaryImage(imageName);
}
2015-07-10 06:01:56 -07:00
// Update existing images
2015-07-10 06:01:56 -07:00
for (String imageName : images.keySet()) {
UpDownImage image = images.get(imageName);
if (image == null)
throw new IllegalStateException("image not found for " + imageName);
StringBuilder sb = map.getMap().get(imageName);
String report = sb == null ? "" : sb.toString();
image.setRevolutions(revolutions);
List<EngineReport.UpDown> list = EngineReport.parse(report);
EngineReport wr = new EngineReport(list);
image.setWaveReport(wr, revolutions);
}
2022-03-05 05:37:57 -08:00
// Repaint now that we've updated state
SwingUtilities.invokeLater(() -> UiUtils.trueRepaint(imagePanel));
2015-07-10 06:01:56 -07:00
}
public JPanel getPanel() {
2017-01-06 04:02:35 -08:00
return mainPanel;
2015-07-10 06:01:56 -07:00
}
private void createSecondaryImage(String name) {
if (images.containsKey(name)) {
// already created, skip
return;
}
// Don't render a row for the TDC mark
if (Fields.TOP_DEAD_CENTER_MESSAGE.equalsIgnoreCase(name)) {
2015-07-10 06:01:56 -07:00
return;
}
2015-07-10 06:01:56 -07:00
int index = getInsertIndex(name, images.keySet());
2022-02-12 13:20:38 -08:00
log.info("Engine sniffer register channel " + name + " at idx " + index);
2015-07-10 06:01:56 -07:00
UpDownImage image = createImage(name);
images.put(name, image);
image.setTranslator(crank.createTranslator());
imagePanel.add(image, index);
imagePanel.setLayout(new GridLayout(images.size(), 1));
}
public static int getInsertIndex(String name, Set<String> strings) {
String[] mapKeys = new String[strings.size()];
int pos = 0;
for (String key : strings)
mapKeys[pos++] = key;
// int index = -Arrays.binarySearch(mapKeys, name) - 1;
int index = -Arrays.binarySearch(mapKeys, 0, mapKeys.length, name, INSTANCE) - 1;
if (index >= strings.size())
index = -1;
return index;
}
private void saveImage() {
int rpm = RpmModel.getInstance().getValue();
double maf = SensorCentral.getInstance().getValue(Sensor.MAF);
2022-02-12 13:16:11 -08:00
String fileName = FileLog.getDate() + "rpm_" + rpm + "_maf_" + maf + ".png";
2015-07-10 06:01:56 -07:00
2017-01-06 04:02:35 -08:00
UiUtils.saveImageWithPrompt(fileName, mainPanel, imagePanel);
2015-07-10 06:01:56 -07:00
}
2015-12-27 17:02:47 -08:00
private UpDownImage createImage(final String name) {
Color signalBody = Color.lightGray;
Color signalBorder = Color.blue;
2016-09-11 20:03:00 -07:00
if (name.startsWith("tach") || name.startsWith("dizzy")) {
signalBody = Color.yellow;
} else if (name.startsWith("t")) {
2015-12-27 17:02:47 -08:00
// trigger
2021-07-21 22:22:40 -07:00
} else if (name.startsWith("r")) {
// trailing coil
signalBody = new Color(0xffa400); // golden yellow
2015-12-27 17:02:47 -08:00
} else if (name.startsWith("c")) {
// coil
signalBody = Color.darkGray;
} else if (name.startsWith("HIP")) {
signalBody = Color.white;
} else if (name.startsWith("i")) {
// injection
signalBody = Color.green;
2016-09-11 20:03:00 -07:00
} else if (name.startsWith("map")) {
2017-06-21 23:19:43 -07:00
signalBody = Color.pink;
2015-12-27 17:02:47 -08:00
} else {
signalBody = Color.gray;
}
UpDownImage image = new UpDownImage(name) {
@Override
protected boolean isShowTdcLabel() {
/**
* TDC label is only displayed on the bottom UpDown image
*/
return name.equals(images.lastKey());
}
};
image.setSignalBody(signalBody);
image.setSignalBorder(signalBorder);
2015-07-10 06:01:56 -07:00
image.addMouseMotionListener(statusPanel.motionAdapter);
return image;
}
public void reloadFile() {
displayChart(ChartRepository.getInstance().getChart(0));
scrollControl.reset();
}
2015-07-15 19:02:21 -07:00
2017-01-29 06:06:38 -08:00
public ActionListener getTabSelectedListener() {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (command != null)
command.requestFocus();
}
};
}
2015-07-15 19:02:21 -07:00
/**
* The job of this comparator is to place Spark charts before Injection charts
*/
static class ImageOrderComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return fixNameForNicerOrder(o1).compareTo(fixNameForNicerOrder(o2));
}
String fixNameForNicerOrder(String s) {
if (s.toLowerCase().startsWith("t"))
return "a" + s; // let's place this at the top
if (s.toLowerCase().startsWith("hip"))
return "z" + s; // let's place this at the bottom
if (s.toLowerCase().startsWith("spa"))
return "d" + s;
return s;
}
}
2015-07-10 06:01:56 -07:00
}