Ein kleines Beispiel (Version1) wie ein OLED2 SSD1306 in Assembler
initialisiert werden kann.
Ein ganz großes Dankeschön an Steffen, wichtige Routinen konnte ich von
ihm nutzen, super!
Beitrag "[ASM] SSD1306 text library für oled displays + AVR 0- und 1-Series"
Der 8MHz getaktete ATmega, ohne viel Schnick-Schnack bedient dieses
kleine Display. Ganz bewußt habe ich alle Vorgänge verlangsamt, SCL und
der µC-Takt kann nach belieben verändert und das keine Programm (12%
Flash, 1008 Byte) aufgebohrt werden.
Besonderheit, der SSD1306 kann nur vertikale 8Bit Pixel darstellen.
Horizontale vermutlich nicht.
Um das gesamte Display zu löschen (clear) sind 1024 TWI/I2C Bytes zu
schreiben.
Bei 16MHz Takt, SCL 444,444kHz, gelingt das in 11,6ms.
Sehen wir kurz nach Progammstart einen wunderschönen "Sternenhimmel",
dann ist das schon ganz gut, der Bildspeicher des Displays hat einen
undefinierten Zustand eingenommen. Erst durch beschreiben des z.B. Clear
Display, ändert sich dieser Zustand.
LED-grün: bereit
LED-gelb: TWI Aktivität
LED-rot: TWI Error, ev. Hardwareproblem, z.B. Problem mit dem Sklave,
SCL zu hoch
Anmerkung: Bei 400kHz SCL könnten ev. bei kurzen Anschlussleitungen
keine zusätzlichen Widerstände (SCL, SDA) gegen Vcc erforderlich sein.
Diesen Beitrag fand ich u.a. auch sehr interessant:
Beitrag "SSD1306/1309 Library zum Darstellen von Text auf OLED Displays"
Für Hinweise und konstruktive Vorschläge bin ich sehr dankbar.
Bernhard
Version2 mit einem ATmega328p, als Grundgerüst für weitere Projekte, er
bietet mehr SRAM um einen 1.024Byte großen virtuellen Bildspeicher im
SRAM zu ermöglichen, das schafft leider der ATmega8 nicht.
Das Display wir in dieser Version nur gelöscht und anschließend wieder
komplett beschrieben, sieht aus, als würde es blinken, s.Video^^
Version3
- mit einem virtuellen 1.024 Byte großen SRAM-Bild-Speicher für Text und
Grafic.
- wird Byte0 des Bildspeichers mit ffh beschrieben entsteht eine
horizontale 8 Pixel Linie oben links
- ist diese Byte eine 01h entsteht ein Pixel in der äusersten linken
oberen Ecke, mit diesm Verfahren lassen sich sehr einfach einzelne
Pixel plazieren, Linien und Kreise zeichnen
- im Timerinterrupt wird alle 100ms der Graficspeicher komplett
übetragen, dauer ca. 50ms da einige Operationen notwendig sind
um die Bits zu bearbeiten, damit eine horizontale Linie entsteht
- der Graficspeicher muss nicht zwingend im 100ms Interrupt erfolgen
- man könnte auch nur dann das Display refreshen, wenn eine Änderung
im Bildspeicher vorliegt
-die gewohnte Clear Diplay Funktion ist natürlich in der üblichen
Form nicht mehr vorhanden, jetzt mussen wir den virtuellen Bildspeicher
löschen^^
Oh, das ist ja super zu sehen - du kommst weiter mit dem OLED Display.
Bernhard S. schrieb:> - ist diese Byte eine 01h entsteht ein Pixel in der äusersten linken> oberen Ecke, mit diesm Verfahren lassen sich sehr einfach einzelne> Pixel plazieren, Linien und Kreise zeichnen
Da bin ich aber mal gespannt. Das hat mir einiges an Hirnschmalz
gekostet dies umzusetzen :)
Gruß Steffen
Steffen H. schrieb:> Da bin ich aber mal gespannt. Das hat mir einiges an Hirnschmalz> gekostet dies umzusetzen :)
Ja, das war nicht ganz ohne :-)
Das "i" in "OLED_REFRESHi" steht für Interrupt-tauglich
Prinzip:
es werden imer 8 SRAM-Bytes geladen, 1 Bock mit 64 Pixeln,
welche horizontal polarisiert, also graficfreundlich sind
(temp1...8)
in der "OLED_REFRESH_BLOCK_s" Routine erfolgt das bitweise
zusammenstellen des neuen Sendebytes, also von horizontal auf vertikal
Zuerst einsammeln Bit0 von temp1...8 im Register temp,
anschließend temp senden
dann Bit1 von temp1...8 und senden usw.
und die Neuberechnung der Adresse für den SRAM
Bernhard S. schrieb:> Um das gesamte Display zu löschen (clear) sind 1024 TWI/I2C Bytes zu> schreiben.>> Bei 16MHz Takt, SCL 444,444kHz, gelingt das in 11,6ms.
11,6ms, da hast du dich wohl etwas vertan. Rein rechnerisch sind bei
1024Bytes zu je 8Bits bei einer Bitzeit von 1/444,444kHz keine 11,6ms
drin. Das wären dann ohne Overhead (Startadresse,Controll Byte,
Adressierungsmode, Startadressen.., usw.) minimal (1024*8)/444444 =
18,4ms ;)
Ich habe mal 2 Animierte Bilder angehangen, wo die beiden
Adressierungsarten verdeutlicht werden.
Gruß Steffen
Steffen H. schrieb:> 11,6ms, da hast du dich wohl etwas vertan
Oh ja, die SCL Frequenz stimmt nicht, sie ist wesentlich höher als
400kHz.
Hatte die Bit-Rate auf NULL gesetzt, allerdings lt. Datenblatt nicht
empfehlenswert, daher die 11,6ms.
1.024Bytes, bei einer noch zulässigen Bitrate von 10 und 16MHz Takt habe
ich 22,6ms gemessen
Steffen H. schrieb:> Ich habe mal 2 Animierte Bilder angehangen, wo die beiden> Adressierungsarten verdeutlicht werden.
angehangen, angeschalten, aufgebauen, aufgezeichnen, eingekaufen,
frisch gewachsen, aufgeputzen, angekleben, eingebauen ....
Bernhard S. schrieb:> 1.024Bytes, bei einer noch zulässigen Bitrate von 10 und 16MHz Takt habe> ich 22,6ms gemessen
Hallo Bernhard
Das kommt schon eher hin. Das hab ich gestern nämlich auch geschafft.
500kHz fTWI..
Und das Display hat sogar noch mitgespielt.
Bernhard S. schrieb:> Kennt jemand Bezugsquellen für 128x128 RGB I2C TWI OLED Display?>> z.B. mit SSD1331
Ich habe mir bei ebay mal ein 1,5Zoll RGB OLED mit SPI und SSD1351
geholt. Hat ca. 15€ gekostet. Die Adressierung ist bei diesem Display
einfacher.
https://www.ebay.de/itm/283708847757
Kommst du mit deiner Pixelgenauen Adressierung weiter? Ich habe deine
Bit/Byte Schubserei nicht mehr folgen können :)
Jadiedeutschesprache schrieb:> Steffen H. schrieb:>> Ich habe mal 2 Animierte Bilder angehangen, wo die beiden>> Adressierungsarten verdeutlicht werden.>> angehangen, angeschalten, aufgebauen, aufgezeichnen, eingekaufen,> frisch gewachsen, aufgeputzen, angekleben, eingebauen ....
Darüber hatte ich kurz mal nachgedacht
Ich fand es trollig
Steffen H. schrieb:> 500kHz fTWI..> Und das Display hat sogar noch mitgespielt.
Und das ohne zusätzliche Widerstände gegen +5V, SDA und SCL am Display
sind vermutlich relativ niederohmig.
Eine Strommessung Display-SCL gegen GND ergab 0,7mA.
R=U/I = 5V:0,7mA = 7k Widerstand,
und wenn dann noch der Pull-UP des Pins aktiviert ist, sind wir bei ca.
5k.
Sind die Leitungskapazitäten klein, dann halten sich die
Signalverfälschungen in Grenzen.
Oh, demnach können durchaus über 1,4mA Strom nur durch SCL und SDA
fließen, die Energiebilanz sieht etwas wacklig aus.
Steffen H. schrieb:> Kommst du mit deiner Pixelgenauen Adressierung weiter?
Ist in Arbeit, ist aber kein Problem, bin noch mit der ASCII Darstellung
beschäftigt.
Steffen H. schrieb:> Darüber hatte ich kurz mal nachgedacht> Ich fand es trollig
Wir dürfen nie nachdenken, wir müssen immer vordenken ;-)
https://www.mikrocontroller.net/attachment/489878/OLED_RGB_SSD1351.jpg
Ist leider SPI, TWI wäre mir lieber, benötigt weniger
Anschlussleitungen,
Greta würde sich feuen.
Version4 mit ASCII Zeichensatz 8x12 und 16x8.
Das Display wird nur refresht, wenn sich im Bildspeicher etwas ändert,
spart Strom.
Strombedarf im Bild 16x24 ca. 6mA bei 5V.
Der Schriftfont ist in einer Tabelle hinterlegt und so konstruiert nach
dem Motto, wie man es optisch sieht, so wird er auch auf dem Display
dargestellt. Kann nach belieben einfach geändert werden.
Leider sind die beiden Fonts sehr speicherintensiv, momentan sind schon
über 54% des Flashs belegt :(
Könnte man ev. in einem externen TWI-EEPROM ablegen :)
Thomas N. schrieb:> ...RDA5807 Radios mit ATtiny45
Toll, Respekt!
Hättest Du noch eine Schaltung für uns?
Mir viel gleich eine Besonderheit auf, Du verwendest keinen virtuellen
Bildschirmspeicher im SRAM, sondern konstruierst die Grafic direkt im
Display.
Wo konntest Du dieses Radiomodul beziehen?
Wie sind die Empfangseigenschaften, besonders bei RDS-Empfang?
Was genau wird mit der "Initab" im OLED eingestellt?
Bernhard
Anbei die Schaltung (geht aber eigentlich aus dem Listing hervor).
Die RDA5807 Module hatte ich vor ca. 1 1/2 Jahren via EBay erworben. Da
findet man auch hiesige Lieferanten.
Die Module haben eine hohe Empfangsempfindlichkeit und liefern eine
überraschend gute Klangqualität.
Von den RDS Signalen habe ich den Radiotext als Lauftext und die Uhrzeit
decodiert (wie in dem Foto vom 21.01.2021 erkennbar ist). Außerdem wird
bei Verkehrsfunk Durchsagen ein "!" eingeblendet.
Die doppelte Zeichengröße leite ich aus einer Tabelle durch Wiederholung
der Pixel ab.
Eigentlich erlaubt die RDS Spezifikation EN50067 auch Fehlererkennung-
und Korrektur der Datenübertragung. Meine Implementierung liefert aber
nur die ungefilterten Rohdaten, was meist ganz brauchbar ist. Leider ist
das englische Datenblatt an den entscheidenden Stellen hier
unvollständig und aus dem chinesischen Programming Manual bin ich erst
recht nicht schlau geworden ;) Ich vermute, dem RDA5807 fehlen hierzu
auch einige Register. Da ist man mit dem Si4703 besser bedient. Hier
habe ich noch ein paar weitere Erläuterungen:
http://tneveling.bplaced.net/radiobasteln.html
Thomas N. schrieb:> Hier mal als Diskussionsbeitrag meine OLED SSD1306 / SH1106 Assembler> Routinen als Teil eins RDA5807 Radios mit ATtiny45
Ein sehr schönes Projekt. Vielen Dank dafür. Ich hab es mir soeben auf
meine Liste geschrieben.
Ich mag auch deinen Programmierstil. Sehr übersichtlich und
nachvollziehbar.
Wie du das mit der doppelten Schriftgröße machst find ich gut. Deine
Multiplikation sehr schön gelöst. Mach ich auch lieber so wenn es eine
2^x Multiplikation ist.
Wenn ich das richtig sehe hast du eine repeat Funktion in der
Tastenabfrage integriert. Da du ja nur 3 Tasten verwendest, kannst du da
mal bitte die einzelnen Funktionen (Menu) der Tasten zusammenstellen?
Über Mode zeigst du ja die verschieden Menüs an, oder?
Toll gemacht!
Bernhard S. schrieb:> Mir viel gleich eine Besonderheit auf, Du verwendest keinen virtuellen> Bildschirmspeicher im SRAM, sondern konstruierst die Grafic direkt im> Display.
Wenn man den Text oder was auch immer an Grafik immer in den 8Bit einer
Spalte abbilden kann, wozu dann einen virtuellen Speicher? Ich habe
diesen nur eingeführt wenn man echte Grafik zeichnen will. Denn dann
muss man Pixelweise adressieren können und da wird es bei den Displays
unmöglich ohne virtuellen Abbild. Denn man kann den Displayspeicher der
kleinen OLED's nicht lesen!
Und genau da beginnt die Pixel und Bit Schubserei..
Siehe hier:
Beitrag "Re: [ASM] SSD1306 text library für oled displays + AVR 0- und 1-Series"
Versuche mal etwas anders - universeller - an die Textgenerierung heran
zu gehen. Jetzt gerade baust du für jede Schrift/Font ein riesiges
Konstrukt um diese in den virtuellen Speicher zu bringen.
Bitte nicht falsch verstehen Bernhard. Das soll keine Kritik sein, nur
ein Hinweis.
Gruß Steffen
Steffen H. schrieb:> Versuche mal etwas anders - universeller - an die Textgenerierung heran> zu gehen. Jetzt gerade baust du für jede Schrift/Font ein riesiges> Konstrukt um diese in den virtuellen Speicher zu bringen.
Ok, ich suche nach einer Lösung :-)
Eventuell hilft eine Funktion "PSET_XY".
Momentan sind die Font-Tabellen so aufgenaut, daß sie einfach geändert
werden können.
So wie ein Datensatz in der Tabelle sichtbar ist z.B. "C", so wird er
auch auf dem Display dargestellt und genau das macht den Assemblercode
komplizierter mit der "ASCII_BITUMKEHR_TEMP", Zeilen und Spalten müssen
auch gezählt werden.
> Wie du das mit der doppelten Schriftgröße machst find ich gut. Deine> Multiplikation sehr schön gelöst.
Eine Tolle Idee, den gerade mein Font mit doppelter Schriftgröße klaut
viel Flash.
Ich schau mir das Schriftbild mit der Schriftverdopplung mal genauer an.
Bernhard
Bernhard S. schrieb:> Eine Tolle Idee, den gerade mein Font mit doppelter Schriftgröße klaut> mit viel Flash.
Man darf nicht vergessen, Thomas hat das alles in ein ATtiny45 bekommen.
4k Speicher und 128bit RAM !!!
Respect nochmal dafür..
Version5 mit Punkt setzen und löschen XY.
Schaut Euch mal bitte die "PUNKT_SET_XY" Routine an, ob man die noch
schneller machen kann, hier kommt es auf jeden Takt an, sonst dauert das
Zeichen der von Figuren, wie Zeiger, Kreise, gefüllte Rechtecke ziemlich
lange.
Bedingung die Register XYZ düfen nach verlassen der Routine nicht
verändert werden, nur temp(R16),R0 und R1.
Im Bild "B2" ist im Hintergrund ein Sternenhimmel zu sehen, per
ZUfallsgenerator werden Punkte gesetzt und gelöscht, sieht putzig aus
:-)
Steffen H. schrieb:> Thomas hat das alles in ein ATtiny45 bekommen
Dafür hat er auch von mir einen dicken Pluspunkt bekommen, das hat er
sich verdient.
Nachtrag: push ZL, push ZH konnte ich ersetzen durch MOVW ZL_KOPIE,ZL.
Kostet allerdings 2 wertvolle Register :(
Ich bin noch ein paar Antworten schuldig geblieben:
>@Bernhard: Was genau wird mit der "Initab" im OLED eingestellt?
Wenn man sich auf die Einstellungen beschränkt, die nicht schon beim
Reset als Standard
definiert sind, kommt man mit 5 Byte zur Initialisierung aus!
0x8D 0x14 Ladungspumpe aktivieren
0xAF Display einschalten
0xA1 Column 127 wird auf Segment 0 gemappt
0xC0 Normal Scan Direction
>@Steffen: Tasten & Menues
Die "Mode" Taste (nicht repetierend) schaltet zwischen "Volume"
(Lautstärke), "Mute" (Stummschaltung) und "Seek" (Sendersuche) um. Ein
entsprechender Text in der Mitte des Displays zeigt die aktuelle
Einstellung.
Mit den Tasten "up" und "down" kann im Modus "Volume" die Lautstärke
geändert werden (repetierend mit Balkenanzeige)
Im Modus "Seek" wird die Sendersuche aufwärts / abwärts gestartet (nicht
repetierend).
Der zuletzt eingestellte Sender wird im EEPROM gespeichert und steht
beim nächsten Einschalten wieder zur Verfügung.
@Thomas
ich schau mir gerade Deine Font-Tabelle an (8x8 Pixel),
so sieht nach meiner Meinung Dein "A" theoretisch mit Bitverdopplung aus
8x16.
Kannst Du uns mal bitte ein Foto mit einem "A" senden.
Welchen Font-Generator verwendest Du?
Danke
@Bernhard
Zeichensatz und hierzu passende OLED Init Sequenz wurde aus
Beitrag "(sehr) kleines "FrameWork" für ATtiny44" (in C codiert)
abgeleitet. Ich habe das Ganze zunächst auch in C auf einen ATtiny85
portiert und dann in mehreren Iterationen auf Assembler umgestellt, den
RDS Decoder ergänzt etc.
Die doppelte Zeichengröße ist aber auch in dem ursprünglichen C-Code
schon vorzufinden. Die Pixel werden sowohl horizontal als auch vertikal
dupliziert, so dass aus dem 8x8 Zeichen aus der Font Tabelle ein 16x16
Zeichen entsteht (siehe Foto von dem gewünschten "A").
Damit ich da selbst später noch durchblicke hatte ich damals eine kleine
Doku über die OLED Ansteuerung und die Verdopplung der Zeichengröße
erstellt, die vielleicht weitere Fragen beantwortet.
Bernhard S. schrieb:> Könnte man ev. in einem externen TWI-EEPROM ablegen :)
Also da hätte ich noch eine Idee, wenn schon ein weiterer Chip im
Gespräch ist, wie wäre es mit einen kleinen Attiny. Damit könnte
gewissermaßen ein intelligentes Display gebaut werden.
Also in etwa so:
Auf die Displayplatine kommt ein Tiny der sich nur um die Oled-Steuerung
kümmert. Dieser wiederum kann per I2C von einen anderen µC angesprochen
werden. Dafür gibt es dann eine Befehlsliste, wie OLED_Init;
SET_Curser....
Bernhard S. schrieb:> OLED_REFRESH_ZEILE:> rcall OLED_REFRESH_BLOCK> rcall OLED_REFRESH_BLOCK
Und beim naechsten mal lernen wir das voellig neue Konstrukt einer
Schleife ...
SCNR, leo
Bernhard S. schrieb:> Schaut Euch mal bitte die "PUNKT_SET_XY" Routine an, ob man die noch> schneller machen kann, hier kommt es auf jeden Takt an, sonst dauert das> Zeichen der von Figuren, wie Zeiger, Kreise, gefüllte Rechtecke ziemlich> lange.
Hallo Bernhard
Ich hab es versucht - blicke aber bei deinem Algorithmus zur
Adressierung nicht durch. Kann das sein, dass du das alles sehr
kompliziert machst weil du dich so sehr auf die einfach ersichtliche
Datenabbildund deiner Fontdaten konzentrierst?
In welchem Adressoerungsmode schreibst du denn die Daten zum Display?
Verikal oder Horizontal?
Bedenke bitte, dass selbst wenn deine Daten im RAM schön in - ich sag
mal Reihe - Byte1,Byte2,..,ByteX im RAM liegt, kann es doch im Display
trotzdem nur Senkrecht und nicht - wie von dir erzwungen - waagerecht
abgebildet werden. Dies alles verkompliziert, meiner Meinung nach, die
ganze Adressierung.
Denn wenn du ein Byte mit mehreren gesetzten Bits (Pixeln) hast rechnest
du diese irgendwie erst in Byte|Bit um und setzt jedes Bit aus dem
Ursprungsdatenbyte dann einzeln
im RAM. Das dauert doch alles viel zu lange.
@Thomas
Heute ist der Radio Empfänger gekommen. Bin voll in Bastellaune :)
@alle hat jemand eine Idee, wie man die Font-Tabelle komprimieren kann,
um wertvollen Speicher zu sparen?
Thomas N. schrieb:> eine kleine Doku über die OLED Ansteuerung und die Verdopplung der> Zeichengröße erstellt
Es kommt nicht immer auf die Größe an, sehr gut gelungen, Daumen hoch!
Einen kleinen selbsgefummelten Visual-Basic Fontgenerator nutze ich
gern.
leo schrieb:>> rcall OLED_REFRESH_BLOCK>> rcall OLED_REFRESH_BLOCK> Und beim naechsten mal lernen wir das voellig neue Konstrukt einer> Schleife ...
Hat Gründe. z.B. Schnelligkeit und Registerersparnis um pushen und popen
zu ersparen, Vorbereitung auf Graficfähigkeit
Frank D. schrieb:>> Könnte man ev. in einem externen TWI-EEPROM ablegen :)
Oder in einem internen EEPROM, ca.1k müsste er groß sein.
> Also da hätte ich noch eine Idee, wenn schon ein weiterer Chip im> Gespräch ist, wie wäre es mit einen kleinen Attiny. Damit könnte> gewissermaßen ein intelligentes Display gebaut werden.
Es wäre gut, wenn er eine Harware TWI besäße, ausgangsseitig kann das
Display mit einer Software TWI angesteuert werden.
Für ASCII-Darstellung wäre das eine gute Idee.
Grafic, so wie in einem sehr teuren TFT:
Beitrag "Spektrumanalysator Frequenzspektrumanalysator Frequenzspektrometer Speki Wobbelgenerator TFT Atmega8"
Ein ATmega328p hätte genügend SRAM, um derartige Figuren zu zeichnen.
Steffen H. schrieb:> Heute ist der Radio Empfänger gekommen. Bin voll in Bastellaune :)
Wo konntest Du ihn bestellen?
Ich wäre auch gern in derartiger Bastellaune :)
Steffen H. schrieb:> Ich hab es versucht - blicke aber bei deinem Algorithmus zur> Adressierung nicht durch.
Nicht schlimm, das ist auch nicht ganz einfach zu durchschauen, gebe ich
echt zu, schlussendlich sollen solche Figuren entstehen:
Beitrag "NF Spectrum Analyzer selber bauen Eigenbau TV FBAS ATmega1284p Assembler low cost"> Kann das sein, dass du das alles sehr> kompliziert machst weil du dich so sehr auf die einfach ersichtliche> Datenabbildund deiner Fontdaten konzentrierst?
Ja, die zu entstehende Grafic z.B. schräge Linien, muss später schnell
errechenbar sein, sonst dauert die Figurendarstellung zu lange, das
bereitet wenig Freude.
> In welchem Adressoerungsmode schreibst du denn die Daten zum Display?> Verikal oder Horizontal?
Die Daten werden Vertikal geschrieben, aber horizontal im SRAM abgelegt.
Das Konstrukt
rcall OLED_REFRESH_BLOCK
rcall OLED_REFRESH_BLOCK
rcall OLED_REFRESH_BLOCK
...
dient dazu das horizontale flink in das vertikale umzuwandeln und zu
senden. Es werden immer 8x8Pixel in einem Block zusammengefasst und dann
dieser Block mit 8Bytes gesendet, so das Prinzip.
> Bedenke bitte, dass selbst wenn deine Daten im RAM schön in - ich sag> mal Reihe - Byte1,Byte2,..,ByteX im RAM liegt, kann es doch im Display> trotzdem nur Senkrecht und nicht - wie von dir erzwungen - waagerecht> abgebildet werden. Dies alles verkompliziert, meiner Meinung nach, die> ganze Adressierung.
Ja, Du hast Recht. Wenn Du ein 8Pixel breiten horizontalen Strich
darstellen möchtest, brauchst Du nur ein SRAM Byte auf ffh setzen, den
Rest erledigt die seltsam ausschauende "LED_REFRESH_BLOCK" Routine, die
flott sein muss.
> Denn wenn du ein Byte mit mehreren gesetzten Bits (Pixeln) hast rechnest> du diese irgendwie erst in Byte|Bit um und setzt jedes Bit aus dem> Ursprungsdatenbyte dann einzeln> im RAM. Das dauert doch alles viel zu lange.
Das erledigt alles die "LED_REFRESH_BLOCK" Routine, der gesamte Display
Inhalt wird in 128 Blöcke unterteilt (8x8 Pixel), jeder Block besteht
aus 8 vertikalen Bytes die an das Display gesendet werden.
Ich find Thorstens Font, gestreckt auf 8x16, auch ganz schick^^
Somit passen 16 große schlanke Asciis auf eine Zeile,
so wie die pummeligen^^
@ die Radiobastler:
Hier noch ein kleines Update meines Assembler Codes zur Korrektur der
Zeitzone beim RDS Decoder. Wie gesagt hatte ich das Ganze zunächst in C
programmiert und erst danach in Assembler. Meinen C-Code findet ihr
hier:
Beitrag "Re: DIY UKW-Receiver mit Padauk PFS154 und RDA5807"
Läuft auf der gleichen Hardware und passt immer noch in einen ATtiny45.
Bernhard S. schrieb:> @Thorsten>> könntest Du, wenn's keine große Umstände macht, die Bits in Deinem Font> tauschen Bsp: 0b00000001 ---> 0b10000000
Du reitest dich immer tiefer rein und verkomplizierst alles. Oha, ich
glaub das Wort gibt es gar nicht, aber egal. Ich sagte schon, du musst
umdenken. Wenn du erst eine Linie oder sogar einen Kreis nach Bresenhan
zeichnen willst wird das ganze Ausmaße annehmen und langsam werden.
Bernhard S. schrieb:> PS: die 3 Schriftgrößen, generiert aus einem Font, sehen vernünftig aus,> finde ich.
Find ich auch.
@Thomas -> Danke für deine Codes
Steffen H. schrieb:> Du reitest dich immer tiefer rein und verkomplizierst alles.
Du hast bestimmt für den Grafic-Modus bessere Ideen,
lass es uns wissen :-)
> Wenn du erst eine Linie oder sogar einen Kreis nach Bresenhan> zeichnen willst wird das ganze Ausmaße annehmen und langsam werden.
Ja, es wird langsamer, aber möglich, eine Uhr mit Sekundenzeiger ist der
Prüfstein, die alte Zeigerstellung muss berechnet und gelöscht, die
neue Zeigerstellung berechnet und gezeichnet werden und so ganz nebenbei
ein FBAS-Bild generiert werden, ein 22MHz getakteter AVR kommt dabei
ganz schön in's Schwitzen.
Version6, eine kleine Spielerei^^
B0 Begrüßung
B1 verfügbare Schrift-Fonts Font0, Font1, Font2
B2 TWI-Scanner, momentan nur h3c (Display am Bus)
B3 Zeit für ein Display-Clear
B4 Uhrzeit, Zeit für diese Anzeige, Betriebsspannung, Frequenzzähler
B5 oh Schreck, der ATmega8 ist schon zu 48% belegt
Die größeren Fonts sind etwas rechenintensiver, 32 Bytes SRAM werden
benötigt.
Zuerst wird der obere Teil des ASCII-Zeichens (8 oder 16Bytes)
gezeichnet, anschließend der untere.
Hat den Vorteil, dass nicht ständig die zeitintensive "OLED_GOTO_XY"
aufgerufen werden muss.
Ein gut gefülltes Display s. "B4" benötigt ca, 84ms. Könnt Ihr mal bei
Euch nachmessen?
Wenn die Bitrate auf die nicht empfehlenswerte 1 gesetzt wird sind es
nur noch 48ms.
PS: Momentan versuche ich den Code für schnelle Darstellung zu
optimieren.
Bernhard S. schrieb:> Ja, es wird langsamer, aber möglich, eine Uhr mit Sekundenzeiger ist der> Prüfstein, die alte Zeigerstellung muss berechnet und gelöscht, die neue> Zeigerstellung berechnet und gezeichnet werden und so ganz nebenbei ein> FBAS-Bild generiert werden, ein 22MHz getakteter AVR kommt dabei ganz> schön in's Schwitzen.
Da hast du dir aber ganz schön was vorgenommen.
Wegen der Uhr, wenn man genug RAM an Bord hat kann man mit mehreren
Layern arbeiten. Das Ziffernblatt kann man in einem Layer halten und die
Zeiger dann in einem Anderen.
Falls du dich fragst, Warum? Der Gedanke dahinter ist folgender:
Wenn du den Zeiger zum Beispiel über das Ziffernblatt oder eine Ziffer
zeichnest (Sekundenzeiger), dann ist das ja kein Problem. Löscht du
diesen aber nun um den nächsten zu zeichnen, dann löscht du auch dein
Ziffernblatt oder Ziffern an der Stelle wo vorher der Zeiger war.
Bernhard S. schrieb:> Du hast bestimmt für den Grafic-Modus bessere Ideen, lass es uns wissen> :-)
Ich hab das schon alles hinter mir. Wie schnell meine Routinen bei einem
einzelnen Pixel sind, hab ich noch nicht verifiziert. Aber den Schriften
bin ich schnell und sehr flexiebel. Die Fonts sind gepackt. Das bedeutet
zwar mehr rechnen aber das geht schon. Dabei bediene ich mich der
Tatsache, das verschiedene Zeichen verschiedene Pixelweiten haben und
somit nicht mit konstanter Datenbreite pro Zeichen als Fontdaten
gespeichert werden muss.
Zum Beispiel:
Ein "I" ist schmaler als ein "W". Außerdem benötigt man eher selten den
kompletten ASCII Zeichensatz (256 Zeichen). Ich fange zum Beispiel erst
beim Leerzeichen (0×20) an und dann bloß 96 Zeichen bis zum Charter 127
(~). Das spart Platz im Speicher.
Dazu gibt es dann zu jedem Font einen Daten Header (Kopf) wo die feste
Pixelhöhe der Zeichen, den Charcode des ersten Zeichens der Chardaten
und die Anzahl der Zeichen für die Daten vorliegen. Bevor jetzt die
eigentlichen Daten der Zeichen kommen, ist da noch ein Datensatz zu den
Pixelbreiten jedes einzelnen Zeichens. Also bei 96 Zeichen sind das dann
auch 96 Bytes. Danach beginnen die Daten für die einzelnen Zeichen.
Ich könnt noch mehr darüber schreiben, aber das wäre dann wohl eher was
für eine Bachelor Arbeit oder einen Artikel hier im Forum.
Ich hoffe ich habe dich/euch nicht verwirrt.
@Bernhard
Aber die 3 verschiedenen Schriftgrößen aus ein und demselben Datensatz
sieht gut aus. Vielleicht werde ich auch noch eine abgespeckte
Textversion meiner Lib bauen.
Übrigens, wenn du deine RAM Variablen mal anders deklarieren würdest,
dann siehst du auch deinen RAM Verbrauch..
Statt:
1
.equ adr_DATEN = SRAM_START+0
2
.equ adr_ss10 = SRAM_START+10
3
.equ adr_ss = SRAM_START+11
gibt man einfach die Anzahl zu reservierender Bytes der Daten an. Der
Name bleibt erhalten.
Und zwar so:
1
.dseg
2
.org SRAM_START
3
adr_DATEN: .BYTE 10 ; reserviere 10 Bytes im SRAM
4
adr_ss10: .BYTE 1 ; reserviere 1 Byte
5
adr_ss: .BYTE 1 ; reserviere 1 Byte
6
....
7
....
8
.org SRAM_START+99
9
adr_SRAM_CHECK_A: .BYTE 1
10
adr_BILD_BEREICH: .BYTE 1024-1
11
adr_BILD_BEREICH_ENDE: .BYTE 1024
12
adr_SRAM_CHECK_B: .BYTE 1
13
14
.org SRAM_END
15
adr_SRAM_CHECK: .BYTE 1
Das sind alles Hilfen des AVR Assemblers..
MfG
Steffen
@Bernhard
Sag mal, bist jetzt doch wieder zurück auf einen ATmega8 gewechselt???
Laut deinem letztem Post habe ich einen ATmega328 verwendet und nur
Fehlermeldungen bekommen. Dann hab ich entdeckt, dass du da einen Mega8
eingebunden hast und du alles nicht mehr über ein im RAM angelegten
virtuellen Displayspeicher machst.
Wie gesagt, bei Schrift mit vordefinierter Zeichenhöhe von 8,16,24,32,..
Pixeln geht das noch. Bei Linien und anderen grafischen Funktionen bin
ich schon gespannt wie du das machen willst.
Ich hab dein letzten Post (Version6) für einen ATmega328 umgestrickt und
getestet. Läuft gut. Auch wenn die Error LED ständig leuchtet. Warum
auch immer..
Ich habe auch die Zeit zum Display löschen mit einem LA kontrolliert.
45,79ms hab ich gemessen. Stimmt also.
Was ich auch noch nicht verstanden habe sind deine Variablen
SRAM_CHECK_ und _BILD_BEREICH_ENDE ?
Wozu sind die gut?
MfG Steffen
Version-7, Achtung wieder ATmega328p
ASCII, Punkte, Linien, gerade und schräge.
B0 freundliche Begrüßung mit Helligkeitsänderung
B1 Zeitmessung für OLED-Clear
B2 Zeitmessung für 1s Wait, die 1ms Timerinterrupts bremsen die
Warteschleifen aus
B3 Linienbeispiele
B4 Zeit, Zeit Bildberechnung mit Refresh des Displays
Betreibsspannung, OLED 1Bytes auslesen
Nun macht sich der "seltsame" Aufbau des SRAMs bezahlt, die Berechnung
der Linien ist relativ einfach.
Die Koordinaten für X1, Y1, X2, Y2 sind in den Registern R2 bis R5
hinterlegt.
Linienberechnung:
Zuerst wird untersucht, ob es senkrechhte oder waagerechte Linen sind,
diese lassen sich sehr flott berechnen.
Bei den schrägen linien wirds komplizierter, hier untersuche ich den
Anstieg, ob positiv oder negativ. Anschließend wird die Linie 2x
gezeichnet, beim ersten Durchgang wird X hochgezählt und Y berechnet,
beim zweiten Y hochezählt und X berechnet, damit auch sehr flache und
sehr steile Linien ohne Lücken gezeichnet werden, sonnst sieht etwas
komisch aus.
Steffen H. schrieb:> Was ich auch noch nicht verstanden habe sind deine Variablen> SRAM_CHECK_ und _BILD_BEREICH_ENDE ?> Wozu sind die gut?
SRAM_CHECK dient zur Programmüberwachung, wenn dieses Byte überschrieben
wird, warum auch immer, blinken die LEDs wie wild.
BILD_BEREICH_ENDE... Dummy, keine Bedeutung mehr
> Übrigens, wenn du deine RAM Variablen mal anders deklarieren würdest,> dann siehst du auch deinen RAM Verbrauch..
Da hast Du Recht, gib mir angemessen Zeit, um mich daran zu gewöhnen,
danke für den Tipp
> Dann hab ich entdeckt, dass du da einen Mega8> eingebunden hast und du alles nicht mehr über ein im RAM angelegten> virtuellen Displayspeicher machst.
Und nun ist es wieder ein ATmega328p.
> Wegen der Uhr, wenn man genug RAM an Bord hat kann man mit mehreren> Layern arbeiten.
Das stimmt, ist aber in diesem Fall nicht erforderlich, Linien bzw
Zeiger lassen sich sehr schnell zeichnen, wenn der jedes mal der
Bildbereich im SRAM gelöscht wird, die Uhr dann komplett neu berechnet
und anschließend das Display refresht wird, dann sieht das richtig
schick aus, selbst mit einem Sekundenzeiger.
Steffen H. schrieb:> Ein "I" ist schmaler als ein "W".> Dazu gibt es dann zu jedem Font einen Daten Header (Kopf)
Man könnte auch im Programm diese Header-Daten berechnen, d.h. ein "i"
wird aus einem Standart-Font geladen un dann untersucht, auf welche
Spalten könnte man versichten, damits noch schöner aussieht :-)
Dieser Assemblercode besitzt noch eine Menge Optimierungspotential,
momentan steht die Zeichengeschwindigkeit im Vordergrund^^
Bernhard
Steffen H. schrieb:> Ich habe mir bei ebay mal ein 1,5Zoll RGB OLED mit SPI und SSD1351> geholt. Die Adressierung ist bei diesem Display> einfacher.
Sieht auch schick aus :-)
https://www.mikrocontroller.net/attachment/489878/OLED_RGB_SSD1351.jpg
@Steffen,
nun ist auch bei mir ein solches SSD1351 Display eingetroffen, noch ist
es dunkel, hättest Du ein Assembler-Beispiel und eine Schaltung für uns?
Ein hex-File für einen ATmega8 wäre schön, um wenigstens die Hardware zu
testen.
So mehr ich mich mit diesem OLED 128x128 RGB Color Farbe theoretisch
beschäftige, um so mehr Fragen ergeben sich z.B.
- Betriebsspannung max wirklich nur 3,3V?
- Welche Pins müssen wie beschaltet werden?
- muss Reset beschaltet werden?
- wie erfolgt die Initialisierung?
Da das Display nicht ausgelesen werden kann, wäre z.B. der Betrieb einer
SD-Card am SPI-Bus ohne Aufwand möglich.
Danke
Bernhard
Bernhard S. schrieb:> nun ist auch bei mir ein solches SSD1351 Display eingetroffen, noch ist> es dunkel, hättest Du ein Assembler-Beispiel und eine Schaltung für uns?>> Ein hex-File für einen ATmega8 wäre schön, um wenigstens die Hardware zu> testen.
Ich mache nicht mehr viel mit den uralten AVR wie dem Mega8. Ich habe
mich jetzt vollkommen auf die neuen AVR der Serie-0 und Serie-1
eingeschossen. Da ich vorher schon einiges mit den Xmegas vorher zu tun
hatte, war es nicht so schwer sich in die neue Architektur
einzuarbeiten.
Außerdem benötigen die neuen AVR nur noch eine einzige Ader (und GND
natürlich) um diese zu programmieren und zu debuggen! Nennt sich UPDI.
Ich habe mir meinen eigenen UPDI Programmer/Debugger selber gebaut. Aus
einem Arduino Micro. Firmware drauf und schon hat man einen UPDI
Programmer/Debugger.
Ich hab dir aber mal ein Testfile für einen ATtiny1614 dran gehangen. Da
kannst dir wenigstens die Initialisierung raus suchen. Ach ja, mit dabei
sind ein paar pdf Dokumente.
Bernhard S. schrieb:> So mehr ich mich mit diesem OLED 128x128 RGB Color Farbe theoretisch> beschäftige, um so mehr Fragen ergeben sich z.B.>> - Betriebsspannung max wirklich nur 3,3V?
JA!
> - Welche Pins müssen wie beschaltet werden?
CLK, DIN, CS, DC, RESET, GND, Vcc
Also alle!
> - muss Reset beschaltet werden?
JA
> - wie erfolgt die Initialisierung?
Siehe ZIP-File
Mfg Steffen
Bernhard, ich hab hier mal eine .hex Datei für einen ATmega328 mit einer
Testsequenz zum SSD1351 aus Arduino erstellt. Wenn du diesen mit nur
3,3V und 8MHz betreibst, sollte das doch auch ohne Level Shifter gehen.
In einen Mega8 passt das ganze schon nicht mehr hinein.
MfG Steffen
> Das Display wird nur refresht, wenn sich im Bildspeicher etwas ändert,> spart Strom.
Ein kleiner Tip:
Ich mach das so das ich den Bildspeicher aufteile. Zum Beispiel in
4Segmente und 8Pages. Dann ist ein solches Segment nur 32Byte gross.
(bei 128x64Pixel) Ausserdem hab ich noch ein paar Byte in dem ich mir
merke wenn sich in einem Segment etwas gaendert hat.
Dann macht man einen Ticker-IRQ und sorgt dafuer das alle 5ms ein
Segment uebertragen wird wenn es sich geaendert haben sollte. Dadurch
hat man in der Praxis kaum Datenuebertragung zum Display da sich selten
viel aendert und trotzdem wirkt das Display extrem responsiv.
Olaf
zusatztip: Seit kurzem findet man immer mehr Oled (1.3") mit dem SH1106.
Der ist fast baugleich zum SSD1306, lediglich die Uebergabe der
Columnadresse braucht einen anderen Befehl.
Olaf schrieb:> zusatztip: Seit kurzem findet man immer mehr Oled (1.3") mit dem SH1106.> Der ist fast baugleich zum SSD1306, lediglich die Uebergabe der> Columnadresse braucht einen anderen Befehl.
Könnten wir einmal einen aktuellen Benchmark im Vergleich zur Adafruit
Library bekommen? Der Charme der Adafruit Library ist: extrem
umfangreicher Funktionsumfang, sehr viele Displays werden unterstüzt,
und das API ist (fast) identisch für verschiedene Displays, was
Portierung auf unterschiedliche Display extrem einfach macht...
minimalste Sourcecode-Änderungen.
Ich frage mich halt, ob der Performanz-Vorsprung den man durch diese
Library evtl. erreicht (gegenüber Adafruit Libraries) den Zeitaufwand
rechtfertigt. Eine Entscheidungshilfe wäre nett!
Pat B. schrieb:> Ich frage mich halt, ob der Performanz-Vorsprung den man durch diese> Library evtl. erreicht (gegenüber Adafruit Libraries) den Zeitaufwand> rechtfertigt. Eine Entscheidungshilfe wäre nett!
Ich denke nicht, dass das entwickeln eines Treibers für die kleinen OLED
Dinger etwas mit Performance als Entscheodungshilfe zu tun hat.
Auch wenn Bernhard immer schreibt wie schnell doch seine Routinen sind.
Der Hauptgrund ist sicherlich dies selber mal gemacht zu haben um das
"Dahinter" zu verstehen. Es in Assembler zu machen und nur das zu
implementieren, was man auch wirklich braucht! Und nicht so eine
aufgeblasene Bibliothek in C oder C++. Auch wenn die Bibliotheken
wirklich gut sind.
Bestes Beispiel ist das RDS Radio mit OLED und ATtiny45 !
MfG Steffen
> Ich denke nicht, dass das entwickeln eines Treibers für die kleinen OLED> Dinger etwas mit Performance als Entscheodungshilfe zu tun hat.
Doch, aber nicht so wie man zuerst denkt. Keiner wird den Treiber fuer
ein 128x64 Pixel Display so optimieren eine moeglichst hohe Framerate zu
schaffen damit er damit Videos darstellen kann. Aber es gibt andere
Optimierungsziele.
1. Mir ist es heute wichtig das mein (eigenes!) printf moeglichst
schnell ist. Damit kann es auch mal in zeitkritischen Funktionen
verwenden. (Z.b fuer Diagnosezwecke in einem PID)
2. Mir war es frueher mal wichtig das meine LCD Ansteuerung moeglichst
wenig Ram hatte weil meine Controller nur 1-2kb hatten. (Bufferram war
gepackt)
3. Im professionellem Bereich kann Redundanz interessant sein. Wenn du
sagen wir mal alle 100ms das Display neu initialisiert dann ist es nicht
schlimm wenn der LCD-Controller beim ESD Test abstuerzt.
4. Bei manchen Anwendungen will man das moeglichst selten auf ein
Display geschrieben wird weil der Controller moeglichst lange im
Sleepmode sein soll damit die Batterie so lange wie moeglich haelt.
Diese Ziele widersprechen sich. Deshalb ist die Verwendung von fertigen
Libaries anderer Leute immer schlechter als was eigenes zu machen.
Ausnahmen gibt es nur dort wo man massiv mit unbekannter Hardware im
Kontakt kommt. (SD-Karten, Bluetooth)
Olaf
Olaf schrieb:> Diese Ziele widersprechen sich. Deshalb ist die Verwendung von fertigen> Libaries anderer Leute immer schlechter als was eigenes zu machen.> Ausnahmen gibt es nur dort wo man massiv mit unbekannter Hardware im> Kontakt kommt. (SD-Karten, Bluetooth)
Sofern man unendlich viel Zeit hat sich mit Problemen zu beschäftigen,
die andere schon vor Jahrzehnten gelöst haben, UND wenn die Hardware
nicht sonderlich komplex ist, ist das natürlich richtig. Am Besten baut
man sich auch noch seinen eigenen Computer dann, dann kommt man richtig
schnell vom Fleck (sofern man denn auch noch die Zeit hat, das Rad neu
zu erfinden) :-D
> Sofern man unendlich viel Zeit hat sich mit Problemen zu beschäftigen,> die andere schon vor Jahrzehnten gelöst haben, UND wenn die Hardware
Du hast ein Verstaendnisproblem. Andere haben vor Jahrzehnten genau ihr
Problem geloest. Fuer dich haben sie nur eine Loesung der zweiten Wahl.
Zweite Wahl mag manchmal ausreichend sein, aber nicht immer. Hinzu kommt
das Leute die es sich angewoehnen immer nur die zweite Wahl zu verwenden
niemals die Faehigkeiten entwickeln selber etwas auf die Beine zu
stellen. Ich sehe ja sogar oft Leute welche die Libaries anderer Leute
verwenden die derart dumme Fragen stellen das klar ist das sie da noch
nicht mal versucht haben reinzuschauen, vom echten Verstaendnis sind sie
dann noch meilenweit entfernt. Das schafft dann auch irgendwie Probleme.
.-)
Olaf
Olaf schrieb:>> Sofern man unendlich viel Zeit hat sich mit Problemen zu beschäftigen,>> die andere schon vor Jahrzehnten gelöst haben, UND wenn die Hardware>> Du hast ein Verstaendnisproblem.
Ach ja, jetzt wird wieder selektiv zitiert... nein habe ich nicht. Ich
verstehe genau was Du meinst, und wie gesagt, wenn die Hardware
hinreichend einfach gestrickt ist, kann man mit halbwegs vertretbarem
Aufwand so einen Treiber auch noch in Assembler machen. Damals haben ein
Freund und ich unseren eigenen VGA Graphik-Treiber bzw. schnellen
Linienalgorithmus (Bresenham) für TopSpeed Modula 2 in Assembler auf dem
PC programmiert (1992?), weil das mitgelieferte Zeug von TopSpeed zu
lahm war für mein selbstgeschriebenes CAD-Programm.
Allerdings ist Dein Anspruch "ich mache alles selbst, alles ist besser
was ich mache!" nicht realistisch. Du hast wohl nicht verstanden, über
wieviele Abstraktionsebenen wir heutzutage operieren. Ohne Abstraktion
geht GAR NIX mehr heutzutage. D.h., Libraries und Layers and Layers and
Layers and Layers of abstraction. Für triviales Zeug braucht man das
nicht, da gebe ich Dir Recht!
Es war nicht meine Absicht, Deinen Treiber schlecht zu machen. Deine
Aussage in dieser Allgemeinheit ist allerdings Müll.
Wie gesagt, der ANSPRUCH hinter die Dinge auf der untersten Ebene zu
schauen, und selbst einen kleinen Treiber in Assembler für ein nicht
sehr kompliziertes Device zu schreiben, ist sicherlich ehrenwert. Aber
SKALIERBAR für ECHTE SYSTEME is dieser Vorgehen bzw. Anspruch - mit
vertretbarem Zeitaufwand für Projekte in der Praxis - eben nicht.
Lobenswert ist es natürlich, es dennoch zu machen. Würde ich meine Zeit
lieber in etwas anderes stecken? Bestimmt :-)
@Steffen,
Danke für Dein Testprogramm, es funktionierte auf Anhieb.
Was mich wunderte, der ATmega328p scheint schon total vollgepackt zu
sein, bleibt da noch Platz für weiteres, oder ist das nur der
OLED-Treiber?
Mit Deinem Test-Programm konnte ich mich noch nicht beschäftigen, hab's
aber schon auf dem Radar.
Kannst Du uns mal ganz grob erklären, wie ein farbiger Balken entsteht,
schließlich müssen die Farbwerte auch mit übertragen werden.
Danke
Steffen H. schrieb:> Wenn du diesen mit nur> 3,3V und 8MHz betreibst, sollte das doch auch ohne Level Shifter gehen.
Notfalls ist dieser durch Widerstände schnell zusammengefriemelt.
Vorsichtshalber werde ich an das Display eine 3,3V Z-Diode anschließen,
es könnte ev. sein, daß der AVR-Rogrammer über SPI eine Spannung über
SPI einspeist, wie empfindlich der SSD1351 ist, kann ich nicht
einschätzen.
Olaf schrieb:> Dann macht man einen Ticker-IRQ und sorgt dafuer das alle 5ms ein> Segment uebertragen wird wenn es sich geaendert haben sollte. Dadurch> hat man in der Praxis kaum Datenuebertragung zum Display da sich selten> viel aendert und trotzdem wirkt das Display extrem responsiv.
Ein sehr guter Tipp :-)
Damit befindet sich zwar der µC eine gewisse Zeit in der
Interrupt-Routine, aber für einige Anwendungen sicherlich gut geeignet.
PS: Wer Assembler, klein und verdammt schnell, nicht mag, kein Problem
<ALT+F4> hilft garantiert ^^
Bernhard S. schrieb:> Linienberechnung:> Zuerst wird untersucht, ob es senkrechhte oder waagerechte Linen sind,> diese lassen sich sehr flott berechnen.>> Bei den schrägen linien wirds komplizierter, hier untersuche ich den> Anstieg, ob positiv oder negativ. Anschließend wird die Linie 2x> gezeichnet, beim ersten Durchgang wird X hochgezählt und Y berechnet,> beim zweiten Y hochezählt und X berechnet, damit auch sehr flache und> sehr steile Linien ohne Lücken gezeichnet werden, sonnst sieht etwas> komisch aus.
Da würde ich Dir den Bresenham empfehlen. Auch da braucht man das Rad
nicht neu erfinden (und schneller als da geht's auch nicht...):
https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm>> von Olaf (Gast)> Du hast ein Verstaendnisproblem. Andere haben vor Jahrzehnten genau ihr> Problem geloest. Fuer dich haben sie nur eine Loesung der zweiten Wahl.
Ist das so? Wahrscheinlich ist das so eine Art Geheim-Wissenschaft, wie
man den Bresenham in Assembler implementiert?
Michael W. schrieb:> Da würde ich Dir den Bresenham empfehlen.
Erklär uns mal bitte einfach diesen Algorithmus.
An einer ganz flachen Linie: Linie X1,Y1=0,0 nach X2,Y2=127,1
Vielleicht ist dann die Umsetzung in ASM gar nicht so schwer.
Würde mich interessieren.
Bernhard S. schrieb:> Michael W. schrieb:>> Da würde ich Dir den Bresenham empfehlen.>> Erklär uns mal bitte einfach diesen Algorithmus.>> An einer ganz flachen Linie: Linie X1,Y1=0,0 nach X2,Y2=127,1>> Vielleicht ist dann die Umsetzung in ASM gar nicht so schwer.>> Würde mich interessieren.
1
x0 = 0
2
y0 = 0
3
4
x1 = 127
5
y1 = 1
6
7
abs(y1 - y0) = 1
8
abs(x1 - x0) = 127
9
10
plotLine(x0, y0, x1, y1)
11
if abs(y1 - y0) < abs(x1 - x0)
12
if x0 > x1
13
plotLineLow(x1, y1, x0, y0)
14
else
15
plotLineLow(x0, y0, x1, y1)
16
************************** HIER GEHTS WEITER!
17
end if
18
else
19
if y0 > y1
20
plotLineHigh(x1, y1, x0, y0)
21
else
22
plotLineHigh(x0, y0, x1, y1)
23
end if
24
end if
25
26
27
Also:
28
29
plotLineLow(x0, y0, x1, y1)
30
dx = x1 - x0 = 127
31
dy = y1 - y0 = 1
32
yi = 1
33
/*
34
if dy < 0
35
yi = -1
36
dy = -dy
37
end if
38
*/
39
D = (2 * dy) - dx = 2 - 127 = - 125
40
y = y0 = 0
41
42
for x from 0 to 127
43
plot(x, y)
44
if D > 0
45
// y = y + yi
46
// D = D + (2 * (dy - dx))
47
y = y + 1
48
D = D + 2 * ( 1 - 127 ) = D + 2 * - 126 = D - 254
49
end if
50
else
51
// D = D + 2*dy
52
D = D + 2
53
54
D.h., nach x + 63 Schritten wird von plot(x, 0) auf plot(x, 1) "umgeschaltet".
55
56
Also:
57
58
von x = 0 bis 63: plot(x,0)
59
von x = 63 bis 127: plot(x,1)
60
61
(Toleranz: +/-1 ) ;-) :-D
Interessant ist nun natürlich, wie Du die horizontalen Segmente
plot(x,0) und plot(x,1) in DrawLine umsetzt... mit BlockMove / Copy oder
was auch immer ;-) Auf dem Z80 nahm dafür dann die BlockMove Befehle
wenn ich mich recht erinnere um ohne explizite Schleife auszukommen etc.
Also wie man Linien in der Rastergrafik zeichnet ist nach Bresenham
überall, Wikipedia, YouTube, u.s.w wirklich sehr gut beschrieben und
erklärt. Und das sogar auf Deutsch!
;)
https://www.youtube.com/watch?v=vlZFSzCIwoc&t=40s
Und hier ein Auszug aus meinem Assembler Code:
Bernhard S. schrieb:> Danke für Dein Testprogramm, es funktionierte auf Anhieb.
Bitte schön
Bernhard S. schrieb:> Was mich wunderte, der ATmega328p scheint schon total vollgepackt zu> sein, bleibt da noch Platz für weiteres, oder ist das nur der> OLED-Treiber?
Ja, ein mächtiger OLED Treiber womit man auch viel machen kann. Aber
voll ist der ATmega328 noch nicht.
17114 Bytes Flash (53%)
683 Bytes RAM (33%)
Bernhard S. schrieb:> Kannst Du uns mal ganz grob erklären, wie ein farbiger Balken entsteht,> schließlich müssen die Farbwerte auch mit übertragen werden.
Man schreibt die Pixeladresse pixelgenau an das Display und dann ein
Write zum DRAM Command gefolgt von 2 Datenbytes für jeden Pixel (RGB555
Farbwert). Der interne Adresszähler des DRAM wird nach jedem Pixel
hochgezählt.
Steffen H. schrieb:> Und hier ein Auszug aus meinem Assembler Code:
Sehr gut, wie von der Wikipedia-Seite bzw. aus dem Lehrbuch! Also doch
keine Geheimwissenschaft :-)
@Steffen
ich würde gern zur SSD1351 Initialisierung einen separaten Beitrag
verfassen, vorausgesetzt Du stimmst dem zu, da ich sehr viel
Assembler-Code aus Deinem Programm nutze.
Danke
Bernhard S. schrieb:> @Steffen> ich würde gern zur SSD1351 Initialisierung einen separaten Beitrag> verfassen, vorausgesetzt Du stimmst dem zu, da ich sehr viel> Assembler-Code aus Deinem Programm nutze.>> Danke
Kein Problem, kanst machen.