/******************************************************************************* * 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.cburch.logisim.std.io; import java.awt.Color; import java.awt.Graphics; import java.util.ArrayList; import com.bfh.logisim.designrulecheck.CorrectLabel; import com.bfh.logisim.fpgaboardeditor.FPGAIOInformationContainer; import com.bfh.logisim.fpgagui.MappableResourcesContainer; import com.bfh.logisim.hdlgenerator.IOComponentInformationContainer; import com.cburch.logisim.data.Attribute; import com.cburch.logisim.data.AttributeSet; import com.cburch.logisim.data.Attributes; import com.cburch.logisim.data.Bounds; import com.cburch.logisim.data.Direction; import com.cburch.logisim.instance.Instance; //import com.cburch.logisim.instance.InstanceData; import com.cburch.logisim.instance.InstanceFactory; import com.cburch.logisim.instance.InstancePainter; import com.cburch.logisim.instance.InstanceState; import com.cburch.logisim.instance.Port; import com.cburch.logisim.instance.StdAttr; import com.cburch.logisim.util.GraphicsUtil; import com.cburch.logisim.util.StringUtil; public class PortIO extends InstanceFactory { public static final ArrayList<String> GetLabels(int size) { ArrayList<String> LabelNames = new ArrayList<String>(); for (int i = 0; i < size; i++) { LabelNames.add("pin_" + Integer.toString(i + 1)); } return LabelNames; } public static final int MAX_IO = 128; public static final int MIN_IO = 2; public static final Attribute<Integer> ATTR_SIZE = Attributes .forIntegerRange("number", Strings.getter("pioNumber"), MIN_IO, MAX_IO); // public static final Attribute<Boolean> ATTR_BUS = // Attributes.forBoolean("showBus", Strings.getter("pioShowBus")); public static final String BUSES = Strings.getter("pioBuses").toString(); public static final String PINS = Strings.getter("pioPins").toString(); public static final String[] OPTIONS = { BUSES, PINS }; public static final Attribute<String> ATTR_BUS = Attributes.forOption( "showBus", Strings.getter("pioShowBus"), OPTIONS); private MappableResourcesContainer mapInfo; public PortIO() { super("PortIO", Strings.getter("pioComponent")); int portSize = 8; setAttributes(new Attribute[] { StdAttr.LABEL, Io.ATTR_LABEL_LOC, StdAttr.LABEL_FONT, StdAttr.LABEL_COLOR, StdAttr.LABEL_VISIBILITY, ATTR_SIZE, ATTR_BUS }, new Object[] { "", Direction.EAST, StdAttr.DEFAULT_LABEL_FONT, StdAttr.DEFAULT_LABEL_COLOR, false, portSize, BUSES }); setFacingAttribute(StdAttr.FACING); setIconName("pio.gif"); // setInstancePoker(Poker.class); MyIOInformation = new IOComponentInformationContainer(0, 0, portSize, null, null, GetLabels(portSize), FPGAIOInformationContainer.IOComponentTypes.PortIO); // MyIOInformation.AddAlternateMapType(FPGAIOInformationContainer.IOComponentTypes.Button); MyIOInformation .AddAlternateMapType(FPGAIOInformationContainer.IOComponentTypes.Pin); } private void computeTextField(Instance instance) { Direction facing = Direction.NORTH; Object labelLoc = instance.getAttributeValue(Io.ATTR_LABEL_LOC); Bounds bds = instance.getBounds(); int x = bds.getX() + bds.getWidth() / 2; int y = bds.getY() + bds.getHeight() / 2; int halign = GraphicsUtil.H_CENTER; int valign = GraphicsUtil.V_CENTER; if (labelLoc == Direction.NORTH) { y = bds.getY() - 2; valign = GraphicsUtil.V_BOTTOM; } else if (labelLoc == Direction.SOUTH) { y = bds.getY() + bds.getHeight() + 2; valign = GraphicsUtil.V_TOP; } else if (labelLoc == Direction.EAST) { x = bds.getX() + bds.getWidth() + 2; halign = GraphicsUtil.H_LEFT; } else if (labelLoc == Direction.WEST) { x = bds.getX() - 2; halign = GraphicsUtil.H_RIGHT; } if (labelLoc == facing) { if (labelLoc == Direction.NORTH || labelLoc == Direction.SOUTH) { x += 2; halign = GraphicsUtil.H_LEFT; } else { y -= 2; valign = GraphicsUtil.V_BOTTOM; } } instance.setTextField(StdAttr.LABEL, StdAttr.LABEL_FONT, x, y, halign, valign); } @Override protected void configureNewInstance(Instance instance) { instance.addAttributeListener(); configurePorts(instance); computeTextField(instance); MyIOInformation.setNrOfInOutports( instance.getAttributeValue(ATTR_SIZE), GetLabels(instance.getAttributeValue(ATTR_SIZE))); } private void configurePorts(Instance instance) { if (instance.getAttributeValue(ATTR_BUS).equals(PINS)) { // TODO YSY PINS // Port[] ps = new Port[instance.getAttributeValue(ATTR_SIZE)]; // for (int i = 0; i < instance.getAttributeValue(ATTR_SIZE); i++) { // // ps[i] = new Port((i + 1) * 10, 0, Port.OUTPUT, 1); // ps[i].setToolTip(StringUtil.constantGetter(String.valueOf(i+1))); // } // instance.setPorts(ps); } else { int nbPorts = instance.getAttributeValue(ATTR_SIZE); Port[] ps = new Port[((nbPorts - 1) / 32) + 1]; int i = 0; while (nbPorts > 0) { ps[i] = new Port((i + 1) * 10, 0, Port.INOUT, (nbPorts > 32) ? 32 : nbPorts); ps[i].setToolTip(StringUtil.constantGetter(String .valueOf((32 * i)) + " to " + String.valueOf(32 * i + (nbPorts > 32 ? 32 : nbPorts) - 1))); i++; nbPorts -= (nbPorts > 32) ? 32 : nbPorts; } instance.setPorts(ps); } } @Override public String getHDLName(AttributeSet attrs) { StringBuffer CompleteName = new StringBuffer(); CompleteName.append(CorrectLabel.getCorrectLabel(attrs .getValue(StdAttr.LABEL))); if (CompleteName.length() == 0) { CompleteName.append("PORTIO"); } return CompleteName.toString(); } public MappableResourcesContainer getMapInfo() { return mapInfo; } @Override public Bounds getOffsetBounds(AttributeSet attrs) { if (attrs.getValue(ATTR_BUS).equals(PINS)) { return Bounds.create(0, 0, 10 + attrs.getValue(ATTR_SIZE).intValue() * 10, 40).rotate( Direction.NORTH, Direction.NORTH, 0, 0); } else { return Bounds.create(0, 0, 100, 40).rotate(Direction.NORTH, Direction.NORTH, 0, 0); } } /* * private static class State implements InstanceData, Cloneable { * * private int Value; private int size; * * public State(int value, int size) { Value = value; this.size = size; } * * public boolean BitSet(int bitindex) { if (bitindex >= size) { return * false; } int mask = 1 << bitindex; return (Value & mask) != 0; } * * public void ToggleBit(int bitindex) { if ((bitindex < 0) || (bitindex >= * size)) { return; } int mask = 1 << bitindex; Value ^= mask; } * * @Override public Object clone() { try { return super.clone(); } catch * (CloneNotSupportedException e) { return null; } } } */ // @Override // public boolean HDLSupportedComponent(String HDLIdentifier, // AttributeSet attrs) { // if (MyHDLGenerator == null) { // MyHDLGenerator = new PortHDLGeneratorFactory(); // } // return MyHDLGenerator.HDLTargetSupported(HDLIdentifier, attrs); // } @Override protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) { if (attr == Io.ATTR_LABEL_LOC) { computeTextField(instance); } else if (attr == ATTR_SIZE) { instance.recomputeBounds(); configurePorts(instance); computeTextField(instance); MyIOInformation.setNrOfInOutports( instance.getAttributeValue(ATTR_SIZE), GetLabels(instance.getAttributeValue(ATTR_SIZE))); } } @Override public void paintInstance(InstancePainter painter) { /* * State state = (State) painter.getData(); if (state == null) { state = * new State(0,painter.getAttributeValue(ATTR_SIZE)); * painter.setData(state); } */ Bounds bds = painter.getBounds().expand(-1); Graphics g = painter.getGraphics(); GraphicsUtil.switchToWidth(g, 2); g.setColor(Color.darkGray); g.fillRect(bds.getX(), bds.getY(), bds.getWidth(), bds.getHeight()); GraphicsUtil.switchToWidth(g, 1); if (painter.getAttributeValue(ATTR_BUS).equals(PINS)) { // TODO YSY PINS g.setColor(Color.white); g.setFont(StdAttr.DEFAULT_LABEL_FONT .deriveFont(StdAttr.DEFAULT_LABEL_FONT.getSize2D() * 0.6f)); for (int i = 0; i < painter.getAttributeValue(ATTR_SIZE); i++) { g.fillRect(bds.getX() + 6 + (i * 10), bds.getY() + 15, 6, 6); if (i == 0 || i == painter.getAttributeValue(ATTR_SIZE) - 1) { g.drawChars(Integer.toString(i).toCharArray(), 0, Integer .toString(i).toCharArray().length, bds.getX() + 6 + (i < 10 ? 0 : -2) + i * 10, bds.getY() + 12); } } } else { g.setColor(Color.LIGHT_GRAY); for (int i = 0; i < 9; i++) { g.fillRect(bds.getX() + 6 + (i * 10), bds.getY() + 15, 6, 6); g.fillRect(bds.getX() + 6 + (i * 10), bds.getY() + 25, 6, 6); } g.setColor(Color.WHITE); g.setFont(StdAttr.DEFAULT_LABEL_FONT); String text = painter.getAttributeValue(ATTR_SIZE).toString() + " PIN"; g.drawChars(text.toCharArray(), 0, text.toCharArray().length, bds.getX() + 6, bds.getY() + 12); } painter.drawLabel(); painter.drawPorts(); } @Override public void propagate(InstanceState state) { throw new UnsupportedOperationException( "PortIO simulation not implemented"); // State pins = (State) state.getData(); // if (pins == null) { // pins = new State(0, state.getAttributeValue(ATTR_SIZE)); // state.setData(pins); // } // for (int i = 0; i < state.getAttributeValue(ATTR_SIZE); i++) { // Value pinstate = (pins.BitSet(i)) ? Value.TRUE : Value.FALSE; // state.setPort(i, pinstate, 1); // } } // public static class Poker extends InstancePoker { // // @Override // public void mousePressed(InstanceState state, MouseEvent e) { // State val = (State) state.getData(); // Location loc = state.getInstance().getLocation(); // int cx = e.getX() - loc.getX() - 5; // int i = cx / 10; // val.ToggleBit(i); // state.getInstance().fireInvalidated(); // } // } // @Override public boolean RequiresNonZeroLabel() { return true; } public void setMapInfo(MappableResourcesContainer mapInfo) { this.mapInfo = mapInfo; } }