mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-26 22:41:59 -04:00
Added a floating gate N channel fet
This commit is contained in:
parent
46e8891d26
commit
e82e59a67d
45
src/main/java/de/neemann/digital/core/switching/FGNFET.java
Normal file
45
src/main/java/de/neemann/digital/core/switching/FGNFET.java
Normal file
@ -0,0 +1,45 @@
|
||||
package de.neemann.digital.core.switching;
|
||||
|
||||
import de.neemann.digital.core.ObservableValue;
|
||||
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;
|
||||
|
||||
/**
|
||||
* P-Channel MOS FET
|
||||
* Created by hneemann on 22.02.17.
|
||||
*/
|
||||
public class FGNFET extends NFET {
|
||||
/**
|
||||
* The switch description
|
||||
*/
|
||||
public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(FGNFET.class, input("G"))
|
||||
.addAttribute(Keys.ROTATE)
|
||||
.addAttribute(Keys.BITS)
|
||||
.addAttribute(Keys.LABEL)
|
||||
.addAttribute(Keys.BLOWN);
|
||||
|
||||
private final boolean programmed;
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param attr the attributes
|
||||
*/
|
||||
public FGNFET(ElementAttributes attr) {
|
||||
super(attr);
|
||||
getOutput1().setPinDescription(DESCRIPTION);
|
||||
getOutput2().setPinDescription(DESCRIPTION);
|
||||
programmed = attr.get(Keys.BLOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean getClosed(ObservableValue input) {
|
||||
if (input.isHighZ() || programmed)
|
||||
return false;
|
||||
else
|
||||
return input.getBool();
|
||||
}
|
||||
}
|
@ -25,7 +25,6 @@ public class NFET extends Node implements Element {
|
||||
private final Switch s;
|
||||
private ObservableValue input;
|
||||
private boolean closed;
|
||||
private boolean invert;
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
@ -33,18 +32,7 @@ public class NFET extends Node implements Element {
|
||||
* @param attr the attributes
|
||||
*/
|
||||
public NFET(ElementAttributes attr) {
|
||||
this(attr, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param attr the attributes
|
||||
* @param invert invert the input
|
||||
*/
|
||||
protected NFET(ElementAttributes attr, boolean invert) {
|
||||
s = new Switch(attr, false);
|
||||
this.invert = invert;
|
||||
s.getOutput1().setPinDescription(DESCRIPTION);
|
||||
s.getOutput2().setPinDescription(DESCRIPTION);
|
||||
}
|
||||
@ -63,10 +51,20 @@ public class NFET extends Node implements Element {
|
||||
|
||||
@Override
|
||||
public void readInputs() throws NodeException {
|
||||
closed = getClosed(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the state of the FET debending on its input
|
||||
*
|
||||
* @param input the input
|
||||
* @return true if FET is conducting
|
||||
*/
|
||||
boolean getClosed(ObservableValue input) {
|
||||
if (input.isHighZ())
|
||||
closed = false;
|
||||
return false;
|
||||
else
|
||||
closed = input.getBool() ^ invert;
|
||||
return input.getBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,14 +87,14 @@ public class NFET extends Node implements Element {
|
||||
/**
|
||||
* @return output 1
|
||||
*/
|
||||
public ObservableValue getOutput1() {
|
||||
ObservableValue getOutput1() {
|
||||
return s.getOutput1();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return output 2
|
||||
*/
|
||||
public ObservableValue getOutput2() {
|
||||
ObservableValue getOutput2() {
|
||||
return s.getOutput2();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.neemann.digital.core.switching;
|
||||
|
||||
import de.neemann.digital.core.ObservableValue;
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.ElementTypeDescription;
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
@ -25,8 +26,17 @@ public class PFET extends NFET {
|
||||
* @param attr the attributes
|
||||
*/
|
||||
public PFET(ElementAttributes attr) {
|
||||
super(attr, true);
|
||||
super(attr);
|
||||
getOutput1().setPinDescription(DESCRIPTION);
|
||||
getOutput2().setPinDescription(DESCRIPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean getClosed(ObservableValue input) {
|
||||
if (input.isHighZ())
|
||||
return false;
|
||||
else
|
||||
return !input.getBool();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import de.neemann.digital.core.memory.DataFieldConverter;
|
||||
import de.neemann.digital.core.pld.Diode;
|
||||
import de.neemann.digital.core.pld.DiodeBackward;
|
||||
import de.neemann.digital.core.pld.DiodeForeward;
|
||||
import de.neemann.digital.core.switching.FGNFET;
|
||||
import de.neemann.digital.core.wiring.Clock;
|
||||
import de.neemann.digital.draw.graphics.Graphic;
|
||||
import de.neemann.digital.draw.graphics.Polygon;
|
||||
@ -614,7 +615,8 @@ public class Circuit {
|
||||
for (VisualElement ve : visualElements)
|
||||
if (ve.equalsDescription(DiodeForeward.DESCRIPTION)
|
||||
|| ve.equalsDescription(DiodeBackward.DESCRIPTION)
|
||||
|| ve.equalsDescription(Diode.DESCRIPTION)) {
|
||||
|| ve.equalsDescription(Diode.DESCRIPTION)
|
||||
|| ve.equalsDescription(FGNFET.DESCRIPTION)) {
|
||||
ve.getElementAttributes().set(Keys.BLOWN, false);
|
||||
modified = true;
|
||||
}
|
||||
|
@ -13,10 +13,7 @@ import de.neemann.digital.core.pld.DiodeBackward;
|
||||
import de.neemann.digital.core.pld.DiodeForeward;
|
||||
import de.neemann.digital.core.pld.PullDown;
|
||||
import de.neemann.digital.core.pld.PullUp;
|
||||
import de.neemann.digital.core.switching.NFET;
|
||||
import de.neemann.digital.core.switching.PFET;
|
||||
import de.neemann.digital.core.switching.Relay;
|
||||
import de.neemann.digital.core.switching.Switch;
|
||||
import de.neemann.digital.core.switching.*;
|
||||
import de.neemann.digital.core.wiring.*;
|
||||
import de.neemann.digital.draw.elements.Circuit;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
@ -133,6 +130,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
.add(Relay.DESCRIPTION)
|
||||
.add(NFET.DESCRIPTION)
|
||||
.add(PFET.DESCRIPTION)
|
||||
.add(FGNFET.DESCRIPTION)
|
||||
.add(Reset.DESCRIPTION)
|
||||
.add(Break.DESCRIPTION))
|
||||
.add(new LibraryNode(Lang.get("lib_test"))
|
||||
|
@ -18,6 +18,7 @@ public abstract class FETShape implements Shape {
|
||||
private final PinDescriptions inputs;
|
||||
private final PinDescriptions outputs;
|
||||
private final String label;
|
||||
private int xOffs = SIZE2 - 2;
|
||||
private NFET fet;
|
||||
|
||||
/**
|
||||
@ -27,12 +28,21 @@ public abstract class FETShape implements Shape {
|
||||
* @param inputs the inputs
|
||||
* @param outputs the outputs
|
||||
*/
|
||||
protected FETShape(ElementAttributes attributes, PinDescriptions inputs, PinDescriptions outputs) {
|
||||
FETShape(ElementAttributes attributes, PinDescriptions inputs, PinDescriptions outputs) {
|
||||
this.inputs = inputs;
|
||||
this.outputs = outputs;
|
||||
label = attributes.getCleanLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gap width
|
||||
*
|
||||
* @param xOffs the gap width
|
||||
*/
|
||||
void setXOffs(int xOffs) {
|
||||
this.xOffs = xOffs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractorInterface applyStateMonitor(IOState ioState, Observer guiObserver) {
|
||||
fet = (NFET) ioState.getElement();
|
||||
@ -42,19 +52,18 @@ public abstract class FETShape implements Shape {
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic graphic, boolean highLight) {
|
||||
final int x1 = SIZE2 - 2;
|
||||
final int g = SIZE2 / 2;
|
||||
graphic.drawPolygon(new Polygon(false)
|
||||
.add(SIZE, 0)
|
||||
.add(x1, 0)
|
||||
.add(x1, SIZE2 - g), Style.NORMAL);
|
||||
.add(xOffs, 0)
|
||||
.add(xOffs, SIZE2 - g), Style.NORMAL);
|
||||
|
||||
graphic.drawPolygon(new Polygon(false)
|
||||
.add(SIZE, SIZE * 2)
|
||||
.add(x1, SIZE * 2)
|
||||
.add(x1, SIZE * 2 - SIZE2 + g), Style.NORMAL);
|
||||
.add(xOffs, SIZE * 2)
|
||||
.add(xOffs, SIZE * 2 - SIZE2 + g), Style.NORMAL);
|
||||
|
||||
graphic.drawLine(new Vector(x1, SIZE2 + g), new Vector(x1, SIZE + SIZE2 - g), Style.NORMAL);
|
||||
graphic.drawLine(new Vector(xOffs, SIZE2 + g), new Vector(xOffs, SIZE + SIZE2 - g), Style.NORMAL);
|
||||
|
||||
graphic.drawLine(new Vector(1, 0), new Vector(1, SIZE * 2), Style.NORMAL);
|
||||
|
||||
|
@ -0,0 +1,60 @@
|
||||
package de.neemann.digital.draw.shapes;
|
||||
|
||||
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.Pin;
|
||||
import de.neemann.digital.draw.elements.Pins;
|
||||
import de.neemann.digital.draw.graphics.Graphic;
|
||||
import de.neemann.digital.draw.graphics.Polygon;
|
||||
import de.neemann.digital.draw.graphics.Style;
|
||||
import de.neemann.digital.draw.graphics.Vector;
|
||||
|
||||
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
|
||||
import static de.neemann.digital.draw.shapes.GenericShape.SIZE2;
|
||||
|
||||
/**
|
||||
* The n-chan FET shape
|
||||
*/
|
||||
public class FGFETShapeN extends FETShape {
|
||||
|
||||
private final boolean programmed;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param attributes the attributes
|
||||
* @param inputs the inputs
|
||||
* @param outputs the outputs
|
||||
*/
|
||||
public FGFETShapeN(ElementAttributes attributes, PinDescriptions inputs, PinDescriptions outputs) {
|
||||
super(attributes, inputs, outputs);
|
||||
programmed = attributes.get(Keys.BLOWN);
|
||||
setXOffs(SIZE2 + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pins getPins() {
|
||||
return new Pins()
|
||||
.add(new Pin(new Vector(0, SIZE * 2), getInputs().get(0)))
|
||||
.add(new Pin(new Vector(SIZE, 0), getOutputs().get(0)))
|
||||
.add(new Pin(new Vector(SIZE, SIZE * 2), getOutputs().get(1)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTo(Graphic graphic, boolean highLight) {
|
||||
super.drawTo(graphic, highLight);
|
||||
|
||||
if (programmed)
|
||||
graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), Style.HIGHLIGHT);
|
||||
else
|
||||
graphic.drawLine(new Vector(6, 2 * SIZE - 4), new Vector(6, 4), Style.THIN);
|
||||
|
||||
// the arrow
|
||||
graphic.drawLine(new Vector(SIZE2 + 5, SIZE), new Vector(SIZE, SIZE), Style.THIN);
|
||||
graphic.drawPolygon(new Polygon(true)
|
||||
.add(SIZE2 + 2, SIZE)
|
||||
.add(SIZE - SIZE2 / 3, SIZE - SIZE2 / 4)
|
||||
.add(SIZE - SIZE2 / 3, SIZE + SIZE2 / 4), Style.THIN_FILLED);
|
||||
}
|
||||
}
|
@ -11,10 +11,7 @@ import de.neemann.digital.core.memory.RAMDualPort;
|
||||
import de.neemann.digital.core.memory.RAMSinglePort;
|
||||
import de.neemann.digital.core.memory.RAMSinglePortSel;
|
||||
import de.neemann.digital.core.pld.*;
|
||||
import de.neemann.digital.core.switching.NFET;
|
||||
import de.neemann.digital.core.switching.PFET;
|
||||
import de.neemann.digital.core.switching.Relay;
|
||||
import de.neemann.digital.core.switching.Switch;
|
||||
import de.neemann.digital.core.switching.*;
|
||||
import de.neemann.digital.core.wiring.*;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.elements.Tunnel;
|
||||
@ -88,6 +85,7 @@ public final class ShapeFactory {
|
||||
map.put(Switch.DESCRIPTION.getName(), SwitchShape::new);
|
||||
map.put(Relay.DESCRIPTION.getName(), RelayShape::new);
|
||||
map.put(NFET.DESCRIPTION.getName(), FETShapeN::new);
|
||||
map.put(FGNFET.DESCRIPTION.getName(), FGFETShapeN::new);
|
||||
map.put(PFET.DESCRIPTION.getName(), FETShapeP::new);
|
||||
map.put(Out.DESCRIPTION.getName(), OutputShape::new);
|
||||
map.put(Out.LEDDESCRIPTION.getName(), LEDShape::new);
|
||||
|
@ -10,6 +10,7 @@ import de.neemann.digital.core.element.Keys;
|
||||
import de.neemann.digital.core.pld.Diode;
|
||||
import de.neemann.digital.core.pld.DiodeBackward;
|
||||
import de.neemann.digital.core.pld.DiodeForeward;
|
||||
import de.neemann.digital.core.switching.FGNFET;
|
||||
import de.neemann.digital.draw.elements.*;
|
||||
import de.neemann.digital.draw.graphics.*;
|
||||
import de.neemann.digital.draw.library.ElementLibrary;
|
||||
@ -236,7 +237,8 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
|
||||
VisualElement ve = circuit.getElementAt(pos);
|
||||
if (ve != null && (ve.equalsDescription(DiodeBackward.DESCRIPTION)
|
||||
|| ve.equalsDescription(DiodeForeward.DESCRIPTION)
|
||||
|| ve.equalsDescription(Diode.DESCRIPTION))) {
|
||||
|| ve.equalsDescription(Diode.DESCRIPTION)
|
||||
|| ve.equalsDescription(FGNFET.DESCRIPTION))) {
|
||||
boolean blown = ve.getElementAttributes().get(Keys.BLOWN);
|
||||
ve.getElementAttributes().set(Keys.BLOWN, !blown);
|
||||
hasChanged();
|
||||
|
@ -372,6 +372,14 @@ Die gesammte Speichergröße beträgt damit damit dx*dy*2 Speicherworte.</string
|
||||
<string name="elem_PFET_pin_G">Gate</string>
|
||||
<string name="elem_PFET_pin_out1">Source</string>
|
||||
<string name="elem_PFET_pin_out2">Drain</string>
|
||||
|
||||
<string name="elem_FGNFET">N-Kanal Floating Gate FET</string>
|
||||
<string name="elem_FGNFET_tt">N-Kanal Feldeffekttransistor mit Floating Gate. Der Bulk ist mit Masse verbunden jedoch wird der Transistor ohne eine Body-Diode simuliert.
|
||||
Ist das Floating Gate geladen, ist der Transistor immer sperrend.</string>
|
||||
<string name="elem_FGNFET_pin_G">Gate</string>
|
||||
<string name="elem_FGNFET_pin_out2">Source</string>
|
||||
<string name="elem_FGNFET_pin_out1">Drain</string>
|
||||
|
||||
<string name="elem_RotEncoder">Drehencoder</string>
|
||||
<string name="elem_RotEncoder_tt">Drehknopf mit Drehencoder zur zustandsfreien Erfassung der Drehbewegung.</string>
|
||||
<string name="elem_RotEncoder_pin_A">Encodersignal A</string>
|
||||
@ -551,7 +559,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="key_isProgramMemory">Programmspeicher</string>
|
||||
<string name="key_isProgramMemory_tt">Zeichnet dieses ROM als Programmspeicher aus. Es kann damit von einer externen IDE beschrieben werden.</string>
|
||||
<string name="key_Blown">Programmiert</string>
|
||||
<string name="key_Blown_tt">Wenn gesetzt wird die Diode als "Durchgebrannt" bzw "Programmiert" betrachtet. Diese Einstellung kann direkt über die Taste 'P' verändert werden.</string>
|
||||
<string name="key_Blown_tt">Wenn gesetzt ist die Diode als "Durchgebrannt" bzw "Programmiert". Bei Floating Gate FETs wird das Gate geladen. Diese Einstellung kann direkt über die Taste 'P' verändert werden.</string>
|
||||
<string name="key_ExpressionFormat">Format</string>
|
||||
<string name="key_ExpressionFormat_tt">Anzeigeformat der Ausdrücke.</string>
|
||||
<string name="key_relayNormallyClosed">Relais ist ein Öffner</string>
|
||||
@ -702,8 +710,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="menu_runTests_tt">Führt alle Tests in der Schaltung aus!</string>
|
||||
<string name="menu_actualToDefault">Eingänge übernehmen</string>
|
||||
<string name="menu_actualToDefault_tt">Aktuelle Eingangswerte als neue Vorgabewerte übernehmen.</string>
|
||||
<string name="menu_unprogramAllFuses">Alle Dioden zurücksetzen</string>
|
||||
<string name="menu_unprogramAllFuses_tt">Setzt alle Dioden (Fuses) in den unprogrammierten Zustand zurück. Die Konfiguration geht dabei verloren!</string>
|
||||
<string name="menu_unprogramAllFuses">Alle Dioden/FGFETS zurücksetzen</string>
|
||||
<string name="menu_unprogramAllFuses_tt">Setzt alle Dioden (Fuses) bzw. FGFETs in den unprogrammierten Zustand zurück. Die Konfiguration geht dabei verloren!</string>
|
||||
<string name="menu_programDiode">Diode programmieren</string>
|
||||
<string name="menu_help_elements">Hilfe</string>
|
||||
<string name="menu_help_elements_tt">Zeigt eine Dokumentation der vorhandenen Elemente.</string>
|
||||
|
@ -354,6 +354,14 @@
|
||||
<string name="elem_NFET_pin_G">Gate</string>
|
||||
<string name="elem_NFET_pin_out2">Source</string>
|
||||
<string name="elem_NFET_pin_out1">Drain</string>
|
||||
|
||||
<string name="elem_FGNFET">N-Channel floating gate FET</string>
|
||||
<string name="elem_FGNFET_tt">N-Channel Floating Gate Field Effect Transitor. The bulk is connected to ground and the transistor is simulated without a body diode.
|
||||
If there is a charge stored in the floating gate, the fet isn't conducting even if the gate is high.</string>
|
||||
<string name="elem_FGNFET_pin_G">Gate</string>
|
||||
<string name="elem_FGNFET_pin_out2">Source</string>
|
||||
<string name="elem_FGNFET_pin_out1">Drain</string>
|
||||
|
||||
<string name="elem_PFET">P-Channel FET</string>
|
||||
<string name="elem_PFET_tt">P-Channel Field Effect Transitor. The bulk is connected to the pos. voltage rail and the transistor is simulated without a body diode.</string>
|
||||
<string name="elem_PFET_pin_G">Gate</string>
|
||||
@ -538,7 +546,7 @@ The names of the variables may not be unique.</string>
|
||||
<string name="key_isProgramMemory">Program Memory</string>
|
||||
<string name="key_isProgramMemory_tt">Makes this ROM to program memory. So it can be accessed by an external IDE.</string>
|
||||
<string name="key_Blown">Programmed</string>
|
||||
<string name="key_Blown_tt">If set the diode is treated as a "blown" or "programmed" diode or fuse. You can change this setting with the key 'p'.</string>
|
||||
<string name="key_Blown_tt">If set a diode is "blown" or "programmed". At a floating gate FETS the floating gate is charged. You can change this setting with the key 'p'.</string>
|
||||
<string name="key_ExpressionFormat">Format</string>
|
||||
<string name="key_ExpressionFormat_tt">Screen format of expressions.</string>
|
||||
<string name="key_relayNormallyClosed">Relay is normally closed.</string>
|
||||
@ -691,8 +699,8 @@ The names of the variables may not be unique.</string>
|
||||
<string name="menu_runTests_tt">Runs all test cases in the circuit</string>
|
||||
<string name="menu_actualToDefault">Set Inputs</string>
|
||||
<string name="menu_actualToDefault_tt">Use actual input values as new default values.</string>
|
||||
<string name="menu_unprogramAllFuses">Reset all diodes</string>
|
||||
<string name="menu_unprogramAllFuses_tt">Resets all diodes (fuses) to the unprogramed state. The actual fuse configuration is lost!</string>
|
||||
<string name="menu_unprogramAllFuses">Reset all diodes and FGFETs</string>
|
||||
<string name="menu_unprogramAllFuses_tt">Resets all diodes (fuses) and FGFETs to the unprogramed state. The actual fuse configuration is lost!</string>
|
||||
<string name="menu_programDiode">Program diode</string>
|
||||
<string name="menu_help_elements">Components</string>
|
||||
<string name="menu_help_elements_tt">Shows a list of all available components.</string>
|
||||
|
@ -39,8 +39,8 @@ public class TestExamples extends TestCase {
|
||||
*/
|
||||
public void testTestExamples() throws Exception {
|
||||
File examples = new File(Resources.getRoot(), "/dig/test");
|
||||
assertEquals(53, new FileScanner(this::check).scan(examples));
|
||||
assertEquals(47, testCasesInFiles);
|
||||
assertEquals(54, new FileScanner(this::check).scan(examples));
|
||||
assertEquals(48, testCasesInFiles);
|
||||
}
|
||||
|
||||
|
||||
|
5884
src/test/resources/dig/test/switch/GAL2v3.dig
Normal file
5884
src/test/resources/dig/test/switch/GAL2v3.dig
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user