Hallo zusammen Ich hoffe alle hatten/haben frohe Ostern. Ich sitze nun seit stunden an einem Problem und habe den Faden inzwischen komplett verloren. Folgende Ausgangslage: Es gibt ein Bytearray namens uint8_t ScreenBuffer[1024]; Dieser repräsentiert mein Display welches 128x64 Pixel hat. Das Display ist in 8 Pages zu je 128Bytes aufgeteilt. Also in etwa so: P0 | | | |.... | | | | P1 | | | |.... | | | | . . . P7 | | | |.... | | | | Wobei ein | ein Byte ist. LSB ist oben MSB ist unten. Genau so interpretiere ich auch mein Array. Mein Font ist ebenfalls so orientiert, dass er mir die Fontdaten als "stehendes byte" angibt. Somit wäre es ideal, wenn ich direkt das Byte in meinen Buffer schreiben könnte. An eine beliebige x,und y stelle natürlich. Und hier beginnt das Problem. Ich schaffe es nicht, das Byte auf eine elegante, vernünftige Art und Weise in den Buffer zu schreiben. Weil ich irgendwie auf dem Schlauch stehe. Wenn sich das Byte innerhalb einer Page befindet, ist es ja noch ziemlich einfach. Sobald es sich aber auf zwei pages aufteil, muss ich das alte Byte auslesen, maskieren, die daten um den versatz schieben und mit dem alten verodern und schreiben. Dann die zweite Page einlesen, maskieren, daten schieben, verodern, schreiben.... Soviel zur theorie. Es kann auch sein, dass man nur einen bestimmten Bereich des Fontdatenbyte schreiben möchte, dann brauche ich eine Funktion, welcher ich eine maske übergeben kann um zu wählen welche daten ich brauche. Im Anhang ist mein Versuch es so zu lösen. Leider klappt das nicht und ich blicke nicht mehr durch. Ich hoffe jemand kann mir eine elegante Lösung vorschlagen oder Tipps geben. Danke schonmal.
@Holger Krähenbühl (holgerkraehe) >Es gibt ein Bytearray namens uint8_t ScreenBuffer[1024]; >Dieser repräsentiert mein Display welches 128x64 Pixel hat. >Das Display ist in 8 Pages zu je 128Bytes aufgeteilt. Dann sollte man das aber auch so in der Definition wiederfinden, uint8_t ScreenBuffer[8][128] >Wobei ein | ein Byte ist. > LSB ist oben MSB ist unten. ??? >Ich schaffe es nicht, das Byte auf eine elegante, vernünftige Art und >Weise in den Buffer zu schreiben. Weil ich irgendwie auf dem Schlauch >stehe. Wenn sich das Byte innerhalb einer Page befindet, ist es ja noch >ziemlich einfach. Wozu überhaupt die logische Einteilung in Pages? Sollte das nicht besser zeilenweise orientiert sein? Bei 128 Spalten macht das 16 Bytes/Zeile. Also so uint8_t ScreenBuffer[64][16] >Sobald es sich aber auf zwei pages aufteil, muss ich das alte Byte >auslesen, maskieren, die daten um den versatz schieben und mit dem alten >verodern und schreiben. Ja. >Ich hoffe jemand kann mir eine elegante Lösung vorschlagen oder Tipps >geben. Vergiss die Pages. Sturkturiere das Array zeilenorientiert. Dann übergibst man zur Zeichenausgabe die x/y Koordinaten und einen Zeiger auf das auszugebende Zeichen. Durch die Zeilenorientierung ist es einfach die Startzeile bzw. Adresse auszurechnen, denn die ist direkt nutzbar ;-). Bei der Spalte muss man rechnen, aber auch das ist einfach. Etwa so.
1 | void write_char(uint8_t *letter, uint8_t x, uint8_t y) { |
2 | uint8_t i, shift, mask; |
3 | |
4 | shift = x % 8; |
5 | x = x & 0x7; |
6 | mask = ~(0xFF >> shift); |
7 | |
8 | for(i=0; i<8; i++) { |
9 | if (shift==0) { // Zeichen exakt auf Bytegrenze, keine Maskierung nötig |
10 | ScreenBuffer[y+i][x] = letter[i] |
11 | } else { // Zeichen zwischen 2 Bytes, maskieren und verknüpfen |
12 | ScreenBuffer[y+i][x] = ScreenBuffer[y+i][x] & mask | |
13 | (letter[i]>>shift) & ~mask; |
14 | ScreenBuffer[y+i][x+1] = ScreenBuffer[y+i][x+1] & ~mask | |
15 | (letter[i]<<(8-shift)) & mask; |
16 | }
|
17 | }
|
18 | }
|
Siehe auch Bitmanipulation, dort gibt es ein paar Links auf Artikel mit Beispielen, auch wenn die dort nur eindimensional sind.
Anbei habe ich noch kurz ein PDF Erstellt, welches das ganze etwas verdeutlichen soll.
Vielen Dank Falk für deine Antwort. Falk B. schrieb: > Wozu überhaupt die logische Einteilung in Pages? Sollte das nicht besser > zeilenweise orientiert sein? Bei 128 Spalten macht das 16 Bytes/Zeile. > Also so Dies wäre mir auch lieber, das Problem ist, dass das Display mit Pages arbeitet. SSD1306 Controller. Ich schreibe den Buffer mit dem DMA automatisch per SPI zum Display. deshalb muss mein Buffer ebenfalls in Pages orientiert sein. Oder übersehe ich hier gerade etwas? Falk B. schrieb: > Bei der Spalte muss man rechnen, aber auch das ist einfach. > Etwa so. Vielen Dank für dein Beispiel. Ist das jetzt für ein Buffer mit Pages ala [8][128]? Falk B. schrieb:
1 | } else { // Zeichen zwischen 2 Bytes, maskieren und verknüpfen |
2 | ScreenBuffer[y+i][x] = ScreenBuffer[y+i][x] & mask | |
3 | (letter[i]>>shift) & ~mask; |
4 | ScreenBuffer[y+i][x+1] = ScreenBuffer[y+i][x+1] & ~mask | |
5 | (letter[i]<<(8-shift)) & mask; |
6 | }
|
Falls ja, müsste es im obigen code nicht y+i +1 sein anstelle von x +1? Denn Man muss ja die Page und nicht die Column wechseln Danke
@ Holger Krähenbühl (holgerkraehe) >Dies wäre mir auch lieber, das Problem ist, dass das Display mit Pages >arbeitet. SSD1306 Controller. Ich schreibe den Buffer mit dem DMA >automatisch per SPI zum Display. deshalb muss mein Buffer ebenfalls in >Pages orientiert sein. Oder übersehe ich hier gerade etwas? Ja. Man kann das auch trennen. Es ist ja im Endeffekt nur eine Berechungsweise für Adressen. Die sollte man so legen, das die Schreibzugriffe möglichst einfach und logisch erfolgen. >Ist das jetzt für ein Buffer mit Pages ala [8][128]? Nein, für [64][16]. Ich hab übersehen, daß du 7x12 Zeichen hast. Mein Beispiel ist für 8x8 Zeichen. Aber das Prinzip bleibt gleich. >Denn Man muss ja die Page und nicht die Column wechseln Das mit den Pages sollte man vermeiden! Sonst wird es zuviel Chaos!
Falk B. schrieb: > Nein, für [64][16]. Ich hab übersehen, daß du 7x12 Zeichen hast. Mein > Beispiel ist für 8x8 Zeichen. Aber das Prinzip bleibt gleich. Ich verwende sowieso unterschiedlich grosse und breite fonts. Dehslab würde ich dort einfach die jeweilige breite auslesen und verwenden. Das mit den [64][16] verwirrt mich jetzt ungemein. mir ist bewusst, dass es schlussendlich auch "nur" 1024bytes sind. Und man damit einfach anderst auf die Daten zugreifen kann. Jedoch erwartet das Display von mir die Bytes momentan wie im Bild im Anhang dargestellt. (rot markierter Bereich) Zuerst also 128Bytes für die erste Page. Dann die nächsten für die zweite usw... Ich sende mommentan mit dem DMA alle 1024Bytes in einem rutsch. Deshalb bin ich nach meine Verständnis an die Pages gebunden oder nicht? Wäre ich eventuell besser dran, wenn ich das DIsplay auf den Vertical Mode umstellen würde? Danke
@Holger Krähenbühl (holgerkraehe) >Ich verwende sowieso unterschiedlich grosse und breite fonts. >Dehslab würde ich dort einfach die jeweilige breite auslesen und >verwenden. Das macht die Sache aber nicht einfacher. Schreib erst einmal ein paar Funktion für einen gegbenen Font. Wenn das alles läuft und du es WIRKLICH verstanden hast, kannst du Funktionen für verschieden große Fonts schreiben. >Das mit den [64][16] verwirrt mich jetzt ungemein. Das war eine Annahme von mir. >mir ist bewusst, dass es schlussendlich auch "nur" 1024bytes sind. >Und man damit einfach anderst auf die Daten zugreifen kann. ?? Was soll man mit so einer Aussage anfangen? Willst du alles ala Turingmaschine programmieren? Viel Spaß! ;-) Der Sinn einer SINNVOLLEN Datenstruktur ist es ja eben, bestimmte Datenzuordnungen verständlich zu machen und leicht auf die Daten zugreifen zu können. >Jedoch erwartet das Display von mir die Bytes momentan wie im Bild im >Anhang dargestellt. (rot markierter Bereich) >Zuerst also 128Bytes für die erste Page. >Dann die nächsten für die zweite usw... Sicher, aber ich sehe da keinen nennenswerten Unterschied zu einer linearen Adressierung ohne Pages. >Deshalb bin ich nach meine Verständnis an die Pages gebunden oder nicht? Oder nicht. Was in dem Bild fehlt ist der Zusammenhang zwischen den Zeilen und den Daten, denn dein LCD hat sicher nicht nur 8 Zeilen ;-) >Wäre ich eventuell besser dran, wenn ich das DIsplay auf den Vertical >Mode umstellen würde? Nein.
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.
