Teensy 3.6 - buffer is drawn only once

Description

LVGL prints only one buffer and then stops working.

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

Teensy 3.6, Arduino Studio 1.49.2

What do you want to achieve?

I’d like to display a button on screen.

What have you tried so far?

Followed the “porting” page and implemented all neccessary parts.

Code to reproduce

I use default lvgl_conf file, only changed dimensions to 320x240 and added logging.

Complete code of my .ino file follows.

#include "src\lvgl\lvgl.h"
#include <ILI9341_t3.h>
#include <XPT2046_Touchscreen.h>

#define DISPLAY_CS 10
#define DISPLAY_DC 9
#define DISPLAY_MOSI 11
#define DISPLAY_MISO 12
#define DISPLAY_SCK 13

#define DISPLAY_RST 255 // Not connected

#define TOUCH_CS 8
#define TOUCH_IRQ 23

#define TS_MINX 250
#define TS_MAXX 3800
#define TS_MINY 250
#define TS_MAXY 3800

#define LV_BUFFER_SIZE (320*10)

#define GUI_TIMER_MS 5

ILI9341_t3 tft(DISPLAY_CS, DISPLAY_DC, 255, DISPLAY_MOSI, DISPLAY_SCK, DISPLAY_MISO);
XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ);
IntervalTimer guiTimer;

lv_disp_buf_t lvDisplayBuffer;
lv_color_t lvBuffer1[LV_BUFFER_SIZE];
lv_color_t lvBuffer2[LV_BUFFER_SIZE];

lv_obj_t * screen;
lv_obj_t * button;

void drawBuffer(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
  /* DEBUG */
  Serial.print("Printing buffer: ");
  Serial.print(area->x1);
  Serial.print(",");
  Serial.print(area->y1);
  Serial.print(" .. ");
  Serial.print(area->x2);
  Serial.print(",");
  Serial.println(area->y2);
  /* END DEBUG */

  tft.writeRect(area->x1, 
    area->y1, 
    (area->x2 - area->x1 + 1), 
    (area->y2 - area->y1 + 1), 
    (uint16_t *)color_p);

  Serial.print("End printing buffer");
}

bool readInput(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
  TS_Point p = ts.getPoint();
  data->point.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
  data->point.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
  data->state = ts.touched() ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
  return false;
}

void timeGui()
{
  lv_tick_inc(GUI_TIMER_MS);
}

#if LV_USE_LOG
void logCallback(lv_log_level_t level, const char * file, long unsigned int line, const char * fn_name, const char * dsc)
{
  Serial.print(file);
  Serial.print("\t");
  Serial.print(fn_name);
  Serial.print(" (line ");
  Serial.print(line);
  Serial.print(")\t");
  Serial.println(dsc);
}
#endif

void setup() {
  // put your setup code here, to run once:

  // Start serial port
  Serial.begin(9600);
  while (!Serial) ;

  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);

  ts.begin();
  ts.setRotation(1);

  // Initialize LVGL
  lv_init();

  // Initialize display buffer
  lv_disp_buf_init(&lvDisplayBuffer, lvBuffer1, lvBuffer2, LV_BUFFER_SIZE);

  // Initialize display driver
  lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.buffer = &lvDisplayBuffer;
  disp_drv.flush_cb = drawBuffer;
  lv_disp_t * disp;
  disp = lv_disp_drv_register(&disp_drv);

  // Initialize input driver
  lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = readInput;
  lv_indev_t * indev = lv_indev_drv_register(&indev_drv);

  // Start the interval timer
  guiTimer.begin(timeGui, GUI_TIMER_MS * 1000);

#if LV_USE_LOG
  lv_log_register_print_cb(logCallback);
#endif

  // Create controls
  screen = lv_obj_create(nullptr, nullptr);

  button = lv_btn_create(screen, nullptr);
  lv_obj_set_pos(button, 10, 10);
  lv_obj_set_size(button, 150, 50);

  lv_scr_load(screen);
}

void loop() {
  // put your main code here, to run repeatedly:
  lv_task_handler();
}

Screenshot and/or video

I don’t have screenshot, but dump from the log from LVGL along with my own logs. It looks like following (I stripped the paths):

C:\...\src\lvgl\src\lv_core\lv_obj.c	    lv_obj_create (line 267)	Screen create started
C:\...\src\lvgl\src\lv_core\lv_obj.c	    lv_obj_create (line 456)	Object create ready
C:\..\src\lvgl\src\lv_widgets\lv_btn.c  	lv_btn_create (line 61)	button create started
C:\...\src\lvgl\src\lv_widgets\lv_cont.c	lv_cont_create (line 70)	container create started
C:\...\src\lvgl\src\lv_core\lv_obj.c	    lv_obj_create (line 299)	Object create started
C:\...\src\lvgl\src\lv_core\lv_obj.c	    lv_obj_create (line 456)	Object create ready
C:\...\src\lv_widgets\lv_cont.c	            lv_cont_create (line 118)	container created
C:\...\src\lvgl\src\lv_widgets\lv_btn.c	    lv_btn_create (line 106)	button created
C:\...\lvgl\src\lv_misc\lv_task.c	        lv_task_handler (line 74)	lv_task_handler started
C:\...\lvgl\src\lv_core\lv_refr.c	        _lv_disp_refr_task (line 177)	lv_refr_task: started
Printing buffer: 0,0 .. 319,9
End printing buffer

You need to call lv_disp_flush_ready after you finish drawing the buffer.

1 Like

Thank you for help :slight_smile: Works like charm now.

Best regards – Wojciech “Spook” Sura.