Ich hab hier eine LED Matrix die Zeichen darstellen soll. Ich würde jetzt für jeden Buchstaben eine Funktion schreiben und als Parameter eine x/y Koordinate und vielleicht einen RGB Wert übergeben. Macht man das so? Und was ist denn wenn man es mit einem Display zu tun hat? "Beschreibt" man jedes Pixel einzeln mit xy, Helligkeit und Farbe? Jedes mal einzeln für jeden vorkommenden Fall?
Attila C. schrieb: > Ich hab hier eine LED Matrix die Zeichen darstellen soll. Ich würde > jetzt für jeden Buchstaben eine Funktion schreiben und als Parameter > eine x/y Koordinate und vielleicht einen RGB Wert übergeben. > Macht man das so? Eher nicht. Üblich wäre vielmehr ein Satz "Kontextfunktionen", also z.B.: setze Position, setze Farbe, ggf. zusätzlich: setze Schriftart, setze Schriftschnitt, setze Schriftrichtung usw. usf. Und dann eine Funktion zur eigentlichen Zeichenausgabe, die als Parameter das auzugebende Zeichen bekommt. Alles andere an Information bezieht sie aus dem Kontext, den man natürlich ebenfalls übergeben muss, allerdings nicht notwendigerweise als Parameter, der Kontext kann u.U. auch global sein. Die Zeichenausgabefunktion malt dann den richtigen Glyph in der korrekten Orientierung an die korrekte Stelle und inkrementiert typischerweise die Zeichenausgabeposition entsprechend Zeichengröße und Ausgaberichtung. Der Sinn dieser Konstruktion ist, dass man typisch halt Text ausgibt, der aus mehr als einem Zeichen besteht. > Und was ist denn wenn man es mit einem Display zu tun hat? "Beschreibt" > man jedes Pixel einzeln mit xy, Helligkeit und Farbe? Jedes mal einzeln > für jeden vorkommenden Fall? Das hängt dann vom Treiber für das Ausgabegerät ab. Im Minimum stellt das eine SetPixel(X,Y,Farbe) zur Verfügung. Bei komplexeren Grafiksystemen gibt es aber auch oft Beschleunigungsfeatures, so dass die Routine zur Zeichenausgabe nicht jedes einzelne Pixel eines Zeichens setzen muss. Aber das überfliegt deinen Horizont wohl noch deutlich. Bleib' erstmal bei der Sache, die auf SetPixel() basiert. Da gibt es schon genug zu lernen.
c-hater schrieb: > Bleib' erstmal bei der Sache, die auf SetPixel() basiert. Da gibt es > schon genug zu lernen. Ja, aber so wird er ganz bestimmt keinen "Zeichensatz" hinkriegen...na ja, vielleicht ala 7-Segment-Anzeige...aber darauf zielt die Frage doch nicht ab. Attila C. schrieb: > "Beschreibt" > man jedes Pixel einzeln mit xy, Helligkeit und Farbe? Jedes mal einzeln > für jeden vorkommenden Fall? Ja und nein. Ja, du hast im einfachsten Fall eine Tabelle mit den Eigenschaften eines Pixel (falls das das kleinste darstellbare Element ist) und baust daraus dann z.B. den Buchstaben "a" wiederum in einer Tabelle mit allen deinen Zeichen (oder mit allen möglichen Zeichen). Dann brauchst du noch die Zuordnung zu Koordinaten auf deinem Anzeigefeld und dann bist du erst mal fertig. Nein, weil eben der tabellarische Aufbau eine beliebige aktuelle Tabelle ermöglicht, die deine aktuell gewünschte Anzeige beschreibt. Wenn du ein wenig suchst, wirst du schnell herausfinden, dass das insgesamt eine gehörig komplexe Materie ist... Viel Spass trotzdem, Rainer
Rainer V. schrieb: > Ja, aber so wird er ganz bestimmt keinen "Zeichensatz" hinkriegen... Wieso nicht? Natürlich kann man basierend auf einer SetPixel-Funktion jeden beliebigen Zeichensatz darstellen, sogar einen Vector-Zeichensatz (der mit Pixeln naturgemäß eigentlich garnix am Hut hat).
Attila C. schrieb: > Macht man das so Nein. Man speichert einen font, also die Pixelbilder aller druckbarer Zeichen, und schreibt eine Funktion die das n-te Zeichen aus dem font an Position x,y klatscht. Falls es wirklich ein LED moving sign ist, spart man sich sogar den Speicher für die Pixel und holt die bits bei jedem Multiplexdurchgang aus dem font, speichert also nur den darzustellenden String und dessen Anfangspixelposition, denn Fontzugriff ist schnell.
Attila C. schrieb: > ch würde > jetzt für jeden Buchstaben eine Funktion schreiben und als Parameter > eine x/y Koordinate und vielleicht einen RGB Wert übergeben. > Macht man das so? Nö, man baut eine Funktion der man das Zeichen, die position und ggf. die Farbe übergibt. Diese holt dann aus einer Tabelle, in der alle benötigten Zeichen abgelegt sind, dass betreffende Zeichen und kopiert das an die passende Position in deinem Ausgabe-Puffer. https://de.wikipedia.org/wiki/Bitmap-Schrift
MaWin schrieb: > Man speichert einen font, also die Pixelbilder aller druckbarer Zeichen, > und schreibt eine Funktion die das n-te Zeichen aus dem font an Position > x,y klatscht. Ergänzend: Mit "klatscht" ist hier gemeint, dass die Pixel des Zeichens an die Zielposition im Bidspeicher kopiert werden.
Die einen sagen "genau so" muss das gemacht werden, die anderen antworten "nööö, so macht man das nicht"... ich würde da einfach mal sagen: Es kommt drauf an wie man etwas ansteuert, wie sehr man es abstrahieren möchte und ob man Performance braucht/möchte. LED Matrix wirst du wohl multiplexen? Oder nutzt du eine WS2812B LED Matrix, da du von Farbe gesprochen hast? Kleines Bsp. von meinem OLED (SPI Interface): Natürlich könnte man dort je Befehl ein Pixel einzeln setzen, was jedoch von der Verarbeitung mehr Zeit in Anspruch nehmen würde. Ich nutze dort das Farbformat RGB565 welches über SPI übertragen wird, somit entspricht ein Pixel 2 Byte (Farbinformation). Für 160x128 Pixel habe ich mir ein Framebuffer angelegt
1 | /* RGB565 Format */
|
2 | #define BYTE_PER_PIXEL 2
|
3 | |
4 | #define FB_PIXEL_CNT (OLED_WIDTH*OLED_HEIGHT)
|
5 | #define FB_SIZE (OLED_WIDTH*OLED_HEIGHT*BYTE_PER_PIXEL)
|
6 | |
7 | static uint8_t fb[FB_SIZE]; |
Um mir jetzt für eine Schriftart nicht jedes Pixel einzeln zu Pixeln habe ich folgendes Tool benutzt: http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/ Natürlich musst du dir da noch die Funktionen schreiben, die dir dann die richtigen Pixel im Buffer setzen oder direkt übertragen/ansteuern. Ob du nun ein Buffer nutzt oder nicht, wäre der grobe Aufbau z.B. so:
1 | led_str(const char *str, uint8_t x, uint8_t y, uint32_t color) |
2 | |
|
3 | |-> led_char(char c, uint8_t x, uint8_t y, uint32_t color) |
4 | |
|
5 | |-> led_pixel(uint8_t *dst, uint32_t color) |
Bei led_pixel() zeigt der *dst auf mein Buffer, da die Position im Buffer in led_char() berechnet wird. Ein Zeichen besteht ja aus mehreren Pixeln :) Es gibt für verschiedene Aufgabenstellungen auch mehrere Lösungen, da muss man einfach selbst abwägen, was für diesen Fall angebracht ist. Meistens bestimmen die Anforderungen den Lösungsweg. Aber für eine WS2812B Matrix, würde ich mir wohl auch ein Buffer anlegen und dann erst alles im RAM zusammenbastlen und anschliessend heraustakten. Bei der Erstellung von Display Funktionen bin ich immer gut mit dem Bottom-up-Prinzip gefahren.
:
Bearbeitet durch User
Attila C. schrieb: > Ich würde > jetzt für jeden Buchstaben eine Funktion schreiben Das ist Quatsch mit Soße. Man schreibt nur eine einzige Funktion, der man den Index auf den entsprechenden Eintrag in der Zeichensatztabelle übergibt. Je nach Schriftgröße hat man mehrere Tabellen. Für den ersten Test nimmt man Putpixel. Und wenn das funktioniert, kann man optimierte Funktionen schreiben. Es kann auch sinnvoll sein, alles erstmal in den RAM zu schreiben und dann den RAM in einem Rutsch in das Display zu kopieren.
> Und was ist denn wenn man es mit einem Display zu tun hat? "Beschreibt" > man jedes Pixel einzeln mit xy, Helligkeit und Farbe? Jedes mal einzeln > für jeden vorkommenden Fall? Verschiedene Displays haben verschiedene Ansteuerungen. Bei manchen 24 Bit Farbe pro Pixel, bei anderen beschreiben je 1 Byte 8 Pixel an oder aus. Die einfachste Schnittstelle ist jedoch noch immer SetPixel(x, y, pixel). Wobei x und y die Koordinaten sind (oft von oben links, aber alles ist möglich) und pixel halt 0/1 oder 3 Byte für rgb oder was auch immer. Wenn Du ein Pixel setzen kannst, kannst Du alle setzen. Das ist die einfachste Schnittstelle zwischen der HW (dem physikalischen Display, welche Kommandos oder Pins du brauchst) und einem Grafikpaket (dass Fonts enthält und kommandos zum Zeichnen von Kreisen oder Rechtecken. Wenn es dann auf Performance ankommt, dann kannst Du immer noch optimieren, aber für einen Anfänger ist es einfacher, über SetPixel zu gehen.
Na, vielleicht meldet sich der TO ja auch noch einmal zu Wort, so dass wir evtl. mehr Informationen zu seiner Hardware bekommen. Sollte er WS2812B LED nutzen, dann wäre der Aufwand gar nicht so groß, seine Matrix wie ein Display zu nutzen, ist ja in dem Sinne nichts anderes. (Abgesehen von der Ansteuerung) Bin gespannt...
Eigentlich hat der TO ja zwei Fragen gestellt. Da er seine LED Matrix nicht näher bezeichnet hat, ist eigentlich alles gesagt. Die zweite Frage spricht allgemein von einem Display. Das kann natürlich beliebig ausführlich und endlos beantwortet werden. Ich sehe an der Art der Fragestellung, dass dem TO das Konzept von Zeichensätzen und Tabellen für den Aufbau und die Ausgabe von Schrift oder allgemeiner Grafik auf ein Display nicht ganz klar ist. Vielleicht hat er hier jetzt schon einige Anregungen für Vertiefung des Themas bekommen. Falls er aber nur mit seiner Matrix klar kommen möchte, dann erwarte ich weitere Fragen. Gruß Rainer
weil man eine WS2812 Matrix genauso wie ein TFT Display betrachten kann, funktioniert die Adafruit GFX Lib dafür ganz gut und das gibt es sogar fertig: https://learn.adafruit.com/adafruit-neopixel-uberguide/neomatrix-library das baut auf die generische GFX Klasse auf, die das mit NeoPixel kombiniert. Damit hat man dann Zeichenfunktionen und Character Ausgaben. Für Zeichen gibt es die einfachen fixed size Fonts, und wenn das Display größer ist, dann kann man die schöneren Fonts mit variabler Zeichengröße einsetzen. Dafür gibt es dann auch noch Fontgeneratoren. Da würde ich das Rad nicht neu erfinden wollen.
Zu wenige Informationen zur Anzeige! Können die Pixel außer an und aus noch andere Kunststückchen? So Sachen wie Helligkeit und/oder Farbe? Beim Konzept besteht auch ein "kleiner" Unterschied zwischen Anzeigen, die 307 Bildpunkte unterstützen und denen die 5 Millionen im Angebot haben. Können einzelne Bildpunkte bedient werden oder nur Bereiche? Meine Glaskugel ist leider in der Reparatur.
Attila C. schrieb: > "Beschreibt" > man jedes Pixel einzeln mit xy, Helligkeit und Farbe? Jedes mal einzeln > für jeden vorkommenden Fall? Ja, natürlich muss man für das Pixel an Position x=38 Y=22 rot eine extra Funktion schreiben. Damit man den Überblick behält nennt man die zweckmässigerweise SetPixel3822rot. Für ein grosses Display und Millionen Farben braucht man halt viele viele Funktionen. :-) Rainer V. schrieb: > Ich sehe an der Art der > Fragestellung, dass dem TO das Konzept von Zeichensätzen und Tabellen > für den Aufbau Üblicherweise baut man das hierarchisch auf, man fängt mit einer SetPixel-Funktion an, der man Position und Farbe übergibt, dann eine Funktion SetCharacter, der man das Zeichen, Position und Farbe übergibt und die dann für alle Pixel SetPixel aufruft und die Pixelwerte aus der Zeichensatztabelle holt, und dann eine Funktion SetText... Aber das dürfte den TO heillos überfordern. Georg
Rainer V. schrieb: > Ja, aber so wird er ganz bestimmt keinen "Zeichensatz" hinkriegen...na > ja, vielleicht ala 7-Segment-Anzeige...aber darauf zielt die Frage doch > nicht ab. Nö, genau so funktioniert es bei allen Systemen im Prinzip. Man hat eine Start- bzw. Basis-Position, das darzustellende Zeichen in passender Codierung und einen Font, der für seine enthaltenen Zeichen die Glyphen enthält. Dazu gibt es den Device-Kontext, der die Farbe, Richtung und andere globale Attribute vorhält. Soweit zum Darstellen von Texten. Das Darstellen von Grafiken (um beim Thema zu bleiben) ist fast gleich, lediglich die Farben werden aus den Glyphen geliefert und die Hintergrundfarbe ist bei 100% Deckung egal. W.S.
Johannes S. schrieb: > weil man eine WS2812 Matrix genauso wie ein TFT Display betrachten kann, Es ist zu bezweifeln, dass das wirklich immer so ist. Allein schon die Organisation der "Pixeladdressen" kann total unterschiedlich sein. OK, bei einem TFT wird's wohl im Allgemeinen darauf hinauslaufen, dass die Adressen innerhalb einer Zeile aufsteigend sind mit Increment bpp und die Zeilenadressen aufsteigend mit Increment bpp * ppl. Eine Matrix aus WS28xx-LEDs könnte genauso organisiert sein, muss es aber nicht. Insbesondere ist hier die Variante "zig zag" zu berücksichtigen (die aus elektrischen Gründen durchaus Sinn ergeben kann). Hat man so eine Matrix, fällt man auf die Schnauze. Dazu kommt noch folgendes Problem: Was ist eigentlich die Zeile, was die Spalte. Bei TFTs ist typischerweise die größere Dimension die Zeile, weil elektrisch vieles dafür spricht, das so zu handhaben. Bei WS28xx-Matrizen hingegen gibt es keine solche Vorzugsrichtung. Und weiters: TFTs müssen nicht notwendigerweise 24bit-Farben verwenden. Es gibt viele, die nur 16bit verwenden. Sprich: Wer clever ist, trennt die Adressierung logisch komplett von dem restlichen Kram...
Die Trennung von Framebuffer und Displayorganisation ist doch in dem genannten Link sogar beschrieben, die NeoMatrix kann verschiedene umsetzen. Auch bei TFT/LCD können die Daten Zeilen- oder Spaltenweise reingeschoben werden müssen. Mit den Adafruit Klassen ist das jedenfalls realisierbar. Eine schöne C++ Anwendung.
OK! Wow! Vielen Dank für die Hilfe! Es handelt sich um eine WS2812Matrix. Ich mache also eine Tabelle pro Buchstaben in der die x/y Koordinaten der Buchstaben"teile" aufgelistet sind? Und dann eine Funktion diese abfragt und zu der Matrix "schiebt"? Das ganze soll in C stattfinden. Ich werde jetzt erst mal die ganzen links die hier gepostet wurden studieren, denke aber dass ich noch einige Fragen haben werde. Es scheint, wie hier einige schon bemerkt haben, keine einfache Sache zu sein. Wegen dem Display habe ich gefragt da ich schon mal auf einem kleinen TFT Bildpunkte mit x/y angezeigt bekommen habe aber dann keinerlei Idee hatte wie man dann weiter macht? Wie man z.B. , angenommen man hat eine Blume "gemalt", diese z.B. dreht ohne jedes mal die ganze Blume neu "zu zeichnen". Gibt es dazu Material?
Attila C. schrieb: > angenommen man hat eine > Blume "gemalt" Du solltest dich erstmal mit den "einfacheren" Dingen befassen. Einzelne Zeichen bzw. Buchstaben einer festen Grösse auf das Display schreiben beispielsweise.
Attila C. schrieb: > Ich mache also eine Tabelle pro Buchstaben in der die x/y Koordinaten > der Buchstaben"teile" aufgelistet sind? Nein, natürlich nicht, das wäre schwachsinnig und ineffizient. Schwachsinnig deshalb, weil selbst jemandem wie dir paktisch sofort klar sein sollte: 1) Buchstaben können in einem Text mehrfach vorkommen. 2) Text könnte an verschiedenen Stellen ausgegeben werden sollen. Beides führt sofort zu dem logischen Schluß, dass es kompletter Schwachsinn wäre, absolute Positionen bezüglich irgendeines Zielgerätes im Zeichensatz zu speichern. Nein. Ein Zeichensatz hat sinnvollerweise sein eigenes Pixelformat und seine eigenes Koordinatensystem. Bei Pixel-Zeichensätzen ist das typisch implizit, gespeicheichert werden also nicht Koordinaten, sondern Bits. Die Koordinaten (bezüglich des Zeichenursprungs) ergeben sich aus der Position der Bits. Bei Vector-Zeichensätzen hingegen werden tatsächlich Koordinaten gespeichert. Allerdings auch ohne jeglichen Bezug zum Ziel-Device, sondern immer nur relativ zum Ursprung des Zeichens im Koordinatensystem des Zeichensatzes.
Attila C. schrieb: > Es handelt sich um eine > WS2812Matrix. Dachte ich mir schon... Attila C. schrieb: > Ich mache also eine Tabelle pro Buchstaben in der die x/y Koordinaten > der Buchstaben"teile" aufgelistet sind? Schau dir dafür lieber den Link an, den ich dir gepostet habe: "the dot factory" - das Prog. erstellt dir ein array mit bereits allen pixeln und für alle Zeichen die du möchtest. --- ok, wie bereits vermutet, ihm fehlt die Grundlage - aber hey...irgendwann muss jeder mal ins kalte Wasser :-D
:
Bearbeitet durch User
Attila C. schrieb: > WS2812Matrix. Ist offensichtlich aus der Arduino-Welt. Deshalb empfehle ich erst mal: https://www.instructables.com/Getting-Started-With-NeoPixle-WS2812-RGB-LED/ Dann warten wir auf weitere Fragen... Gruß Rainer
Attila C. schrieb: > Ich mache also eine Tabelle pro Buchstaben Nein du machst eine Tabelle für den ganzen (5x7) font. bit font[0..255,0..4,0..6]; allerdings packt man bits gerne in bytes oder worte.
Hallo! Also: Es ist eine 32*8 WS2812 Matrix. Ich habe jetzt eine Funktion "setPixel" gebaut die ich nach dem Neopixel (link siehe oben) Vorbild programmiert habe. x geht von links nach rechts und y von oben nach unten. Auch die Übergabe der Farbe habe ich nachgebaut (alle 3 Werte in einer 16 bit Variable gepackt). Auch habe ich beim stöbern in den Neopixel Codes einen "Standart ASCII 5x7 font" gefunden. Dort befindet sich eine recht lange Kette von HEX Werten. Ich verstehe nicht was diese Werte darstellen. Ich habe auch eine andere Tabelle gefunden, 5x8 diesmal, wo jedem ASCII Zeichen 4 HEX Werte zugeordnet sind. Auch da erschließt sich mir nicht wie daraus ein Buchstabe gemacht wird? Für ein großes A bräuchte man ja 16 Werte als Koordinaten. Wo verstecken sich diese in diesen HEX Codes? Oder denke ich in die völlig falsche Richtung?
Wenn du die Nullen und Einsen eines Zeichens in zwei Farben auf Papier malst siehst du es vielleicht.
Attila C. schrieb: > Also: Es ist eine 32*8 WS2812 Matrix. Ich habe jetzt eine Funktion > "setPixel" gebaut die ich nach dem Neopixel (link siehe oben) Vorbild > programmiert habe. x geht von links nach rechts und y von oben nach > unten. Auch die Übergabe der Farbe habe ich nachgebaut (alle 3 Werte in > einer 16 bit Variable gepackt). Was ist denn das schon wieder für ein Quatsch? Deine LEDs können doch 24Bit-Farben. Da ergibt es absolut keinen Sinn, die Farbe auf 16Bit einzudampfen. Benutze uint32_t für die Farbe (und darin nur die unteren drei Bytes). > Auch habe ich beim stöbern in den Neopixel Codes einen "Standart ASCII > 5x7 font" gefunden. Dort befindet sich eine recht lange Kette von HEX > Werten. Ich verstehe nicht was diese Werte darstellen. Dann musst du halt weiter nachdenken. Erkenntnis kannst du nicht aus Foren schöpfen, die kannst du nur selbst gewinnen. > Ich habe auch eine andere Tabelle gefunden, 5x8 diesmal, wo jedem ASCII > Zeichen 4 HEX Werte zugeordnet sind. Auch da erschließt sich mir nicht > wie daraus ein Buchstabe gemacht wird? Gleiches Problem. Was du hier nicht verstehst, kann dir niemand wirklich erklären. Das kannst du nur durch selbst Denken lernen > Für ein großes A bräuchte man ja 16 Werte als Koordinaten. Wie kommst du darauf? Wieviele Koordinaten es für ein "A" gibt, ergibt sich aus dem Zeichensatz. Wenn es ein 5x7-Pixel-Zeichensatz ist, dann müssen das mindestens 35 Koordinaten sein, wobei hier, wie schon weiter oben gesagt, keine expliziten Kordinaten gespeichert werden, sondern Bits. Es sind also im Zeichensatz mindestens 35 Bits für ein "A" nötig. Aus praktischen Gründen dürfte der Zeichensatz aber in Bytes organisiert sein. Da bleiben aber immer noch mindestens zwei mögliche Lösungen über: Es können entweder 5 Bytes sein, die je sieben Nutzbits enthalten oder aber 7 Bytes, die je 5 Nutzbits enthalten.
Johannes S. schrieb: > Wenn du die Nullen und Einsen eines Zeichens in zwei Farben auf Papier > malst siehst du es vielleicht. Karriertes Papier nehmen und für jede 1 im Byte das Kästchen ausmalen. Links anfangen Bit 0, rechts Bit 7 Nächstes Byte genauso darunter. Und dann drehen und spiegeln bis ein Zeichen erkennbar ist. Nicht mit dem Leerzeichen anfangen.
Attila C. schrieb: > Auch habe ich beim stöbern in den Neopixel Codes einen "Standart ASCII > 5x7 font" gefunden. Dort befindet sich eine recht lange Kette von HEX > Werten. Ich verstehe nicht was diese Werte darstellen. Jedes Byte entspricht einer vertikalen Reihe von Pixeln. Oben ist Bit 0, unten ist bit 6. Bit 7 wird nicht verwendet. Jedes Zeichen besteht auf 5 solcher Pixelreihen, die erste ist links, die letzte ist rechts. > Ich habe auch eine andere Tabelle gefunden, 5x8 diesmal, wo jedem ASCII > Zeichen 4 HEX Werte zugeordnet sind. Auch da erschließt sich mir nicht > wie daraus ein Buchstabe gemacht wird? Da besteht halt jedes Zeichen aus 4x8 Pixeln. Wobei in diesem Fall meistens eine vertikale Reihe als Abstand zwischen den Buchstaben per Software eingefügt wird. Also ist es eigentlich ein 5x8 Font, nur dass man das immer leere Byte weg gespart hat.
Ahaaaaaaaaaaaaa! Wie krass ist das denn? Was es für geniale Sachen gibt! Vielen Dank für en Input! :-) Das Ganze jetzt auch noch umzusetzen wird wohl ein separater Spass! :-) Es soll übrigens ein Anzeige der nächsten 3 Flugzeuge an einem Flughafen basierend auf Distanz und den Daten der opensky-network API werden. Dieser Thread ist also noch eine Weile "alive"!
Stefan ⛄ F. schrieb: > Da besteht halt jedes Zeichen aus 4x8 Pixeln Das ist aber sehr ungünstig und gibt nur schlecht lesbare Zeichen, 5 x 7 ist so etwa das sinnvolle Minimum. Ich glaube eher er hat sich da verzählt und es sind 5 Bytes pro Character. Georg
Georg schrieb: > Stefan ⛄ F. schrieb: >> Da besteht halt jedes Zeichen aus 4x8 Pixeln > > Das ist aber sehr ungünstig und gibt nur schlecht lesbare Zeichen, 5 x 7 > ist so etwa das sinnvolle Minimum. Ich glaube eher er hat sich da > verzählt und es sind 5 Bytes pro Character. > > Georg Ja, für ein m braucht man 5 Spalten, egal ob klein oder groß. Alles andere ginge auch mit 4. Falls der Zeichensatz wirklich 5x7 ist und das ganze auf 4 byte komprimiert (wegen soll in 0 Byte RoM passen), dann wäre mein Tipp oben, dass auszukästeln, wohl vergeblich.
Hallo, du zeichnest im Prinzip eine Rotte von kleinen Bitmaps, immer pro Zeichen eines. Also wird aus dem String HURZ die Kombination H U R Z. Trick dabei ist der Ascii-Code, du kannst Z.B. 'b' - 'a', um 1 zu bekommen...wen du nicht einfach alle 255 ASCII-Zeichen als Bitmap mitschleppen willst. Für die Erzeugung der Bitmaparrays empfehle ich den GLCD Font Creator, findet sich unter https://www.mikroe.com/glcd-font-creator. Vollständiges Tutorial, damals mit einer 16x16 LED-Matrix die mir meine Ex-LZ aufgeschwatzt hat, findest du unter https://www.elektormagazine.de/magazine/elektor-201604/28886.
c-hater schrieb: > Da bleiben aber immer noch mindestens zwei mögliche Lösungen über: > Es können entweder 5 Bytes sein, die je sieben Nutzbits enthalten oder > aber 7 Bytes, die je 5 Nutzbits enthalten. Tatsächlich sind es 3..4 mögliche Lösungen: - 5 Byte, von denen je 7 Bit genutzt werden - 7 Byte, von denen je 5 Bit genutzt werden - Bitstream (also wo die Bytegrenzen nicht mit den Pixelpositionen übereinstimmen) - Bitstream komprimiert W.S.
Hier ist der Font aus meiner OLED Bibliothek:
1 | static const uint8_t font6x8 [] PROGMEM = { |
2 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // space |
3 | 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // ! |
4 | 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // " |
5 | 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // # |
6 | 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ |
7 | 0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // % |
8 | 0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // & |
9 | 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // ' |
10 | 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // ( |
11 | 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // ) |
12 | 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // * |
13 | 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // + |
14 | 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // , |
15 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // - |
16 | 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // . |
17 | 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // / |
18 | 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 |
19 | 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 |
20 | 0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2 |
21 | 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3 |
22 | 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 |
23 | 0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5 |
24 | 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 |
25 | 0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7 |
26 | 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8 |
27 | 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 |
28 | 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // : |
29 | 0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ; |
30 | 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // < |
31 | 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // = |
32 | 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // > |
33 | 0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ? |
34 | 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @ |
35 | 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A |
36 | 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B |
37 | 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C |
38 | 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D |
39 | 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E |
40 | 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F |
41 | 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G |
42 | 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H |
43 | 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I |
44 | 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J |
45 | 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K |
46 | 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L |
47 | 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M |
48 | 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N |
49 | 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O |
50 | 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P |
51 | 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q |
52 | 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R |
53 | 0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S |
54 | 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T |
55 | 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U |
56 | 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V |
57 | 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W |
58 | 0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X |
59 | 0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y |
60 | 0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z |
61 | 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [ |
62 | 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // backslash |
63 | 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ] |
64 | 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^ |
65 | 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _ |
66 | 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // ' |
67 | 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a |
68 | 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b |
69 | 0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c |
70 | 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d |
71 | 0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e |
72 | 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f |
73 | 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g |
74 | 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h |
75 | 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i |
76 | 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j |
77 | 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k |
78 | 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l |
79 | 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m |
80 | 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n |
81 | 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o |
82 | 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p |
83 | 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q |
84 | 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r |
85 | 0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s |
86 | 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t |
87 | 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u |
88 | 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v |
89 | 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w |
90 | 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x |
91 | 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y |
92 | 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z |
93 | 0x00, 0x00, 0x08, 0x77, 0x41, 0x00, // { |
94 | 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, // ¦ |
95 | 0x00, 0x00, 0x41, 0x77, 0x08, 0x00, // } |
96 | 0x00, 0x08, 0x04, 0x08, 0x08, 0x04, // ~ |
97 | 0x00, 0x3D, 0x40, 0x40, 0x20, 0x7D, // ü |
98 | 0x00, 0x3D, 0x40, 0x40, 0x40, 0x3D, // Ü |
99 | 0x00, 0x21, 0x54, 0x54, 0x54, 0x79, // ä |
100 | 0x00, 0x7D, 0x12, 0x11, 0x12, 0x7D, // Ä |
101 | 0x00, 0x39, 0x44, 0x44, 0x44, 0x39, // ö |
102 | 0x00, 0x3D, 0x42, 0x42, 0x42, 0x3D, // Ö |
103 | 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, // ° |
104 | 0x00, 0x7E, 0x01, 0x49, 0x55, 0x73, // ß |
105 | };
|
(Verdammt, ich kriege die Leerzeilen am Ende nicht weg. Die Foren-Software stellt das nicht korrekt dar.)
Fiken wird auf jeden Fall richtig mit "C" geschrieben! Ich muss es schließlich wissen.
W.S. schrieb: > Tatsächlich sind es 3..4 mögliche Lösungen: [...] Wenn man so penibel sein will, gibt es noch viel mehr Möglichkeiten. Sind aber letztlich alles nur Varianten zweier Grundschemata: zeilenweise vs. spaltenweise. Das war, was ich eigentlich ausdrücken wollte.
So! Guten Tag! Jetzt habe ich das so hinbekommen dass Buchstaben, Zahlen, Zeichen usw. aus dem program space ausgelesen werden und korrekt auf der Matrix dargestellt werden. Ich gebe dazu die Stelle an in der sich das erste byte im Array befindet und lese die folgenden 4 auch aus. Muss ich jetzt eine weitere ( womöglich switch case ) Tabelle bauen um jedem Zeichen, Buchstaben usw. einen Wert zuzuordnen? Also so würde ich es machen. Die Frage ist ob man das so macht?
Attila C. schrieb: > Muss ich jetzt eine weitere ( womöglich switch case ) Tabelle bauen um > jedem Zeichen, Buchstaben usw. einen Wert zuzuordnen? Also so würde ich > es machen. Was hast Du immer mit Deinem Switch/Case? Ja, man braucht Arrays für Fonts, ja, es Switch/Case hat seine Berechtigung, aber was willst Du tun?
Ich mag switch/case. Ja die fonts hab ich schon im Array. Die bytes für mein großes "A" liegen da z.B. an Stelle 325,326,327,328 und 329. Mache ich jetzt eine Tabelle und ordne jedem Buchstaben, Zeichen usw. 5 Zahlenwerte zu? Oder gibt es da elegantere Wege?
Attila C. schrieb: > Stelle 325,326,327,328 und 329. Warum? Das große A sollte an der Stelle array[65] liegen
"Warum mal 5? Mache doch ein zweidimensionales Array" Könnte man machen aber es beantwortet meine Frage nicht: Muss ich eine Tabelle machen bei der ich jedem Buchstaben eine Zahl zuordne damit dieser "seine" bytes im Array findet. Oder geht das eleganter?
Attila C. schrieb: > Muss ich eine > Tabelle machen bei der ich jedem Buchstaben eine Zahl zuordne damit > dieser "seine" bytes im Array findet Das wäre mM nach die eleganteste Lösung. Eine Tabelle, was ja ein Array ist. Dort ist Index gleich ASCI-Code. Und in diesem Index steht der entsprechende Buchstabe, bwz die Beschreibung wie er aussieht.
Attila C. schrieb: > Jetzt habe ich das so hinbekommen dass Buchstaben, Zahlen, Zeichen usw. > aus dem program space ausgelesen werden und korrekt auf der Matrix > dargestellt werden. Ich gebe dazu die Stelle an in der sich das erste > byte im Array befindet und lese die folgenden 4 auch aus. OK, es scheint sich also um die spaltenweise abgelegte Variante eines 5xirgendwas-Fonts zu handeln. "irgendwas" dürfte typisch entweder 7 oder 8 sein. > Muss ich jetzt eine weitere ( womöglich switch case ) Tabelle bauen um > jedem Zeichen, Buchstaben usw. einen Wert zuzuordnen? Also so würde ich > es machen. Die Frage ist ob man das so macht? Egal ob nun "irgendwas" 7 oder 8 ist. Solange der Zeichensatz lückenlos ist, kann man die Startadresse des Glyphs einfach aus dem Zeichencode berechnen, der dargestellt werden soll. Nehmen wir einfach mal an, der Zeichensatz würde 8 Zeilen pro Zeichen umfassen und bei dem Zeichen mit dem Code 32, also dem Leerzeichen beginnen und bei dem Zeichen 127 enden. Dann muss man bei der Ausgabe erstmal checken, ob der Code eines auszugebenden Zeichens zwischen 32 und 127 liegt. Wenn nicht, wäre die typische Lösung ein Ersatzcode für das Zeichen, z.B. 63, also Fragezeichen. Nachdem nun das Zeichen erstmal auf seine Darstellbarkeit geprüft und notfalls angepasst ist, ist die verbleibende Rechnung ganz simpel. Als erstes zieht man vom Zeichencode den Code des ersten Zeichens ab, der überhaupt im Zeichensatz verfügbar ist. Das, was überbleibt, multipliziert man einfach mit dem Speicherbedarf eines Zeichens in der Tabelle, was bei dir ja offensichtlich 5 Bytes sind. Für ein grosses 'A' mit Zeichencode 65 würde sich also ergeben: (65 - 32) * 5 = 165 Du findest deine 5 Bytes für das Zeichen also ab Offset 165 im Zeichensatz. Noch ein Tipp: statt 65 kannst du in C (und Asm) auch 'A' schreiben...
Mir ist nicht klar wo da die Prüfung stattfindet. Angenommen ich habe einen Stream von Buchstaben in dem jetzt ein "A" vorkommt. Wie "merkt" ein Array dass es sich um ein "A" handelt (und verweist auf ->65)? Ich kann doch jetzt nicht 255 "if" Anweisungen für jedes mögliche ASCII schreiben? Oder etwa doch?
"Noch ein Tipp: statt 65 kannst du in C (und Asm) auch 'A' schreiben..." Ach das ist ja krass!!! Ist das abgefahren! Vielen Dank!
Attila C. schrieb: > Angenommen ich habe > einen Stream von Buchstaben in dem jetzt ein "A" vorkommt. Wie "merkt" > ein Array dass es sich um ein "A" handelt (und verweist auf ->65)? Ich > kann doch jetzt nicht 255 "if" Anweisungen für jedes mögliche ASCII > schreiben? Oder etwa doch? WOzu auch? Du nimmst einfach das Zeichen (in einem byte oder char) und nutzt das als Arrayindex. Die oben genannten Prüfungen natürlich beachten. char c = ...; // one letter from stream array[c]...
Ich hatte das nicht mehr auf dem Schirm dass ASCII ja genau dafür gemacht ist, nämlich einem Zeichen genau eine Zahl in der Range 0-255 zuzuordnen. Und dass man es natürlich auch einfach umkehren kann. Also Buchstabe entspricht Zahl.
Attila C. schrieb: > Ich hatte das nicht mehr auf dem Schirm dass ASCII ja genau dafür > gemacht ist, nämlich einem Zeichen genau eine Zahl in der Range 0-255 > zuzuordnen. Nö, ASCII geht nur von 0..127. Und die ersten 32 Codes sind eigentlich nicht "druckbar". Was du da versuchst umzusetzen, ist was anderes: eine "Codepage". > Und dass man es natürlich auch einfach umkehren kann. Also > Buchstabe entspricht Zahl. Tatsächlich gibt es eigentlich aus Sicht eines Rechenknechts überhaupt keine Buchstaben. Der kann nur Zahlen, nix anderes.
Ich denke, der TO sollte sich noch einmal den Unterschied zwischen der Definition eines Zeichens und der Nutzung dieses Zeichens, z.B. "Zeichen anzeigen" klarmachen. Er könnte sich auch noch einmal anschauen, wie man in so einem gängigen Display (z.B. 2 Zeilen mit 16 Zeichen) "eigene Zeichen" definiert. Genau so geht das ja im Prinzip für jedes Zeichen, nur dass das Display eben schon definierte Zeichen mitbringt. Gruß Rainer
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.