Screen displays garbage, wrong colors, flashes black and white

Description

I’m trying to write my own driver. The first draw of the screen works (although with wrong colors), but any touches makes the screen flash black and white randomly and I’ll get partial writes to the display (see attached video). I’m writing code in Platformio using an Arduino framework. I appreciate any help in advance!

What MCU/Processor/Board and compiler are you using?

Teensy 4.1 with a 320x480 TFT that has a ILI9486 driver. The screen is a clone of lcdwiki 3.5inch_Arduino_Display-UNO (can’t post the link for some reason) and has an 8 bit parallel display. I was able to get the screen to work fine with teensy using the MCUFRIEND_kbv library.

What have you tried so far?

I tried playing with lv_conf.h LV_COLOR_DEPTH and LV_COLOR_16_SWAP. When I try to call my flush_cb function from outside of lvgl I can get a square with a color gradient to display properly. I also tried playing with LV_MEM_SIZE and the size of the frame buffer. I think the problem is with my flush_cb function but I can’t figure it out.

Code to reproduce

Buffer:

static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * LV_VER_RES_MAX / 5];

flush_cb function:

  void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{

  int32_t x, y;
    
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {

            myGLCD.setColor( *((uint16_t *)color_p) );
            myGLCD.drawPixel(x, y);
            color_p++;
        }
    }
    
  lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
  
}

Initialization

myGLCD.InitLCD();
  myGLCD.fillScr(VGA_WHITE);
  lv_init();
  lv_log_register_print_cb(my_print); /* register print function for debugging */
  lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX / 5);
  lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  
  disp_drv.buffer = &disp_buf;
  lv_disp_drv_register(&disp_drv);

  lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);          /*Descriptor of a input device driver*/
  indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
  indev_drv.read_cb = my_touchpad_read;   /*Set your driver function*/
  lv_indev_drv_register(&indev_drv);

  lv_demo_widgets(); // Start demo

  tick.begin(lv_tick_handler, LVGL_TICK_PERIOD * 1000);

Relevant lv_conf.h sections

#define LV_COLOR_DEPTH     16
#define LV_COLOR_16_SWAP   1
#  define LV_MEM_SIZE    (128 * 1024U)

Screenshot and/or video

I figured it out. On screen shield that I’m using the TFT display and the touchscreen share some pins, so whenever LVGL tries to query the touchscreen for touches it messes up with the flushing of the buffer to the screen. The solution is to turn the pin labeled SD_SCK to high before you read the touchscreen, and turn it back to low after you finish reading the touch event.

Screen Shot 2020-12-24 at 1.14.29 AM|304x475

2 Likes