/**
*
* @author greg (at) myrobotlab.org
*
* This file is part of MyRobotLab (http://myrobotlab.org).
*
* MyRobotLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version (subject to the "Classpath" exception
* as provided in the LICENSE.txt file that accompanied this code).
*
* MyRobotLab is distributed in the hope that it will be useful or fun,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* All libraries in thirdParty bundle are subject to their own license
* requirements - please refer to http://myrobotlab.org/libraries for
* details.
*
* Enjoy !
*
* */
package org.myrobotlab.control;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultCaret;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.myrobotlab.control.widget.DigitalButton;
import org.myrobotlab.image.SerializableImage;
import org.myrobotlab.image.Util;
import org.myrobotlab.io.FileIO;
import org.myrobotlab.service.Arduino;
import org.myrobotlab.service.GUIService;
import org.myrobotlab.service.data.Pin;
import org.myrobotlab.service.interfaces.PinDefinition;
public class ArduinoGUI extends ServiceGUI implements ActionListener, TabControlEventHandler, ItemListener {
String[] BOARD_TYPES = new String[] { "", "Arduino Uno", "Arduino Duemilanove w/ ATmega328", "Arduino Diecimila or Duemilanove w/ ATmega168", "Arduino Nano w/ ATmega328",
"Arduino Nano w/ ATmega168", "Arduino Mega 2560 or Mega ADK", "Arduino Mega (ATmega1280)", "Arduino Leonardo", "Arduino Micro", "Arduino Mini w/ ATmega328",
"Arduino Mini w/ ATmega168", "Arduino Ethernet", "Arduino Fio", "Arduino BT w/ ATmega328", "Arduino BT w/ ATmega168", "LilyPad Arduino w/ ATmega328",
"LilyPad Arduino w/ ATmega168", "Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328", "Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega168",
"Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328", "Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168", "Arduino NG or older w/ ATmega168",
"Arduino NG or older w/ ATmega8" };
class TraceData {
Color color = null;
String controllerName;
int data[] = new int[DATA_WIDTH];
int index = 0;
String label;
int max = 0;
int mean = 0;
int min = 1024; // TODO - user input on min/max
int pin;
int sum = 0;
int total = 0;
int traceStart = 0;
}
JPanel statePanel = new JPanel();
JLabel state = new JLabel();
JLabel version = new JLabel();
JComboBox<String> boardTypes = new JComboBox<String>(BOARD_TYPES);
final RSyntaxTextArea editor = new RSyntaxTextArea();
final RTextScrollPane editorScrollPane = new RTextScrollPane(editor);
static final long serialVersionUID = 1L;
static final int DATA_WIDTH = 600;
static final int DATA_HEIGHT = 512;
Graphics g = null;
JLayeredPane imageMap;
int lastTraceXPos = 0;
public Arduino myArduino;
VideoWidget oscope = null;
JPanel oscopePanel = null;
/**
* array list of graphical pin components built from pinList
*/
ArrayList<PinComponent> pinComponentList = null;
List<PinDefinition> pinList = null;
public ArduinoGUI self;
SerializableImage sensorImage = null;
private JMenuItem serialDisconnect = new JMenuItem("disconnect");
private JMenuItem serialRefresh = new JMenuItem("refresh");
Dimension size = new Dimension(DATA_WIDTH, DATA_HEIGHT);
private JMenuItem softReset = new JMenuItem("soft reset");
JTabbedPane tabs = new JTabbedPane();
HashMap<Integer, TraceData> traceData = new HashMap<Integer, TraceData>();
DigitalButton uploadButton = null;
JButton openMrlComm = new JButton("Open in Arduino IDE");
JTextField arduinoPath= new JTextField(20);
JTextField ports = new JTextField(5);
JTextField boardType= new JTextField(5);
JButton uploadMrlComm = new JButton("Upload MRLComm");
JLabel uploadResult = new JLabel();
/**
* Get the number of lines in a file by counting the number of newline
* characters inside a String (and adding 1).
*/
static public int countLines(String what) {
int count = 1;
for (char c : what.toCharArray()) {
if (c == '\n')
count++;
}
return count;
}
/**
* Spew the contents of a String object out to a file.
*/
static public void saveFile(String str, File file) throws IOException {
File temp = File.createTempFile(file.getName(), null, file.getParentFile());
// PApplet.saveStrings(temp, new String[] { str }); FIXME
if (file.exists()) {
boolean result = file.delete();
if (!result) {
throw new IOException("Could not remove old version of " + file.getAbsolutePath());
}
}
boolean result = temp.renameTo(file);
if (!result) {
throw new IOException("Could not replace " + file.getAbsolutePath());
}
}
public ArduinoGUI(final String boundServiceName, final GUIService myService, final JTabbedPane tabs) {
super(boundServiceName, myService, tabs);
self = this;
}
/**
* The guts of the business logic of handling all the graphical components and
* their relations with each other.
*/
@Override
public void actionPerformed(ActionEvent e) {
Object o = e.getSource();
String cmd = e.getActionCommand();
Component c = (Component) e.getSource();
if (o == serialRefresh) {
// myService.send(boundServiceName, "getPortNames");
myService.send(boundServiceName, "publishState");
return;
}
if (o == softReset) {
myService.send(boundServiceName, "softReset");
return;
}
if (o == serialDisconnect) {
myService.send(boundServiceName, "disconnect");
return;
}
// buttons
if (DigitalButton.class == o.getClass()) {
DigitalButton b = (DigitalButton) o;
if (uploadButton == c) {
uploadButton.toggle();
return;
}
PinComponent pin = null;
int address = -1;
int value = -1;
if (b.parent != null) {
address = ((PinComponent) b.parent).pinNumber;
pin = ((PinComponent) b.parent);
}
if (b.type == PinComponent.TYPE_ONOFF) {
if ("off".equals(cmd)) {
// now on
value = PinComponent.HIGH;
myService.send(boundServiceName, "digitalWrite", address, value);
b.toggle();
} else {
// now off
value = PinComponent.LOW;
myService.send(boundServiceName, "digitalWrite", address, value);
b.toggle();
}
} else if (b.type == PinComponent.TYPE_INOUT) {
if ("out".equals(cmd)) {
// is now input
value = PinComponent.INPUT;
myService.send(boundServiceName, "pinMode", address, value);
myService.send(boundServiceName, "digitalReadPollingStart", address);
b.toggle();
} else if ("in".equals(cmd)) {
// is now output
value = PinComponent.OUTPUT;
myService.send(boundServiceName, "pinMode", address, value);
myService.send(boundServiceName, "digitalReadPollingStop", address);
b.toggle();
} else {
log.error(String.format("unknown digital pin cmd %s", cmd));
}
} else if (b.type == PinComponent.TYPE_TRACE || b.type == PinComponent.TYPE_ACTIVEINACTIVE) {
// digital pin
if (!pin.isAnalog) {
if (!pin.inOut.isOn) { // pin is off turn it on
value = PinComponent.INPUT;
myService.send(boundServiceName, "pinMode", address, value);
myService.send(boundServiceName, "digitalReadPollingStart", address);
pin.inOut.setOn(); // in
b.setOn();
} else {
value = PinComponent.OUTPUT;
myService.send(boundServiceName, "pinMode", address, value);
myService.send(boundServiceName, "digitalReadPollingStop", address);
pin.inOut.setOff();// out
b.setOff();
}
} else {
value = PinComponent.INPUT;
myService.send(boundServiceName, "pinMode", address, value);
// analog pin
if (pin.activeInActive.isOn) {
myService.send(boundServiceName, "analogReadPollingStop", address);
pin.activeInActive.setOff();
pin.trace.setOff();
b.setOff();
} else {
myService.send(boundServiceName, "analogReadPollingStart", address);
pin.activeInActive.setOn();
pin.trace.setOn();
b.setOn();
}
}
} else {
log.error("unknown pin type " + b.type);
}
log.info("DigitalButton");
}
if (o == openMrlComm){
myService.send(boundServiceName, "openMrlComm");
}
if (o == uploadMrlComm){
uploadResult.setText("Uploading Sketch");
myService.send(boundServiceName, "uploadSketch",arduinoPath.getText(),ports.getText(),boardType.getText());
}
}
public void onDisconnect(String portName) {
state.setText("not connected");
version.setText("");
openMrlComm.setEnabled(true);
arduinoPath.setText(myArduino.arduinoPath);
}
public void onConnect(String portName) {
state.setText(String.format("connected on port %s", portName));
openMrlComm.setEnabled(false);
}
@Override
public void attachGUI() {
subscribe("publishPin", "publishPin", Pin.class);
subscribe("publishVersion", "publishVersion", Integer.class);
subscribe("publishState", "getState", Arduino.class);
// subscribe("getPortNames", "onPortNames", List.class);
subscribe("getPorts", "getPorts", String.class);
subscribe("onConnect", "onConnect", String.class);
subscribe("onDisconnect", "onDisconnect", String.class);
// subscribe("setBoard", "setBoard", String.class);
// myService.send(boundServiceName, "broadcastState");
//send("getPortNames");
send("publishState");
}
public void publishVersion(Integer xver) {
if (xver != null) {
version.setText(xver + "");
}
}
@Override
public void detachGUI() {
unsubscribe("publishPin", "publishPin", Pin.class);
unsubscribe("publishVersion", "publishVersion", Integer.class);
unsubscribe("publishState", "getState", Arduino.class);
//unsubscribe("getPortNames", "getPortNames", ArrayList.class);
unsubscribe("onConnect", "onConnect", String.class);
unsubscribe("onDisconnect", "onDisconnect", String.class);
}
public void clearScreen() // TODO - static - put in oscope/image package
{
g.setColor(Color.BLACK);
g.fillRect(0, 0, DATA_WIDTH, DATA_HEIGHT); // TODO - ratio - to expand
// or reduce view
}
public void drawGrid() // TODO - static & put in oscope/image package
{
g.setColor(Color.DARK_GRAY);
g.drawLine(0, DATA_HEIGHT - 25, DATA_WIDTH - 1, DATA_HEIGHT - 25);
g.drawString("50", 10, DATA_HEIGHT - 25);
g.drawLine(0, DATA_HEIGHT - 50, DATA_WIDTH - 1, DATA_HEIGHT - 50);
g.drawString("100", 10, DATA_HEIGHT - 50);
g.drawLine(0, DATA_HEIGHT - 100, DATA_WIDTH - 1, DATA_HEIGHT - 100);
g.drawString("200", 10, DATA_HEIGHT - 100);
g.drawLine(0, DATA_HEIGHT - 200, DATA_WIDTH - 1, DATA_HEIGHT - 200);
g.drawString("400", 10, DATA_HEIGHT - 200);
g.drawLine(0, DATA_HEIGHT - 300, DATA_WIDTH - 1, DATA_HEIGHT - 300);
g.drawString("600", 10, DATA_HEIGHT - 300);
g.drawLine(0, DATA_HEIGHT - 400, DATA_WIDTH - 1, DATA_HEIGHT - 400);
g.drawString("800", 10, DATA_HEIGHT - 400);
}
public void getDuemilanovePanel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (imageMap != null) {
tabs.remove(imageMap);
}
imageMap = new JLayeredPane();
imageMap.setPreferredSize(size);
pinComponentList = new ArrayList<PinComponent>();
// set correct arduino image
JLabel image = new JLabel();
ImageIcon dPic = Util.getImageIcon("Arduino/arduino.duemilanove.200.pins.png");
image.setIcon(dPic);
Dimension s = image.getPreferredSize();
image.setBounds(0, 0, s.width, s.height);
imageMap.add(image, new Integer(1));
for (int i = 0; i < 20; ++i) {
PinComponent p = null;
if (i < 14) {
if (((i == 3) || (i == 5) || (i == 6) || (i == 9) || (i == 10) || (i == 11))) {
p = new PinComponent(myService, boundServiceName, i, true, false, false);
} else {
p = new PinComponent(myService, boundServiceName, i, false, false, false);
}
} else {
p = new PinComponent(myService, boundServiceName, i, false, true, false);
}
// set up the listeners
p.onOff.addActionListener(self);
p.inOut.addActionListener(self);
p.activeInActive.addActionListener(self);
p.trace.addActionListener(self);
// p.inOut2.addActionListener(this);
pinComponentList.add(p);
if (i < 2) {
continue;
}
if (i < 14) { // digital pins -----------------
int yOffSet = 0;
if (i > 7)
yOffSet = 18; // skip pin
p.inOut.setBounds(406, 297 - 18 * i - yOffSet, 30, 15);
imageMap.add(p.inOut, new Integer(2));
p.onOff.setBounds(436, 297 - 18 * i - yOffSet, 30, 15);
// p.onOff.getLabel().setUI(new VerticalLabelUI(true));
imageMap.add(p.onOff, new Integer(2));
if (p.isPWM) {
p.pwmSlider.setBounds(256, 297 - 18 * i - yOffSet, 90, 15);
imageMap.add(p.pwmSlider, new Integer(2));
p.data.setBounds(232, 297 - 18 * i - yOffSet, 32, 15);
p.data.setForeground(Color.white);
p.data.setBackground(Color.decode("0x0f7391"));
p.data.setOpaque(true);
imageMap.add(p.data, new Integer(2));
}
} else {
// analog pins -----------------
p.activeInActive.setBounds(11, 208 - 18 * (14 - i), 48, 15);
imageMap.add(p.activeInActive, new Integer(2));
p.data.setBounds(116, 205 - 18 * (14 - i), 32, 18);
p.data.setForeground(Color.white);
p.data.setBackground(Color.decode("0x0f7391"));
p.data.setOpaque(true);
imageMap.add(p.data, new Integer(2));
}
}
tabs.insertTab("pins", null, imageMap, "pin panel", 0);
}
});
}
public void getMrlCommPanel(){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JPanel mrlcommPanel = new JPanel();
mrlcommPanel.add(openMrlComm);
mrlcommPanel.add(new JLabel("Arduino IDE path"));
mrlcommPanel.add(arduinoPath);
mrlcommPanel.add(new JLabel("Port"));
mrlcommPanel.add(ports);
mrlcommPanel.add(new JLabel("Type"));
mrlcommPanel.add(boardType);
mrlcommPanel.add(uploadMrlComm);
// mrlcommPanel.add(uploadResult); FIXME super long message makes gui unmanagble
tabs.insertTab("mrlcomm", null, mrlcommPanel, "mrlcomm", 0);
tabs.setTabComponentAt(0, new TabControl2(self,tabs,mrlcommPanel,"mrlcomm"));
}
});
}
public void getEditorPanel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// editor.setEnabled(false);
String resourcePath = "Arduino/MRLComm.c";
log.info(String.format("loadResourceFile %s", resourcePath));
String sketch = FileIO.resourceToString(resourcePath);
// editorPanel.add(editor, BorderLayout.CENTER);
editor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_C);
editor.setCodeFoldingEnabled(true);
editor.setAntiAliasingEnabled(true);
editor.setText(sketch);
editorScrollPane.setPreferredSize(new Dimension(800, 600));
tabs.insertTab("mrlcomm", null, editorScrollPane, "mrlcomm", 0);
tabs.setTabComponentAt(0, new TabControl2(self, tabs, editorScrollPane, "mrlcomm"));
myService.getFrame().pack();
DefaultCaret caret = (DefaultCaret) editor.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
Cursor cursor = new Cursor(0);
editor.setCursor(cursor);
editor.setCaretPosition(0);
}
});
}
public void getMegaPanel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (imageMap != null) {
tabs.remove(imageMap);
}
pinComponentList = new ArrayList<PinComponent>();
imageMap = new JLayeredPane();
imageMap.setPreferredSize(size);
// set correct arduino image
JLabel image = new JLabel();
ImageIcon dPic = Util.getImageIcon("Arduino/mega.200.pins.png");
image.setIcon(dPic);
Dimension s = image.getPreferredSize();
image.setBounds(0, 0, s.width, s.height);
imageMap.add(image, new Integer(1));
for (int i = 0; i < 70; ++i) {
PinComponent p = null;
if (i > 1 && i < 14) { // pwm pins -----------------
p = new PinComponent(myService, boundServiceName, i, true, false, true);
int xOffSet = 0;
if (i > 7)
xOffSet = 18; // skip pin
p.inOut.setBounds(252 - 18 * i - xOffSet, 30, 15, 30);
imageMap.add(p.inOut, new Integer(2));
p.onOff.setBounds(252 - 18 * i - xOffSet, 0, 15, 30);
// p.onOff.getLabel().setUI(new VerticalLabelUI(true));
imageMap.add(p.onOff, new Integer(2));
if (p.isPWM) {
p.pwmSlider.setBounds(252 - 18 * i - xOffSet, 75, 15, 90);
imageMap.add(p.pwmSlider, new Integer(2));
p.data.setBounds(252 - 18 * i - xOffSet, 180, 32, 15);
p.data.setForeground(Color.white);
p.data.setBackground(Color.decode("0x0f7391"));
p.data.setOpaque(true);
imageMap.add(p.data, new Integer(2));
}
} else if (i < 54 && i > 21) {
// digital pin racks
p = new PinComponent(myService, boundServiceName, i, false, false, false);
if (i != 23 && i != 25 && i != 27 && i != 29) {
if ((i % 2 == 0)) {
// first rack of digital pins
p.inOut.setBounds(472, 55 + 9 * (i - 21), 30, 15);
imageMap.add(p.inOut, new Integer(2));
p.onOff.setBounds(502, 55 + 9 * (i - 21), 30, 15);
// p.onOff.getLabel().setUI(new
// VerticalLabelUI(true));
imageMap.add(p.onOff, new Integer(2));
} else {
// second rack of digital pins
p.inOut.setBounds(567, 45 + 9 * (i - 21), 30, 15);
imageMap.add(p.inOut, new Integer(2));
p.onOff.setBounds(597, 45 + 9 * (i - 21), 30, 15);
// p.onOff.getLabel().setUI(new
// VerticalLabelUI(true));
imageMap.add(p.onOff, new Integer(2));
}
}
} else if (i > 53) {
p = new PinComponent(myService, boundServiceName, i, false, true, true);
// analog pins -----------------
int xOffSet = 0;
if (i > 61)
xOffSet = 18; // skip pin
p.activeInActive.setBounds(128 + 18 * (i - 52) + xOffSet, 392, 15, 48);
imageMap.add(p.activeInActive, new Integer(2));
/*
* bag data at the moment - go look at the Oscope
* p.data.setBounds(208 + 18 * (i - 52) + xOffSet, 260, 32, 18);
* p.data.setForeground(Color.white);
* p.data.setBackground(Color.decode("0x0f7391"));
* p.data.setOpaque(true); imageMap.add(p.data, new Integer(2));
*/
} else {
p = new PinComponent(myService, boundServiceName, i, false, false, false);
}
// set up the listeners
p.onOff.addActionListener(self);
p.inOut.addActionListener(self);
p.activeInActive.addActionListener(self);
p.trace.addActionListener(self);
// p.inOut2.addActionListener(this);
pinComponentList.add(p);
}
tabs.insertTab("pins", null, imageMap, "pin panel", 0);
tabs.setTabComponentAt(0, new TabControl2(self, tabs, imageMap, "pins"));
}
});
}
public void getOscopePanel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (oscopePanel != null) {
tabs.remove(oscopePanel);
}
// CREATE SERVICE GUI !!!
oscopePanel = new JPanel(new GridBagLayout());
GridBagConstraints opgc = new GridBagConstraints();
JPanel tracePanel = new JPanel(new GridBagLayout());
opgc.fill = GridBagConstraints.HORIZONTAL;
opgc.gridx = 0;
opgc.gridy = 0;
float gradient = 1.0f / pinComponentList.size();
// pinList.size() mega 60 deuo 20
for (int i = 0; i < pinComponentList.size(); ++i) {
PinComponent p = pinComponentList.get(i);
if (!p.isAnalog) { // digital pins -----------------
p.trace.setText("D " + (i));
p.trace.onText = "D " + (i);
p.trace.offText = "D " + (i);
} else {
// analog pins ------------------
p.trace.setText("A " + (i - 14));
p.trace.onText = "A " + (i - 14);
p.trace.offText = "A " + (i - 14);
}
tracePanel.add(p.trace, opgc);
Color hsv = new Color(Color.HSBtoRGB((i * (gradient)), 0.8f, 0.7f));
p.trace.setBackground(hsv);
p.trace.offBGColor = hsv;
++opgc.gridy;
if (opgc.gridy % 20 == 0) {
opgc.gridy = 0;
++opgc.gridx;
}
}
opgc.gridx = 0;
opgc.gridy = 0;
oscope = new VideoWidget(boundServiceName, myService, tabs, false);
oscope.init();
sensorImage = new SerializableImage(new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB), "output");
g = sensorImage.getImage().getGraphics();
oscope.displayFrame(sensorImage);
oscopePanel.add(tracePanel, opgc);
++opgc.gridx;
oscopePanel.add(oscope.display, opgc);
tabs.insertTab("oscope", null, oscopePanel, "oscope panel", 0);
tabs.setTabComponentAt(0, new TabControl2(self, tabs, oscopePanel, "oscope"));
myService.getFrame().pack();
}
});
}
// public
public void getPinPanel() {
if (myArduino != null && myArduino.getBoardType() != null && myArduino.getBoardType().toLowerCase().contains(" mega ")) {
getMegaPanel();
return;
}
getDuemilanovePanel();
}
/**
* getState is called when the Arduino service changes state information FIXME
* - this method is often called by other threads so gui - updates must be
* done in the swing post method way
*
* @param arduino
*/
public void getState(final Arduino arduino) { // TODO - all getState data
// should be final
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
log.info("getState Arduino");
if (arduino != null) {
myArduino = arduino; // FIXME - super updates registry state
// ?
pinList = myArduino.getPinList();
if (arduino.isConnected()) {
onConnect(arduino.getPortName());
send("getVersion");
}
// update panels based on state change
// TODO - check what state the panels are to see if a
// change is needed
getPinPanel();
getOscopePanel();
uploadResult.setText(myArduino.uploadSketchResult);
}
}
});
}
@Override
public void init() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
display.setLayout(new BorderLayout());
state.setText("not connected");
statePanel.add(boardTypes);
statePanel.add(new JLabel("state: "));
statePanel.add(state);
statePanel.add(new JLabel(" version: "));
statePanel.add(version);
display.add(statePanel, BorderLayout.NORTH);
// ---------------- tabs begin ----------------------
tabs.setTabPlacement(SwingConstants.RIGHT);
getPinPanel();
getOscopePanel();
//getEditorPanel();
getMrlCommPanel();
display.add(tabs, BorderLayout.CENTER);
serialRefresh.addActionListener(self);
softReset.addActionListener(self);
serialDisconnect.addActionListener(self);
boardTypes.addItemListener(self);
openMrlComm.addActionListener(self);
uploadMrlComm.addActionListener(self);
}
});
}
public void publishPin(final Pin pin) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
log.info("PinData:{}",pin);
if (!traceData.containsKey(pin.pin)) {
TraceData td = new TraceData();
float gradient = 1.0f / pinComponentList.size();
Color color = new Color(Color.HSBtoRGB((pin.pin * (gradient)), 0.8f, 0.7f));
td.color = color;
traceData.put(pin.pin, td);
td.index = lastTraceXPos;
}
int value = pin.value / 2;
TraceData t = traceData.get(pin.pin);
t.index++;
lastTraceXPos = t.index;
t.data[t.index] = value;
++t.total;
t.sum += value;
t.mean = t.sum / t.total;
g.setColor(t.color);
if (pin.type == Pin.DIGITAL_VALUE || pin.type == Pin.PWM_VALUE) {
int yoffset = pin.pin * 15 + 35;
int quantum = -10;
g.drawLine(t.index, t.data[t.index - 1] * quantum + yoffset, t.index, value * quantum + yoffset);
} else if (pin.type == Pin.ANALOG_VALUE) {
g.drawLine(t.index, DATA_HEIGHT - t.data[t.index - 1], t.index, DATA_HEIGHT - value);
// log.info("" + (value / 2));
} else {
log.error("dont know how to display pin data method");
}
// computer min max and mean
// if different then blank & post to screen
if (value > t.max)
t.max = value;
if (value < t.min)
t.min = value;
if (t.index < DATA_WIDTH - 1) {
} else {
// TODO - when hit marks all startTracePos - cause the
// screen is
// blank - must iterate through all
t.index = 0;
clearScreen();
drawGrid();
g.setColor(Color.BLACK);
g.fillRect(20, t.pin * 15 + 5, 200, 15);
g.setColor(t.color);
g.drawString(String.format("min %d max %d mean %d ", t.min, t.max, t.mean), 20, t.pin * 15 + 20);
t.total = 0;
t.sum = 0;
}
oscope.displayFrame(sensorImage);
}
});
}
@Override
public void itemStateChanged(ItemEvent event) {
Object o = event.getSource();
if (o == boardTypes && event.getStateChange() == ItemEvent.SELECTED) {
String type = (String) boardTypes.getSelectedItem();
if (type != null && type.length() > 0) { // &&
// type.toUpperCase().contains("MEGA")
send("setBoard", type);
}
}
}
}