Forum: Mikrocontroller und Digitale Elektronik littlevGL Graphiclib, benutzt die hier jemand?


von Johannes S. (Gast)


Angehängte Dateien:

Lesenswert?

https://littlevgl.com/
wurde hier schonmal erwähnt, 
Beitrag "Re: LCD Displays, die Qual der Wahl :-("
Jetzt habe ich das mal in mein STM32F407 'Black' board reingehackt, 
sieht schon ganz gut aus. Das bringt schon eine Menge Widgets mit um 
irgendwelche Gerätchen zu bedienen, ist gut dokumentiert und Code ist 
auf github.
Die Portierung ist noch nicht fertig, ich konnte aber recht schnell 
fertige Screens aus dem Tutorial oder der Demo anzeigen.
Benutzt das hier noch jemand?

von Sebastian T. (labude)


Lesenswert?

Moin,

ich versuche mich gerade an der selben Kombination.

Die Ansteuerung des Displays und das Schreiben einzelner Pixel 
funktioniert ohne Probleme mit ensprechenden Funktionen.

Ich scheiter aber dabei die Funktion zum Pixelarray schreiben zu 
implementieren. Darf ich da um Hilfestellung bitten.

von Johannes S. (Gast)


Lesenswert?

dazu müsstest du einfach mal deinen Code für den Displaytreiber hier 
reinstellen.

von Sebastian T. (labude)


Angehängte Dateien:

Lesenswert?

Hallo Johannes

Danke erstmal für die schnelle Reaktion. Ich verwende den Code von 
diesem Tutorial:
https://www.youtube.com/watch?v=NUErX4dx2Tw
nur halt angepasst für das 16-bit aufsteck Panel.

Das funktioniert auch soweit. Nur wenn ich die Routine zum Pixel 
schreiben so umsetze wird das ganze etwas langsam. Der ganze FSMC 
Geschwindigkeitsvorteil geht damit verloren.

Außerdem funktioniert mein XPT2046 Treiber noch nicht wirklich (ist 
ebenfalls sehr langsam).

von Johannes S. (Gast)


Lesenswert?

ja, der Code ist ok aber durch das setPixel wird das langsam. Beim ILI 
kann man ein Fenster setzen und dann einfach alle Pixel rausfeuern. 
Müsste auch mit DMA gehen, habe ich aber auch noch nicht umgesetzt.
1
volatile uint16_t *ili9341_fsmcCommand;
2
volatile uint16_t *ili9341_fsmcData;
3
4
void LVGLDispSTM32F407VE_BLACK::disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
5
{
6
    int32_t x;
7
    int32_t y;
8
    ili9341_fsmc_setAddrWindow(area->x1, area->y1, area->x2, area->y2);
9
    *ili9341_fsmcCommand = ILI9341_MEMORYWRITE; // 0x2c
10
    for (y = area->y1; y <= area->y2; y++) {
11
        for (x = area->x1; x <= area->x2; x++) {
12
            *ili9341_fsmcData = color_p->full;
13
            color_p++;
14
        }
15
    }
16
17
    /* IMPORTANT!!!
18
     * Inform the graphics library that you are ready with the flushing*/
19
    lv_disp_flush_ready(disp_drv);
20
}

Die Namen für fsmcCommand/fsmcData werden bei dir anders sein, die musst 
du aus dem FSMC Teil rausholen und public machen. Dazu brauchst du noch 
setAddrWindow Kommando. Müsste auch schon irgendwo in deinem Code sein, 
ansonsten:
1
extern volatile uint16_t *ili9341_fsmcCommand;
2
extern volatile uint16_t *ili9341_fsmcData;
3
4
#define lcdCommand (*ili9341_fsmcCommand)
5
#define lcdData    (*ili9341_fsmcData)
6
7
#define writeCmd(d)  { lcdCommand = d; }
8
#define writeData(d) { lcdData = d; }
9
10
static void writeRegister8(uint16_t a, uint8_t d)
11
{
12
  writeCmd(a);
13
  writeData(d&0x00FF);
14
}
15
16
static void writeRegister32(uint16_t r, uint32_t d)
17
{
18
  writeCmd(r);
19
  writeData((d >> 24));
20
  writeData((d >> 16)&0x00FF);
21
  writeData((d >> 8)&0x00FF);
22
  writeData(d&0x00FF);
23
}
24
25
void ili9341_fsmc_setAddrWindow(int16_t x1, int16_t y1, int16_t x2, int16_t y2)
26
{
27
    writeRegister32(ILI9341_COLADDRSET, ((uint32_t)(x1 << 16) | x2));
28
    writeRegister32(ILI9341_PAGEADDRSET, ((uint32_t)(y1 << 16) | y2));
29
}

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Hmm,
> 17.10.2019
dann wird auchnoch auf mich verlinkt und ich habs bis heute nicht 
gesehen.

Bisher habe ich nur vor mit littlegl mal zu arbeiten.
Wenn ich dann mal meine Universal UI anfange für meine zukünftigen 
Projekte.
Bei meinem Wirkleistungsmessgerät hab ich das noch selber gemacht um mal 
zu gucken wie sich sone Eigenbau GUI Lib schreibt mit Widgets und co.
Aber das macht echt kein Spaß und verkommt zur Zeitverschwendung.
ZUdem sieht das dann noch schlimmer aus als Win95 ;)

Johannes S. schrieb:
> Beim ILI
> kann man ein Fenster setzen und dann einfach alle Pixel rausfeuern.
> Müsste auch mit DMA gehen, habe ich aber auch noch nicht umgesetzt.

MUSS man sogar machen bei den Displays die weniger Pixel haben als der 
Controller.
So wie bei dem 240x240px fürn schmalen Taler, denn der Controller ist 
für 320x240.

Was haste denn bisher damit gebaut?

von Johannes S. (Gast)


Lesenswert?

Mw E. schrieb:
> MUSS man sogar machen bei den Displays die weniger Pixel haben als der
> Controller.

? Nein, es geht ohne DMA. lvgl verwaltet einen virtuellen Screen und 
erkennt welche Bereiche gezeichnet und dann aktualisiert werden müssen. 
Dazu reicht ein Buffer welcher nur min. 10*Breite groß sein muss. Wenn 
der µC genügend RAM hat kann man auch einen kompletten Framebuffer oder 
gar einen double Buffer anlegen. Auch GPU beschleunigtes Zeichnen ist im 
Treiber vorgesehen (geht dann mit dem ST DMA2D ganz fix).

Ich habe bisher die Treiber für Mbed angepasst und eine einfache GUI für 
Schrittmotortests gemacht. Bin jetzt aber zu Ethernet abgedriftet und 
die Grafik lag erstmal still.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Na das war jetzt auf SPI + DMA + ILI und LCD px < Controller px bezogen.
Wenn du dann ein zweites (ganzes) Bild per DMA übertragen willst landet 
das ja dann um 80px Versetzt auf dem LCD.

Beim Teilübertragen des Bildes mit der Lib ist das natürlich etwas 
anders.

von Sebastian T. (labude)


Lesenswert?

Vielen Dank erstmal. Das sieht auf jeden Fall viel übersichtlicher aus 
als bei mir. Ich hab das alles sehr verschachtelt:
1
void my_disp_flush(lv_disp_t * disp, const lv_area_t * area, lv_color_t * color_p)
2
 {
3
     int32_t x, y;
4
     for(y = area->y1; y <= area->y2; y++) {
5
         for(x = area->x1; x <= area->x2; x++) {
6
             set_pixel(x, y, *color_p);  /* Put a pixel to the display.*/
7
             color_p++;
8
         }
9
     }
10
11
     lv_disp_flush_ready(disp);         /* Indicate you are ready with the flushing*/
12
 }
13
14
void set_pixel(int x,int y,int color_p)
15
{
16
  ILI9341_DrawPixel(x, y, color_p);
17
}
18
19
20
void ILI9341_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
21
  ILI9341_SetCursorPosition(x, y, x, y);
22
    ILI9341_SendData(color);
23
}
24
25
void ILI9341_SetCursorPosition(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
26
27
  ILI9341_SendCommand (ILI9341_COLUMN_ADDR);
28
  ILI9341_SendData(x1>>8);
29
  ILI9341_SendData(x1 & 0xFF);
30
  ILI9341_SendData(x2>>8);
31
  ILI9341_SendData(x2 & 0xFF);
32
33
  ILI9341_SendCommand (ILI9341_PAGE_ADDR);
34
  ILI9341_SendData(y1>>8);
35
  ILI9341_SendData(y1 & 0xFF);
36
  ILI9341_SendData(y2>>8);
37
  ILI9341_SendData(y2 & 0xFF);
38
  ILI9341_SendCommand (ILI9341_GRAM);
39
}
40
41
void ILI9341_SendData(uint16_t data)
42
{
43
  *(__IO uint16_t *)(0x60080000) = data;
44
}


Kannst Du mir noch für das Touch Panel einen Hinweis geben. Das ist bei 
mir wahnsinnig ungenau. Nicht nur die X/Y Position, sondern auch der 
Z-Wert. Kalibrierst Du das und machst eine Art Mittelwert, oder was kann 
man da machen...?

von Johannes S. (Gast)


Angehängte Dateien:

Lesenswert?

der Code für den Touchscreen ist im wesentlichen aus dem lvgl 
Beispielcode. Darin wird ein Mittelwert über 4 gelesene Werte als 
Standard gemacht. Es gab in dem Beispiel einen Fehler im return code, 
den hatte ich gemeldet und als PR in das github Repo eingebracht. War 
vor 4 Monaten, seitdem ist da auch nichts geändert worden. Für lvgl6, 
mittlerweile ist ja schon v7 in Arbeit.
https://github.com/littlevgl/lv_drivers/tree/master/indev

Die Kalibrierwerte für den screen habe ich empirisch ermittelt, dazu 
hatte ich die Rohwerte in die lv_indev_data_t struktur geschrieben damit 
ich die auslesen kann (im raw member). Ist aber unschön weil die org Lib 
geändert wird. Es gibt aber auch irgendwo eine Kalibrierroutine, die 
habe ich aber noch nicht angesehen.
Die Kalibrierwerte als Konstanten sollten auch nur als Initwerte dienen, 
können ja bei anderen touchs anders sein. Aber wie gesagt, die lib ist 
bei mir auch noch nicht ganz fertig.
1
#define XPT2046_HOR_RES     320
2
#define XPT2046_VER_RES     240
3
#define XPT2046_X_MIN       200
4
#define XPT2046_Y_MIN       260
5
#define XPT2046_X_MAX       3750
6
#define XPT2046_Y_MAX       3860
7
#define XPT2046_INV         0
8
9
#define XPT2046_XY_SWAP     0
10
#define XPT2046_X_INV       1
11
#define XPT2046_Y_INV       1
12
13
14
** Data structure passed to an input driver to fill */
15
typedef struct
16
{
17
    lv_point_t point; /**< For LV_INDEV_TYPE_POINTER the currently pressed point*/
18
    lv_point_t raw;   /**< For LV_INDEV_TYPE_POINTER the raw data point*/
19
    uint32_t key;     /**< For LV_INDEV_TYPE_KEYPAD the currently pressed key*/
20
    uint32_t btn_id;  /**< For LV_INDEV_TYPE_BUTTON the currently pressed button*/
21
    int16_t enc_diff; /**< For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/
22
23
    lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/
24
};

Sebastian T. schrieb:
> Ich hab das alles sehr verschachtelt:

das mit vielen Pixeln multipliziert macht sehr viel aus...
Im Demo Code kann man den Screen mit dem Finger hin- und herschieben, 
das folgt quasi dem Finger direkt ohne Ruckeln.

von Sebastian T. (labude)


Lesenswert?

ich werd mal meinen Code aufräumen und die XPT2046 Routine überarbeiten. 
Das mit den Festen Werten fürs Kalibrieren find ich nicht so dramatisch, 
weil man das ja nur einmal einstellen muss und wenn man das bei jedem 
Start neu Kalibrieren muss nervt das vermutlich.

Ansonsten find ich dieses Board nicht verkehrt. Mal sehen was sich damit 
noch  alles anstelllen lässt...

von Johannes S. (Gast)


Lesenswert?

Sebastian T. schrieb:
> Ansonsten find ich dieses Board nicht verkehrt. Mal sehen was sich damit
> noch  alles anstelllen lässt...

hier wird das auch verwendet:
Beitrag "STECCY - ZX-Spectrum-Emulator mit STM32"
aber mit 7" Display (was etwas aufwändiger anzuschliessen ist)

Ich benutze das mit Mbed, die SD Karte und der SPI Flash funktionieren 
da auch. Mit einem zusätzlichen PHY Board kann das Dingen auch Ethernet. 
So ein LAN8720 Phy bekommt man für 5€ beim Chinesen. Allerdings muss man 
da mit der Belegung aufpassen, das RMII Interface überschneidet sich da 
mit ein paar Leitungen für den TS.

von Vincent H. (vinci)


Lesenswert?

Kanns sein dass manche Widgets die in der Doku drin stehen nicht 
existieren?

So etwa das "Gauge" Widget:
https://docs.lvgl.io/latest/en/html/widgets/gauge.html#

Nicht einmal im "dev" Zweig ist Code davon zu finden...?

/edit
ah ok, Doku is veraltet
v8.0.0 (01.06.2021)
- `lv_meter` added as the unioin of `lv_linemeter` and `lv_gauge`

/edit2
Ach nein doch nicht. Ich bin nur zu blöd die richtige Version der Doku 
auszuwählen.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.