1
0
mirror of https://github.com/arduino/Arduino.git synced 2024-12-02 13:24:12 +01:00
This commit is contained in:
Wilhelm Wiens 2024-11-28 04:20:14 +01:00 committed by GitHub
commit a657266537
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 104 additions and 14 deletions

View File

@ -41,6 +41,8 @@ public class SerialPlotter extends AbstractMonitor {
private final StringBuffer messageBuffer; private final StringBuffer messageBuffer;
private JComboBox<String> serialRates; private JComboBox<String> serialRates;
private JButton clearButton;
private JSpinner graphWidth;
private Serial serial; private Serial serial;
private int serialRate, xCount; private int serialRate, xCount;
@ -50,15 +52,18 @@ public class SerialPlotter extends AbstractMonitor {
private JComboBox<String> lineEndings; private JComboBox<String> lineEndings;
private ArrayList<Graph> graphs; private ArrayList<Graph> graphs;
private final static int BUFFER_CAPACITY = 500; private final static int BUFFER_CAPACITY_DEFAULT = 500;
private final static int BUFFER_CAPACITY_MAX = 5000;
private final static int BUFFER_CAPACITY_MIN = 10;
private int buffer_capacity = BUFFER_CAPACITY_DEFAULT;
private static class Graph { private static class Graph {
public CircularBuffer buffer; public CircularBuffer buffer;
private Color color; private Color color;
public String label; public String label;
public Graph(int id) { public Graph(int id, int capacity) {
buffer = new CircularBuffer(BUFFER_CAPACITY); buffer = new CircularBuffer(capacity);
color = Theme.getColorCycleColor("plotting.graphcolor", id); color = Theme.getColorCycleColor("plotting.graphcolor", id);
} }
@ -156,12 +161,12 @@ public class SerialPlotter extends AbstractMonitor {
} }
// handle data count // handle data count
int cnt = xCount - BUFFER_CAPACITY; int cnt = xCount - buffer_capacity;
if (xCount < BUFFER_CAPACITY) cnt = 0; if (xCount < buffer_capacity) cnt = 0;
double zeroTick = ticks.getTick(0); double zeroTick = ticks.getTick(0);
double lastTick = ticks.getTick(ticks.getTickCount() - 1); double lastTick = ticks.getTick(ticks.getTickCount() - 1);
double xTickRange = BUFFER_CAPACITY / ticks.getTickCount(); double xTickRange = buffer_capacity / ticks.getTickCount();
for (int i = 0; i < ticks.getTickCount() + 1; i++) { for (int i = 0; i < ticks.getTickCount() + 1; i++) {
String s; String s;
@ -177,7 +182,7 @@ public class SerialPlotter extends AbstractMonitor {
s = String.valueOf((int)(xTickRange * i)+cnt); s = String.valueOf((int)(xTickRange * i)+cnt);
fBounds = fm.getStringBounds(s, g); fBounds = fm.getStringBounds(s, g);
sWidth = (int)fBounds.getWidth()/2; sWidth = (int)fBounds.getWidth()/2;
xValue = (int)((bounds.width - xOffset - xPadding) * ((xTickRange * i) / BUFFER_CAPACITY) + xOffset); xValue = (int)((bounds.width - xOffset - xPadding) * ((xTickRange * i) / buffer_capacity) + xOffset);
} }
// draw graph x axis, ticks and labels // draw graph x axis, ticks and labels
g.setColor(boundsColor); g.setColor(boundsColor);
@ -194,8 +199,8 @@ public class SerialPlotter extends AbstractMonitor {
g.drawLine(xOffset, (int) transformY(zeroTick), bounds.width - xPadding, (int)transformY(zeroTick)); g.drawLine(xOffset, (int) transformY(zeroTick), bounds.width - xPadding, (int)transformY(zeroTick));
g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0)); g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0));
float xstep = (float) (bounds.width - xOffset - xPadding) / (float) BUFFER_CAPACITY;
float xstep = (float) (bounds.width - xOffset - xPadding) / (float) buffer_capacity;
// draw legend // draw legend
int legendXOffset = 0; int legendXOffset = 0;
for(int i = 0; i < graphs.size(); ++i) { for(int i = 0; i < graphs.size(); ++i) {
@ -255,6 +260,10 @@ public class SerialPlotter extends AbstractMonitor {
messageBuffer = new StringBuffer(); messageBuffer = new StringBuffer();
graphs = new ArrayList<>(); graphs = new ArrayList<>();
graphWidth.addChangeListener(cl -> {commandNewSize((int)graphWidth.getValue()); } );
clearButton.addActionListener(ae -> {commandClearGraph();});
} }
protected void onCreateWindow(Container mainPane) { protected void onCreateWindow(Container mainPane) {
@ -273,9 +282,23 @@ public class SerialPlotter extends AbstractMonitor {
serialRates.setMaximumSize(serialRates.getMinimumSize()); serialRates.setMaximumSize(serialRates.getMinimumSize());
clearButton = new JButton(tr("Clear output"));
graphWidth = new JSpinner(new SpinnerNumberModel(
BUFFER_CAPACITY_DEFAULT, //initial value
BUFFER_CAPACITY_MIN, //min
BUFFER_CAPACITY_MAX, //max
1)); //step
graphWidth.setMaximumSize(graphWidth.getMinimumSize());
JSpinner.NumberEditor editor = new JSpinner.NumberEditor(graphWidth);
editor.getFormat().setGroupingUsed(false);
graphWidth.setEditor(editor);
pane.add(Box.createHorizontalGlue()); pane.add(Box.createHorizontalGlue());
pane.add(Box.createRigidArea(new Dimension(8, 0))); pane.add(Box.createRigidArea(new Dimension(8, 0)));
pane.add(serialRates); pane.add(serialRates);
pane.add(clearButton);
pane.add(graphWidth);
mainPane.add(pane, BorderLayout.SOUTH); mainPane.add(pane, BorderLayout.SOUTH);
@ -381,6 +404,9 @@ public class SerialPlotter extends AbstractMonitor {
} }
protected void onEnableWindow(boolean enable) { protected void onEnableWindow(boolean enable) {
serialRates.setEnabled(enable);
graphWidth.setEnabled(enable);
clearButton.setEnabled(enable);
textField.setEnabled(enable); textField.setEnabled(enable);
sendButton.setEnabled(enable); sendButton.setEnabled(enable);
} }
@ -389,6 +415,34 @@ public class SerialPlotter extends AbstractMonitor {
serialRates.addActionListener(listener); serialRates.addActionListener(listener);
} }
private void setNewBufferCapacity(int capacity){
if(buffer_capacity != capacity) {
if(capacity > BUFFER_CAPACITY_MAX) buffer_capacity = BUFFER_CAPACITY_MAX;
else if(capacity < BUFFER_CAPACITY_MIN) buffer_capacity = BUFFER_CAPACITY_MIN;
else buffer_capacity = capacity;
for(int i = 0; i < graphs.size(); i++) {
graphs.get(i).buffer.newCapacity(buffer_capacity);
}
xCount=0;
}
}
private void commandClearGraph()
{
graphs.clear();
xCount=0;
}
private void commandNewSize(int newSize)
{
setNewBufferCapacity(newSize);
if((int)graphWidth.getValue() != newSize) {
graphWidth.setValue(newSize);
}
}
public void message(final String s) { public void message(final String s) {
messageBuffer.append(s); messageBuffer.append(s);
while (true) { while (true) {
@ -413,6 +467,35 @@ public class SerialPlotter extends AbstractMonitor {
int validParts = 0; int validParts = 0;
int validLabels = 0; int validLabels = 0;
for(int i = 0; i < parts.length; ++i) { for(int i = 0; i < parts.length; ++i) {
// all commands start with #
if(parts[i].startsWith("#") && parts[i].length() > 1) {
String command = parts[i].substring(1, parts[i].length()).trim();
if("CLEAR".equals(command)) {
commandClearGraph();
}
else if(command.startsWith("SIZE:")) {
String[] subString = parts[i].split("[:]+");
int newSize = BUFFER_CAPACITY_DEFAULT;
if(subString.length > 1) {
try {
newSize = Integer.parseInt(subString[1]);
} catch (NumberFormatException e) {
// Ignore
}
}
commandNewSize(newSize);
}
} else {
try {
double value = Double.valueOf(parts[i]);
if(validParts >= graphs.size()) {
graphs.add(new Graph(validParts, buffer_capacity));
}
graphs.get(validParts).buffer.add(value);
validParts++;
} catch (NumberFormatException e) {
// ignore
}
Double value = null; Double value = null;
String label = null; String label = null;
@ -451,14 +534,14 @@ public class SerialPlotter extends AbstractMonitor {
if(value != null) { if(value != null) {
if(validParts >= graphs.size()) { if(validParts >= graphs.size()) {
graphs.add(new Graph(validParts)); graphs.add(new Graph(validParts, buffer_capacity));
} }
graphs.get(validParts).buffer.add(value); graphs.get(validParts).buffer.add(value);
validParts++; validParts++;
} }
if(label != null) { if(label != null) {
if(validLabels >= graphs.size()) { if(validLabels >= graphs.size()) {
graphs.add(new Graph(validLabels)); graphs.add(new Graph(validLabels, buffer_capacity));
} }
graphs.get(validLabels).label = label; graphs.get(validLabels).label = label;
validLabels++; validLabels++;
@ -467,10 +550,11 @@ public class SerialPlotter extends AbstractMonitor {
else if(validLabels > validParts) validParts = validLabels; else if(validLabels > validParts) validParts = validLabels;
} }
} }
}
SwingUtilities.invokeLater(SerialPlotter.this::repaint); SwingUtilities.invokeLater(SerialPlotter.this::repaint);
} }
public void open() throws Exception { public void open() throws Exception {
super.open(); super.open();

View File

@ -4,10 +4,10 @@ import java.util.NoSuchElementException;
public class CircularBuffer { public class CircularBuffer {
private final double[] elements; private double[] elements;
private int start = -1; private int start = -1;
private int end = -1; private int end = -1;
private final int capacity; private int capacity;
public void add(double num) { public void add(double num) {
end = (end + 1) % capacity; end = (end + 1) % capacity;
@ -37,6 +37,12 @@ public class CircularBuffer {
elements = new double[capacity]; elements = new double[capacity];
} }
public void newCapacity(int capacity) {
elements = new double[capacity];
this.capacity = capacity;
start = end = 0;
}
public double min() { public double min() {
if (size() == 0) { if (size() == 0) {
throw new NoSuchElementException(); throw new NoSuchElementException();