diff --git a/src/main/java/de/neemann/digital/core/element/Keys.java b/src/main/java/de/neemann/digital/core/element/Keys.java index d629a7e68..04f925bfa 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -523,9 +523,12 @@ public final class Keys { /** * Used to indicate if the 7-seg display has a common cathode output */ - public static final Key COMMON_CATHODE + public static final Key COMMON_CONNECTION = new Key<>("commonCathode", false).allowGroupEdit(); + public static final Key COMMON_ANODE + = new Key<>("commonAnode", false).setDependsOn(COMMON_CONNECTION).allowGroupEdit(); + /** * Used to enable the storage of the last state in the Seven Seg display. */ diff --git a/src/main/java/de/neemann/digital/core/io/Out.java b/src/main/java/de/neemann/digital/core/io/Out.java index 1037d9012..35640d605 100644 --- a/src/main/java/de/neemann/digital/core/io/Out.java +++ b/src/main/java/de/neemann/digital/core/io/Out.java @@ -142,23 +142,30 @@ public class Out implements Element { private final static class SevenSegTypeDescription extends ElementTypeDescription { private SevenSegTypeDescription() { super("Seven-Seg", attributes -> { - if (attributes.get(Keys.COMMON_CATHODE)) + if (attributes.get(Keys.COMMON_CONNECTION)) return new Out(1, 1, 1, 1, 1, 1, 1, 1, 1); else return new Out(1, 1, 1, 1, 1, 1, 1, 1); }); addAttribute(Keys.COLOR); - addAttribute(Keys.COMMON_CATHODE); + addAttribute(Keys.COMMON_CONNECTION); + addAttribute(Keys.COMMON_ANODE); addAttribute(Keys.LED_PERSISTENCE); } @Override - public PinDescriptions getInputDescription(ElementAttributes attributes) throws NodeException { - if (attributes.get(Keys.COMMON_CATHODE)) { - return new PinDescriptions( - input("a"), input("b"), input("c"), - input("d"), input("e"), input("f"), - input("g"), input("dp"), input("cc")).setLangKey(getPinLangKey()); + public PinDescriptions getInputDescription(ElementAttributes attributes) { + if (attributes.get(Keys.COMMON_CONNECTION)) { + if (attributes.get(Keys.COMMON_ANODE)) + return new PinDescriptions( + input("a"), input("b"), input("c"), + input("d"), input("e"), input("f"), + input("g"), input("dp"), input("ca")).setLangKey(getPinLangKey()); + else + return new PinDescriptions( + input("a"), input("b"), input("c"), + input("d"), input("e"), input("f"), + input("g"), input("dp"), input("cc")).setLangKey(getPinLangKey()); } else return new PinDescriptions( input("a"), input("b"), input("c"), diff --git a/src/main/java/de/neemann/digital/draw/shapes/SevenSegShape.java b/src/main/java/de/neemann/digital/draw/shapes/SevenSegShape.java index 85ecf5cb4..7e70eddb3 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/SevenSegShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/SevenSegShape.java @@ -27,9 +27,10 @@ import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; */ public class SevenSegShape extends SevenShape { private final PinDescriptions inputPins; - private final boolean commonCatode; + private final boolean commonConnection; private final boolean persistence; private final boolean[] data; + private final boolean anode; private ObservableValues inputValues; private Value[] inputs = new Value[8]; private Value ccin; @@ -45,7 +46,8 @@ public class SevenSegShape extends SevenShape { public SevenSegShape(ElementAttributes attr, PinDescriptions inputs, PinDescriptions outputs) { super(attr); this.inputPins = inputs; - commonCatode = attr.get(Keys.COMMON_CATHODE); + commonConnection = attr.get(Keys.COMMON_CONNECTION); + anode = attr.get(Keys.COMMON_ANODE); persistence = attr.get(Keys.LED_PERSISTENCE); data = new boolean[8]; } @@ -62,7 +64,7 @@ public class SevenSegShape extends SevenShape { pins.add(new Pin(new Vector(SIZE, SIZE * HEIGHT), inputPins.get(5))); pins.add(new Pin(new Vector(SIZE * 2, SIZE * HEIGHT), inputPins.get(6))); pins.add(new Pin(new Vector(SIZE * 3, SIZE * HEIGHT), inputPins.get(7))); - if (commonCatode) + if (commonConnection) pins.add(new Pin(new Vector(SIZE * 4, SIZE * HEIGHT), inputPins.get(8))); } return pins; @@ -79,7 +81,7 @@ public class SevenSegShape extends SevenShape { @Override public void drawTo(Graphic graphic, Style highLight) { super.drawTo(graphic, highLight); - if (commonCatode) + if (commonConnection) graphic.drawLine( new Vector(SIZE * 4 - SIZE2, SIZE * HEIGHT - 1), new Vector(SIZE * 4, SIZE * HEIGHT - 1), Style.NORMAL); @@ -90,7 +92,7 @@ public class SevenSegShape extends SevenShape { if (inputValues != null) { for (int i = 0; i < 8; i++) inputs[i] = inputValues.get(i).getCopy(); - if (commonCatode) + if (commonConnection) ccin = inputValues.get(8).getCopy(); } } @@ -100,15 +102,18 @@ public class SevenSegShape extends SevenShape { if (inputValues == null) return true; - if (persistence && commonCatode) { + if (persistence && commonConnection) { if (!ccin.isHighZ() && !ccin.getBool()) data[i] = inputs[i].getBool(); return data[i]; } else { - if (commonCatode && (ccin.isHighZ() || ccin.getBool())) + if (commonConnection && (ccin.isHighZ() || (ccin.getBool() ^ anode))) return false; - return inputs[i].getBool(); + if (inputs[i].isHighZ()) + return false; + + return inputs[i].getBool() ^ anode; } } diff --git a/src/test/java/de/neemann/digital/draw/shapes/SevenSegShapeTest.java b/src/test/java/de/neemann/digital/draw/shapes/SevenSegShapeTest.java new file mode 100644 index 000000000..c7a5af3f7 --- /dev/null +++ b/src/test/java/de/neemann/digital/draw/shapes/SevenSegShapeTest.java @@ -0,0 +1,121 @@ +package de.neemann.digital.draw.shapes; + +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.ObservableValues; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.Keys; +import de.neemann.digital.core.element.PinDescriptions; +import de.neemann.digital.draw.elements.IOState; +import junit.framework.TestCase; + +public class SevenSegShapeTest extends TestCase { + + public void testCommonCathode() { + ElementAttributes attr = new ElementAttributes() + .set(Keys.COMMON_CONNECTION, true) + .set(Keys.COMMON_ANODE, false); + + ObservableValue a = new ObservableValue("a", 1); + ObservableValue b = new ObservableValue("b", 1); + ObservableValue c = new ObservableValue("c", 1); + ObservableValue d = new ObservableValue("d", 1); + ObservableValue e = new ObservableValue("e", 1); + ObservableValue f = new ObservableValue("f", 1); + ObservableValue g = new ObservableValue("g", 1); + ObservableValue dp = new ObservableValue("dp", 1); + ObservableValue cc = new ObservableValue("cc", 1); + final ObservableValues observableValues = new ObservableValues(a, b, c, d, e, f, g, dp, cc); + PinDescriptions inputs = new PinDescriptions(observableValues); + SevenSegShape ss = new SevenSegShape(attr, inputs, new PinDescriptions()); + IOState state = new IOState(observableValues, null, null); + ss.applyStateMonitor(state, null); + + checkValue(false, ss, 0, a, 0, 1, cc, 0, 1); + checkValue(false, ss, 0, a, 0, 1, cc, 1, 1); + checkValue(false, ss, 0, a, 1, 1, cc, 0, 1); + checkValue(false, ss, 0, a, 1, 1, cc, 1, 1); + + checkValue(false, ss, 0, a, 0, 1, cc, 0, 0); + checkValue(false, ss, 0, a, 0, 1, cc, 1, 0); + checkValue(false, ss, 0, a, 1, 1, cc, 0, 0); + checkValue(false, ss, 0, a, 1, 1, cc, 1, 0); + + checkValue(false, ss, 0, a, 0, 0, cc, 0, 1); + checkValue(false, ss, 0, a, 0, 0, cc, 1, 1); + checkValue(false, ss, 0, a, 1, 0, cc, 0, 1); + checkValue(false, ss, 0, a, 1, 0, cc, 1, 1); + + checkValue(false, ss, 0, a, 0, 0, cc, 0, 0); + checkValue(false, ss, 0, a, 0, 0, cc, 1, 0); + checkValue(true, ss, 0, a, 1, 0, cc, 0, 0); + checkValue(false, ss, 0, a, 1, 0, cc, 1, 0); + + checkValue(false, ss, 1, b, 0, 1, cc, 0, 1); + checkValue(false, ss, 1, b, 0, 1, cc, 1, 1); + checkValue(false, ss, 1, b, 1, 1, cc, 0, 1); + checkValue(false, ss, 1, b, 1, 1, cc, 1, 1); + + checkValue(false, ss, 1, b, 0, 1, cc, 0, 0); + checkValue(false, ss, 1, b, 0, 1, cc, 1, 0); + checkValue(false, ss, 1, b, 1, 1, cc, 0, 0); + checkValue(false, ss, 1, b, 1, 1, cc, 1, 0); + + checkValue(false, ss, 1, b, 0, 0, cc, 0, 1); + checkValue(false, ss, 1, b, 0, 0, cc, 1, 1); + checkValue(false, ss, 1, b, 1, 0, cc, 0, 1); + checkValue(false, ss, 1, b, 1, 0, cc, 1, 1); + + checkValue(false, ss, 1, b, 0, 0, cc, 0, 0); + checkValue(false, ss, 1, b, 0, 0, cc, 1, 0); + checkValue(true, ss, 1, b, 1, 0, cc, 0, 0); + checkValue(false, ss, 1, b, 1, 0, cc, 1, 0); + } + + public void testCommonAnode() { + ElementAttributes attr = new ElementAttributes() + .set(Keys.COMMON_CONNECTION, true) + .set(Keys.COMMON_ANODE, true); + + ObservableValue a = new ObservableValue("a", 1); + ObservableValue b = new ObservableValue("b", 1); + ObservableValue c = new ObservableValue("c", 1); + ObservableValue d = new ObservableValue("d", 1); + ObservableValue e = new ObservableValue("e", 1); + ObservableValue f = new ObservableValue("f", 1); + ObservableValue g = new ObservableValue("g", 1); + ObservableValue dp = new ObservableValue("dp", 1); + ObservableValue cc = new ObservableValue("ca", 1); + final ObservableValues observableValues = new ObservableValues(a, b, c, d, e, f, g, dp, cc); + PinDescriptions inputs = new PinDescriptions(observableValues); + SevenSegShape ss = new SevenSegShape(attr, inputs, new PinDescriptions()); + IOState state = new IOState(observableValues, null, null); + ss.applyStateMonitor(state, null); + + checkValue(false, ss, 0, a, 0, 1, cc, 0, 1); + checkValue(false, ss, 0, a, 0, 1, cc, 1, 1); + checkValue(false, ss, 0, a, 1, 1, cc, 0, 1); + checkValue(false, ss, 0, a, 1, 1, cc, 1, 1); + + checkValue(false, ss, 0, a, 0, 1, cc, 0, 0); + checkValue(false, ss, 0, a, 0, 1, cc, 1, 0); + checkValue(false, ss, 0, a, 1, 1, cc, 0, 0); + checkValue(false, ss, 0, a, 1, 1, cc, 1, 0); + + checkValue(false, ss, 0, a, 0, 0, cc, 0, 1); + checkValue(false, ss, 0, a, 0, 0, cc, 1, 1); + checkValue(false, ss, 0, a, 1, 0, cc, 0, 1); + checkValue(false, ss, 0, a, 1, 0, cc, 1, 1); + + checkValue(false, ss, 0, a, 0, 0, cc, 0, 0); + checkValue(true, ss, 0, a, 0, 0, cc, 1, 0); + checkValue(false, ss, 0, a, 1, 0, cc, 0, 0); + checkValue(false, ss, 0, a, 1, 0, cc, 1, 0); + } + + private void checkValue(boolean expected, SevenSegShape ss, int i, ObservableValue a, int av, int ahz, ObservableValue b, int bv, int bhz) { + a.set(av, ahz); + b.set(bv, bhz); + ss.readObservableValues(); + assertEquals(expected, ss.getStyle(i)); + } +} \ No newline at end of file