Hallo Forum, ich würde gerne einem Projekt, das den ATtiny84 verwenden, ein Display hinzufügen. Dafür habe ich das DOGM128 (128x64) ausgewählt, da ich das schon hier rum liegen habe. Der ATtiny ist nicht fest ausgewählt, es muss nur ein Controller im SOIC-Gehäuse mit weniger als 20 Pins sein (SOIC ist nicht auf meinem Mist gewachsen). Beim AVR sollte es aber schon bleiben, es ist schon einiges implementiert. Das Display anzuschließen und anzusteuern ist an sich kein Problem. Zum eigentlichen Problem: Meine bisherige Ansteuerung sah so aus, dass erst alle Display-Operationen auf einen "Shadow-RAM" ausgeführt wurden, der dann bei Bedarf zum Display gesendet wurde. Dieser Shadow-RAM muss natürlich groß genug sein, um das gesamt Display darstellen zu können. Also hier 128 * 64 / 8 = 1kB. Das bedeutet man braucht auf diese Weise mdst. ~1.25kB SRAM (Display-RAM, ein paar Variablen, serielle Puffer, Stack). Aber die Tinys, vor allem die im "richtigen" Gehäuse, haben alle 1kB oder weniger. Und genau jetzt fängt mein Problem an: Wie zeichne ich das Display (das afaik in 8 Pages organisiert ist) ohne riesen Aufwand neu? Am liebsten würde ich dabei bleiben, dass alle Funktionen nur auf eine SetPixel(x,y,on)-Funktion zugreifen, die dann das Display Handling macht. Aber ich könnte mir vorstellen, dass das "ewig" raucht, pro Pixel ein Pixel-Byte zu schreiben. Und prinzipiell müssen ja auch immer 8 Pixel geschickt werden, weil der AVR ja nicht weis, ob die anderen 7 an oder aus sind, und das Display auch keine Möglichkeit zu lesen anbietet Auch weil der AVR mit den internen 8MHz laufen soll und Soft-SPI machen muss(USI ist schon mit I²C belegt). Deswegen: wie sollte die Ansteuerung am besten aussehen? Mit freundlichen Grüßen, N.G.
Statt Rücklesen vom Display: Kleinen STM32 kaufen, fast nach Belieben Speicher ver(sch)wenden, keinen Cent mehr dafür bezahlen und genug SPI (sogar mit DMA) haben... Keine Option?
Robin S. schrieb: > Statt Rücklesen vom Display: Kleinen STM32 kaufen, fast nach > Belieben > Speicher ver(sch)wenden, keinen Cent mehr dafür bezahlen und genug SPI > (sogar mit DMA) haben... Das diese Argument kommt war klar. Wenn dann eher was von NXP die gefallen mir persönlich besser. Kennen tue ich alle 3 (LPC, STM32, AVR), von der Seite gibts keine Probleme, aber: > Keine Option? N. G. schrieb: > Beim AVR sollte es aber schon bleiben, es ist schon > einiges implementiert. Dazu ist das Projekt nicht nur für mich, sondern zusammen mit anderen, die nur den AVR kennen (und z.T. noch kennen lernen) und deswegen ist es schlecht einfach mal die komplette Architektur zu wechseln (inklusive Toolchain, bisher geschriebenen Low-Level Code (also hier im Prinzip alles), Utility-Programmen, ...) Des weiteren bin ich mir gar nicht sicher, ob es STM32 im SOIC-14 o.Ä. Gehäuse gibt Also: keine Option Aber danke schon mal für deinen Beitrag.
Das DOG M128 kannst du doch auch über I2C Bus betreiben. Dann gibt es verschiedene Möglichkeiten. z.B. den Atmega 1284, ist wohl zu gross, oder den Ati 2313 oder 4313 oder 261 Klaus
Klaus schrieb: > Das DOG M128 kannst du doch auch über I2C Bus betreiben. Das wäre mir neu. Habe auch im Datenblatt nichts dazu gefunden. Auch der verwendete Controller (ST7565R) spricht im Datenblatt nur von SPI. > Dann gibt es > verschiedene Möglichkeiten. z.B. den Atmega 1284, ist wohl zu gross, > oder den Ati 2313 oder 4313 oder 261 Der Atmega1284 ist dezent zu groß, hat etwa das 8fache RAM was ich brauche und auch mehr als 20 Pins ;) Die anderen sind interessant, danke. Aber die eigentliche Frage hat bisher noch keiner angesprochen.
N. G. schrieb: > Deswegen: wie sollte die Ansteuerung am besten aussehen? 2mm mehr für einen Atmega in SOIC28 (statt SOIC20) und alle Probleme sind gelöst. Hast du genug Speicher für einen kompletten Buffer und Hardware für I2C und SPI. Ich kann mir kaum vorstellen, dass sich diese 2mm nicht irgendwie beschaffen lassen sollten... Wenn du aber auf deiner Meinung beharrst, dass das nicht geht, bleiben nur mehr oder weniger aufwendige "Kompressions-Tricks", um das Problem in Software zu lösen. Es läuft immer darauf hinaus, keinen vollständigen Buffer im Speicher zu halten und trotzdem alles über den Displayinhalt zu wissen. Dieses Wissen wird dann genutzt, um Teile des Buffers im Speicher zu rekonstruieren, die neue Graphikoperation darauf anzuwenden und das Ergebnis einerseits zum Display zu schreiben und andererseits wieder in die komprimierte Form zu überführen. Die einfachste Möglichkeit für sowas ist dynamische Blockgrafik. Ziemlich leicht zu implementieren, sehr schnell, aber auch recht stark beschränkt bezüglich der grafischen Möglichkeiten. Und die Hohe Schule ist das, was z.B. X oder auch RemoteDesktop tut, um Bandbreite zu sparen. Übertragen (bzw. in deinem Fall: gespeichert) wird nicht das Image, sondern die zu seiner Erzeugung nötigen grafischen Primitives. Sozusagen Kompression an der Wurzel. Die Herausforderung hier ist vorallem das Clipping. Also: wie finde ich überhaupt erstmal heraus, welche Displaybereiche die neu auszuführende Operation betreffen wird und wie rekonstruiere ich stückweise möglichst effizient deren Inhalt aus meinen bisherigen Aufzeichnungen.
Hi >Das wäre mir neu. Habe auch im Datenblatt nichts dazu gefunden. Auch der >verwendete Controller (ST7565R) spricht im Datenblatt nur von SPI. Stimmt, aber mit dem kannst du nichts vom Display lesen. Damit kann man nur Schreiben. Ich würde ohne Controller mit ordentlich Flasch gar nicht mit so etwas anfangen. Pixelweises schreiben schreiben, evtl. noch mit vorherigem pixelweisen lesen , kostet eine Menge unnötige Zeit. MfG Spess
N. G. schrieb: > Aber ich könnte mir vorstellen, dass das "ewig" raucht, pro Pixel ein > Pixel-Byte zu schreiben. In solchen Fällen ist es zielführend, wenn man einfach einen Adapter auf die Platine lötet und darauf dann einen ATMega1284. Der hat RAM und Flash zur Genüge. Nun kann man ohne Restriktionen verschiedene Varianten ausprobieren und dem Entscheider zeigen. Wenn dann die Ernüchterung eingesetzt hat, dass das alles elend lahm ist, kann man über eine bessere Lösung nachdenken. Am Anfang einer Entwicklung schon sparen zu wollen, ist kontraproduktiv. Wenn alles fertig ist, kann man immer noch abstrippen.
>Ich würde ohne Controller mit ordentlich Flasch gar nicht mit so etwas >anfangen. Ich auch. Die 8kB Flash gehen ja schon für den ersten schönen Font drauf;)
c-hater schrieb: > N. G. schrieb: > >> Deswegen: wie sollte die Ansteuerung am besten aussehen? > > 2mm mehr für einen Atmega in SOIC28 (statt SOIC20) und alle Probleme > sind gelöst. Hast du genug Speicher für einen kompletten Buffer und > Hardware für I2C und SPI. > > Ich kann mir kaum vorstellen, dass sich diese 2mm nicht irgendwie > beschaffen lassen sollten... Irgendwie ginge das bestimmt. Aber der Attiny828 hat z.B. auch Hardware I2C und SPI, nur halt etwas weniger RAM. > Es läuft immer darauf hinaus, keinen vollständigen Buffer im Speicher zu > halten und trotzdem alles über den Displayinhalt zu wissen. Dieses > Wissen wird dann genutzt, um Teile des Buffers im Speicher zu > rekonstruieren, die neue Graphikoperation darauf anzuwenden und das > Ergebnis einerseits zum Display zu schreiben und andererseits wieder in > die komprimierte Form zu überführen. > > Die einfachste Möglichkeit für sowas ist dynamische Blockgrafik. > Ziemlich leicht zu implementieren, sehr schnell, aber auch recht stark > beschränkt bezüglich der grafischen Möglichkeiten. > > Und die Hohe Schule ist das, was z.B. X oder auch RemoteDesktop tut, um > Bandbreite zu sparen. Übertragen (bzw. in deinem Fall: gespeichert) wird > nicht das Image, sondern die zu seiner Erzeugung nötigen grafischen > Primitives. Sozusagen Kompression an der Wurzel. > > Die Herausforderung hier ist vorallem das Clipping. Also: wie finde ich > überhaupt erstmal heraus, welche Displaybereiche die neu auszuführende > Operation betreffen wird und wie rekonstruiere ich stückweise möglichst > effizient deren Inhalt aus meinen bisherigen Aufzeichnungen. Ja gut das sind schonmal keine Schlechten Tipps, danke. spess53 schrieb: > Ich würde ohne Controller mit ordentlich Flasch gar nicht mit so etwas > anfangen. Pixelweises schreiben schreiben, evtl. noch mit vorherigem > pixelweisen lesen , kostet eine Menge unnötige Zeit. 8kB sollten reichen. Das Programm ist ja nicht sonderlich aufwändig. Das mit den Pixeln hatte ich ja schon vermutet. Georg G. schrieb: > Am Anfang einer > Entwicklung schon sparen zu wollen, ist kontraproduktiv. Wenn alles > fertig ist, kann man immer noch abstrippen. Im Prinzip gebe ich dir recht, aber in dem Fall doch wieder nicht. Natürlich entwickelt man erst mal auf einem Controller mit genug Reserven, und schaut dann wie klein man alles bekommt. In dem Fall läuft es ja schon auf einem größeren Controller und soll nun abgespeckt werden, darum gehts mir ja hauptsächlich. Und eine neue Platine muss auch nicht unbedingt sein (gilt aber in beide Richtungen) holger schrieb: > Ich auch. Die 8kB Flash gehen ja schon für den ersten schönen Font > drauf;) Naja, 1-2kB reichen da schon ;-) (Ich rede von einem 5x8 großen Font mit 8 Byte pro Zeichen) Danke aber an alle bis hierhin
Ich habe mal eine ganze Weile solche Displays mit einer Zusatzplatine mit eigenem uC ausgerüstet und mir eine Steuersprache dazu ausgedacht. So konnte ich das mit einem Mega8 ansteuern. Ich hab dann auch noch einige Festgrafiken im Display-Controler abgelegt, welche mit "ZeichneBMP,X,Y,GrafikNummer" (minimal 4 Byte) gezeichnet werden können. HG-Beleuchtung (RGB) auch steuerbar, diese Platine hatte sogar noch 2 zusätzliche LED-Ausgänge und eine serielle Schnittstelle mit drauf (mit Pegelwandler). Sorry keine besseren Fotos grad da.
:
Bearbeitet durch User
Crazy H. schrieb: > Ich habe mal eine ganze Weile solche Displays mit einer Zusatzplatine > mit eigenem uC ausgerüstet und mir eine Steuersprache dazu ausgedacht. > So konnte ich das mit einem Mega8 ansteuern. Klingt interessant, im Prinzip möchte ich ja etwas ähnliches machen. > Sorry keine besseren Fotos grad da. Schade, macht aber nichts. Hast du dein Projekt hier irgendwo dokumentiert? War wohl was fürs Auto. Ist zwar offtopic, interessiert mich aber auch :-)
... ich hab zwar kein DOGM128 Display bei einer Aufgabenstellung verwendet, sondern ein OLED 128x64 mit SSD1306 Controller und hatte auch das Problem, dort eine Grafik aufzubauen. Ich bin dann ähnlich wie oben genannt hergegangen und habe einen Framebufferspeicher angelegt, der 32x64 Pixel oder 128x8 Pixel (entspricht dann einer Zeile Text) aufnehmen kann (benötigt dann 256 Byte Speicher für 1/4 des Screens plus 2 Bytes die als Dimensionsangaben des Framebuffers benötigt werden). Beim Aufbauen des Screens erfolgt von links nach rechts. Jedes mal, wenn ein Viertel des Bildspeichers gefüllt ist, wird dieser ans Display geschickt und der weitere Aufbau des Displaybildes erfolgte dann sequentiell.
Wenn du nicht genug RAM hast, um einen Framebuffer bereitzustellen, musst du den Bildinhalt irgendwie anders ablegen. Kompression ist eine Möglichkeit, eine andere Abstraktionsebene eine andere. Eine Fortschrittsanzeige oder einen Button musst du ja nicht als Pixelgrafik vorhalten, es reicht schließlich die Information "ist eine Fortschrittsanzeige von (x0,y0) bis (x1,y1) mit 50%"; der Code, um sowas zu zeichnen, kann im Flash liegen. Für einen Button (oder ein Bild) gilt das gleiche. Aus dem Widget-Baum (oder wie auch immer du das aktuelle Bild speicherst) kannst du dann den Bildschirminhalt jederzeit rekonstruieren und brauchst keinen Speicher für das Ergebnis vorhalten.
N. G. schrieb: > ich würde gerne einem Projekt, das den ATtiny84 verwenden, ein Display > hinzufügen. 8kB Flash für ein GLCD ist viel zuwenig. Wenn es hübsch aussehen soll, möchte man schon mehrere Schriften und Größen darstellen können und das braucht viel Flash. Ein 12*16 Font kostet schon 6,2kB Flash.
S. R. schrieb: > Wenn du nicht genug RAM hast, um einen Framebuffer bereitzustellen, > musst du den Bildinhalt irgendwie anders ablegen. Man muß den Bildschirminhalt überhaupt nicht als Kopie im RAM ablegen, sondern kann auch immer direkt auf das Display zeichnen. Wie gut das geht, hängt von der Anwendung ab. > Eine Fortschrittsanzeige oder einen Button musst du ja nicht als > Pixelgrafik vorhalten Fortschrittsanzeige ist ein gutes Beispiel. Dafür füllt man einmal ein Rechteck mit Hintergrundfarbe und malt dann den Balken Schritt für Schritt in der Vordergrundfarbe hinein. Da hat man genau gar keinen Vorteil, das erst in den Framebuffer zu pinseln und den dann am Stück rauszuschreiben.
Axel S. schrieb: > Man muß den Bildschirminhalt überhaupt nicht als Kopie im RAM ablegen, > sondern kann auch immer direkt auf das Display zeichnen. Entweder, der Controller hält einen Framebuffer (bzw. kann den Displayinhalt zurücklesen) oder er muss in der Lage sein, den gesamten Inhalt jederzeit zu rekonstruieren. Beides kann man auch mischen. Aber alles andere ist Murks.
Axel S. schrieb: > Fortschrittsanzeige ist ein gutes Beispiel. Dafür füllt man einmal ein > Rechteck mit Hintergrundfarbe und malt dann den Balken Schritt für > Schritt in der Vordergrundfarbe hinein. Da hat man genau gar keinen > Vorteil, das erst in den Framebuffer zu pinseln und den dann am Stück > rauszuschreiben. Vielleicht machst du dazu einfach mal ein Beispiel. Viele Anfänger haben damit ein Problem sich so etwas vorzustellen. ;)
Hallo an alle, ich habe mich heute morgen mal hingesetzt und ein Testprogramm geschrieben. Mangels Hardware kann ich das Programm noch nicht testen, aber es sieht bisher so aus: ATtiny841 (testweise, hat einen echten I2C-Slave, kein USI) mit 8kB Flash und 512B RAM DOGM128 Implementierte Funktionen: - spi_init() und spi_send(data) - twi_slave_init(address), twi_slave_has_data, twi_slave_read(), TWI-ISR, FIFO-Buffer - dogm_init(): initialisiert das Display - dogm_set_pos(line, x): setzt die Page und die Spalte für die nächsten Daten - dogm_clear(): löscht das Display - dogm_putc(char): schreibt einen 6x8 Buchstaben an die aktuelle Position - dogm_put_picture(data): überschreibt das komplette Display mit einem Bild aus dem Flash - eine 6x8-Font mit 128 Zeichen im Flash - ein 128x64 Pixel großes Bild im Flash - eine rudimentäre main()-Funktion, die das alles einmal benutzt Wie man sieht fehlen noch alle (schwierigen) Grafik-Funktionen. Aktuell schreiben alle Funktionen nicht in den RAM, sondern senden es direkt an das Display. Das wird sich aber mit den Grafik-Funktionen zwangsläufig ändern müssen. Das interessante dabei: (das Device ist falsch, weil das gepatchte avr-size keinen ATtiny841 kenn, aber der ATtiny84 hat die selben Speichergrößen) (Compiler avr-gcc 7)
1 | avr-size --format=avr --mcu=attiny84 display.elf |
2 | AVR Memory Usage |
3 | ---------------- |
4 | Device: attiny84 |
5 | |
6 | Program: 2822 bytes (34.4% Full) |
7 | (.text + .data + .bootloader) |
8 | |
9 | Data: 12 bytes (2.3% Full) |
10 | (.data + .bss + .noinit) |
Wie man sieht noch kein (nennenswerter) RAM-Verbrauch. Ist bisher nämlich nur: - Read-Index + Write-Index vom FIFO (1 + 1 Byte) - FIFO-Buffer an sich (8 Byte) - current_line + current_x_pos vom Dispaly (1 + 1 Byte) Dazu käme dann noch ein 128 Byte großer Buffer für eine Page, sobald die Grafik-Funktionen kommen. Natürlich wird das ganze beschränkt. Es wird nur eine Schriftart geben, diese kann auch maximal 8 Pixel hoch sein. Es kann genau 8 Zeilen geben und diese sind immer (selbst wenn man eine 4x7 Schrift verwenden würde) genau 8 Pixel hoch. Das liegt einfach an den 8 Pages vom Display. Das macht aber nichts, mit diesen Beschränkungen kann ich leben. Im wesentlichen brauche ich jetzt nur noch einen Kreis mit konstanter Größe (das könnte man theoretisch auch als vorberechnetes Array in den Flash legen) über dem eine Linie vom Mittelpunkt in jede Richtung gehen kann. Das kann man sich ähnlich wie eine Uh vorstellen. Dazu käme dann noch invertierter Text, aber das ist kein Aufwand (einfach die Daten vom Font-Array bitweise mit ~ negieren). Sieht für mich machbar aus. Was haltet ihr bisher davon? Um noch auf eure Beiträge einzugehen: Peter D. schrieb: > 8kB Flash für ein GLCD ist viel zuwenig. Wenn es hübsch aussehen soll, > möchte man schon mehrere Schriften und Größen darstellen können und das > braucht viel Flash. > Ein 12*16 Font kostet schon 6,2kB Flash. Ja, aber einen solch großen Font brauche ich gar nicht, es reichen 5x8 oder 6x8. Alleine schon wegen den Limitierungen, die ich oben genannt habe. Und hübsch wirds wahrscheinlich eh nicht ;-) M. K. schrieb: > Axel S. schrieb: >> Fortschrittsanzeige ist ein gutes Beispiel. Dafür füllt man einmal ein >> Rechteck mit Hintergrundfarbe und malt dann den Balken Schritt für >> Schritt in der Vordergrundfarbe hinein. Da hat man genau gar keinen >> Vorteil, das erst in den Framebuffer zu pinseln und den dann am Stück >> rauszuschreiben. > > Vielleicht machst du dazu einfach mal ein Beispiel. Viele Anfänger haben > damit ein Problem sich so etwas vorzustellen. ;) Danke für den Anfänger... ;) Ich kann es mir schon vorstellen, ich habe so was auch schon gemacht... Aber danke für alle Beiträge bis hier her. N.G.
Wie wäre der Ansatz: Du benutzt weiterhin ein Shadow-RAM. Allerdings deckt dieses nur ein Viertel Deines LCD-Inhalts ab. Der komplette Aufbau der Graphik und das Übertragen aufs LCD erfolgt 4* hintereinander. Jedesmal deckt das Shadow-RAM dabei ein anderes Viertel des LCD ab. Deine bisherigen Graphikroutinen können dadurch (fast) so bleiben wie sie sind, außer einer Abfrage, ob der Graphikinhalt (oder Teile davon) im gerade gewählten Shadow-Viertel ist und einem Offset je nach Shadow-Viertel. Gruß, Stefan
N. G. schrieb: > Aktuell schreiben alle Funktionen nicht in den RAM, sondern senden es > direkt an das Display. > Das wird sich aber mit den Grafik-Funktionen zwangsläufig ändern müssen. Muss es das? Du kannst natürlich deine Grafikfunktionen so stricken, dass sie einen Bytestrom in ein FIFO schreiben, den du dann im Hintergrund an das Display schickst. Das wäre sinnvoll, wenn du dir keine langen Renderzeiten leisten kannst, ansonsten ist das eher nutzlos. Im Prinzip willst du eine High-Level-Funktion redraw(), welche deine internen Datenstrukturen (z.B. den Widget-Baum oder was auch immer) nimmt und mit Hilfe der Low-Level-Funktionen direkt aufs Display rendert. Ob da nun ein Framebuffer(-ausschnitt) als Cache dazwischen liegt, ist eine Feinheit. Für Linien und Kreise gibt es den Bresenham-Algorithmus, und beide Funktionen würde ich als Low-Level-Funktionen betrachten, genauso wie das Rendern von Zeichen (bzw. Strings) an eine bestimmte Position. Allein schon deswegen, weil bessere Displays das selbst schon können und du dann dort nicht mit Pixeln hantieren musst.
Stefan K. schrieb: > Du benutzt weiterhin ein Shadow-RAM. Allerdings deckt dieses nur ein > Viertel Deines LCD-Inhalts ab. Der komplette Aufbau der Graphik und das > Übertragen aufs LCD erfolgt 4* hintereinander. Jedesmal deckt das > Shadow-RAM dabei ein anderes Viertel des LCD ab. > Deine bisherigen Graphikroutinen können dadurch (fast) so bleiben wie > sie sind, außer einer Abfrage, ob der Graphikinhalt (oder Teile davon) > im gerade gewählten Shadow-Viertel ist und einem Offset je nach > Shadow-Viertel. Darauf wird es warscheinlich hinauslaufen, evtl. auch mit 8tel Display, das wäre dann genau eine Page. S. R. schrieb: > Du kannst natürlich deine Grafikfunktionen so stricken, dass sie einen > Bytestrom in ein FIFO schreiben, den du dann im Hintergrund an das > Display schickst. Das wäre sinnvoll, wenn du dir keine langen > Renderzeiten leisten kannst, ansonsten ist das eher nutzlos. Der Display-Prozessor wird sich langweilen, und sich wahrscheinlich sogar schlafen legen können. Von dem her ist dieses Vorgehen (hier) unnötig. > Für Linien und Kreise gibt es den Bresenham-Algorithmus, und beide > Funktionen würde ich als Low-Level-Funktionen betrachten, genauso wie > das Rendern von Zeichen (bzw. Strings) an eine bestimmte Position. > Allein schon deswegen, weil bessere Displays das selbst schon können und > du dann dort nicht mit Pixeln hantieren musst. Kenne ich, würde ich auch normalerweise wieder nutzen (meine Bestehende Ansteuerung nutzt diesen für Linien und Kreise), aber dieser ist Pixel-basiert und eine Set-Pixel Funktion ist ohne Shadow-RAM und ohne Zurücklesen nicht möglich. Aber es wird auf eine Zwischenlösung mit kleinerem Puffer und dort die Manipulationen hinauslaufen.
N. G. schrieb: > Schade, macht aber nichts. Hast du dein Projekt hier irgendwo > dokumentiert? War wohl was fürs Auto. Ist zwar offtopic, interessiert > mich aber auch :-) Nein das ist hier nirgends dokumentiert. Wenn du da näheres wissen willst, schreib mich per PM an. Und nein fürs Motorrad ;-)
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.