Hallo,
ich habe eine 16x16 LED Matrix, welche auch wunderbar schon seit einiger
Zeit funktioniert. Der AVR spielt Snake auf der Matrix und in gewissen
Abständen wird ein Text eingeblendet. Zeichen für Zeichen. Soweit alles
gut.
Ich möchte nun aber nicht mehr den Text Zeichen für Zeichen nacheinander
ausgeben, sonder als Laufschrift. Leider bekomme ich es überhaupt nicht
geschissen. Mir gehn die Ideen aus.
Hier die Funktion der ein String übergeben wird:
Ingo Less schrieb:> Kann mir mal jemand n Tip geben wie man das am geschicktesten anstellt?
Du musst dich von der Denkweise lösen, dass du Text ausgibst. D.h.
natürlich gibst du Text aus, aber nur bis in eine
Softwarezwischenschicht. Dort wird der Text als Pixel in ein 'Bild'
gemalt und was du wirklich ausgibst, das ist dieses Bild, dass du Spalte
für Spalte durch die Anzeige scrollst.
Ein anderer Ansatz besteht darin, an der Anzeige nicht mit fixen
Buchstabenpositionen zu operieren (der erste Buchstabe kommt an die
Spalte 0, der zweite kommt an die Spalte 8, der dritte an die Spalte 16,
etc.) sondern mit Sub-Buchstaben Positionen. Im Moment seh ich aber noch
nicht, wie man das einfach in deine Routine einbauen könnte. Dein putc
müsste hier noch einen Offset mitkriegen, der angibt um wieviele
Pixelspalten der Buchstabe verschoben auszugeben ist
1
voidMatrix_Putc(unsignedintc,intOffset)
und ich denke mal, dieser Offset müsste hier
1
Matrix.Snake.Field[i+j]=....
in irgendeiner Form mit eingehen.
1
Matrix.Snake.Field[i+j+Offset]=....
Beim Aufruf, dann 8 mal dieselben 2 aufeinanderfolgenden Buchstaben
ausgeben, mit einem Offsetwert von 7 bis 0 (bzw. für den ersten
Buchstaben von 0 bis -7), wobei du natürlich komplett ausserhalb des
sichtbaren Bereichs liegende Spalten gar nicht ausgibst, und dann erst
auf den nächsten Buchstaben weiterschalten.
Also wenn du genug Speicher hast, dann mach dein Array mit dem
Matrixinhalt größer als die Anzeige, rotier da mit den Indizes drüber
und änder immer den Teil der grade nicht sichtbar ist.
Hier am Bsp. von 4x4 pixeln
0110x
1001x
1001x
0110x
\ / |------ Hier schreiben wir neu
\/
Wird angezeigt
Noch einfach wird es wenn du doppelt so viel Platz lässt und immer den
verdeckten Buchstaben austauschst. Gerade mit 16 px ist der wraparound
dann praktischerweise bei 32.
Ich gebs voresrt auf. Bei der Bitschieberei bekomme ich n Knoten im
Kopf. Mit dem Offset klappt auch nicht wie ich das will. Dummerweise
muss ich mein eigenes Programm erstmal wieder verstehen, weil ich es
natürlich auch super dokumentiert hab, wie immer :(
mach das am besten so, dass du zuerst mal definierst wie lange deine
Laufschrift maximal ist.
Dann definierst du ein Array mit Grösse = max Anzahl Buchstaben x 16.
Dann definierst du 2 Variablen ( Textlänge + Startposition)
Du brauchst dann eine Funktion, die dir deinen String quasi Buchstaben
für Buchstaben ins Array einfüllt also dirrekt die Bitmuster
Für die Ausgabe hast du dann Halt immer ein sichtbares Fenster von 16
Spalten welche sichtbar sind. Jetzt kommen die beiden Variablen
Textlänge und Startposition zum zug. Du gibst dann halt immer das
aktuelle Fenster von deinem Array aus... wenn du du mit deiner
Laufschrift am Anfang bist ist Startposition = 0, daher du gibst die
ersten 16 Stellen aus deinem Array auf dem Display aus. Wenn du die
ausgegeben hast, incrementierst du Startposition. Beim nächsten aufruf
ist ja dann Startposition nicht mehr 0 sondern 1... damit gibst du dann
quasi die Felder 1-16 aus. Nach der Ausgabe incrementierst du
Startposition wieder um 1... das machst du solange bis Startposition =
Textlänge x 16 ist. Also du alle Buchstaben ausgegeben hast. Und dann
kannst du entweder wieder den ersten Buchstaben langsam einlaufen
lassen, oder halt direkt wieder Startposition auf 0 setzen. Ich hoffe
meine erklärung ist verständlch.
Gruss Bastler
Hallo,
danke erstmal für die vielen Antworten. Ich habe es jetzt mit einer
zweiten Buffermatrix gelöst, in welcher ich die Zeichen speichere und
dann in die anzuzeigende Matrix kopiere (den sichtbaren Teil). Garnnicht
so einfach.
Aber funktioniert soweit. Was ich jetzt noch machen muss, ist den
Zeichenabstand zu verkürzen. Jedoch hab ich noch keinen Plan wie.
Warum ich allerdings mit "Counter" den Zeichenabstand einstellen kann
ist mir im Moment noch überhaupt nicht klar... So wie es jetzt ist habe
ich 2 Pixel Zeichenabstand, warum auch immer...
@ Ingo Less (corrtexx)
>So wie es jetzt ist wird jedes Zeichen nacheinader einzeln ausgegeben.>Der Font ist 8 LEDs breit und 16 hoch. Hier mal ein Auszug für ein "A":>/* char = 0x41 */>0x00, /* ........ */>0x00, /* ........ */>0x18, /* ...OO... */>0x18, /* ...OO... */>0x3c, /* ..OOOO.. */>0x24, /* ..O..O.. */>0x66, /* .OO..OO. */>0x6e, /* .OO.OOO. */>0x7a, /* .OOOO.O. */>0xe3, /* OOO...OO */>0xc3, /* OO....OO */>0xc3, /* OO....OO */>0x00, /* ........ */>0x00, /* ........ */>0x00, /* ........ */>0x00, /* ........ */
Vor Ewigkeiten habe ich mal ne Propelleruhr gebaut, dort war auch eine
Laufschrift drin, welche pixelweise scrollte. Dort habe ich aber einfach
den Zeichensatz nicht zeilenweise, sondern spaltenweise gespeichert!
Damit ist es geradezu trivial, eine pixelweise Verschiebung vorzunehmen.
Denn man muss nicht mit Bitmanipulation hantieren, sondern die
Spalten der Laufschrift sind ganze Bytes, bei dir wären es 16 Bit Worte.
Das ist deutlich einfacher und schneller! Ausserdem muss man keine
Zeichen echt verschieben, sondern verschiebt nur die Anzeige. D.h. EIn
Puffer enthält vielleicht 32 Spalten, wovon nur 16 angezeigt werden.
Jetzt verschiebt man langsam die Startspalte der Anzeige. Wenn man in
der Mitte angekommen ist, zwird somit das 2. Zeichen angezeigt. Jetzt
muss man, natürlich "unsichtbar" beim nächsten Schritt die Laufschift um
1 volles Zeichen verschieben und mit der Anzeige wieder bei Spalte 0
anfangen.
Eine 1. Möglichkeit wäre auch, den Zeiger über den Zwischenpuffer
überlaufen zu lassen, und damit ein Art unendlichen Puffer zu erzeugen.
Dann muss man nicht mal das Umkopieren machen, sondern immer nur neue
Zeichen in den Puffer schreiben, mal an Position 1, mal an Position 2.
Sinn des Ganzen ist eine Deutliche Einsparung an CPU Last, clever ist es
ausserdem ;-)
>Kann mir mal jemand n Tip geben wie man das am geschicktesten anstellt?>Ich glaube so trivial ist das nicht :-(
Everything is easy if you know how!
Ingo Less schrieb:> Ich habe es jetzt mit einer> zweiten Buffermatrix gelöst, in welcher ich die Zeichen speichere und> dann in die anzuzeigende Matrix kopiere
Das ist die ineffiziente Variante. Eine effiziente ist den Zeiger auf
einen Speicherinhalt für die Anzeige zu verschieben. Da vermutlich die
Anzeige per INT abgearbeitet wird schiebt man einfach den Zeiger weiter
und "schiebt" damit die Anzeige quasi. Etwas Denksport aber durchaus
interessant.
Hallo,
Ne dieser zeitaufwendige Kram läuft im Hauptprogramm. Da das Ding gegen
sich selbst Snake spielt und ab und zu mal Text über die Anzeige
flimmern lässt ist alles OK. Ma gucken in ich nicht noch etwas optieren
kann.
Aber danke
@ Ingo (Gast)
>Ne dieser zeitaufwendige Kram läuft im Hauptprogramm.
Ist OK, aber warum soll man große Datenmengen kopieren, wenn es reicht,
zwei Pointer zu tauschen?
https://www.mikrocontroller.net/articles/Soft-PWM#Intelligenter_L.C3.B6sungsansatz
Nach dem Democode.
" Beachtet werden sollte hier die Datenübergabe von der Funktion
pwm_update() zur Interruptroutine. Hier werden jeweils zwei Zeiger
verwendet, um auf Arrays zu zeigen. . . . ."