ich habe mal eine Frage zu diesen Grafik LCDs, bisher habe ich nur diese 20x2...Teile verwendet. 1. Muss ich bei 128x64 8kByte RAM haben um den kompletten Bildschirminhalt vorhalten zu können und ihn dann zu übertragen? 2. Oder kann man wie bisher einzelne Buchstaben/Ziffern übertragen und ggf. eine Schriftgröße vorgeben. Im Prinzip möchte ich nur 2 Temperaturwerte etwas größer darstellen und ggf. ein Menü zum durchblättern aufrufen. Gibts ein gutes Tutorial, das ihr empfehlen könnt?
> 1. Muss ich bei 128x64 8kByte RAM haben um den kompletten > Bildschirminhalt vorhalten zu können und ihn dann zu übertragen? Manche Display koenntest du parallel ansprechen. Dann kannst du sie auslesen und brauchst kein internes Ram. Es gibt aber auch viele die koennen nur SPI und selbst wenn nicht, man will eigentlich nichts parallel machen. Daher brauchst du 128x64Bit. > 2. Oder kann man wie bisher einzelne Buchstaben/Ziffern übertragen und > ggf. eine Schriftgröße vorgeben. Nein. Im Gegenteil du brauchst sogar noch einen Font in deinem Flashrom. Olaf
Thomas O. schrieb: > 1. Muss ich bei 128x64 8kByte RAM haben um den kompletten > Bildschirminhalt vorhalten zu können und ihn dann zu übertragen? Hier geht es nicht um Bytes sondern um bit. Deshalb nur 1 kByte. Aber extra RAM braucht man dafür nicht. Man kann immer aus dem Bildschirm lesen, modifizieren und zurück schreiben. Das ist notwendig, wenn man Byte-"Streifen" des Bildschirms nicht beachten und Zeichen dazwischen schreiben will. Ich habe auf meiner Platine DIP128-6 von EA. Ich habe drei verschiedene Fonts gemacht und ich kann sie punktgenau platzieren. Das ist möglich gerade durch Lesen-Ändern-Zurückschreiben. Thomas O. schrieb: > 2. Oder kann man wie bisher einzelne Buchstaben/Ziffern übertragen und > ggf. eine Schriftgröße vorgeben. Du muß alles selber machen, aus gespeicherten Muster Punkt für Punkt. Fertige Zeichensatz gibt es im Graphik-LCD nicht. Dafür aber hast du volle Freiheit. Als Beispiel: in Symbol-LCD ist untere Hälfte von Zeichen immer gleich, die obere aber hat viele Varianten, damit man nationale Sprachen verwenden kann. So kann man für Deutsch Umläute haben oder auch kyrillische Buchstaben für Russisch. Aber nicht gleichzeitig! Mit Graphik-LCD hast du alles immer. Du kannst beliebige Schriftgröße haben. Alles ist in deinen Händen. Du bekommst alles, was du einprogrammierst.
Es sollte inzwischen auch solche Displays geben, die ein wenig intelligenter sind und z.B. einen Zeichensatz selbst vorhalten (kenne keines, aber ich würde es der DOG-Reihe oder so zutrauen). Die 8K RAM sind nur empfehleswert wenn Du Änderungen am Display-Inhalt vornehmen willst und keine schnelle Schnittstelle hast. Dann macht sich so ein Framebuffer gut, ohne mußt Du erst die betroffenen RAM-Zellen vom Display in den Controller laden, ändern und zurückschreiben. Die 8K RAM sind bei einfachen Pixeln auch nur 1Kbyte, da pro Byte acht Pixel gespeichert werden. 1K RAM hat fast jeder Controller übrig, auf dem sich die Programmierung mit grafischen Displays lohnt.
Mal angenommen, du meinst OLED mit SSD1306 Controller, dann... kannst du direkt in den Speicher des Displays schreiben. Pufferspeicher ist nicht zwingend erforderlich. Über SPI kann man angeblich schreiben und lesen (habe ich nicht ausprobiert). Über die I²C Schnittstelle kann man nur schreiben, nicht lesen. In letzter Konsequenz bewirkt dies, dass jede Ausgabe im 8-Pixelzeilen Raster erfolgen muss. Damit könntest du zum Beispiel 8 Zeilen Text mit einem kleinen Font 8x5 oder 4 Zeilen mit einem großen 16x10 Font darstellen. Oder Bilder deren Höhe genau ein vielfaches von 8 ist. Für Ausgaben mit anderen Abmessungen muss man das RAM auslesen und die neuen Ausgaben in das existierende Bild hinein zeichnen. Das geht wie gesagt mit I²C gar nicht. Mit SPI geht es, aber ziemlich umständlich und langsam. Deswegen benutzen die meisten Bibliotheken einen Puffer im RAM, auf den man jederzeit wahlfreien Zugriff hat. Die Ausgabe wird im RAM vorbereitet und dann zum Display gesendet. 128x64 sind 8192 Pixel, also 1 Kilobyte.
Wenn man interne Mikrocontroller-SRAM dafür benutzt, geht es wohl etwas schneller, wenn man zwischen Byte-Streifen schreiben muß. Aber es geht auch ohne SRAM. Hier sind Symbol- und Graphik-LCD etwa gleich: Graphik-LCD braucht keine Wartezeit nach jedem Befehl oder Datenschreiben. Dafür sind deutlich mehr Zugriffe notwendig: auch wenn man innerhalb von Byte-Streifen schreibt (und somit kein Lesen notwendig), braucht ein Symbol immer noch 6 Byte (5x8 Symbol + 1 byte dazwischen), die einzeln zu schreiben sind.
:
Bearbeitet durch User
Stefan ⛄ F. schrieb: > Über SPI kann man angeblich schreiben > und lesen (habe ich nicht ausprobiert). Man kann mit einfachen Logik-IC aus jedem Bildschirm einen SPI-Bildschirm machen. Hier ist ein Beispiel dafür. R49-R56 sind eigentlich nicht notwendig. Hier sind sie für mögliche Fehler beim Programmieren gedacht. Es werden über SPI immer 2 Bytes geschrieben: Data und Control. Dabei ist erste empfangene Byte (falls vorher Bildschirm auf Lesen eingestellt wurde) auch Data aus dem Bildschirm. Für Lesen braucht man E-Strob zweimal, deshalb braucht Lesen mehr Zugriffe als einfaches Schreiben. Schreiben:
1 | // Treiber fuer Schreiben
|
2 | void graph_128x64_write(u8 data, u8 dienst){ |
3 | |
4 | // liest data aus Puffer, schreibt Data und Dienstport
|
5 | // spi_intern_start();
|
6 | spi_master_transmit(data); |
7 | spi_master_transmit(dienst); |
8 | spi_intern_start(); |
9 | spi_intern_stop(); |
10 | |
11 | }
|
12 | |
13 | void graph_128x64_writedata(u8 data, graph_enmode_t haelfte){ |
14 | // haelfte == EN1 > E1, haelfte == EN2 > E2
|
15 | // haelfte == EN12 > E1+E2
|
16 | u8 temp = GRAPH_128X64_DI; // DI>1 |
17 | u8 temp1 = temp; |
18 | |
19 | switch(haelfte){ |
20 | case EN1 : |
21 | {
|
22 | temp1 |= GRAPH_128X64_E1; |
23 | break; |
24 | }
|
25 | case EN2 : |
26 | {
|
27 | temp1 |= GRAPH_128X64_E2; |
28 | break; |
29 | }
|
30 | case EN12 : |
31 | default:
|
32 | {
|
33 | temp1 |= GRAPH_128X64_EE; |
34 | }
|
35 | |
36 | }
|
37 | graph_128x64_write(data, temp); |
38 | graph_128x64_write(data, temp1); |
39 | graph_128x64_write(data, temp); |
40 | }
|
Lesen:
1 | // Treiber fuer Lesen/Schreiben
|
2 | u8 graph_128x64_writeread(u8 data, u8 dienst){ |
3 | |
4 | // liest data aus Puffer, schreibt Data und Dienstport
|
5 | u8 temp = 0; |
6 | spi_intern_start(); |
7 | asm volatile( |
8 | "lpm\n\t" |
9 | );
|
10 | temp = spi_master_transmit(data); |
11 | spi_master_transmit(dienst); |
12 | spi_intern_stop(); |
13 | return temp; |
14 | |
15 | }
|
16 | |
17 | u8 graph_128x64_readdata(graph_enmode_t haelfte){ |
18 | // haelfte == EN1 > E1, haelfte == EN2 > E2
|
19 | |
20 | u8 data = 0; |
21 | u8 temp = (GRAPH_128X64_DI | GRAPH_128X64_RW | GRAPH_128X64_RD); // data read |
22 | u8 temp1 = temp; |
23 | if(haelfte == EN1){ |
24 | temp1 |= GRAPH_128X64_E1; |
25 | }else{ |
26 | temp1 |= GRAPH_128X64_E2; |
27 | }
|
28 | |
29 | graph_128x64_write(0, temp); // E-Doppelimpuls |
30 | graph_128x64_write(0, temp1); |
31 | graph_128x64_write(0, temp); |
32 | graph_128x64_write(0, temp1); |
33 | graph_128x64_write(0, temp); |
34 | |
35 | temp &= ~(GRAPH_128X64_RW | GRAPH_128X64_RD); // data write vorbereiten |
36 | data = graph_128x64_writeread(0, temp); // E > 0, Z>0 |
37 | return data; |
38 | }
|
:
Bearbeitet durch User
Maxim B. schrieb: > Hier ist ein Beispiel dafür. Du bist auf der falschen Hochzeit, bei den Text-Displays mit HD44780 Controller oder ähnlich. Wir sind bei Grafik-Displays, die bereits SPI/I²C on Board haben.
Also wenn sie echtes SPI in Hardware haben, sollten sie eigentlich schnell genug sein, um auch read-modify-write-Zyklen in annehmbarer Zeit zu schaffen. Was sind eigentlich Byte-Streifen?
GOOGLE (Bildersuche) fragen: temperature display on graphic lcd example font temperature display on graphic lcd example font "source code" Da findet sich bestimmt was...
Stefan ⛄ F. schrieb: > Für Ausgaben mit anderen Abmessungen muss man das RAM auslesen und die > neuen Ausgaben in das existierende Bild hinein zeichnen. Das geht wie > gesagt mit I²C gar nicht. Man kann beliebige Graphik-LCD mit Parallelinterface über I2C-Erweiterung anschließen, so wie MCP23017. Das wird zwar langsamer, aber grundsätzlich kein Unterschied mit SPI über MCP23S17 (was ich schon gemacht habe. Zwar langsamer als mit 74HC-Logik, aber Schreiben und Lesen problemlos möglich). Hier ist die von mir früher erprobte Schaltung. MCP23S17 kann man durch MCP23017 ersetzen, somit bekommt man statt SPI I2C, alles andere bleibt unverändert (außer Geschwindigkeit natürlich).
:
Bearbeitet durch User
Ben B. schrieb: > Was sind eigentlich Byte-Streifen? Ein Byte auf der Schnittstelle entspricht 8 Pixeln die untereinander stehen. Eine Folge von 128 Bytes füllt 8 Linien auf dem Display, das nennt er "Streifen". Ganz oben ist das niederwertigste Bit. Ein L, dass die ganze Höhe des "Streifens" (8 Pixel) ausfüllen würde, hat die Byte-Folge: 255,128,128,128,128,128 In einem echten Font würde man natürlich unten und rechts ein Pixel Abstand frei halten, also: 127,64,64,64,64,0 War das verständlich?
Ben B. schrieb: > Was sind eigentlich Byte-Streifen? Verbreitete Graphik-LCD sind als Zeilen aus vertikalen Bytes organisiert. So hat man bei einem 128x64 Bildschirm 8 Byte-Zeilen je 128 vertikalen Bytes. Die Bytes 0...63 sind mit dem Strob E1 zugreifbar, die restlichen mit E2. Deshalb wenn man Zeichen willkürlich schreiben will, muß man oft auch für 5x8-Zeichen zwei Bytes (übereinander) lesen, einige Bit ändern und zurückschreiben. Etwas mehr Aufwand, aber alles funktioniert bei mir problemlos. Stefan ⛄ F. schrieb: > Du bist auf der falschen Hochzeit, bei den Text-Displays mit HD44780 > Controller oder ähnlich. Du irrst dich. DIP128-6 von EA gehört zu einer sehr verbreiteten Art von Graphik-LCD. Nur daß die meisten als Module zum Löten gemacht sind und DIP128-6 als DIL eingesteckt sein kann.
:
Bearbeitet durch User
> Also wenn sie echtes SPI in Hardware haben, sollten sie eigentlich
Ach Leute. Lest ihr eigentlich auch mal Datenblaetter?
Die meisten GrafikLCD die man seriell beschreiben kann haben keinen
Datenausgang. Die kann man wirklich nur beschreiben. Es gibt Ausnahmen,
aber die sind selten.
Und parallel will man nicht, Aufwand, lahm, Portpinverlust, EMV.
Bei dem was heutige Mikrocontroller an Ram haben ist das aber auch kein
Problem mehr. Frueher war das anders. So um 2005 hab ich mir mal einen
Algorythmus geschrieben der Displayinhalte im Ram datenreduziert
gespeichert hat. Ich hab dabei immer die letzten x (einstellbar) Bytes
im Ram gehalten und konnte darauf dann Pixelweise zugreifen. Damit kommt
man erstaunlich weit weil man doch das meiste zusammenhaengend ausgibt.
So hab ich anstatt 1kb immer nur 200-300Bytes gebraucht.
Aber heute natuerlich alles unnoetig.
Olaf
Stefan ⛄ F. schrieb: > Wir sind bei Grafik-Displays, die bereits SPI/I²C on Board haben. TO hat darüber nichts geschrieben. Er schrieb nur von Graphik-LCD, der er statt bisher benutzten von ihm Symbol-LCD verwenden will. Es gibt viele solcher Art. Ein paar Beispiele: https://www.reichelt.de/lcd-grafikdisplay-128x64-pixel-ge-gn-m-bel--lcd-128x64gn-ab-p197566.html?&trstct=pol_5&nbc=1 https://www.reichelt.de/lcd-grafikdisplay-128x64-pixel-bl-ws-m-bel--lcd-128x64bl-aa-p197563.html?&trstct=pol_10&nbc=1 https://www.reichelt.de/lcd-dip-grafikmodul-128-x-64-punkte-lcd-128sw-dip-p53971.html?&trstct=pol_13&nbc=1
Olaf schrieb: > Bei dem was heutige Mikrocontroller an Ram haben ist das aber auch kein > Problem mehr. Es sei denn, man hält wie Manfred am ATmega328 fest. Beitrag "Arduino China-ProMini stürzt ab" Für den sind die 1kB in Kombination mit einer SD Karte zum Problem geworden.
Thomas, bevor hier wieder ein unnötiger Streit ausbricht, benenne deine Produkte um die es geht.
Es gibt auch andere Graphik-Bildschirme, farbig. So wie dieser: https://www.ebay.de/itm/240x320-2-8-SPI-TFT-LCD-Touch-Panel-Serial-Port-Module-with-PCB-ILI9341-Xs4/283974309434?hash=item421e30163a:g:HHUAAOSwArFbz85E Die können zwar mehr und haben von Natur aus SPI, Schreiben und Lesen, dazu oft auch Touch noch. Aber die sind mit AVR etwas zu langsam: deutlich mehr Pünkte, 240 x 320, und jeder Punkt braucht zwei oder drei (je nach Einstellung) Bytes über SPI zu schreiben. Ich spiele gerade mit so einem. Farbig, aber langsamer... Trotzdem kann man sie auch mit AVR verwenden.
:
Bearbeitet durch User
> man will eigentlich nichts parallel machen.
Ist das zu schnell?
Wo liegt das Problem grademal 8 Pins zu nem Bus heraus zu führen?
> Ist das zu schnell? Nein, das ist zu langsam. Weil internes Ram krass viel schneller ist als wenn du da mit Ports rumwedelst. > Wo liegt das Problem grademal 8 Pins zu nem Bus heraus zu führen? Kannst du nicht lesen? Es sind erstmal nicht 8Pins sondern eher 11 oder 12. Wenn du so einen armseligen Mickrichprozessor hast wo du dir um 1k Gedanken machen musst dann hast du auch keine Portpins. Dann darfst du auch noch schoen 12Leitungen ueber die Platine, oder gar ein laengeres Kabel routen. Damit kannst du dann tolle EMV Probleme haben. Das tut man sich nicht an wenn es viel einfacher geht. Olaf
Thomas O. schrieb: > 1. Muss ich bei 128x64 8kByte RAM haben um den kompletten > Bildschirminhalt vorhalten zu können und ihn dann zu übertragen? Nein. Wie gesagt, jedes Pixel = 1 Bit. Damit gilt 128*64/8=1024 Byte für den Bildspeicher. Hier wurde auch ein paarmal gesagt, daß man ja den Bildspeicher des Displays zurücklesen, modifizieren und wieder hinschreiben kann. Ja, geht im Prinzip, ist aber ausgesprochen umständlich und langsam. Deswegen wäre mein Rat, daß du dir einen µC gönnst, der genug RAM hat, wo du dir einen Bildspeicher von 1 K Größe reservieren kannst, wo du freiweg drauf zeichnen, malen, schreiben kannst. Den dann als Block ins Display zu schieben, ist garantiert einfacher als sich auszurechnen, was man alles zurücklesen, modifizieren etc. muß, um die Kringel auf's Display zu kriegen, die man dort haben will. > 2. Oder kann man wie bisher einzelne Buchstaben/Ziffern übertragen und > ggf. eine Schriftgröße vorgeben. Ein Grafikdisplay kann Pixel anzeigen. Wenn du Text anzeigen willst, dann brauchs du eine Font dafür. Oder mehrer Fonts, je nachdem, was du tun willst. Guck hier im Forum herum, da haben so einige Leute ihre Ideen von Fonts und GDI's gepostet - auch ich. Da kannst du dir raussuchen, was dir gefällt. > Im Prinzip möchte ich nur 2 Temperaturwerte etwas größer darstellen und > ggf. ein Menü zum durchblättern aufrufen. Ach, etwa so etwas: https://www.mikrocontroller.net/attachment/434172/Loetstation-3.jpg Und gegebenenfalls ein Menü? Hast du dir da bereits Gedanken gemacht, wie du das machen willst? Jaja, natürlich geht das, aber es ist etwas umfänglicher als bei einem Alpha-LCD, wenn es gut aussehen und gut benutzbar sein soll. > Gibts ein gutes Tutorial, das ihr empfehlen könnt? Nö. W.S.
Man braucht nicht unbedingt einen Buffer, solange man sich auf Text beschränkt: Beitrag "SSD1306/1309 Library zum Darstellen von Text auf OLED Displays" Der Nachteil dieser Lib ist allerdings, dass nur kleine Fonts oder hochskalierte damit gehen. Die kleinen Fonts kann ich bei den gängigen 0,96" kaum lesen, die skalierten schauen prinzipbedingt nicht sonderlich schön aus. Deshalb habe ich mir mal eine Lib gebaut, die größere Fonts, Sonderzeichen und Symbole direkt darstellen kann. Das geht auch ohne Buffer. Der Speicherbedarf für die Fonts muss nicht mal groß sein, wenn man sich auf die tatsächlich verwendeten Zeichen beschränkt. Irgendwelche Grafiken gehen ohne Buffer dagegen kaum, zumindest nicht sinnvoll. Allerdings it es doch fraglich, ob man in der Realität Bildchen auf solchen Displays braucht. Falls ja, ist auf jeden Fall ein größerer Controller als ein AVR sinnvoll.
>> Ist das zu schnell? >Nein, das ist zu langsam. Weil internes Ram krass viel schneller ist als >wenn du da mit Ports rumwedelst. Ein einzelner (Pin)Port wird nicht langsamer, wenn es parallel rausgeschickt wird als wenn es über SPI rausgeschickt wird. Zudem gibt es Ports, die mit der gleichen Frequenz wie RAM auch die Bits verschicken können. Also parallel ist (wenn nicht mehrere Gbps auf einer Leitung übertragen werden) schneller, nicht langsamer. Zudem oft auch, weniger Befehle und weniger CPU-Overhead nötig (je nach CPU, grade bei kleineren CPUs). Einen 8-Bit-Bus mit einigen Steuerleitungen zu routen oder zu verlegen stellt keinerlei EMV-Problem dar, wenn man es richtig macht.
Was du da schreibst trifft nicht auf die kleinen 8bit Mikrocontroller zu, um die es hier zu 90% geht.
Thomas O. schrieb: > 2 Temperaturwerte Ganz ehrlich? Wir leben nicht mehr in der Steinzeit, wo soll diese Diskussion hinführen? Selbst moderne 8bit Tiny Mikrocontroller haben ausreichend RAM um das ganze Bild zwischenzuhalten, vor allem will der TO nur zwei Temperaturwerte anzeigen. Ich habe mit Displays von EA (Dog) und Display Elektronik gearbeitet. Bei beiden musste ich den Inhalt im RAM des Mikrocontrollers zwischenhalten. Ist doch aber kein Problem? Genug RAM ist immer da und die Übertragung mit SPI ist dann richtig flott. I²C würde ich vermeiden, SPI finde ich einfacher, stabiler und weniger fehleranfällig. Wer natürlich auf Herausforderungen steht und die Ressourcen des Mikrocontrollers zu eng wählt, der hat selber Schuld. W.S. schrieb: > Deswegen wäre mein Rat, daß du dir einen µC gönnst, der genug RAM hat, > wo du dir einen Bildspeicher von 1 K Größe reservieren kannst, wo du > freiweg drauf zeichnen, malen, schreiben kannst. Den dann als Block ins > Display zu schieben, ist garantiert einfacher als sich auszurechnen, was > man alles zurücklesen, modifizieren etc. muß, um die Kringel auf's > Display zu kriegen, die man dort haben will. So siehts aus. Und bitte programmiere nicht in Assembler ...
:
Bearbeitet durch User
Ben S. schrieb: > Selbst moderne 8bit Tiny Mikrocontroller haben > ausreichend RAM um das ganze Bild zwischenzuhalten Nur der eine halt nicht, den eine gewisse italienische Firma verwendet hat, um sie alle zu knechten.
Stefan ⛄ F. schrieb: > Nur der eine halt nicht, den eine gewisse italienische Firma verwendet > hat, um sie alle zu knechten. Keine Ahnung welchen du genau meinst, da für mich Arduino wirklich nur was für den Einstiegsbastler ist der sich hoffentlich schnell davon abwendet. Aber selbst der ATmega328P hat 2kByte, was für seine Anforderungen durchaus reichen sollte. Aber wie gesagt gibt es deutlich bessere Alternativen und es gibt auch Arduino mit STM32.
Ben S. schrieb: > Keine Ahnung welchen du genau meinst, da für mich Arduino ... > Aber selbst der ATmega328P hat 2kByte Na also, du weisst es ja doch. Ja er hat 2kB und das reicht für ein kleines Display. Wenn er sonst nicht viel zu tun hat. Das ist aber der Knackpunkt. Dinge mit solchen Displays haben sinnvollerweise meistens doch sehr viel mehr zu tun, als nur das Display anzusteuern. > Aber wie gesagt gibt es deutlich bessere Alternativen ja
ich dachte an soetwas https://www.aliexpress.com/item/4000388237877.html angegeben ist ein ST9720, werde mir mal das Datenblatt ziehen, klar sind ja nur 1 kByte für eine Seite das sieht dann schon besser aus.
Thomas O. schrieb: > https://www.aliexpress.com/item/4000388237877.html Kann man (möglicherweise) prinzipiell benutzen. Schau auch mal hier: Filtere dort nach 128x64 und SPI. Da gibt dann die unterschiedlichsten Modelle mit verschiedenen Dimensionen, LED Beleuchtungsfarbe, etc. https://www.display-elektronik.de/Products_LCD_Graphic-mono.html Z.B: DEM 128064F SBH-PW-N
:
Bearbeitet durch User
Erwin E. schrieb: > Deshalb habe ich mir mal eine Lib gebaut, die größere Fonts, > Sonderzeichen und Symbole direkt darstellen kann. Das geht auch ohne > Buffer. Der Speicherbedarf für die Fonts muss nicht mal groß sein, wenn > man sich auf die tatsächlich verwendeten Zeichen beschränkt. Magst Du mir dazu etwas mehr verraten und die Lib zeigen?
SPI-Probleme bei (bisherigen, nicht die allerneusten) AVRs: 1.) SPI -TX hat keinen einzigen Byte-Buffer ...(es kann also nichtmal mit einem Jitter von +- der Länge eines ....ausgeschriebenen (SPI)Bytes in das SPI-Modul geschrieben werden) ...(evtl. kann man (wenn im Master-Mode) taktgenau 'warten' (diese Takte ....gehen aber verloren) und so weitere Bytes an TX rausschicken) ...(selbst ein winziger STM8 ist hier besser, und es gibt faktisch keine ....neuere CPU, die hier nicht wenigstens einen Buffer hat) 2.) Die SPI kann zwar einen EndOfTransm-INT auslösen, nur die ...Interrupt-Möglichkeiten sind sehr schlecht, ...keine setzbaren INT-Prioritäten möglich ...(somit muss u.U. eine riesige Menge (!) an Takt-Cyclen gewartet werden ....(was ja genaugenommen schon einen Gau darstellt), bis höher prioris. ....ISRs fertig sind) 3.) DMA oder Ähnliches? gibts nicht. ...(die CPU muss also heran gezogen werden) Also noch schlechter kann es eine CPU bei SPI-Transfer nicht mehr machen! Man könnte u.a. wenn nötig SPI-Hardware diskret an nen AVR dranhängen.
Erwin E. schrieb: > Man braucht nicht unbedingt einen Buffer, solange man sich auf Text > beschränkt: Dann hat Graphik-LCD wenig Sinn. Wenn man schon von Symbol-LCD zu Graphik-LCD wechselt, sollte Lib mindestens können, Linien und einfache Figuren (Viereck und Kreis, gestrichen und nicht) zeigen. Ich verstehe die Panik nicht: auch mit Lesen und schreiben, und quer gegen Byte-Zeilen (d.h. doppel so viel schreiben und lesen) schafft Lib bei mir mit F_CPU=16MHz 5 ms/Symbol. Gegen 1 ms/Symbol für Symbol-LCD. Ja, das ist mehr, aber immer noch zu verkraften. Für vollen Bildschirm und 5x8 Zeichen wird das 5 ms 21 Zeichen pro Zeile 8 Zeilen ca. 840 ms (und nur ein Drittel, wenn man innerhalb von Byte-Zeilen bleibt und nichts liest). Wenn man anders als bei mir Bildschirm nicht über SPI sondern direkt anspricht (12 Pins werden gebraucht, aber 10 davon (alle außer E1 und E2) können auch andere Geräte bedienen, z.B. andere LCD oder Tasten (für Tasten empfehle ich 4k7 Widerstand seriell)), wird nicht viel schneller, da LCD-Zyklus mindestens 1 us lang sein sollte, es muß auch viel berechnet werden, um ein Symbol aus Flash zu holen und auszugeben. MCUA schrieb: > Also noch schlechter kann es eine CPU bei SPI-Transfer nicht mehr > machen! Wenn du SPI mit ISR benutzt, schon. Mit SCK = F_CPU/2 hat das natürlich wenig Sinn, aber wenn man Bildschirm mit eingebauten SPI benutzt, welche oft auf nur 2 MHz oder auch niedriger beschränkt sind, dann kann ISR helfen. Daten und Befehle in Puffer und los, CPU macht was anderes, z.B. nächste Daten für LCD.
:
Bearbeitet durch User
Maxim, deine Zahlen passen vermutlich auf dein Display, aber nicht auf ein SSD1306. Das ist so schnell, darauf kann man Animationen und Soft-Scrolling darstellen, wenn man Puffer verwendet. Da reden wir von ganz andere Zeiten.
Stefan ⛄ F. schrieb: > Da reden wir von > ganz andere Zeiten. Aber gängige Symbol-LCD gehören zu "meinen" Zeiten auch. Wenn TO einen Symbolbildschirm für einen Graphik-Bildschirm tauschen will, sollte er Vergleichbares vergleichen. Erst dann wird klar, was gewinnt man und was verliert man, wenn Rechenleistung bei Symbolausgabe aus dem inneren Controller von Symbol-LCD auf Mikrocontroller (ATMega wie TO macht) überlagert wird.
:
Bearbeitet durch User
Maxim B. schrieb: > Aber gängige Symbol-LCD gehören zu "meinen" Zeiten auch. Wenn TO einen > Symbolbildschirm für einen Graphik-Bildschirm tauschen will, sollte er > Vergleichbares vergleichen. Ja.
TO könnte vielleicht versuchen (wenn Geschwindigkeit für ihn so wichtig ist) für Bildschirm separaten Mikrocontroller verwenden, der Routinenarbeit macht und Eingangspuffer hat. Dann kann Haupt-Mikrocontroller ganz bequem z.B. über TWI Befehle senden, so etwa: "zeichne mir mal eine Linie von dem Punkt xy bis zu dem Punkt xy" oder "schreib mir mal Text "xxx". Aber das ist eine schon viel anspruchsvollere Aufgabe...
:
Bearbeitet durch User
Maxim B. schrieb: > Erwin E. schrieb: >> Man braucht nicht unbedingt einen Buffer, solange man sich auf Text >> beschränkt: > > Dann hat Graphik-LCD wenig Sinn. > Wenn man schon von Symbol-LCD zu Graphik-LCD wechselt, sollte Lib > mindestens können, Linien und einfache Figuren (Viereck und Kreis, > gestrichen und nicht) zeigen. Was eine LCD-Lib mindestens können muss, hängt nur von der Anwendung ab. Braucht (!= möchte) man eine Grafikausgabe, nimmt man eben eine Lib die das bietet, sinnvollerweise auch gleich einen Controller, der die nötigen Ressourcen hat. Für viele Anwendungen, wo man bisher Characterdisplays verbaut hat, wird man meistens ohne Grafik auskommen. Vierecke, Kreise und Sterne sind nett für Demos, aber bei realen Geräten z.B. einer Steuerung stören irgendwelche kaum erkennbaren Bildchen doch mehr als sie nutzen. Bei Displays mit höherer Auflösung sieht das natürlich wieder anders aus. Wobei es Anwendungen gibt, wo Symbole nützlich sind. Beispiel: Transistortester. Aber auch dort braucht man keine Sternchen oder Kreise zeichnen, es genügt ein fester Satz von Symbolen. Schriften können auf Grafikdisplays wesentlich besser lesbarer sein als auf Charakterdisplays, spätestens wenn Umlaute benötigt werden. Darin sehe ich einen echten Mehrwert von Grafikdisplays gegenüber Charakterdisplays. Beim Batteriebetrieb haben OLEDs aufgrund des geringen Stromverbrauchs auch wieder einen Sinn, obwohl nur Schrift ausgegeben wird.
Ich spiele z.Z. mit einer selbstgemachten Platine. Ich bin ja kein Profi-Elektroniker, ich bin ein Musiker. Deshalb kann ich mir erlauben, zu machen, was ich möchte :) Symbol-LCD geht ohne Frage. Graphik-LCD auch, obwohl deutlich mehr Code. Symbol-LCD über TWI mit ISR geht auch gut, obwohl für wirklich bequeme Arbeit zwei Puffer gemacht: TWI-Puffer und noch extra LCD-Puffer, für Daten und Befehle. Wenn nur TWI-Puffer, dann wäre innere SRAM zu stark genutzt, 18 Bytes pro Command oder Data. Dabei sollte Puffer mindestens so groß sein, um 80 Symbole und 4 Command speichern zu können (80 Symbole und 4 Cursor-Einstellungen), sonst gibt es Verluste. Aber noch ILI9341-Bildschirm 240x320 Pünkte dazu scheint System schon etwas zu übelasten: Drehgeber ist wie im Schlaf. Vielleicht sollte diesen Bildschirm im Hintergrund über Puffer arbeiten, d.h. erst wenn keine anderen Aufgaben zu erledigen sind? Hier habe ich etwa theoretische Interesse. Klar: wenn ich etwas weniger schalte (z.B. ein oder zwei Bildschirme weg), wird Drehgeber wieder in Ordnung. Aber ob das auch so noch geht? Schließlich ist unwichtig, ob ein paar Ziffer auf dem Farb-TFT in 100 ms oder in 500 ms kommen... Dabei verwende ich noch kein Dispatcher, nur einfache Hauptschleife... Kontrollschleife ist bei mir so: 1. Jede Sekunde kommt ISR von DS3234. Datum, Zeit und Raumtemperatur werden gelesen und auf allen 4 Bildschirmen, jeder anders als die anderen, ausgegeben. 2. Drehgeber wird jede 1ms gefragt. Daraus wird u16-Zähler geändert und auf zwei verschiedenen Anzeigen mit MAX7219 ausgegeben, auch auf allen Bildschirmen. Darüber hinaus wird die Zahl in SPI-SRAM 23LCV1024 geschickt, wieder gelesen und auch gezeigt. 3. Tasten werden jede 10 ms gefragt. Wenn gedruckt, wird auf allen Bildschirmen Name von Taste ausgegeben, und auf den Graphik-Bildschirmen auch verschiedene Figuren, je nach der Taste. So foltere ich z.Z. eine AT Mega324PA. Gedacht ist alles dafür, um verschiedene Eingabe- und Ausgabemittel auf bequemere Weise arbeitsbereit zu machen: damit ich verschiedene externe Module testen könnte. Deshalb ist auch Graphik-LCD gerade das, was ich z.Z. quäle (glücklicherweise hat Bildschirm kein Piepser und kann sich nicht beschweren :) ).
Erwin E. schrieb: > Was eine LCD-Lib mindestens können muss, hängt nur von der Anwendung ab. Ich finde es sinnvoll, EINMAL eine Lib zu machen (und gründlich überprüfen), die alles macht. Und später diese gut geprüfte Lib immer verwenden. Wenn man fürchtet, zu viel unnützlichen Code in einigen Anwendungen zu haben, so kann man per #ifdef - #ifndef verschiedene Teile von Lib ausschalten. Immer für ein neues Gerät neue Lib zu schreiben (und zu überprüfen) finde ich nicht sinnvoll. Denn so außer vergeudeter Zeit wird auch notwendig, bei jedem Gerät ausreichende Debug-Möglichkeiten vorzusehen, die sonst auf vernünftigen Minimum reduziert sein könnten. Daraus kommt Forderung, sowohl Text wie auch geometrischen Figuren und einzenle Pünkte möglich zu machen. Lib sollte jeder möglichst selber schreiben oder mindestens selber überprüfen und korrigieren: nur so kann man ausreichend gut vorstellen, was und wie eigentlich gemacht wird.
:
Bearbeitet durch User
Manfred schrieb: > Magst Du mir dazu etwas mehr verraten und die Lib zeigen? Wollen tät ich schon, aber können tu ich nicht. Na ja, ich tu's trotzdem, obwohl manches noch ziemlich unfertig ist. Es fehlt leider auch (noch) an einer Doku. Das derzeitig Vorhandene hänge ich an. Disclaimer: Das ist mein Erstlingswerk in C. Momentan funktioniert die Lib nur mit OLEDs mit SSD1306, die über I²C angesteuert werden. Mit dem Fontconverter lcd-image-converter https://sourceforge.net/projects/lcd-image-converter/ rastere ich den gewünschten TTF-Font in der benötigten Größe. Proportional oder unproportional ist dabei egal. Es sind auch beliebige Sonderzeichen möglich wie Batteriesymbole oder was auch immer sonst im Font enthalten ist. Das Batteriesymbol im Foto ist ein Symbol aus dem verwendeten Zeichensatz und wird im Code genau wie ein Buchstabe behandelt. Als nächstes erstelle ich eine csv-Datei (Excel), in der festlegt wird, welche Unicodes benötigt werden und welchem ASCII-Code sie jeweils zugewiesen werden sollen. Das ist für Sonderzeichen und Symbole wichtig. Bei größeren Schriften binde ich nur diejenigen Zeichen ein, die ich tatsächlich im jeweiligen Projekt brauche. Bei einem Thermometer würden z.B. nur die Ziffern sowie '°' und 'C' in großer Schrift benötigt. Also binde ich auch nur diese Zeichen ein, was eine Menge Platz spart. Ein Haken dabei ist, dass für jede verwendetet Zeichengröße eine Sprungtabelle von ca. 450 Byte Größe benötigt wird, zusätzlich zu den Fontdaten. Mit VC habe ich ein Tool geschrieben (sehr, sehr Q&D!), das aus den gerasterten Fonts die .h Files generiert, welche dann von der Lib eingebunden werden. Es sind gleichzeitig Fonts mit 8, 16, 24, 32, 48 und 64 Größe möglich, nur abhängig von der Größe des verfügbaren Flashspeichers, jedoch nur eine Schriftart pro Fontgröße. Grafik ist derzeit nicht möglich, es gehen lediglich vertikale Linien. Das liegt an der Organisation des Grafikrams des OLED. Es ist aber denkbar sich mit Blockgrafik zu behelfen, wenn Rahmen oder ähnliches gebraucht werden. Habe ich aber noch nicht getestet. Die Funktion zur rechtsbündigen Ausgabe von Text ist noch buggy - bei proportionalen Fonts gibt es bei sehr breiten Zeichen Darstellungsfehler. Irgendwann werde ich die Lib nebst Tools abrunden, dokumentieren und hier vorstellen, das wird sich aber noch etwas hinziehen. Es gibt auch noch einige Ideen für Erweiterungen. Sorry, falsches Foto angehängt. Siehe nächsten Beitrag.
:
Bearbeitet durch User
> .. können auch andere Geräte bedienen, z.B. andere LCD oder Tasten Ja. Bus-System (komplizierter). Mit Zwischenspeicher am BusNode kann man auch weitaus höhere Frequenzen betreiben. >Daten und Befehle in Puffer und los, CPU macht was anderes, z.B. >nächste Daten für LCD. Der AVR-SPI-TX hat kein Puffer. >Drehgeber ist wie im Schlaf. Tja so ist das bei falschem Timing. Für Echtzeit kann man es nicht benutzen. Falsche INT-Handhabung. >So foltere ich z.Z. eine AT Mega324PA. Nein, der foltert dich.
MCUA schrieb: > Ja. Bus-System (komplizierter). Nicht unbedingt Bus. Tasten kann man einfach so an diese Linien (außer E1 und E2) anbinden. Damit Tasten kein Kurzschluß machen, Widerstand seriell. Um Tastenzustand abzulesen: E1=E2=0, DDR = 0, PORT = 1 (somit Rpu Ein), ein bißchen Warten (Rpu * (Cpin + C_Lin)), Pin einlesen. Da Rpu von 20k bis 50k sein kann, dürfen serielle Widerstände 4k7 nicht überschreiten. Viel kleiner sind die auch nicht sinnvoll, da unnötige Last für Pin bei Datenaustausch.
Erwin E. schrieb: > Na ja, ich tu's trotzdem, Erstmal danke! Ich schaue mir das die nächsten Tage an.
MCUA schrieb: > Tja so ist das bei falschem Timing. > Für Echtzeit kann man es nicht benutzen. > Falsche INT-Handhabung. Wie wirst du das anders machen? Eine Zeile 7 Symbole Font 16x10 Größe 5 (d.h. aus jedem Punkt wird 5x5 Pünkte gemacht) dauert 5120389 Z. oder bei F_CPU=16 MHz ca. 320 ms. Wird Drehgeber nicht jede ms abgefragt sondern jede 20 ms, bringt das wenig.
am nano nutze ich gerne die Nokia5110 mit dieser sparsamen LIB http://www.rinkydinkelectronics.com/library.php?id=44 RTC und Display auf dem Steckbrett am nano ohne weitere Kabel Helligkeit per PWM (per Kommando) und Kontrast per Kommando
:
Bearbeitet durch User
Erwin E. schrieb: > Disclaimer: Das ist mein Erstlingswerk in C. Ja, man sieht das. Nun, du kannst natürlich tun was dir beliebt, aber ich würde es an deiner Stelle komplett anders machen. Erstens würde ich generell trennen zwischen dem Lowlevel-Treiber, der für das physische Ansteuern des Displays verantwortlich ist und dem GDI, also dem Treiber, der die ganzen grafischen Funktionen beinhaltet und den diversen Fonts, die ebenfalls völlig separate Dinge sein sollten. Deine arial32.h ist viel zu umfänglich. Schreib ein GDI, das mit einem sinnvollen Font-Format zurechtkommt und separate Fontdateien, die dieses Fontformat bieten, so daß du allenfalls im GDI sowas wie extern char Helvetica16[]; schreiben mußt. Keine aufgeblasene Headerdatei. Hier mal zwei Links: https://www.mikrocontroller.net/attachment/436998/Fonts_machen.zip und http://www.mikrocontroller.net/attachment/301321/Fonts-machen-2.zip Damit kannst du so ziemlich alles an Fonts machen, was dir beliebt, egal ob nun variable oder feste Breite, tatsächliche Textzeichen oder Icons usw. Für dein Display wäre dann nur noch eine Funktion void CgPixel_at(X, Y, mode) von dir beizusteuern und fertig. Das mode ist hier bei Monochrom-Displays eben schwarz, weiß oder invert und bei Farbdisplays wäre es die Farbe bzw. ein Index in eine Farbpalette. Ich mache es immer so, daß ich (wie oben geschrieben) einen Grafikspeicher im RAM anlege, wo das GDI drauf herumzeichnet. Die Funktion CgPixel setzt eine boolean Variable, die damit anzeigt, daß das Display zu aktualisieren ist. Wenn die so alle 10 ms mal abgefragt wird, reicht das aus. Anbei als Beispiel ein altes GDI für nen Kinetis, damals mit reinem Soft-Treiber für das Display. Aber der Kinetis lief ja auch mit einer ordentlichen Taktfrequenz. W.S.
W.S. schrieb: > aber ich würde es an deiner Stelle komplett anders machen. Scheinbar machen es alle anders. Entweder so, wie du vorschlägst, mit einem Buffer in Displaygröße oder indem ausschließlich mit Text einer vorgegebenen Größe gearbeitet wird. Meistens können die kleinen Fonts noch geometrisch skaliert werden, was aber unschön aussieht. Beide Ansätze gefallen mir nicht. Wohlgemerkt, das gilt für AVR oder andere kleine Controller. Wenn ein schneller 32Bit Controller mit viel RAM benutzt wird, ist ist ein Buffer die sinnvolle Lösung. Was ich erreichen wollte: * Es sollen gleichzeitig Fonts verschiedener Größe benutzt werden können * Im Flash sollen nur diejenigen Zeichen abgelegt werden, die tatsächlich benötigt werden * Es sollen Zeichen mit beliebige Unicodes verwendet werden können * Es soll kein RAM für einen Framebuffer benutzt werden Allen diese Vorgaben habe ich in meiner Lib umgesetzt. Grafische Funktionen brauche ich nicht. Lediglich horizontale Linien wären mitunter nett, aber wirklich wichtig waren sie bisher nicht. Falls ich wirklich mal Grafikfunktionen brauche, nehme ich eine der fertigen Libraries. > Erstens würde ich generell trennen [..] Lowlevel-Treiber [..] physische Ansteuern des > Displays [GDI] D'accord, wenn verschiedene Displaycontroller sowie Grafikfunktionen mit der Lib benutzt werden sollen. Ob höher auflösende TFT-Displays überhaupt sinnvoll an einem AVR betrieben werden können? Das werde ich bei Gelegenheit mal testen. Was ich bisher gesehen habe, hat mich geschwindigkeitsmäßig nicht überzeugt. > Deine arial32.h ist viel zu umfänglich. Welchen Nachteil haben große Headerdateien? Du hast deine Fontdaten in .c Files abgelegt, wenn ich das richtig verstehe. Ich habe sie in Headerdateien. Macht das einen Unterschied? Außerdem sieht es für mich aus, als würden deine Fontdaten alle Zeichen fortlaufend von z.B 0x20 bis 0xnn enthalten. Landen die vollständig im Flash? Das wollte ich gerade vermeiden. Allerdings brauche ich pro Schriftgröße eine Tabelle, die recht groß ist. Das amortisiert sich aber bei großen Fonts sehr schnell. > Ich mache es immer so, daß ich (wie oben geschrieben) einen > Grafikspeicher im RAM anlege, wo das GDI drauf herumzeichnet. Das ist der gängige Ansatz, aber aus meiner Sicht ist der für kleine Controller unnötig - falls man keine Grafikfunktionen braucht. Spätestens bei einem 320x240 TFT kann dieser Weg nicht eingeschlagen werden, die kleinen Controller haben einfach nicht genug RAM für den nötigen Buffer. 16er oder 32er Schriften könnten aber auch bei einem TFT von der Geschwindigkeit her noch praktikabel sein, das möchte ich irgendwann mal testen. Mit welchem Programm erzeugst du eigentlich die Fonts? Ich nehme lcd-immage-converter. Falls es da was besseres gibt, bin ich interessiert, obwohl das jetzige Tool gut funktioniert.
Hier sind doch Unterschiede in Bildschirm-Structur wichtig. Wenn ein Bildschirm nach Byte-Linien innere Ordnung hat, dann wird immer mit Bytes geschrieben, gleichzeitig je 8 Punkte. Um einen Punkt zu ändern und andere Punkte unverändert lassen, sollte man entweder lesen-schreiben oder RAM-Puffer benutzen. Falls aber Bildschirm nach Punkten organisiert ist (wie z.B. ILI9341), kann man sowieso jeden Punkt unabhängig von anderen ändern. Dann ist weder Lesen noch RAM-Puffer notwendig. Man kann einfach einen Punkt beschreiben ohne Rücksicht auf alles Andere. Deshalb kann ein RAM-Puffer für Bildschirm auf KS0108B sinnvoll sein, dann braucht man aber für 128x64 Bildschirm lediglich 1 kB RAM. Für ILI9341 und Ähnlichen braucht man im Prinzip keinen RAM-Puffer. Erwin E. schrieb: > Welchen Nachteil haben große Headerdateien? Du hast deine Fontdaten in > .c Files abgelegt, wenn ich das richtig verstehe. Ich habe sie in > Headerdateien. Macht das einen Unterschied? Unterschied kommt, wenn man gleichzeitig mehrere Bildschirme nutzt. Dann kann man für alle eine Schriftdatei benutzen, aber nur wenn sie in *.c steht. Wenn in *.h, dann hat man für jeden Bildschirm eigene Kopie von der gleichen Schrift.
:
Bearbeitet durch User
Was Unicode angeht, ist dir bewusst dass es Zeichen gibt, die aus mehreren Unicodes zusammen gesetzt sind? Und wo willst du Fonts für beliebige Codes ablegen? Die werden doch mehrere MB groß!
Maxim B. schrieb: > Wenn ein Bildschirm nach Byte-Linien innere Ordnung hat, dann wird immer > mit Bytes geschrieben, gleichzeitig je 8 Punkte. Um einen Punkt zu > ändern und andere Punkte unverändert lassen, sollte man entweder > lesen-schreiben oder RAM-Puffer benutzen. Aus diesem Grund haben meine Fonts alle eine Höhe in Vielfachen von acht. Damit brauche ich weder einen Buffer noch bin ich auf read/modify/write angewiesen. In der Breite eines Zeichens habe ich keine Einschränkung, was auch proportionale Fonts erlaubt. > Falls aber Bildschirm nach Punkten organisiert ist (wie z.B. ILI9341), > kann man sowieso jeden Punkt unabhängig von anderen ändern. Dann ist > weder Lesen noch RAM-Puffer notwendig. Man kann einfach einen Punkt > beschreiben ohne Rücksicht auf alles Andere. Ob solche großen TFTs mit einem AVR sinnvoll genutzt werden können weiß ich nicht, das möchte ich bei Bedarf aber noch testen. Mein Gefühl sagt mir aber, dass das zu langsam wird. > Deshalb kann ein RAM-Puffer für Bildschirm auf KS0108B sinnvoll sein, > dann braucht man aber für 128x64 Bildschirm lediglich 1 kB RAM. Kann man machen, ja. Aber, q.e.d., es geht auch sehr gut ohne Buffer. > Unterschied kommt, wenn man gleichzeitig mehrere Bildschirme nutzt. Dann > kann man für alle eine Schriftdatei benutzen, aber nur wenn sie in *.c > steht. Wenn in *.h, dann hat man für jeden Bildschirm eigene Kopie von > der gleichen Schrift. Meinst du wirklich? Ich habe das noch nicht gemacht, sehe aber nicht, warum ich nicht auch mehrere Displays ansteuern könnte. Ob .c oder .h, auf welchem Display die Ausgabe landet, bestimmt nur die I²C-Adresse. Meine ich zumindest, da bin sogar ziemlich sicher.
Stefan ⛄ F. schrieb: > Was Unicode angeht, ist dir bewusst dass es Zeichen gibt, die aus > mehreren Unicodes zusammen gesetzt sind? Ja, das ist mir aufgefallen. ;) Wenn du dir das Beispielfoto vom 14.10.2020 16:51 anschaust, das Batteriesymbol das du dort siehst, hat den Unicode 0xeba3. Im Code wird das auf ASCII 0x9d gemappt. Insgesamt brauche ich 20 Symbole für die Batterie, die werden auf aufeinanderfolgende ASCII Codes gemappt. > Und wo willst du Fonts für beliebige Codes ablegen? Die werden doch > mehrere MB groß! Wer braucht denn alle Unicodezeichen gleichzeitig? Ich binde diejenigen Zeichen ein, die ich tatsächlich verwende. Das muss ich mir natürlich bei der Entwicklung überlegen, dann lege die benötigeten Unicodes und ihren ASCII-Code in einer Excel-Tabelle fest und lasse mir die Headerdatei mit den Fontdaten erzeugen. So mache ich es auch mit den 'normalen' Zeichen. Wenn ich nur Ziffern benötige, warum sollte ich Bcuhsateben einbinden?
Erwin E. schrieb: > Aus diesem Grund haben meine Fonts alle eine Höhe in Vielfachen von > acht. Damit brauche ich weder einen Buffer noch bin ich auf > read/modify/write angewiesen. Dann kannst du auf dem 128x64 entweder 8 Zeilen je 21 Symbol haben, oder 4 Zeilen je 10 Symbole, oder 2 Zeilen je 5 Symbole. Keine Zwischenvarianten, keine Graphik zusammen mit Symbolen (keine Linien, Rechtecke, Kreise - nichts). Braucht jemand so einen Bildschirm wirklich? Hier ein Testbeispiel, was man mit 128x64 machen kann, wenn man Lesen+Schreiben-Mode verwendet (darüber ist auch 20x4 LCD zu sehen). Erwin E. schrieb: > Ob solche großen TFTs mit einem AVR sinnvoll genutzt werden können weiß > ich nicht, das möchte ich bei Bedarf aber noch testen. Mein Gefühl sagt > mir aber, dass das zu langsam wird. Ja, etwas langsam. Aber kleinere Symbole noch ganz OK. Wirklich langsam sind gefüllte Kreise und Symbole mit so ca. ab 30 Punkte hoch, auch ganzen Bildschirm mit einer Farbe füllen. Deshalb ist manchmal sinnvoll nicht ganzen Bildschirm zu löschen sondern über zum Löschen bestimmten Text einen gefüllten Rechteck mit bg_color zu zeichnen. Dafür aber ist solche Bildschirm viel mehr informativ. Man kann gleichzeitig mehrere Fenster haben, z.B. für Modus und auch für Daten, die gezeigt sein müssen.
:
Bearbeitet durch User
Erwin E. schrieb: >> Falls aber Bildschirm nach Punkten organisiert ist (wie z.B. ILI9341), >> kann man sowieso jeden Punkt unabhängig von anderen ändern. Dann ist >> weder Lesen noch RAM-Puffer notwendig. Man kann einfach einen Punkt >> beschreiben ohne Rücksicht auf alles Andere. > Ob solche großen TFTs mit einem AVR sinnvoll genutzt werden können weiß > ich nicht, das möchte ich bei Bedarf aber noch testen. Mein Gefühl sagt > mir aber, dass das zu langsam wird. Einen Film kann man nicht ansehen. Aber zum Anzeigen von Text und Ziffern reicht es locker: Ich benutze an meiner Fräse ein 240x320 Farbdisplay mit 16-Bit Farbmode. Beitrag "Re: 10stelliges 7-Segment DRO für WABECO Messschieber" Angesteuert mit 16-Bit Bus von einem Atmega64. Die Zahlen werden alle 100ms aktualisiert und springen so schnell dass keinerlei Verzögerung zu erkennen ist.
Thomas F. schrieb: > Angesteuert mit 16-Bit Bus von einem Atmega64. > Die Zahlen werden alle 100ms aktualisiert und springen so schnell dass > keinerlei Verzögerung zu erkennen ist. Interessant! Hast du mal getestet, ob SPI sehr viel langsamer ist? Ich nehme an, die aktualisierst nur die jeweilige Textzeile und beschreibst nicht das vollständige Display? Hast du eine fertige Library für die Ansteuerung genommen oder selbst eine gebaut?
Erwin E. schrieb: > Welchen Nachteil haben große Headerdateien? Du hast deine Fontdaten in > .c Files abgelegt, wenn ich das richtig verstehe. Ich habe sie in > Headerdateien. Macht das einen Unterschied? Ja, einen erheblichen Unterschied. Bei dir erstickt man ja geradezu in einer Flut von namen wie "static const tImage arial32_0x20 PROGMEM = ...", die alle in deiner Headerdatei stehen? Und du stellst dir vor, daß man dein Konstrukt über deine Tabelle "static const tImage* const charset32[] PROGMEM =..", die aus Pointern besteht, verwendet. Mit dem Auseinandernehmen deines Fonts sparst du keinerlei Platz im Flash ein und mir scheint, daß du auch massenweise Platz vergeigst, indem du für jedes Zeichen (auch für große) zeilenweise auf ganze Bytes auffüllst. Obendrein besteht ein Großteil deines Codes aus "PROGMEM", was für eine völlige Un-Portierbarkeit sorgt. Meine Fonts könnte man hingegen selbst rein binär auf so ziemlich alle Plattformen portieren. Siehe unten. > Außerdem sieht es für mich aus, als würden deine Fontdaten alle Zeichen > fortlaufend von z.B 0x20 bis 0xnn enthalten. Landen die vollständig im > Flash? Das wollte ich gerade vermeiden. Allerdings brauche ich pro > Schriftgröße eine Tabelle, die recht groß ist. Das amortisiert sich aber > bei großen Fonts sehr schnell. Das Prinzip sollte ich dir hier mal erläutern: 1. Bei mir besteht ein Font aus einer variablen Struktur, die als Byte-Block gespeichert werden kann und die zum Zugriff NUR einen einzigen Zeiger auf ihren Anfang benötigt und auch nur einen einzigen Bezeichner in der gesamten Firmware einträgt. 2. Diese Struktur ist so ausgelegt, daß sie sowohl auf bigendian als auch auf littleendian Maschinen zu benutzen ist. 3. Jeder Font besteht aus 3 Teilen: - einem Fontheader - einer variablen Anzahl von Zeichen-Einträgen - den eigentlichen Glyphen 4. Der Fontheader beschreibt die Gesamthöhe, die Höhe der Großbuchstaben, die Höhen über und unter der gedachten Schreiblinie und den Bereich der enthaltenen Zeichen (also ChMin und ChMax). In dieser Struktur sind lediglich 8 Bit Werte für die Zeichen möglich, also keine Zeichencodierungen von 16 Bit und aufwärts (Unicode). Wer also dringend chinesische Zeichen oder Farsi benötigt, braucht ein anderes Fontsystem. Innerhalb der üblichen ANSI-Zeichen von 0 bis FF ist jedoch alles möglich. Wenn es Lücken zwischen ChMin und ChMax gibt, wird für diese auf ChMin umgelenkt. 5. Die Zeichen-Einträge beschreiben das Displacement des zuständigen Glyphen vom Fontanfang sowie die Größe des Glyphen in X und Y Richtung. 6. Die Glyphen sind Bitstreams. Das Fenster für das Zeichen ist ja bereits per dX,dY in dem Zeichen-Eintrag festgelegt und dessen Inhalt wird von links oben bis rechts unten gefüllt, zeilenweise, aber nicht byteweise. Eben ein Bitstream, kein padding am Zeilenende, deswegen relativ platzsparend. Padding auf ein ganzes Byte nur am Ende nach dem letzten Pixel des Zeichens. 7. Mit diesem Font Format sind sowohl Proportionalfonts als auch solche mit fester Zeichenbreite möglich. Letztere sind ja nur eine Untermenge der ersteren. Ein Font braucht nicht alle zeichen zu enthalten, man kann ihn auch so gestalten, daß er nur die Zeichen enthält, die man tatsächlich benutzt. Das ist wichtig für das Darstellen von großen Ziffern, wo man eben nur '0'..'9','-','+','.' benötigt. 8. Die zugehörige GDI-Routine zum Zeichnen eines Char's an beliebiger Stelle hab ich ja schon gepostet. Sie funktioniert wie ein Schreibstift und nicht wie ein Stempel. Das heißt, nichtgesetzte Pixel werden auch nicht gezeichnet. Ist wie an der Schultafel: Wo man schreiben will, muß man vorher auswischen. So, das sollte als Erklärung reichen. Erwin E. schrieb: > * Es sollen Zeichen mit beliebige Unicodes verwendet werden können Wie bitte? Ein Font für beliebige Unicodes würde schlichtweg aus allen Nähten platzen! Erwin E. schrieb: > Mit welchem Programm erzeugst du eigentlich die Fonts? Ich nehme > lcd-immage-converter. Falls es da was besseres gibt, bin ich > interessiert, obwohl das jetzige Tool gut funktioniert. Lade dir die zwei Archive herunter, die ich weiter oben angegeben habe. Dort ist FM.EXE drin, was mein Eigenbau-Fontcompiler ist. Der setzt von einer textuellen Darstellung (die man zum Editieren braucht) in eine C-Quelle um. Daneben steckt dort auch Fontex.exe drin, ebenfalls ein Eigenbau von mir, was aber nur zum ungefähren Importieren von Windows-Fonts gedacht war. Ist hakelig, hatte mir aber ausgereicht für das, was ich damit machen wollte. W.S.
Erwin E. schrieb: > Meinst du wirklich? Ich habe das noch nicht gemacht, sehe aber nicht, > warum ich nicht auch mehrere Displays ansteuern könnte. Ob .c oder .h, > auf welchem Display die Ausgabe landet, bestimmt nur die I²C-Adresse. Du denkst wohl, wenn du mehrere Bildschirme von gleichem Typ benutzt? Aber das kann man selten brauchen. Öfter braucht man gleichzeitig Bildschirme verschiedener Art. Trotzdem kann man für mehrere Bildschirme gleiche Zeichentabellen benutzen, obwohl für jeden Bildschirm eigene Befehle notwendig sind und entsprechend eigene *.c + *.h - Dateien. Unterschied ist darin, daß du in einem Fall immer wieder die Daten im Speicher hast. In anderem Fall hast du immer wieder einen Zeiger auf eine und dieselbe Datei.
:
Bearbeitet durch User
Erwin E. schrieb: > Thomas F. schrieb: >> Angesteuert mit 16-Bit Bus von einem Atmega64. >> Die Zahlen werden alle 100ms aktualisiert und springen so schnell dass >> keinerlei Verzögerung zu erkennen ist. > > Interessant! Hast du mal getestet, ob SPI sehr viel langsamer ist? Ja, ist deutlich langsamer: Für ein anderes Projekt habe ich die 2,8' TFTs mit SPI eingesetzt. Hier geht der Bildaufbau deutlich langsamer. Ein flüssiger Bildaufbau war aber in dieser Anwendung nicht nötig. > Ich nehme an, du aktualisierst nur die jeweilige Textzeile und > beschreibst nicht das vollständige Display? Ja. Für jedes Zeichen wird ein Schreibfenster passender Größe im RAM des TFT definiert und dieses dann geschrieben. > Hast du eine fertige Library für die Ansteuerung genommen oder selbst eine gebaut? Ist alles in Assembler selbst geschrieben.
noch größerer Unsinn scheint mir zu sein Trenner 0x00 in jedes Zeichen zu packen! LCD5110_Basic: DefaultFonts.c 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A der Font ist verschwenderischer, aber dafür die LIB sparsamer! ideal für nano328p platzsparender: Adafruit glcdfont.c 0x7C, 0x12, 0x11, 0x12, 0x7C, // A der Font ist sparsamer, aber dafür die LIB verschwenderischer! beim ESP32 egal, RAM und flash genug vorhanden
Zu genau der gleichen Erkenntnis bin ich auch gekommen, als ich meine OLED Klasse implementierte. Das gesparte Byte (pro Zeichen) zahlt man an anderer Stelle mit Performance und Code-Bedarf wieder drauf. "Unsinn" würde ich genau deswegen aber eben nicht sagen. Außerdem möchte man vielleicht später mal Zeichen hinzufügen, die keinen Trenner haben, zum Beispiel um im Turbo-Vision Stil Rahmen aus Text-Zeichen zu erstellen.
W.S. schrieb: > Ja, einen erheblichen Unterschied. Bei dir erstickt man ja geradezu in > einer Flut von namen wie "static const tImage arial32_0x20 PROGMEM = > ...", die alle in deiner Headerdatei stehen? Nicht nur in einer... Jede Schriftgröße hat eine eigene Header Datei. Diese Dateien werden aber automatisch generiert und müssen deshalb nicht (von mir) angesehen werden. Dem Compiler ist es wurscht, 1000 mal "static const tImage arial32_0x20 PROGMEM =" lesen zu müssen. > Und du stellst dir vor, daß man dein Konstrukt über deine Tabelle > "static const tImage* const charset32[] PROGMEM =..", die aus Pointern > besteht, verwendet. Eher nicht. Dafür gibts oled_write_char(..) und weitere Ausgabefunktionen. > Mit dem Auseinandernehmen deines Fonts sparst du keinerlei Platz im > Flash ein und mir scheint, daß du auch massenweise Platz vergeigst, > indem du für jedes Zeichen (auch für große) zeilenweise auf ganze Bytes > auffüllst. Nein, das täuscht. Die Zeichendaten werden nicht aufgefüllt. Allerdings sind sie um 90° gedreht, weil ich sie so ohne Umrechnung direkt ans Display schicken kann. Da ich keinen Buffer verwende ist das schneller. Prinzipiell haben alle Zeichensätze eine Höhe von einem Vielfachen von acht. Die Breite ist beliebig. Das ist nur der Architektur des SSD1306 geschuldet. Die Größe der Fontdaten sind bei deiner und bei meiner Methode vergleichbar. Kein Wunder, denn auch ich speichere lediglich gerasterte Fontdaten. So wie du auch. Zum Vergleich den Platzbedarf des Zeichens '0': Helvetica Größe 14 = 13 Byte bei dir gegenüber Noto Größe 16 = 16 Byte bei mir. Lucida Größe 25: 47 Byte bei dir gegenüber Noto Größe 24 mit 39 Byte bei mir. Die Organisation unserer Fonts scheint mir durchaus vergleichbar. Du hast ebenfalls eine Sprungtabelle in der Fontdatei über welche die Zeichen adressiert werden. Diese Tabelle belegt 2 Byte pro ASCII-Zeichen und ist der größte Platzfresser. Bei kleinen Schriftgrößen mit wenigen Glyphen benötigt die Tabelle mit knapp 500Byte mehr Platz wie die Fontdaten. Bei großen Fonts fällt die Tabelle weniger ins Gewicht. Eine 64 Pixel hohe Glyphe benötigt z.B. 8 * 30 Bytes, da spielt die Tabelle mit 500 Bytes keine Rolle mehr. Du lässt einzelne Zeichen aus um Platz zu sparen, ich mache das auch. Ein Unterschied ist, dass ich beliebige (ja, wirklich) Unicode-Zeichen in den Font einbauen kann, aber natürlich nicht mehr als 256 insgesamt. Die Symbole aus dem Unicodebereich > 0xff werden innerhalb der Sprungtabelle auf beliebige Positionen gemappt. Für chinesisch taugt die Methode also auch nicht, weil es insgesamt nur max 256 unterschiedliche Glyphen geben kann. Welche das sind, kann ich ohne Einschränkung beim Erzeugen der Fontdatei über eine simple .csv Textdatei festlegen. Alle Zeichensätze haben als Höhe ein Vielfaches von 8 und beginnen immer auf einer Page von Bit Höhe. Einen 24er Font kann ich also auf Zeile 2..7 ausgeben, einen 8er Font auch auf Zeile 0. Das erinnert an Charakter Displays. Allerdings kann ich innerhalb einer Zeile die Schriftgröße beliebig wechseln. Die Textausgabe ist sehr schnell, weil die Zeichen und Strings direkt vom Flash ins Display geschrieben werden. Das geht deutlich schneller, als einen vollständigen 1k großen Buffer mit dem vollständigen Displayinhalt auf einmal zu schreiben. Wird nämlich ein Buffer benutzt, ist das für den Controller doppelte Arbeit: Zuerst müssen die Zeichen in den Buffer geschrieben werden. Anschließend wird der Buffer zyklisch zum Display übertragen. Letztes kann ich mir sparen. > Obendrein besteht ein Großteil deines Codes aus "PROGMEM", was für eine > völlige Un-Portierbarkeit sorgt. Sorry, aber das ist bei einer AVR-Library wohl so. Ohne PROGMEM kann ich den Flashspeicher nicht ansprechen. Natürlich ist die Lib als solche deshalb nicht (direkt) portierbar. Das Prinzip der Fonterzeugung kann jedoch durchaus auf beliebige Architekturen übertragen werden. Auch andere Displaycontroller kann ich mit mäßigem Aufwand ansteuern. Das bereits erwähnte ILI9143 interessiert mich, das werde ich bei Gelegenheit mal angehen. Dazu muss ich den Fontcompiler an die Architektur des ILI anpassen und die Ausgaberoutine in der Lib. Der Rest kann bleiben. > 1. Bei mir besteht ein Font aus einer variablen Struktur, die als > Byte-Block gespeichert werden kann und die zum Zugriff NUR einen > einzigen Zeiger auf ihren Anfang benötigt und auch nur einen einzigen > Bezeichner in der gesamten Firmware einträgt. Bei mir gibt es in der Sprungtabelle eines Fonts (nur einmal vorhanden) für jeden Zeichencode einen Zeiger, über den die Zeichendaten adressiert werden. Jeder Zeiger ist 2 Byte groß. Die Zeichen des Fonts und die Springtabelle liegen direkt hintereinander im Flash. Das sollte das selbe Ergebnis bringen wie deine Methode. > 2. Diese Struktur ist so ausgelegt, daß sie sowohl auf bigendian als > auch auf littleendian Maschinen zu benutzen ist. Bei mir ist die Struktur auf die Organisation des Grafik-RAM meines LCD-Controllers abgestimmt. Damit die Daten ohne Umrechnug direkt aufs Display geschrieben werden können. > 3. Jeder Font besteht aus 3 Teilen: > - einem Fontheader > - einer variablen Anzahl von Zeichen-Einträgen > - den eigentlichen Glyphen Mache ich auch so. > 4. Der Fontheader beschreibt die Gesamthöhe, die Höhe [..] > In dieser > Struktur sind lediglich 8 Bit Werte für die Zeichen möglich, [..] Genau wie bei mir. > keine Zeichencodierungen von 16 Bit und aufwärts (Unicode). Das ist ein Unterschied, beliebige Unicodezeichen mappe ich auf 8Bit Werte. Natürlic nicht mehr als insgesamt 255. Für Chinesisch wird das nicht reichen. > Wenn es Lücken zwischen ChMin und ChMax gibt, wird für diese > auf ChMin umgelenkt. Mache ich genauso. > 5. Die Zeichen-Einträge beschreiben das Displacement des zuständigen > Glyphen vom Fontanfang sowie die Größe des Glyphen in X und Y Richtung. Bei mir steht ein 16Bit Zeiger auf die Adresse des Glyphen in der Tabelle. Das könnte minimal schneller sein, beim Zugriff auf ein Zeichen. Bin mir da aber nicht ganz sicher. > 6. Die Glyphen sind Bitstreams. > bereits per dX,dY in dem Zeichen-Eintrag festgelegt und dessen Inhalt > wird von links oben bis rechts unten gefüllt, zeilenweise, aber nicht > byteweise. Das mache ich genauso, nur eben ohne Puffer. Der SSD1306 braucht die Daten eben spaltenweise, weshalb ich sie entsprechend im Font abgelegt habe. > 7. Mit diesem Font Format sind sowohl Proportionalfonts als auch solche > mit fester Zeichenbreite möglich. Exakt das gleiche Prinzip wie bei mir. > 8. Die zugehörige GDI-Routine zum Zeichnen eines Char's an beliebiger > Stelle hab ich ja schon gepostet. Sie funktioniert wie ein Schreibstift > und nicht wie ein Stempel. Das heißt, nichtgesetzte Pixel werden auch > nicht gezeichnet. Ist wie an der Schultafel: Wo man schreiben will, muß > man vorher auswischen. Das geht beim SSD1306 nicht, wenn kein Puffer oder r/m/w-Verfahren verwendet wird. Diese Einschränkung war der Auslöser, dass ich diese Library so gemacht habe. Das ist auch der Grund, warum ich keine geometrischen Figuren ausgeben kann. Senkrechte Linien beliebiger Breite sind möglich. Kreise, Rechtecke dagegen nicht. Weil kein Puffer vorhanden ist und ich über I²C das Display-RAM nur schreiben, aber nicht lesen kann. > Wie bitte? Ein Font für beliebige Unicodes würde schlichtweg aus allen > Nähten platzen! Wie geschrieben, beliebige Codes sind möglich - aber nicht alle gleichzeitig. > Erwin E. schrieb: >> Mit welchem Programm erzeugst du eigentlich die Fonts? Ich nehme >> lcd-immage-converter. Falls es da was besseres gibt, bin ich >> interessiert, obwohl das jetzige Tool gut funktioniert. > > Lade dir die zwei Archive herunter, die ich weiter oben angegeben habe. Habe ich bereits gemacht. Danke fürs Zeigen! Was bei dir die txt-Dateien sind, sind bei mir .c Files, welche der lcd-image-converter (oben verlinkt) erzeugt und von meinem primitiven Fontcompiler in die eigentliche .h umsetzt wird. Danke für deinen Beitrag. Eine Library zu benutzen und zu Verstehen sind wirklich zwei paar Stiefel. Diese Antwort hat mich gezwungen, meine Library nochmals zu durchdenken und selbst wieder zu begreifen, was ich vor einem halben Jahr wie und warum gemacht habe.
Joachim B. schrieb: > noch größerer Unsinn scheint mir zu sein Trenner 0x00 in jedes Zeichen > zu packen! Das wäre wirklich Unsinn. Allerdings gibts da keinen 'Trenner' 0x00. Wozu auch, für jedes Zeichen gibt es einen 16Bit Zeiger in den Flashspeicher.
Erwin E. schrieb: > Wozu auch, für jedes Zeichen gibt es einen 16Bit Zeiger in den > Flashspeicher. du scheinst es nicht verstanden zu haben! Das 0x00 Byte belegt flash und für jedes Zeichen etliche Bytes die immer redundant sind!
Joachim B. schrieb: > du scheinst es nicht verstanden zu haben! > Das 0x00 Byte belegt flash und für jedes Zeichen etliche Bytes die immer > redundant sind! Was du als 'Trenner' zu erkennen glaubst, sind vermutlich die weißen Ränder eines Zeichens. Die sind aber nötig, damit die Zeichen nicht direkt aneinanderstoßen. Allerdings ändert das nichts daran, dass bei einem proportionalen Font ein 'I' weniger Platz braucht als ein 'W'. Jedoch ist links und rechts vom 'W' ein weißer Streifen als Abstand genau (aber nicht unbedingt gleich breit) wie beim 'I'. Natürlich könnte ich für jedes Zeichen die Breite des linken und rechten Rands als Zahlenwert in die Fontdatei schreiben und erst bei der Ausgabe entsprechend viele '0x00' schreiben. Das bedingt aber zusätzlichen Rechenaufwand, den ich sparen möchte. Dann lieber gleich RLE-Kompression, die spart wirklich Speicher, aber eben auch auf Kosten der Rechenzeit beim Beschreiben des Displays.
Joachim B. schrieb: > noch größerer Unsinn scheint mir zu sein Trenner 0x00 in jedes Zeichen > zu packen! Sieh das mal ein bissel relativiert. Ich betreibe Grafik-Displays in allen möglichen Versionen - aber NICHT an irgend einem kleinen 8 Bit µC, sondern nur mit 32 Bit µC. Da ist es mit dem Platz im Flash weitaus entspannter. Das wiederum macht es leicht, durch das Gestalten der Glyphen die Schrift so hinzukriegen, daß man bei Bedarf auch Kerning und Unterschneidungen etc. hinkriegen kann, also trotz recht simpler Fontgestaltung doch noch einiges an typografischen Dingen realisieren kann - wenn man das will und sich die ja nicht unerhebliche Mühe macht. Das ist der Grund, weshalb auch bei meinen Fonts Zeichenzwischenräume eingearbeitet sind - anstatt sie zentral in der Grafikroutine unterzubringen. Wenn allerdings das ganze auf einem beengten 8 Bit System laufen soll, dann wäre es ganz sicher viel sinnvoller, Leer-Räume sowohl vertikal als auch horizontal aus dem Font zu entfernen und diese pauschal von der Ausgaberoutine erledigen zu lassen. Ebenso wäre es dort auch ausreichend, auf die Offset-Tafel bzw. Adreßtafel zu verzichten und jedem Glyphen an seinem Anfang ein Längenbyte voranzustellen, so daß man mit nur jeweils 1 Byte zum Erreichen des Glyphen auskommen kann. Man muß sich dabei lediglich durch das Glyphenfeld hindurchhangeln. Nun hat Erwin sich jede nur erdenkliche Mühe gegeben, darzustellen, daß er es besser kann - ok, ich will ihn da nicht bremsen, allerdings ist sein Konzept umständlicher in jeder Hinsicht, stellt aus Nutzersicht ein riesiges Gewirr von Tabellen dar, ist nicht portabel und kommt auch nicht mit beliebigen Textkoordinaten klar. Dafür ist es ganz speziell an die AVR und an eine bestimmte Sorte von Display gebunden und eben daran angepaßt. Ob das nun jedem so gefällt und woanders nachnutzbar ist, ist eine andere Frage. Ich habe da eine völlig andere Herangegensweise: Ich will bei allen Dingen eine möglichst sinnvolle Abstraktion, so daß ich damit nicht auf einen Chip oder einen Hersteller festgenagelt bin. Also trenne ich auch bei grafischen Displays zwischen der niederen Seite der physischen Display-Ansteuerung und der eher logischen Seite des Zeichnens von grafischen Elementen auf einem Canvas und trenne davon obendrein auch Grafik-Elementen wie Fonts, Icons und Bildern ab. Eben deshalb ist bei mir ein Font eben ein einziges "Ding", also ein einziger Datenblock und nicht ein Sammelsurium von Tafel verschiedenster Art wie bei Erwin. Ein Gleiches gilt für Grafiken. Auch hier sind die diversen Grafiken jeweils ein einziges Ding. Wie das aussieht, siehe angehängte Datei. Ich hatte sowas m.W. schon mal gepostet, hier also nur der Ansicht halber. Im ZIP sind sowohl die eigentliche Grafik als auch die Umsetzung in C in mehreren verschieden stark farbreduzierten Versionen. Ist immer dasselbe Bild, aber deutlich unterschiedlich im Byteumfang. Um auf die Fonts zurückzukommen: Die Fontausgabe auf so kleinen monochromen 128x64 Displays ist bei mir nur ein Sonderfall, normal ist eher die Ausgabe auf bunten TFT, so ab QVGA bis WVGA. Die zugehörigen Zeichenausgaberoutinen hab ich mir hier gespart, sie sind fast gleich zum bereits Geposteten, lediglich "mode" ist dort durch einen Zeiger auf den zugehörigen Device-Kontext ersetzt. Damit haben die Routinen auch die Charakteristika des Canvas, der wiederum zu einem TFT oder zu einem Drucker gehören kann. Das alles würde hier zu weit führen, wir reden hier ja über einfache 128x64 Displays. W.S.
MCUA schrieb: > SPI-Probleme bei (bisherigen, nicht die allerneusten) AVRs: > > 1.) SPI -TX hat keinen einzigen Byte-Buffer > ...(es kann also nichtmal mit einem Jitter von +- der Länge eines > ....ausgeschriebenen (SPI)Bytes in das SPI-Modul geschrieben werden) > ...(evtl. kann man (wenn im Master-Mode) taktgenau 'warten' (diese Takte > ....gehen aber verloren) und so weitere Bytes an TX rausschicken) > ...(selbst ein winziger STM8 ist hier besser, und es gibt faktisch keine > ....neuere CPU, die hier nicht wenigstens einen Buffer hat) MCUA schrieb: >>Daten und Befehle in Puffer und los, CPU macht was anderes, z.B. >>nächste Daten für LCD. > Der AVR-SPI-TX hat kein Puffer. Dazu nimmt man auch nicht das SPI Peripheral, sondern den USART im Master-SPI Mode...
Erwin E. schrieb: > Ohne PROGMEM kann ich den Flashspeicher nicht ansprechen. Das ist auch kein Problem, da sieht nur W.S. welche. Alle anderen schreiben sowas wie
1 | #ifndef AVR
|
2 | #define PROGMEM
|
3 | #endif
|
Und schon ist es weg gebeamt. Bzw beim ESP wird es auch genutzt um Daten ins Flash zu legen wimre.
Hi >Dazu nimmt man auch nicht das SPI Peripheral, sondern den USART im >Master-SPI Mode... Naja, dann fallen erst mal einige Arduinos raus. MfG Spess
>Dazu nimmt man auch nicht das SPI Peripheral, sondern den USART im >Master-SPI Mode... ich weis, dass der das hat (auch keine Hardw-FIFOs), trotzdem sind die weiter genannten Mängel an der CPU vorhanden.
Man kann auch ohne PROGMEM.
1 | const __flash char myarray[] = |
2 | {0,1,2,3,4,5}; |
Natürlich sollte man dafür GSS nicht aus dem Jahre 2010 nehmen. Bei mir arbeitet das mit 5.4.0 Das gibt deutlich mehr Freiheit: man braucht keine besonderen Funktionen mehr, es reicht, Argumente in einer Funktion als const __flash zu erklären. Hier sind drei Funktionen zum Vergleich, die String auf LCD bringen: für String in RAM, in FLASH mit PROGMEM und in FLASH mit const __flash
1 | void lcd_string( char *data ){ |
2 | while( *data != '\0' ) |
3 | lcd_data( *data++ ); |
4 | }
|
5 | |
6 | void lcd_string_P( PGM_P data ){ |
7 | char tmp; |
8 | tmp=pgm_read_byte(data); |
9 | while( tmp != '\0' ) { |
10 | lcd_data( tmp ); |
11 | data++; |
12 | tmp = pgm_read_byte(data); |
13 | }
|
14 | }
|
15 | |
16 | void lcd_string_F( const __flash char *data ){ |
17 | while( *data != '\0' ) |
18 | lcd_data( *data++ ); |
19 | }
|
Hier sieht man, wie bequemer es mit const __flash geht.
:
Bearbeitet durch User
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.