mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-02 13:24:12 +01:00
Merge 945f542ed5
into 3278173ef8
This commit is contained in:
commit
a657266537
@ -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();
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user