Ich nutze die LVGL-library zur Grafikdarstellung auf einem 1.5" Oled-Display. Kurz zusammengefasst: Das Display mit SSD1351-Controller hat 128x128 Pixel, jedes Pixel belegt 2 Bytes im RGB565-Format. Es wird von einem ESP32 gesteuert, der das Display über SPI mit Daten füttert. Initialisierungs- und Flushroutine habe ich selbst geschrieben und funktionieren auch soweit. Allerdings werden völlig falsche Farben dargestellt. Die Ursache ist, dass LVGL die 16-bit Pixelwerte im Little-Endian-Format mit low-Byte voran im Framebuffer ablegt, das Display sie aber als Big-Endian haben will, also high-Byte zuerst. Dies ist in der Doku von LVGL auch beschrieben: "You may set LV_COLOR_16_SWAP in lv_conf.h to swap bytes of RGB565 colors. You may need this when sending 16-bit colors via a byte-oriented interface like SPI. As 16-bit numbers are stored in little-endian format (lower byte at the lower address), the interface will send the lower byte first. However, displays usually need the higher byte first. A mismatch in the byte order will result in highly distorted colors." Leider gibt es LV_COLOR_16_SWAP als Konfigurationsoption anscheinend nicht mehr. Wie mache ich das Vertauschen der Bytes dann? In der flush-Routine ist das leider nicht möglich, da LVGL oft nur Teile des Framebuffers neu beschreibt und ich daher für jedes einzelne Pixel Buch führen müsste, ob es schon getauscht wurde oder nicht.
:
Bearbeitet durch User
Fritz G. schrieb: > Little-Endian-Format sicher? meine Falschfarben bei TFT kamen vom GRB statt RGB Format. Fritz G. schrieb: > ich daher für jedes einzelne Pixel Buch > führen müsste woran klemmts, am Speicher?
Fritz G. schrieb: > Wie mache ich das Vertauschen der Bytes dann? Vertausche deine Eingangsdaten (Bilder). Das löst aber nicht das Problem, wenn du einzelne Punkte, Linei etc. zeichnen willst. > In der > flush-Routine ist das leider nicht möglich, da LVGL oft nur Teile des > Framebuffers neu beschreibt und ich daher für jedes einzelne Pixel Buch > führen müsste, ob es schon getauscht wurde oder nicht. Du muss die Vertauschung beim Schreiben auf das Display machen, wenn die aten per SPI gesendet werden. Dann ist ALLES korrekt.
Falk B. schrieb: > Vertausche deine Eingangsdaten (Bilder). Das löst aber nicht das > Problem, wenn du einzelne Punkte, Linei etc. zeichnen willst. Richtig, insbesondere bei Text sieht es blöd aus. R mit B zu vertauschen (das kann der Display-Controller) ist auch nicht zielführend, denn aus RRRRRGGG GGGBBBBB wird GGGBBBBB RRRRRGGG. Die Farben werden also nicht nur vertauscht, sondern auch gemischt. > Du muss die Vertauschung beim Schreiben auf das Display machen, wenn die > aten per SPI gesendet werden. Dann ist ALLES korrekt. Nach etwas Suchen habe ich die Funktion
1 | lv_draw_sw_rgb565_swap
|
gefunden, die alle Bytes im Framebuffer vertauscht. Damit funktioniert es. LVGL scheint beim Rendern immer den kompletten Frame neu zu schreiben. Ich hätte gedacht, dass z.B. bei der Änderung weniger Pixel nur Teile davon geändert werden.
:
Bearbeitet durch User
Fritz G. schrieb: > für jedes einzelne Pixel Buch > führen müsste sind doch nur 32768 Byte, mit aktuellen µC (z.B. ESP32) sollte das möglich sein
https://github.com/lvgl/lvgl/blob/1e2261683e23fcb7e472a4baef3c4ebb2225d794/src/core/lv_refr.c#L1404 Das sollte dein Problem erst einmal lösen, und auch einen Hinweis drauf geben, wie das eigentlich in der aktuellen Version gehandelt wird. Oliver
:
Bearbeitet durch User
Was für eine Version hast du denn genau von LVGL. Teilweise schreiben sie das die Funktion wieder dazu kam und man nur das define setzen müsse: https://github.com/lvgl/lvgl/issues/6317 Bzw in der letzten Version (9.3) schreiben sie in der Doku man solle die Funktion lv_draw_sw_rgb565_swap(buf, buf_size_in_px) in seinem Flush Callback oder evtl Hardware nutzen um zu Swappen: https://docs.lvgl.io/9.3/details/main-modules/display/color_format.html#swapping-endian-ness Edit: zu spät 😄
:
Bearbeitet durch User
N. M. schrieb: > Was für eine Version hast du denn genau von LVGL. > Teilweise schreiben sie das die Funktion wieder dazu kam und man nur das > define setzen müsse: > https://github.com/lvgl/lvgl/issues/6317 Ich habe die neueste Version 9.3. Warum sie die Option aus der Konfiguration geworfen haben, erschließt sich mir nicht. Es gibt doch viele Farbdisplays mit SPI oder I2C-Interface. > Bzw in der letzten Version (9.3) schreiben sie in der Doku man solle die > Funktion > lv_draw_sw_rgb565_swap(buf, buf_size_in_px) > in seinem Flush Callback oder evtl Hardware nutzen um zu Swappen: > > https://docs.lvgl.io/9.3/details/main-modules/display/color_format.html#swapping-endian-ness Leider funktioniert das nur eingeschränkt. Setze ich z.B. einen neuen Text in ein Label, wird nur das vom Label belegte Rechteck neu gerendert und es zerschießt ie Grafik. Nur wenn der Framebuffer komplett neu gezeichnet wird, funktioniert es. Das geht natürlich auf die Performance. In meiner Anwendung mit 128x128 Pixeln und einer Handvoll Widgets ist das allerdings kein Problem.
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.