Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with ESP32_S3 and ILI9488 16 bit-parallel display #540

Closed
Neothai opened this issue Mar 6, 2024 · 13 comments
Closed

Problem with ESP32_S3 and ILI9488 16 bit-parallel display #540

Neothai opened this issue Mar 6, 2024 · 13 comments

Comments

@Neothai
Copy link

Neothai commented Mar 6, 2024

Carefully written Issues are more likely to be given priority.
丁寧に記述された報告は優先して対応される可能性が高くなります。

Environment ( 実行環境 )

  • MCU or Board name: ESP32-S3
  • Panel Driver IC: ILI9488(Display Driver) with GT911(Touch Driver)
  • Bus type: Parallel 16bit
  • LovyanGFX version: 1.1.12
  • FrameWork version: ArduinoESP32 v2.0.14
  • Build Environment: ArduinoIDE
  • Operating System: Windows

Problem Description ( 問題の内容 )

I encountered an issue with an ILI9488 3.5 inch TFT display with an ESP32-S3 with LVGL version 9. I'm guessing the issue is caused by incomplete data sent in these lines of code.

void dispFlush(lv_display_t *disp, const lv_area_t *area, uint8_t * px_map){
  uint32_t w = ( area->x2 - area->x1 + 1 );
  uint32_t h = ( area->y2 - area->y1 + 1 );

  display.startWrite();
//=======================================================//
  display.setAddrWindow( area->x1, area->y1, w, h );     <---
  display.writePixels((lgfx::rgb565_t *)&px_map, w * h); <---
//=======================================================//
  display.endWrite();

  lv_display_flush_ready(disp);   
}

480x360px

error1.mp4

How to solve this problem?
Thank you very much!

Here's the full code

// basicSystemSetting.h File
#include <LovyanGFX.hpp>

#define TFT_HOR_RES   480
#define TFT_VER_RES   320

class LGFX : public lgfx::LGFX_Device
{
    lgfx::Panel_ILI9488 _panel_instance;
    lgfx::Bus_Parallel16 _bus_instance;
    lgfx::Touch_GT911 _touch_instance;

    public:
      LGFX(void){
      {
        auto cfg = _bus_instance.config();

        cfg.freq_write  = 40000000;
        cfg.pin_wr      = 48;
        cfg.pin_rd      = 11;
        cfg.pin_rs      = 47;

        cfg.pin_d0      = 1;
        cfg.pin_d1      = 2;
        cfg.pin_d2      = 12;
        cfg.pin_d3      = 4;
        cfg.pin_d4      = 5;
        cfg.pin_d5      = 6;
        cfg.pin_d6      = 7;
        cfg.pin_d7      = 10;
        cfg.pin_d8      = 14;
        cfg.pin_d9      = 15;
        cfg.pin_d10     = 16;
        cfg.pin_d11     = 17;
        cfg.pin_d12     = 18;
        cfg.pin_d13     = 21;
        cfg.pin_d14     = 38;
        cfg.pin_d15     = 42;
        
        _bus_instance.config(cfg);
        _panel_instance.bus(&_bus_instance);
      }
      {
        auto cfg = _panel_instance.config();    

        cfg.pin_cs           = -1;  // (-1 = disable)
        cfg.pin_rst          = 13;  // (-1 = disable)
        cfg.pin_busy         = -1;  // (-1 = disable)

        cfg.panel_width      = TFT_VER_RES;  
        cfg.panel_height     = TFT_HOR_RES;  
        cfg.offset_x         = 0;  
        cfg.offset_y         = 0;  
        cfg.offset_rotation  = 1;  

        cfg.dummy_read_pixel = 8; 
        cfg.dummy_read_bits  = 1;  
        cfg.readable         = true;      
        cfg.invert           = false;       
        cfg.rgb_order        = false;    
        cfg.dlen_16bit       = true;
        cfg.memory_width     = TFT_VER_RES;
        cfg.memory_height    = TFT_HOR_RES;
        cfg.bus_shared       = false;

        _panel_instance.config(cfg);
      }
      { 
        auto cfg = _touch_instance.config();

        cfg.x_max      = TFT_VER_RES;  
        cfg.y_max      = TFT_HOR_RES;  
        cfg.pin_int    = -1;   
        cfg.bus_shared = true; 
        cfg.offset_rotation = 0;

        cfg.i2c_port = 1; //(0 or 1)
        cfg.i2c_addr = 0x14;
        cfg.pin_sda  = 8;
        cfg.pin_scl  = 9;
        cfg.freq = 100000;
 
        _touch_instance.config(cfg);
        _panel_instance.setTouch(&_touch_instance);  
      }
      setPanel(&_panel_instance); 
    }    
  };
  
  LGFX display;

#define DRAW_BUF_SIZE (TFT_HOR_RES * TFT_VER_RES / 4 * (LV_COLOR_DEPTH / 8))
uint8_t draw_buf[DRAW_BUF_SIZE];

lv_display_t * disp;

void dispFlush(lv_display_t *disp, const lv_area_t *area, uint8_t * px_map){
  uint32_t w = ( area->x2 - area->x1 + 1 );
  uint32_t h = ( area->y2 - area->y1 + 1 );

  display.startWrite();
  display.setAddrWindow( area->x1, area->y1, w, h );
  display.writePixels((lgfx::rgb565_t *)&px_map, w * h);
  display.endWrite();

  lv_display_flush_ready(disp);   
}

void touchPadRead(lv_indev_t * indev, lv_indev_data_t * data){
 uint16_t touchX, touchY;
    bool touched;
    touched = display.getTouch( &touchX, &touchY);

    if(!touched){data->state = LV_INDEV_STATE_REL;}
    else{data->state = LV_INDEV_STATE_PR;
        data->point.x = touchX;
        data->point.y = touchY;
    }
}

void lvglDisplayConfig(){
  lv_init();
  display.init(); delay(100);
  display.fillScreen(TFT_GREEN); delay(100); // OK
  display.fillScreen(TFT_RED); delay(100);   // OK
  display.fillScreen(TFT_BLUE); delay(100);  // OK
  display.fillScreen(TFT_BLACK);             // OK
  
  disp = lv_display_create(TFT_HOR_RES, TFT_VER_RES);
  lv_display_set_flush_cb(disp, dispFlush);
  lv_display_set_buffers(disp, draw_buf, NULL, DRAW_BUF_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL);

  lv_indev_t * indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); /*Touchpad should have POINTER type*/
  lv_indev_set_read_cb(indev, touchPadRead);
}

Main Code

#include <lvgl.h>
#include "basicSystemSetting.h"
#include <demos/lv_demos.h>

void setup(){
  Serial.begin(115200); 
  lvglDisplayConfig();
  lv_demo_widgets();
}
unsigned long lvgl_tick_millis;

void loop(){
  lv_timer_handler(); /* let the UI do its work */

  unsigned long tick_millis = millis() - lvgl_tick_millis;
  lvgl_tick_millis = millis();  lv_tick_inc(tick_millis);
  delay(5);
}
@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

40MHz is too fast.

@Neothai
Copy link
Author

Neothai commented Mar 6, 2024

I have tried reducing the speed to 10MHz but the problem is still not solved.

cfg.freq_write  = 10000000;

Is there still any part of the code that I need to improve?

@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

Is the LovyanGFX sample program working correctly?

@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

ILI9488
width = 320
height = 480

@Neothai
Copy link
Author

Neothai commented Mar 6, 2024

This example works. But there are some pixels on the display that are slightly distorted.

#include <LovyanGFX.hpp>

class LGFX : public lgfx::LGFX_Device
{

lgfx::Panel_ILI9488     _panel_instance;
lgfx::Bus_Parallel16 _bus_instance;
lgfx::Touch_GT911  _touch_instance;

public:
  LGFX(void)
  {
    {
      auto cfg = _bus_instance.config();

      cfg.freq_write = 44000000;
      cfg.pin_wr = 48;
      cfg.pin_rd = 11;
      cfg.pin_rs = 47;

      cfg.pin_d0 = 1;
      cfg.pin_d1 = 2;
      cfg.pin_d2 = 12;
      cfg.pin_d3 = 4;
      cfg.pin_d4 = 5;
      cfg.pin_d5 = 6;
      cfg.pin_d6 = 7;
      cfg.pin_d7 = 10;
      cfg.pin_d8 = 14;
      cfg.pin_d9 = 15;
      cfg.pin_d10 = 16;
      cfg.pin_d11 = 17;
      cfg.pin_d12 = 18;
      cfg.pin_d13 = 21;
      cfg.pin_d14 = 38;
      cfg.pin_d15 = 42;
      _bus_instance.config(cfg);
      _panel_instance.bus(&_bus_instance);
    }
    { 
      auto cfg = _panel_instance.config();    

      cfg.pin_cs           =    -1;  // CSが接続されているピン番号   (-1 = disable)
      cfg.pin_rst          =    13;  // RSTが接続されているピン番号  (-1 = disable)
      cfg.pin_busy         =    -1;  // BUSYが接続されているピン番号 (-1 = disable)

      cfg.panel_width      =   320;  // 実際に表示可能な幅
      cfg.panel_height     =   480;  // 実際に表示可能な高さ
      cfg.offset_x         =     0;  // パネルのX方向オフセット量
      cfg.offset_y         =     0;  // パネルのY方向オフセット量
      cfg.offset_rotation  =     1;  // 回転方向の値のオフセット 0~7 (4~7は上下反転)
      //cfg.dummy_read_pixel =     8;  // ピクセル読出し前のダミーリードのビット数
      //cfg.dummy_read_bits  =     1;  // ピクセル以外のデータ読出し前のダミーリードのビット数
      cfg.readable         =  true;  // データ読出しが可能な場合 trueに設定
      cfg.invert           = false;  // パネルの明暗が反転してしまう場合 trueに設定
      cfg.rgb_order        = false;  // パネルの赤と青が入れ替わってしまう場合 trueに設定
      cfg.dlen_16bit       =  true;  // 16bitパラレルやSPIでデータ長を16bit単位で送信するパネルの場合 trueに設定
      cfg.bus_shared       = false;  // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います)

      _panel_instance.config(cfg);
    }
    { 
      auto cfg = _touch_instance.config();

      cfg.x_max      = 320;  // タッチスクリーンから得られる最大のX値(生の値)
      cfg.y_max      = 480;  // タッチスクリーンから得られる最大のY値(生の値)
      cfg.pin_int    = -1;   // INTが接続されているピン番号
      cfg.bus_shared = true; // 画面と共通のバスを使用している場合 trueを設定
      cfg.offset_rotation = 0;// 表示とタッチの向きのが一致しない場合の調整 0~7の値で設定

      cfg.i2c_port = 1;      // 使用するI2Cを選択 (0 or 1)
      cfg.i2c_addr = 0x14;   // I2Cデバイスアドレス番号
      cfg.pin_sda  = 8;     // SDAが接続されているピン番号
      cfg.pin_scl  = 9;     // SCLが接続されているピン番号
      cfg.freq = 100000;     // I2Cクロックを設定

      _touch_instance.config(cfg);
      _panel_instance.setTouch(&_touch_instance); 
    }
    setPanel(&_panel_instance);
  }
};
LGFX display;

void setup(void){
  display.init();
  Serial.begin(115200);
/*
  display.setTextSize((std::max(display.width(), display.height()) + 255) >> 8);

  if (display.touch()){
    if (display.width() < display.height()) display.setRotation(display.getRotation() ^ 1);

    display.setTextDatum(textdatum_t::middle_center);
    display.drawString("touch the arrow marker.", display.width()>>1, display.height() >> 1);
    display.setTextDatum(textdatum_t::top_left);

    std::uint16_t fg = TFT_WHITE;
    std::uint16_t bg = TFT_BLACK;
    if (display.isEPD()) std::swap(fg, bg);
    display.calibrateTouch(nullptr, fg, bg, std::max(display.width(), display.height()) >> 3);
  }
*/
  display.fillScreen(TFT_BLACK);
}

uint32_t count = ~0;
void loop(void){
  display.startWrite();
  display.setRotation(++count & 7);
  display.setColorDepth((count & 8) ? 16 : 24);

  display.setTextColor(TFT_WHITE);
  display.drawNumber(display.getRotation(), 16, 0);

  display.setTextColor(0xFF0000U);
  display.drawString("R", 30, 16);
  display.setTextColor(0x00FF00U);
  display.drawString("G", 40, 16);
  display.setTextColor(0x0000FFU);
  display.drawString("B", 50, 16);

  display.drawRect(30,30,display.width()-60,display.height()-60,count*7);
  display.drawFastHLine(0, 0, 10);

  display.endWrite();

  int32_t x, y;
  if (display.getTouch(&x, &y)) {
    delay(1);
    Serial.println(String(x));
    Serial.println(String(y));
    display.fillRect(x-2, y-2, 5, 5, count*7);
  }
}
exampleOK1.mp4

@Neothai
Copy link
Author

Neothai commented Mar 6, 2024

After 10-20 minutes, the display started to distort a little more.
errorimg1
errorimg2

@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

cfg.freq_write = 44000000;

????????????????

@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

why cs pin is -1?

@Neothai
Copy link
Author

Neothai commented Mar 6, 2024

why cs pin is -1?

I disabled the cs pin through software to connect the cs pin to external gnd instead because the ESP32-S3's GPIO was insufficient.

@Neothai
Copy link
Author

Neothai commented Mar 6, 2024

Have you tested LovyanGFX for compatibility with the latest version (v9) of LVGL? Because I just recently came across a discussion with the topic "LVGL v9.0 to work with LovyanGFX and ILI9488 screen". They seem to have a similar problem to me.

@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

通常これらのグリッチは物理的な通信品質が悪いために発生する。
通信速度が速すぎたり配線の状態が悪いのだと思います。

@lovyan03 lovyan03 closed this as completed Mar 6, 2024
@lovyan03
Copy link
Owner

lovyan03 commented Mar 6, 2024

私はあなたのコードに不備があると思います。

  display.writePixels((lgfx::rgb565_t *)&px_map, w * h);

px_map はポインタ型です。
&px_mapと書いた場合はポインタ型変数のポインタを指し示します。
px_mapと書けば良いでしょう。

つまり以下のようにです。

  display.writePixels((lgfx::rgb565_t *)px_map, w * h);

ちなみにその書き方では速度が十分に出ません。
以下のサンプルを参考に見てください。

https://github.com/lovyan03/LovyanGFX/blob/master/examples/Advanced/LVGL_PlatformIO/

@CFTechno
Copy link

CFTechno commented Sep 4, 2024

the above mentioned demo uses void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ) however in LVGL v9 the definition needs to be void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, unsigned char *color_p )

could you explain how the parameters for pushImageDMA now need to be? tft.pushImageDMA(area->x1, area->y1, area->x2 - area->x1 + 1, area->y2 - area->y1 + 1, (lgfx::swap565_t *)&color_p->full); is not correct anymore with v9 of LVGL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants