/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution 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 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution is distributed in the hope that it will be useful,
* 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.
*
* You should have received a copy of the GNU General Public License
* along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.bfh.logisim.fpgaboardeditor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.cburch.logisim.proj.Projects;
public class BoardReaderClass {
final static Logger logger = LoggerFactory
.getLogger(BoardReaderClass.class);
private String myfilename;
private DocumentBuilderFactory factory;
private DocumentBuilder parser;
private Document BoardDoc;
private String pictureError = "/resources/logisim/error.png";
private String pictureWarning = "/resources/logisim/warning.png";
public BoardReaderClass(String filename) {
myfilename = new String(filename);
}
private BufferedImage CreateImage(int width, int height,
String[] CodeTable, String PixelData) {
ImageXmlFactory reader = new ImageXmlFactory();
reader.SetCodeTable(CodeTable);
reader.SetCompressedString(PixelData);
BufferedImage result = reader.GetPicture(width, height);
return result;
}
public BoardInformation GetBoardInformation() {
try {
// Create instance of DocumentBuilderFactory
factory = DocumentBuilderFactory.newInstance();
// Get the DocumentBuilder
parser = factory.newDocumentBuilder();
// Create blank DOM Document
if (myfilename.startsWith("url:")) {
InputStream xml = getClass().getResourceAsStream(
"/" + myfilename.substring("url:".length()));
BoardDoc = parser.parse(xml);
} else if (myfilename.startsWith("file:")) {
File xml = new File(myfilename.substring("file:".length()));
BoardDoc = parser.parse(xml);
} else {
File xml = new File(myfilename);
BoardDoc = parser.parse(xml);
}
NodeList ImageList = BoardDoc
.getElementsByTagName(BoardWriterClass.ImageInformationString);
if (ImageList.getLength() != 1)
return null;
Node ThisImage = ImageList.item(0);
NodeList ImageParameters = ThisImage.getChildNodes();
String[] CodeTable = null;
String PixelData = null;
int PictureWidth = 0;
int PictureHeight = 0;
for (int i = 0; i < ImageParameters.getLength(); i++) {
if (ImageParameters.item(i).getNodeName()
.equals("CompressionCodeTable")) {
NamedNodeMap TableAttrs = ImageParameters.item(i)
.getAttributes();
for (int j = 0; j < TableAttrs.getLength(); j++) {
if (TableAttrs.item(j).getNodeName()
.equals("TableData")) {
String CodeTableStr = TableAttrs.item(j)
.getNodeValue();
CodeTable = CodeTableStr.split(" ");
}
}
}
if (ImageParameters.item(i).getNodeName()
.equals("PictureDimension")) {
NamedNodeMap SizeAttrs = ImageParameters.item(i)
.getAttributes();
for (int j = 0; j < SizeAttrs.getLength(); j++) {
if (SizeAttrs.item(j).getNodeName().equals("Width"))
PictureWidth = Integer.parseInt(SizeAttrs.item(j)
.getNodeValue());
if (SizeAttrs.item(j).getNodeName().equals("Height"))
PictureHeight = Integer.parseInt(SizeAttrs.item(j)
.getNodeValue());
}
}
if (ImageParameters.item(i).getNodeName().equals("PixelData")) {
NamedNodeMap PixelAttrs = ImageParameters.item(i)
.getAttributes();
for (int j = 0; j < PixelAttrs.getLength(); j++)
if (PixelAttrs.item(j).getNodeName().equals("PixelRGB"))
PixelData = PixelAttrs.item(j).getNodeValue();
}
}
if (CodeTable == null) {
showDialogNotification("Error",
"The selected xml file does not contain a compression code table");
return null;
}
if ((PictureWidth == 0) || (PictureHeight == 0)) {
showDialogNotification("Error",
"The selected xml file does not contain the picture dimensions");
return null;
}
if (PixelData == null) {
showDialogNotification("Error",
"The selected xml file does not contain the picture data");
return null;
}
BoardInformation result = new BoardInformation();
BufferedImage Picture = CreateImage(PictureWidth, PictureHeight,
CodeTable, PixelData);
if (Picture == null)
return null;
result.SetImage(Picture);
FPGAClass FPGA = GetFPGAInfo();
if (FPGA == null)
return null;
result.fpga = FPGA;
NodeList CompList = BoardDoc
.getElementsByTagName("PinsInformation"); // for backward
// compatibility
ProcessComponentList(CompList, result);
CompList = BoardDoc.getElementsByTagName("ButtonsInformation"); // for
// backward
// compatibility
ProcessComponentList(CompList, result);
CompList = BoardDoc.getElementsByTagName("LEDsInformation"); // for
// backward
// compatibility
ProcessComponentList(CompList, result);
CompList = BoardDoc
.getElementsByTagName(BoardWriterClass.ComponentsSectionString); // new
// format
ProcessComponentList(CompList, result);
return result;
} catch (Exception e) {
logger.error(
"Exceptions not handled yet in GetBoardInformation(), but got an exception: {}",
e.getMessage());
/* TODO: handle exceptions */
return null;
}
}
private FPGAClass GetFPGAInfo() {
NodeList FPGAList = BoardDoc
.getElementsByTagName(BoardWriterClass.BoardInformationSectionString);
long frequency = -1;
String clockpin = null;
String clockpull = null;
String clockstand = null;
String Unusedpull = null;
String vendor = null;
String Part = null;
String family = null;
String Package = null;
String Speed = null;
String UsbTmc = null;
String JTAGPos = null;
String FlashName = null;
String FlashPos = null;
if (FPGAList.getLength() != 1)
return null;
Node ThisFPGA = FPGAList.item(0);
NodeList FPGAParameters = ThisFPGA.getChildNodes();
for (int i = 0; i < FPGAParameters.getLength(); i++) {
if (FPGAParameters.item(i).getNodeName()
.equals(BoardWriterClass.ClockInformationSectionString)) {
NamedNodeMap ClockAttrs = FPGAParameters.item(i)
.getAttributes();
for (int j = 0; j < ClockAttrs.getLength(); j++) {
if (ClockAttrs.item(j).getNodeName()
.equals(BoardWriterClass.ClockSectionStrings[0]))
frequency = Long.parseLong(ClockAttrs.item(j)
.getNodeValue());
if (ClockAttrs.item(j).getNodeName()
.equals(BoardWriterClass.ClockSectionStrings[1]))
clockpin = ClockAttrs.item(j).getNodeValue();
if (ClockAttrs.item(j).getNodeName()
.equals(BoardWriterClass.ClockSectionStrings[2]))
clockpull = ClockAttrs.item(j).getNodeValue();
if (ClockAttrs.item(j).getNodeName()
.equals(BoardWriterClass.ClockSectionStrings[3]))
clockstand = ClockAttrs.item(j).getNodeValue();
}
}
if (FPGAParameters.item(i).getNodeName()
.equals(BoardWriterClass.UnusedPinsString)) {
NamedNodeMap UnusedAttrs = FPGAParameters.item(i)
.getAttributes();
for (int j = 0; j < UnusedAttrs.getLength(); j++)
if (UnusedAttrs.item(j).getNodeName()
.equals("PullBehavior"))
Unusedpull = UnusedAttrs.item(j).getNodeValue();
}
if (FPGAParameters.item(i).getNodeName()
.equals(BoardWriterClass.FPGAInformationSectionString)) {
NamedNodeMap FPGAAttrs = FPGAParameters.item(i).getAttributes();
for (int j = 0; j < FPGAAttrs.getLength(); j++) {
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[0]))
vendor = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[1]))
Part = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[2]))
family = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[3]))
Package = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[4]))
Speed = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[5]))
UsbTmc = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[6]))
JTAGPos = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[7]))
FlashName = FPGAAttrs.item(j).getNodeValue();
if (FPGAAttrs.item(j).getNodeName()
.equals(BoardWriterClass.FPGASectionStrings[8]))
FlashPos = FPGAAttrs.item(j).getNodeValue();
}
}
}
if ((frequency < 0) || (clockpin == null) || (clockpull == null)
|| (clockstand == null) || (Unusedpull == null)
|| (vendor == null) || (Part == null) || (family == null)
|| (Package == null) || (Speed == null)) {
showDialogNotification("Error",
"The selected xml file does not contain the required FPGA parameters");
return null;
}
if (UsbTmc == null)
UsbTmc = Boolean.toString(false);
if (JTAGPos == null)
JTAGPos = "1";
if (FlashPos == null)
FlashPos = "2";
FPGAClass result = new FPGAClass();
result.Set(frequency, clockpin, clockpull, clockstand, family, Part,
Package, Speed, vendor, Unusedpull,
UsbTmc.equals(Boolean.toString(true)), JTAGPos, FlashName, FlashPos);
return result;
}
private void ProcessComponentList(NodeList CompList, BoardInformation board) {
Node tempNode = null;
if (CompList.getLength() == 1) {
tempNode = CompList.item(0);
CompList = tempNode.getChildNodes();
for (int i = 0; i < CompList.getLength(); i++) {
FPGAIOInformationContainer NewComp = new FPGAIOInformationContainer(
CompList.item(i));
if (NewComp.IsKnownComponent()) {
board.AddComponent(NewComp);
}
}
}
}
private void showDialogNotification(String type, String string) {
final JFrame dialog = new JFrame(type);
JLabel pic = new JLabel();
if (type.equals("Warning")) {
pic.setIcon(new ImageIcon(getClass().getResource(pictureWarning)));
} else {
pic.setIcon(new ImageIcon(getClass().getResource(pictureError)));
}
GridBagLayout dialogLayout = new GridBagLayout();
dialog.setLayout(dialogLayout);
GridBagConstraints c = new GridBagConstraints();
JLabel message = new JLabel(string);
JButton close = new JButton("close");
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// panel.setAlwaysOnTop(true);
dialog.dispose();
}
};
close.addActionListener(actionListener);
c.gridx = 0;
c.gridy = 0;
c.ipadx = 20;
dialog.add(pic, c);
c.gridx = 1;
c.gridy = 0;
dialog.add(message, c);
c.gridx = 1;
c.gridy = 1;
dialog.add(close, c);
dialog.pack();
// dialog.setLocation(100, 100);
dialog.setLocation(Projects.getCenteredLoc(dialog.getWidth(),
dialog.getHeight()));
dialog.setAlwaysOnTop(true);
dialog.setVisible(true);
}
}