From 8e4621c2e06396e3c0971c7872b0227340cc1f1e Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 8 Apr 2017 14:34:57 +0200 Subject: [PATCH] added a LED matrix display --- distribution/ReleaseNotes.txt | 1 + .../de/neemann/digital/core/element/Keys.java | 12 +++ .../de/neemann/digital/core/io/LedMatrix.java | 96 +++++++++++++++++++ .../digital/draw/library/ElementLibrary.java | 1 + .../graphics/LedMatrixComponent.java | 80 ++++++++++++++++ .../components/graphics/LedMatrixDialog.java | 46 +++++++++ src/main/resources/lang/lang_de.xml | 9 ++ src/main/resources/lang/lang_en.xml | 9 ++ 8 files changed, 254 insertions(+) create mode 100644 src/main/java/de/neemann/digital/core/io/LedMatrix.java create mode 100644 src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixComponent.java create mode 100644 src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixDialog.java diff --git a/distribution/ReleaseNotes.txt b/distribution/ReleaseNotes.txt index c7159f066..c99893051 100644 --- a/distribution/ReleaseNotes.txt +++ b/distribution/ReleaseNotes.txt @@ -9,6 +9,7 @@ planned as v0.10 - Added a real bidirectional switch and a relay. - Added N and P channel FETs and some CMOS examples, including a 16 bit SRAM - Added a rotary encoder +- Added a LED matrix display - Improved and documented the file import strategy. - Added a tree view to insert components. - Added support for the ATF1502 and ATF1504 CPLDs. 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 787b4e1b7..97506b184 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -308,4 +308,16 @@ public final class Keys { public static final Key PIN = new Key<>("pin", ""); + /** + * row bits in led matrix + */ + public static final Key.KeyBits ROW_DATA_BITS + = new Key.KeyBits("rowDataBits", 8);; + + /** + * column address bits in led matrix + */ + public static final Key.KeyBits COL_ADDR_BITS + = new Key.KeyBits("colAddrBits", 3);; + } diff --git a/src/main/java/de/neemann/digital/core/io/LedMatrix.java b/src/main/java/de/neemann/digital/core/io/LedMatrix.java new file mode 100644 index 000000000..6ece1a4bf --- /dev/null +++ b/src/main/java/de/neemann/digital/core/io/LedMatrix.java @@ -0,0 +1,96 @@ +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 de.neemann.digital.draw.elements.PinException; +import de.neemann.digital.gui.components.graphics.LedMatrixDialog; + +import javax.swing.*; + +import java.awt.*; + +import static de.neemann.digital.core.element.PinInfo.input; + +/** + * LED-Matrix + * Created by hneemann on 08.04.17. + */ +public class LedMatrix extends Node implements Element { + + /** + * the LED-Matrix description + */ + public static final ElementTypeDescription DESCRIPTION + = new ElementTypeDescription(LedMatrix.class, input("r-data"), input("c-addr")) + .addAttribute(Keys.ROTATE) + .addAttribute(Keys.LABEL) + .addAttribute(Keys.ROW_DATA_BITS) + .addAttribute(Keys.COL_ADDR_BITS) + .addAttribute(Keys.COLOR) + .addAttribute(Keys.LED_PERSISTENCE); + + private final int rowDataBits; + private final int colAddrBits; + private final int dx; + private final int dy; + private final long[] data; + private final Color color; + private final boolean ledPersist; + private ObservableValue rowDataVal; + private ObservableValue colAddrVal; + private LedMatrixDialog ledMatrixDialog; + + /** + * create a new instance + * + * @param attr the attributes of the element + */ + public LedMatrix(ElementAttributes attr) { + rowDataBits = attr.get(Keys.ROW_DATA_BITS); + colAddrBits = attr.get(Keys.COL_ADDR_BITS); + color=attr.get(Keys.COLOR); + ledPersist = attr.get(Keys.LED_PERSISTENCE); + dx = 1 << colAddrBits; + dy = rowDataBits; + data = new long[dx]; + } + + @Override + public void setInputs(ObservableValues inputs) throws NodeException { + rowDataVal = inputs.get(0).checkBits(rowDataBits, this).addObserverToValue(this); + colAddrVal = inputs.get(1).checkBits(colAddrBits, this).addObserverToValue(this); + } + + @Override + public ObservableValues getOutputs() throws PinException { + return ObservableValues.EMPTY_LIST; + } + + @Override + public void readInputs() throws NodeException { + long rowData = rowDataVal.getValue(); + int colAddr = (int) colAddrVal.getValue(); + if (colAddr < dx && data[colAddr] != rowData) { + data[colAddr] = rowData; + dataChanged(colAddr, rowData); + } + } + + @Override + public void writeOutputs() throws NodeException { + } + + private void dataChanged(int colAddr, long rowData) { + SwingUtilities.invokeLater(() -> { + if (ledMatrixDialog == null || !ledMatrixDialog.isVisible()) + ledMatrixDialog = new LedMatrixDialog(dy, data, color, ledPersist); + ledMatrixDialog.updateGraphic(colAddr, rowData); + }); + } +} diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index bb3394084..477b2d54f 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -88,6 +88,7 @@ public class ElementLibrary implements Iterable node.add(Out.SEVENDESCRIPTION); node.add(Out.SEVENHEXDESCRIPTION); node.add(RotEncoder.DESCRIPTION); + node.add(LedMatrix.DESCRIPTION); node.add(DummyElement.DATADESCRIPTION); node.add(DummyElement.TEXTDESCRIPTION); node.add(Keyboard.DESCRIPTION); diff --git a/src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixComponent.java b/src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixComponent.java new file mode 100644 index 000000000..102112a64 --- /dev/null +++ b/src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixComponent.java @@ -0,0 +1,80 @@ +package de.neemann.digital.gui.components.graphics; + +import javax.swing.*; +import java.awt.*; + +/** + * Component to visualize a LED matrix + * Created by hneemann on 08.04.17. + */ +public class LedMatrixComponent extends JComponent { + private final int width; + private final int height; + private final long[] data; + private final Color color; + private final boolean ledPersist; + private int lastCol; + + /** + * Create a new instance + * + * @param dy height of matrix + * @param data data + * @param color the LEDs color + * @param ledPersist if true the LEDs light up indefinite + */ + public LedMatrixComponent(int dy, long[] data, Color color, boolean ledPersist) { + this.width = data.length; + this.height = dy; + this.data = data; + this.color = color; + this.ledPersist = ledPersist; + + int pw = 320 / width; + if (pw < 2) pw = 2; + int ph = 200 / height; + if (ph < 2) ph = 2; + int ledSize = (pw + ph) / 2; + + Dimension size = new Dimension(width * ledSize, height * ledSize); + setPreferredSize(size); + setOpaque(false); + } + + /** + * Update the graphic + * + * @param colAddr col update + * @param rowData updated data + */ + public void updateGraphic(int colAddr, long rowData) { + lastCol = colAddr; + repaint(); + } + + @Override + protected void paintComponent(Graphics g) { + for (int x = 0; x < width; x++) { + int xPos = x * getWidth() / width; + int dx = (x + 1) * getWidth() / width - xPos; + long word = data[x]; + long mask = 1; + for (int y = 0; y < height; y++) { + + boolean ledState = (word & mask) != 0; + + if (ledState && (ledPersist || (x == lastCol))) + g.setColor(color); + else + g.setColor(Color.BLACK); + + int ypos = y * getHeight() / height; + int dy = (y + 1) * getHeight() / height - ypos; + + g.fillOval(xPos, ypos, dx, dy); + mask *= 2; + } + } + } + +} diff --git a/src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixDialog.java b/src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixDialog.java new file mode 100644 index 000000000..2fc8d08f3 --- /dev/null +++ b/src/main/java/de/neemann/digital/gui/components/graphics/LedMatrixDialog.java @@ -0,0 +1,46 @@ +package de.neemann.digital.gui.components.graphics; + +import de.neemann.digital.lang.Lang; + +import javax.swing.*; +import java.awt.*; + +/** + * The LED matrix dialog + * Created by hneemann on 08.04.17. + */ +public class LedMatrixDialog extends JDialog { + + private final LedMatrixComponent ledMatrixComponent; + + /** + * Create a new instance + * + * @param dy height of matrix + * @param data data + * @param color the LEDs color + * @param ledPersist if true the LEDs light up indefinite + */ + public LedMatrixDialog(int dy, long[] data, Color color, boolean ledPersist) { + super((JFrame) null, Lang.get("elem_LedMatrix"), false); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + ledMatrixComponent = new LedMatrixComponent(dy, data, color, ledPersist); + getContentPane().add(ledMatrixComponent); + pack(); + + setAlwaysOnTop(true); + setLocationRelativeTo(null); + setVisible(true); + } + + /** + * Update the graphic + * + * @param colAddr col update + * @param rowData updated data + */ + public void updateGraphic(int colAddr, long rowData) { + ledMatrixComponent.updateGraphic(colAddr, rowData); + } +} diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 6b8ec1f21..01c7f5e40 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -376,6 +376,11 @@ Die gesammte Speichergröße beträgt damit damit dx*dy*2 Speicherworte.Drehknopf mit Drehencoder zur zustandsfreien Erfassung der Drehbewegung. Encodersignal A Encodersignal B + LED-Matrix + Eine Matrix aus LEDs. Die LEDs werden in einem eigenen Fenster dargestellt. + Die LEDs können in der Simulation unendlich lange nachleuchten, um ein Flimmern der Anzeige zu verhindern. + Der Zeilen-Zustand der LEDs einer Spalte. Jedes Bit in diesem Datenwort repräsentiert den Zustand einer Zeile der aktuellen Spalte. + Die Nummer der aktuellen Spalte, dessen Zustand gerade am anderen Eingang anliegt. Fehler Flipflop hat keine Bezeichnung! @@ -560,6 +565,10 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Pfad zum Fitter für den ATF1502. Geben Sie hier den vollen Pfad zur Datei fit1502.exe an. Diese Datei wird von ATMEL zu Verfügung gestellt. Pinnummer Ist das Feld leer bedeutet das, dass dieses Signal keinem Pin zugewiesen ist. + Zeilen + Gibt direkt die Zahl der Zeilen an, indem die Anzahl der Bits des Zeilenwortes festgegelgt wird. + Adressbits der Spalten + Adressiert die einzelnen Spalten. Drei Bits bedeuten also acht Spalten. Logisch Arithmetik diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index ded1cd99b..da87dff2a 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -363,6 +363,11 @@ Rotary knob with rotary encoder for stateless detecting rotational movements. encoder signal A encoder signal B + LED-Matrix + A matrix of LEDs. The LEDs are shown in a separate window. + The LEDs are able to light up indefinitely in the simulation to prevent the display from flickering. + The row state of the LEDs of a column. Each bit in this data word represents the state of a row of the current column. + The number of the current column whose state is currently visible at the other input. Error D-flip-flop has no label set @@ -547,6 +552,10 @@ The names of the variables may not be unique. Path to the fitter for the ATF1502. Enter the full path to the file fit1502.exe provided bei ATMEL. Pin number An empty field means this signal is not assigned to a pin. + Rows + Specifies the number of rows by specifying the number of bits of the row word. + Address bits of columns + Addresses the individual columns. Three bits means eight columns. Logic Arithmetic