/*******************************************************************************
* 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.gray;
import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Direction;
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.util.GraphicsUtil;
import com.cburch.logisim.util.StringUtil;
/**
* Manufactures a simple counter that iterates over the 4-bit Gray Code. This
* example illustrates how a component can maintain its own internal state. All
* of the code relevant to state, though, appears in CounterData class.
*/
class SimpleGrayCounter extends InstanceFactory {
private static final BitWidth BIT_WIDTH = BitWidth.create(4);
// Again, notice how we don't have any instance variables related to an
// individual instance's state. We can't put that here, because only one
// SimpleGrayCounter object is ever created, and its job is to manage all
// instances that appear in any circuits.
public SimpleGrayCounter() {
super("Gray Counter (Simple)");
setOffsetBounds(Bounds.create(-30, -15, 30, 30));
setPorts(new Port[] { new Port(-30, 0, Port.INPUT, 1),
new Port(0, 0, Port.OUTPUT, BIT_WIDTH.getWidth()), });
}
@Override
public void paintInstance(InstancePainter painter) {
painter.drawBounds();
painter.drawClock(0, Direction.EAST); // draw a triangle on port 0
painter.drawPort(1); // draw port 1 as just a dot
// Display the current counter value centered within the rectangle.
// However, if the context says not to show state (as when generating
// printer output), then skip this.
if (painter.getShowState()) {
CounterData state = CounterData.get(painter, BIT_WIDTH);
Bounds bds = painter.getBounds();
GraphicsUtil.drawCenteredText(painter.getGraphics(), StringUtil
.toHexString(BIT_WIDTH.getWidth(), state.getValue()
.toIntValue()), bds.getX() + bds.getWidth() / 2,
bds.getY() + bds.getHeight() / 2);
}
}
@Override
public void propagate(InstanceState state) {
// Here I retrieve the state associated with this component via a helper
// method. In this case, the state is in a CounterData object, which is
// also where the helper method is defined. This helper method will end
// up creating a CounterData object if one doesn't already exist.
CounterData cur = CounterData.get(state, BIT_WIDTH);
boolean trigger = cur.updateClock(state.getPortValue(0));
if (trigger)
cur.setValue(GrayIncrementer.nextGray(cur.getValue()));
state.setPort(1, cur.getValue(), 9);
// (You might be tempted to determine the counter's current value
// via state.getPortValue(1). This is erroneous, though, because another
// component may be pushing a value onto the same point, which would
// "corrupt" the value found there. We really do need to store the
// current value in the instance.)
}
}