Thank you Marian. I have made progress - it would seem you do need the TFT_eSPI library but it gets created and initialised by LVGL.
For future explorers, here is roughly how I did it:
- Add TFT_eSPI and lvgl liraries to your project via PlatformIO library manager
- Copy
lv_conf.h
to a src dir (in my case include
)
- Update
platformio.ini
for TFT_eSPI pins and lv_conf.h
location:
[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
lib_deps =
bodmer/TFT_eSPI@^2.5.43
lvgl/lvgl@^9.2.2
adafruit/Adafruit TouchScreen@^1.1.5
build_flags =
-D USER_SETUP_LOADED=1
-D ILI9341_DRIVER=1
-D TFT_WIDTH=240
-D TFT_HEIGHT=320
-D TFT_MISO=12
-D TFT_MOSI=11
-D TFT_SCLK=13
-D TFT_CS=10
-D TFT_DC=9
-D TFT_RST=-1
-D TOUCH_CS=-1
-D LOAD_GLCD=1
-D SPI_FREQUENCY=80000000
-D LV_CONF_PATH="${PROJECT_DIR}/include/lv_conf.h"
- In
lv_conf.h
update the following to 1:
4.1 #define LV_USE_TFT_ESPI 1
4.2 #define LV_USE_ILI9341 1
Edit: I’m not convinced I’m using the inbuilt ILI9341 driver as I can set it back to zero with no ill effect. So I guess my first question still stands…
I cannot find any documentation on LV_USE_TFT_ESPI
so just looked at the source code for a clue. It does not implement an SPI touch controller but that is not a problem for me as the Adafruit display uses analog pins.
- Your
main.cpp
should look something like this (I’m currently just playing, so this will likely get refactored into separate files):
/*
*/
#include <Arduino.h>
#include <lvgl.h>
#include <TouchScreen.h>
#define DRAW_BUF_SIZE (TFT_WIDTH * TFT_HEIGHT / 10 * (LV_COLOR_DEPTH/8))
//For the Adafruit TouchScreen.h
const uint8_t TOUCHSCREEN_XP = A6; // Y+ must be an analog pin, use "An" notation!
const uint8_t TOUCHSCREEN_YP = A9; // X- must be an analog pin, use "An" notation!
const uint8_t TOUCHSCREEN_XM = A8; // Y- can be a digital pin
const uint8_t TOUCHSCREEN_YM = A7; // X+ can be a digital pin
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, it's 300 ohms across the X plate
const uint16_t TOUCHSCREEN_OHMS = 300;
/**
* These four members define the active area (boundaries) of
* the touchscreen.
* We swap these values around with rotate or flipX, flipY
* @TODO store and read these from EEPROM
*/
uint16_t tsRight = 915;
uint16_t tsTop = 115;
uint16_t tsBottom = 915;
uint16_t tsLeft = 105;
uint32_t draw_buf[DRAW_BUF_SIZE / 4];
TouchScreen ts = TouchScreen(TOUCHSCREEN_XP, TOUCHSCREEN_YP, TOUCHSCREEN_XM, TOUCHSCREEN_YM, TOUCHSCREEN_OHMS);
// Get the Touchscreen data
void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data) {
// Checks if Touchscreen was touched, and prints X, Y and Pressure (Z)
// // a point object holds x y and z coordinates
TSPoint p = ts.getPoint();
// // we have some minimum pressure we consider 'valid'
// // pressure of 0 means no pressing!
if (p.z > ts.pressureThreshhold) {
data->state = LV_INDEV_STATE_PRESSED;
// Set the coordinates
data->point.x = max(1, map(p.x, tsLeft, tsRight, 1, TFT_WIDTH));
data->point.y = max(1, map(p.y, tsTop, tsBottom, 1, TFT_HEIGHT));
Serial.printf("Touch X: %i, Y: %i \n", data->point.x, data->point.y);
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
void setup() {
Serial.begin(115200);
lv_init();
/* Set a tick source so that LVGL will know how much time elapsed. */
lv_tick_set_cb((lv_tick_get_cb_t)millis);
/* Create a display using the inbuilt LVGL support for TFT_eSPI*/
lv_display_t *disp = lv_tft_espi_create(TFT_WIDTH, TFT_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_90);
// Initialize an LVGL input device object (Touchscreen)
lv_indev_t * indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
// Set the callback function to read Touchscreen input
lv_indev_set_read_cb(indev, touchscreen_read);
/* Create a simple label. */
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, "Hello Teensy, I'm LVGL v9!" );
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
}
void loop(void) {
lv_task_handler();
}
Note: I’m using Adafruit’s Touchscreen for the analog touch interface and I’m pretty sure I have to add more LVGL stuff to the loop()
This seems to work so far but any comments on whether I am doing it ‘right’ would be very welcome.