I am trying to get LVGL to run 2 screens on an Adafruit Feather ESP32-S3.
The bare library works, but LVGL is not. LVGL gets the upper screen, but when the lower screen is landscape, it corrupts. Please see code and images below for details
Changing rotation to 0 or 2 works, and removing lvgl altogether works too. No memory complaints from compiling on arduino IDE on computer. In the image below, upper is on the right, lower is on the left
#include
#include
#include
#include
// Proven working SPI + ILI9341 pins
#define TFT_SCK 12
#define TFT_MOSI 11
// Upper (ILI9341) pins - proven
#define UPPER_CS 10
#define UPPER_DC 9
#define UPPER_RST 6
#define LOWER_CS 14
#define LOWER_DC 8
#define LOWER_RST 5
Adafruit_ILI9341 upper(UPPER_CS, UPPER_DC, UPPER_RST);
Adafruit_ILI9341 lower(LOWER_CS, LOWER_DC, LOWER_RST);
inline void selectUpper() { digitalWrite(LOWER_CS, HIGH); digitalWrite(UPPER_CS, LOW); }
inline void deselectUpper() { digitalWrite(UPPER_CS, HIGH); }
inline void selectLower() { digitalWrite(UPPER_CS, HIGH); digitalWrite(LOWER_CS, LOW); }
inline void deselectLower() { digitalWrite(LOWER_CS, HIGH); }
#define UPPER_TFT_HOR_RES 320
#define UPPER_TFT_VER_RES 240
#define LOWER_TFT_HOR_RES 320
#define LOWER_TFT_VER_RES 240
static void flush_upper(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
const uint32_t w = area->x2 - area->x1 + 1;
const uint32_t h = area->y2 - area->y1 + 1;
selectUpper();
upper.startWrite();
upper.setAddrWindow(area->x1, area->y1, w, h);
upper.writePixels((uint16_t*)px_map, w * h, true);
upper.endWrite();
deselectUpper();
lv_display_flush_ready(disp);
}
static void flush_lower(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
const uint32_t w = area->x2 - area->x1 + 1;
const uint32_t h = area->y2 - area->y1 + 1;
selectLower();
lower.startWrite();
lower.setAddrWindow(area->x1, area->y1, w, h);
lower.writePixels((uint16_t*)px_map, w * h, true);
lower.endWrite();
deselectLower();
lv_display_flush_ready(disp);
}
static uint32_t my_tick_cb(void)
{
return millis();
}
void setup() {
Serial.begin(115200);
delay(200);
pinMode(UPPER_CS, OUTPUT);
pinMode(LOWER_CS, OUTPUT);
pinMode(UPPER_DC, OUTPUT);
pinMode(LOWER_DC, OUTPUT);
digitalWrite(UPPER_CS, HIGH);
digitalWrite(LOWER_CS, HIGH);
/*Initialize LVGL*/
lv_init();
/*Set millisecond-based tick source for LVGL so that it can track time.*/
lv_tick_set_cb(my_tick_cb);
lv_display_t * upperDisplay = lv_display_create(UPPER_TFT_HOR_RES, UPPER_TFT_VER_RES);
lv_display_t * lowerDisplay = lv_display_create(LOWER_TFT_HOR_RES, LOWER_TFT_VER_RES);
static lv_color_t upperBuf[UPPER_TFT_HOR_RES * UPPER_TFT_VER_RES / 10 ];
lv_display_set_buffers(upperDisplay, upperBuf, NULL, sizeof(upperBuf), LV_DISPLAY_RENDER_MODE_PARTIAL);
static lv_color_t lowerBuf[LOWER_TFT_HOR_RES * LOWER_TFT_VER_RES / 10 ];
lv_display_set_buffers(lowerDisplay, lowerBuf, NULL, sizeof(lowerBuf), LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_flush_cb(upperDisplay, flush_upper);
lv_display_set_flush_cb(lowerDisplay, flush_lower);
SPI.begin(TFT_SCK, -1, TFT_MOSI);
// --- INIT UPPER ---
selectUpper();
upper.begin();
upper.setSPISpeed(8000000);
upper.setRotation(3);
upper.fillScreen(ILI9341_BLACK);
deselectUpper();
// --- INIT LOWER ---
selectLower();
lower.begin();
lower.setSPISpeed(8000000);
lower.setRotation(3);
Serial.print("lower width = ");
Serial.println(lower.width());
Serial.print("lower height = ");
Serial.println(lower.height());
lower.fillScreen(ILI9341_BLACK);
delay(500);
lower.fillScreen(ILI9341_RED);
deselectLower();
lv_obj_t * upperScreen = lv_display_get_screen_active(upperDisplay);
lv_obj_t * lowerScreen = lv_display_get_screen_active(lowerDisplay);
lv_obj_t * upperLabel = lv_label_create(upperScreen);
lv_label_set_text(upperLabel, "Hello world");
lv_obj_center(upperLabel);
lv_obj_t * lowerLabel = lv_label_create(lowerScreen);
lv_label_set_text(lowerLabel, "Hi");
lv_obj_center(lowerLabel);
}
void loop() {
lv_timer_handler();
delay(5);
}
