adds a pin control logic, see #394

This commit is contained in:
hneemann 2019-12-14 10:20:04 +01:00
parent 545e2ab57a
commit a4d65b9d02
7 changed files with 241 additions and 8 deletions

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2019 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.core.io;
import de.neemann.digital.core.Node;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.core.element.Element;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys;
import static de.neemann.digital.core.element.PinInfo.input;
/**
* The pin control logic
*/
public class PinControl extends Node implements Element {
/**
* The description of the pin control logic
*/
public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(PinControl.class, input("wr"), input("oe"))
.addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS);
private final int bits;
private final ObservableValue rdValue;
private final ObservableValue outWriteValue;
private ObservableValue wrValue;
private ObservableValue oeValue;
private ObservableValue outReadValue;
private long wr;
private boolean oe;
private long outRead;
/**
* Creates a new instance
*
* @param attr the elements attributes
*/
public PinControl(ElementAttributes attr) {
bits = attr.getBits();
rdValue = new ObservableValue("rd", bits).setPinDescription(DESCRIPTION);
outWriteValue = new ObservableValue("out", bits).setPinDescription(DESCRIPTION).setBidirectional();
}
@Override
public void setInputs(ObservableValues inputs) throws NodeException {
wrValue = inputs.get(0).addObserverToValue(this).checkBits(bits, this);
oeValue = inputs.get(1).addObserverToValue(this).checkBits(1, this);
outReadValue = inputs.get(2).addObserverToValue(this).checkBits(bits, this);
}
@Override
public void readInputs() throws NodeException {
wr = wrValue.getValue();
oe = oeValue.getBool();
outRead = outReadValue.getValue();
}
@Override
public void writeOutputs() throws NodeException {
if (oe) {
outWriteValue.setValue(wr);
rdValue.setValue(wr);
} else {
outWriteValue.setToHighZ();
rdValue.setValue(outRead);
}
}
@Override
public ObservableValues getOutputs() {
return new ObservableValues(rdValue, outWriteValue);
}
}

View File

@ -143,7 +143,8 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
.add(Keyboard.DESCRIPTION)
.add(Terminal.DESCRIPTION)
.add(VGA.DESCRIPTION)
.add(MIDI.DESCRIPTION)))
.add(MIDI.DESCRIPTION)
.add(PinControl.DESCRIPTION)))
.add(new LibraryNode(Lang.get("lib_wires"))
.add(Ground.DESCRIPTION)
.add(VDD.DESCRIPTION)

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.draw.shapes;
import de.neemann.digital.core.Observer;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.elements.IOState;
import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.Pins;
import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.Style;
import de.neemann.digital.draw.graphics.Vector;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
/**
* The shape for the pin control logic
*/
public class PinControlShape implements Shape {
private final PinDescriptions in;
private final PinDescriptions out;
/**
* Creates a new instance
*
* @param attr the elements attributes
* @param in the inputs
* @param out the outputs
*/
public PinControlShape(ElementAttributes attr, PinDescriptions in, PinDescriptions out) {
this.in = in;
this.out = out;
}
@Override
public Pins getPins() {
return new Pins()
.add(new Pin(new Vector(0, -SIZE), in.get(0)))
.add(new Pin(new Vector(0, 0), out.get(0)))
.add(new Pin(new Vector(0, +SIZE), in.get(1)))
.add(new Pin(new Vector(SIZE * 2, 0), out.get(1)));
}
@Override
public InteractorInterface applyStateMonitor(IOState ioState, Observer guiObserver) {
return null;
}
@Override
public void drawTo(Graphic graphic, Style highLight) {
graphic.drawLine(new Vector(0, -SIZE), new Vector(SIZE, 0), Style.NORMAL);
graphic.drawLine(new Vector(0, 0), new Vector(SIZE, 0), Style.NORMAL);
graphic.drawLine(new Vector(0, SIZE), new Vector(SIZE, 0), Style.NORMAL);
graphic.drawLine(new Vector(SIZE, 0), new Vector(SIZE * 2, 0), Style.NORMAL);
}
}

View File

@ -163,6 +163,7 @@ public final class ShapeFactory {
map.put(DiodeBackward.DESCRIPTION.getName(), DiodeBackwardShape::new);
map.put(PullUp.DESCRIPTION.getName(), PullUpShape::new);
map.put(PullDown.DESCRIPTION.getName(), PullDownShape::new);
map.put(PinControl.DESCRIPTION.getName(), PinControlShape::new);
// disables string formatting for external components, see #272
map.put(External.DESCRIPTION.getName(),

View File

@ -338,25 +338,45 @@
<string name="elem_Driver_pin_sel">Eingang zum Steuern des Treibers.
Ist dieser Eingang auf 1 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 0, ist der Ausgang hochohmig.</string>
<string name="elem_DriverInvSel">Treiber, invertierte Auswahl</string>
<string name="elem_DriverInvSel_tt">Ein Treiber kann dazu verwendet werden, ein Datenwort nur unter speziellen Voraussetzungen auf eine andere Leitung weiterzureichen.
<string name="elem_DriverInvSel_tt">Ein Treiber kann dazu verwendet werden, ein Datenwort nur unter speziellen
Voraussetzungen auf eine andere Leitung weiterzureichen.
Gesteuert wird der Treiber durch den sel Eingang.
Ist der sel Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht.
Ist der Eingang 1, ist der Ausgang hochohmig.
</string>
<string name="elem_DriverInvSel_pin_in">Das Eingangssignal des Treibers.</string>
<string name="elem_DriverInvSel_pin_sel">Eingang zum Steuern des Treibers.
Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1, ist der Ausgang hochohmig.</string>
<string name="elem_DriverInvSel_pin_out">Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0 gesetzt ist.</string>
Ist dieser Eingang auf 0 gesetzt, wird der am Eingang anliegende Wert zum Ausgang gereicht. Ist der Eingang 1,
ist der Ausgang hochohmig.
</string>
<string name="elem_DriverInvSel_pin_out">Gibt den am Eingang anliegenden Wert aus, wenn der Selection Eingang auf 0
gesetzt ist.
</string>
<string name="elem_PinControl">Pinsteuerung</string>
<string name="elem_PinControl_tt">Steuerlogik für einen bidirektionalen Pin.
Nur im Rahmen der VHDL- oder Verilog-Generierung erforderlich!
Diese Komponente ist notwendig, um einen bidirektionalen HDL-Port zu erstellen!
Wenn Sie keinen bidirektionalen IO-Port auf einem FPGA verwenden wollen, verwenden Sie diese Komponente nicht!
</string>
<string name="elem_PinControl_pin_wr">Die auszugebenden Daten</string>
<string name="elem_PinControl_pin_oe">Aktiviert die Ausgabe</string>
<string name="elem_PinControl_pin_rd">Die zu lesenden Daten.</string>
<string name="elem_PinControl_pin_out">Der Anschluss für den eigentlichen Pin. Hier sollte nur noch ein einzelner
Eingang angeschlossen werden.
</string>
<!-- Plexers -->
<string name="elem_Multiplexer">Multiplexer</string>
<string name="elem_Multiplexer_tt">Ein Baustein, welcher den Wert eines der Eingänge am Ausgang ausgibt.
Über den sel-Eingang wird ausgewählt, welcher der Eingänge ausgegeben werden soll.</string>
Über den sel-Eingang wird ausgewählt, welcher der Eingänge ausgegeben werden soll.
</string>
<string name="elem_Multiplexer_input">Der {0}. Dateneingang des Multiplexers.</string>
<string name="elem_Multiplexer_output">Ausgeben wird der Wert, der am gewählten Dateneingang anliegt.</string>
<string name="elem_Multiplexer_pin_sel">Mit dieser Leitung wird der Dateneingang ausgewählt, welcher am Ausgang ausgegeben werden soll.</string>
<string name="elem_Multiplexer_pin_sel">Mit dieser Leitung wird der Dateneingang ausgewählt, welcher am Ausgang
ausgegeben werden soll.
</string>
<string name="elem_Demultiplexer">Demultiplexer</string>
<string name="elem_Demultiplexer_tt">Ein Baustein, welcher einen Eingangswert auf verschiedene Ausgänge ausgeben kann.
Gibt das Eingangssignal auf einem wählbaren Ausgang aus. Die anderen Ausgänge werden auf den Vorgabewert gesetzt.</string>

View File

@ -363,11 +363,24 @@
If the sel input is 1, this output is in high z state.
</string>
<string name="elem_PinControl">Pin Control</string>
<string name="elem_PinControl_tt">Control logic for a bi-directional pin. Only needed in the context of VHDL or
Verilog generation! This component is necessary to create a bi-directional HDL port! If you don't want
to use a di-directional IO-port on an FPGA, don't use this component!
</string>
<string name="elem_PinControl_pin_wr">The data to be output.</string>
<string name="elem_PinControl_pin_oe">Activates the output.</string>
<string name="elem_PinControl_pin_rd">The data to be read.</string>
<string name="elem_PinControl_pin_out">The connector for the actual pin. Only a single input should be connected
here.
</string>
<!-- Plexers -->
<string name="elem_Multiplexer">Multiplexer</string>
<string name="elem_Multiplexer_tt">A component which uses the value of the sel pin to decide which input value is set to the output.</string>
<string name="elem_Multiplexer_tt">A component which uses the value of the sel pin to decide which input value is
set to the output.
</string>
<string name="elem_Multiplexer_input">The {0}. data input of the multiplexer.</string>
<string name="elem_Multiplexer_output">The value of the selected input.</string>
<string name="elem_Multiplexer_pin_sel">This input is used to select the data input which is output.</string>

View File

@ -614,6 +614,30 @@
<elementAttributes/>
<pos x="600" y="920"/>
</visualElement>
<visualElement>
<elementName>PinControl</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
</elementAttributes>
<pos x="780" y="960"/>
</visualElement>
<visualElement>
<elementName>Tunnel</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>NetName</string>
<string>zz</string>
</entry>
</elementAttributes>
<pos x="760" y="940"/>
</visualElement>
</visualElements>
<wires>
<wire>
@ -716,6 +740,10 @@
<p1 x="1080" y="900"/>
<p2 x="1120" y="900"/>
</wire>
<wire>
<p1 x="580" y="900"/>
<p2 x="700" y="900"/>
</wire>
<wire>
<p1 x="780" y="200"/>
<p2 x="800" y="200"/>
@ -856,6 +884,10 @@
<p1 x="580" y="980"/>
<p2 x="600" y="980"/>
</wire>
<wire>
<p1 x="700" y="980"/>
<p2 x="780" y="980"/>
</wire>
<wire>
<p1 x="280" y="980"/>
<p2 x="300" y="980"/>
@ -1060,6 +1092,14 @@
<p1 x="580" y="940"/>
<p2 x="600" y="940"/>
</wire>
<wire>
<p1 x="760" y="940"/>
<p2 x="780" y="940"/>
</wire>
<wire>
<p1 x="780" y="940"/>
<p2 x="820" y="940"/>
</wire>
<wire>
<p1 x="1080" y="620"/>
<p2 x="1100" y="620"/>
@ -1330,7 +1370,7 @@
</wire>
<wire>
<p1 x="580" y="860"/>
<p2 x="580" y="920"/>
<p2 x="580" y="900"/>
</wire>
<wire>
<p1 x="580" y="360"/>
@ -1340,6 +1380,10 @@
<p1 x="580" y="380"/>
<p2 x="580" y="420"/>
</wire>
<wire>
<p1 x="580" y="900"/>
<p2 x="580" y="920"/>
</wire>
<wire>
<p1 x="580" y="920"/>
<p2 x="580" y="940"/>
@ -1460,6 +1504,10 @@
<p1 x="460" y="400"/>
<p2 x="460" y="420"/>
</wire>
<wire>
<p1 x="780" y="940"/>
<p2 x="780" y="960"/>
</wire>
<wire>
<p1 x="780" y="180"/>
<p2 x="780" y="200"/>
@ -1788,6 +1836,10 @@
<p1 x="500" y="760"/>
<p2 x="500" y="840"/>
</wire>
<wire>
<p1 x="820" y="940"/>
<p2 x="820" y="960"/>
</wire>
<wire>
<p1 x="440" y="560"/>
<p2 x="440" y="580"/>
@ -1888,6 +1940,10 @@
<p1 x="700" y="160"/>
<p2 x="700" y="460"/>
</wire>
<wire>
<p1 x="700" y="900"/>
<p2 x="700" y="980"/>
</wire>
<wire>
<p1 x="700" y="460"/>
<p2 x="700" y="540"/>