Skip to content

Commit

Permalink
working touch&display driver
Browse files Browse the repository at this point in the history
  • Loading branch information
KenVanHoeylandt committed Jan 24, 2024
1 parent 10aa06a commit cf44ad4
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 127 deletions.
181 changes: 114 additions & 67 deletions boards/waveshare_s3_touch/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,43 @@ SemaphoreHandle_t sem_gui_ready = NULL;

SemaphoreHandle_t lvgl_mux = NULL;

#define WAVESHARE_LCD_PIXEL_CLOCK_HZ (12 * 1000 * 1000) // NOTE: original was 14MHz, but we had to slow it down with PSRAM frame buffer
#define WAVESHARE_PIN_NUM_HSYNC 46
#define WAVESHARE_PIN_NUM_VSYNC 3
#define WAVESHARE_PIN_NUM_DE 5
#define WAVESHARE_PIN_NUM_PCLK 7
#define WAVESHARE_PIN_NUM_DATA0 14 // B3
#define WAVESHARE_PIN_NUM_DATA1 38 // B4
#define WAVESHARE_PIN_NUM_DATA2 18 // B5
#define WAVESHARE_PIN_NUM_DATA3 17 // B6
#define WAVESHARE_PIN_NUM_DATA4 10 // B7
#define WAVESHARE_PIN_NUM_DATA5 39 // G2
#define WAVESHARE_PIN_NUM_DATA6 0 // G3
#define WAVESHARE_PIN_NUM_DATA7 45 // G4
#define WAVESHARE_PIN_NUM_DATA8 48 // G5
#define WAVESHARE_PIN_NUM_DATA9 47 // G6
#define WAVESHARE_PIN_NUM_DATA10 21 // G7
#define WAVESHARE_PIN_NUM_DATA11 1 // R3
#define WAVESHARE_PIN_NUM_DATA12 2 // R4
#define WAVESHARE_PIN_NUM_DATA13 42 // R5
#define WAVESHARE_PIN_NUM_DATA14 41 // R6
#define WAVESHARE_PIN_NUM_DATA15 40 // R7
#define WAVESHARE_PIN_NUM_DISP_EN (-1)

#define WAVESHARE_BUFFER_HEIGHT (WAVESHARE_LCD_V_RES / 3) // How many rows of pixels to buffer - 1/3rd is about 1MB
#define WAVESHARE_LVGL_TICK_PERIOD_MS 2 // TODO: Setting it to 5 causes a crash - why?

#define WAVESHARE_USE_DOUBLE_FB true // Performance boost at the cost of about extra PSRAM(SPIRAM)

#if WAVESHARE_USE_DOUBLE_FB
#define WAVESHARE_LCD_NUM_FB 2
#else
#define WAVESHARE_LCD_NUM_FB 1
#endif // WAVESHARE_USE_DOUBLE_FB

static bool lvgl_is_running = false;
#define LVGL_MAX_SLEEP 500

void touch_init(lv_disp_t* display);

static bool display_lock(uint32_t timeout_ms) {
Expand All @@ -32,8 +69,6 @@ static void display_unlock(void) {
xSemaphoreGiveRecursive(lvgl_mux);
}

static bool lvgl_is_running = false;
#define LVGL_MAX_SLEEP 500
// Display_task should have lower priority than lvgl_tick_task below
static int32_t display_task(TT_UNUSED void* parameter) {
uint32_t task_delay_ms = LVGL_MAX_SLEEP;
Expand Down Expand Up @@ -74,7 +109,7 @@ static bool on_vsync_event(

static void lvgl_tick_task(TT_UNUSED void* arg) {
// Tell how much time has passed
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
lv_tick_inc(WAVESHARE_LVGL_TICK_PERIOD_MS);
}

static void display_flush_callback(lv_disp_drv_t* drv, const lv_area_t* area, lv_color_t* color_map) {
Expand Down Expand Up @@ -108,64 +143,63 @@ bool waveshare_s3_touch_create_display() {
tt_thread_set_priority(thread, ThreadPriorityHigh);
tt_thread_start(thread);

#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0
ESP_LOGI(TAG, "Turn off LCD backlight");
gpio_config_t bk_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
#endif
ESP_LOGI(TAG, "Install RGB LCD panel driver");
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_rgb_panel_config_t panel_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.timings = {
.pclk_hz = WAVESHARE_LCD_PIXEL_CLOCK_HZ,
.h_res = WAVESHARE_LCD_H_RES,
.v_res = WAVESHARE_LCD_V_RES,
// The following parameters should refer to LCD spec
.hsync_back_porch = 10,
.hsync_front_porch = 20,
.hsync_pulse_width = 10,
.vsync_back_porch = 10,
.vsync_front_porch = 10,
.vsync_pulse_width = 10,
},
.data_width = 16, // RGB565 in parallel mode, thus 16bit in width
.bits_per_pixel = 16,
.num_fbs = WAVESHARE_LCD_NUM_FB,
.bounce_buffer_size_px = 0,
.sram_trans_align = 0,
.psram_trans_align = 64,
.num_fbs = 1,
.bounce_buffer_size_px = 0,
.clk_src = LCD_CLK_SRC_DEFAULT,
.disp_gpio_num = EXAMPLE_PIN_NUM_DISP_EN,
.pclk_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.vsync_gpio_num = EXAMPLE_PIN_NUM_VSYNC,
.hsync_gpio_num = EXAMPLE_PIN_NUM_HSYNC,
.de_gpio_num = EXAMPLE_PIN_NUM_DE,
.hsync_gpio_num = WAVESHARE_PIN_NUM_HSYNC,
.vsync_gpio_num = WAVESHARE_PIN_NUM_VSYNC,
.de_gpio_num = WAVESHARE_PIN_NUM_DE,
.pclk_gpio_num = WAVESHARE_PIN_NUM_PCLK,
.disp_gpio_num = WAVESHARE_PIN_NUM_DISP_EN,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
EXAMPLE_PIN_NUM_DATA8,
EXAMPLE_PIN_NUM_DATA9,
EXAMPLE_PIN_NUM_DATA10,
EXAMPLE_PIN_NUM_DATA11,
EXAMPLE_PIN_NUM_DATA12,
EXAMPLE_PIN_NUM_DATA13,
EXAMPLE_PIN_NUM_DATA14,
EXAMPLE_PIN_NUM_DATA15,
},
.timings = {
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.h_res = EXAMPLE_LCD_H_RES,
.v_res = EXAMPLE_LCD_V_RES,
// The following parameters should refer to LCD spec
.hsync_back_porch = 30,
.hsync_front_porch = 210,
.hsync_pulse_width = 30,
.vsync_back_porch = 4,
.vsync_front_porch = 4,
.vsync_pulse_width = 4,
.flags.pclk_active_neg = true,
WAVESHARE_PIN_NUM_DATA0,
WAVESHARE_PIN_NUM_DATA1,
WAVESHARE_PIN_NUM_DATA2,
WAVESHARE_PIN_NUM_DATA3,
WAVESHARE_PIN_NUM_DATA4,
WAVESHARE_PIN_NUM_DATA5,
WAVESHARE_PIN_NUM_DATA6,
WAVESHARE_PIN_NUM_DATA7,
WAVESHARE_PIN_NUM_DATA8,
WAVESHARE_PIN_NUM_DATA9,
WAVESHARE_PIN_NUM_DATA10,
WAVESHARE_PIN_NUM_DATA11,
WAVESHARE_PIN_NUM_DATA12,
WAVESHARE_PIN_NUM_DATA13,
WAVESHARE_PIN_NUM_DATA14,
WAVESHARE_PIN_NUM_DATA15
},
.flags = {.disp_active_low = false, .refresh_on_demand = false,
.fb_in_psram = true, // allocate frame buffer in PSRAM
.double_fb = false,
.no_fb = false,
.bb_invalidate_cache = false}
.flags = {
.disp_active_low = false,
.refresh_on_demand = false,
.fb_in_psram = true,
#if WAVESHARE_USE_DOUBLE_FB
.double_fb = true,
#else
.double_fb = false,
#endif
.no_fb = false,
.bb_invalidate_cache = false
}
};
ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle));

Expand All @@ -181,30 +215,43 @@ bool waveshare_s3_touch_create_display() {
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));

#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0
ESP_LOGI(TAG, "Turn on LCD backlight");
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
#endif

ESP_LOGI(TAG, "Initialize LVGL library");
lv_init();

void *buf1 = NULL;
void *buf2 = NULL;
#if WAVESHARE_USE_DOUBLE_FB
ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers");
buf1 = heap_caps_malloc(WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
buf2 = heap_caps_malloc(WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
// initialize LVGL draw buffers
lv_disp_draw_buf_init(&display_buffer, buf1, buf2, WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT);
#else
ESP_LOGI(TAG, "Allocate separate LVGL draw buffers from PSRAM");
void* display_buffer_bytes = heap_caps_malloc(EXAMPLE_LCD_H_RES * BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_DMA); // TODO: use MALLOC_CAP_DMA for other drivers too
assert(display_buffer_bytes);
lv_disp_draw_buf_init(&display_buffer, display_buffer_bytes, NULL, EXAMPLE_LCD_H_RES * BUFFER_HEIGHT);
buf1 = heap_caps_malloc(WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
assert(buf1);
lv_disp_draw_buf_init(&display_buffer, buf1, buf2, WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT);
#endif // WAVESHARE_USE_DOUBLE_FB

ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&display_driver);
display_driver.hor_res = EXAMPLE_LCD_H_RES;
display_driver.ver_res = EXAMPLE_LCD_V_RES;
display_driver.hor_res = WAVESHARE_LCD_H_RES;
display_driver.ver_res = WAVESHARE_LCD_V_RES;
display_driver.flush_cb = display_flush_callback;
display_driver.draw_buf = &display_buffer;
display_driver.user_data = panel_handle;

#if CONFIG_EXAMPLE_DOUBLE_FB
disp_drv.full_refresh = true; // the full_refresh mode can maintain the synchronization between the two frame buffers
display_driver.antialiasing = false;
display_driver.direct_mode = false;
display_driver.sw_rotate = false;
display_driver.rotated = 0;
display_driver.screen_transp = false;

#if WAVESHARE_USE_DOUBLE_FB
display_driver.full_refresh = true; // the full_refresh mode can maintain the synchronization between the two frame buffers
#else
display_driver.full_refresh = false;
#endif

lv_disp_t* disp = lv_disp_drv_register(&display_driver);

touch_init(disp);
Expand All @@ -216,7 +263,7 @@ bool waveshare_s3_touch_create_display() {
};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, WAVESHARE_LVGL_TICK_PERIOD_MS * 1000));

return true;
}
Expand Down
48 changes: 19 additions & 29 deletions boards/waveshare_s3_touch/touch.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@

#define TAG "waveshare_s3_touch_i2c"

#define TOUCH_I2C_PORT 0
#define I2C_MASTER_TX_BUF_DISABLE 0
#define I2C_MASTER_RX_BUF_DISABLE 0
#define I2C_MASTER_TIMEOUT_MS 1000
#define WAVESHARE_TOUCH_I2C_PORT 0
#define WAVESHARE_I2C_MASTER_TX_BUF_DISABLE 0
#define WAVESHARE_I2C_MASTER_RX_BUF_DISABLE 0

static esp_err_t i2c_master_init(void) {
const i2c_config_t i2c_conf = {
Expand All @@ -24,26 +23,26 @@ static esp_err_t i2c_master_init(void) {
.master.clk_speed = 400000
};

i2c_param_config(TOUCH_I2C_PORT, &i2c_conf);
i2c_param_config(WAVESHARE_TOUCH_I2C_PORT, &i2c_conf);

return i2c_driver_install(TOUCH_I2C_PORT, i2c_conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
return i2c_driver_install(WAVESHARE_TOUCH_I2C_PORT, i2c_conf.mode, WAVESHARE_I2C_MASTER_RX_BUF_DISABLE, WAVESHARE_I2C_MASTER_TX_BUF_DISABLE, 0);
}


static void touch_init_internal(esp_lcd_touch_handle_t* tp) {
static esp_lcd_touch_handle_t touch_init_internal() {
ESP_ERROR_CHECK(i2c_master_init());
ESP_LOGI(TAG, "I2C initialized successfully");

esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
static esp_lcd_panel_io_handle_t tp_io_handle = NULL;
static esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
ESP_LOGI(TAG, "Initialize touch IO (I2C)");
/* Touch IO handle */
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)TOUCH_I2C_PORT, &tp_io_config, &tp_io_handle));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)WAVESHARE_TOUCH_I2C_PORT, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
.x_max = EXAMPLE_LCD_V_RES,
.y_max = EXAMPLE_LCD_H_RES,
.x_max = WAVESHARE_LCD_V_RES,
.y_max = WAVESHARE_LCD_H_RES,
.rst_gpio_num = -1,
.int_gpio_num = 4,
.int_gpio_num = -1,
.flags = {
.swap_xy = 0,
.mirror_x = 0,
Expand All @@ -52,20 +51,13 @@ static void touch_init_internal(esp_lcd_touch_handle_t* tp) {
};
/* Initialize touch */
ESP_LOGI(TAG, "Initialize touch controller GT911");
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, tp));
esp_lcd_touch_handle_t tp = NULL;
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp));

int ret;
uint8_t write_buf = 0x01;

ret = i2c_master_write_to_device(TOUCH_I2C_PORT, 0x24, &write_buf, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "0x48 0x01 ret is %d", ret);

write_buf = 0x0E;
ret = i2c_master_write_to_device(TOUCH_I2C_PORT, 0x38, &write_buf, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "0x70 0x00 ret is %d", ret);
return tp;
}

static void example_touchpad_read(lv_indev_drv_t* drv, lv_indev_data_t* data) {
static void touch_callback(lv_indev_drv_t* drv, lv_indev_data_t* data) {
uint16_t touchpad_x[1] = {0};
uint16_t touchpad_y[1] = {0};
uint8_t touchpad_cnt = 0;
Expand All @@ -80,22 +72,20 @@ static void example_touchpad_read(lv_indev_drv_t* drv, lv_indev_data_t* data) {
data->point.x = touchpad_x[0];
data->point.y = touchpad_y[0];
data->state = LV_INDEV_STATE_PR;
ESP_LOGI(TAG, "X=%u Y=%u", data->point.x, data->point.y);
} else {
data->state = LV_INDEV_STATE_REL;
}
}

void touch_init(lv_disp_t* display) {
static esp_lcd_touch_handle_t tp = NULL;
touch_init_internal(&tp);
esp_lcd_touch_handle_t touch_handle = touch_init_internal();

ESP_LOGI(TAG, "Register display indev to LVGL");
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.disp = display;
indev_drv.read_cb = &example_touchpad_read;
indev_drv.user_data = tp;
indev_drv.read_cb = &touch_callback;
indev_drv.user_data = touch_handle;
lv_indev_drv_register(&indev_drv); // TODO: store result for deinit purposes
}
2 changes: 1 addition & 1 deletion boards/waveshare_s3_touch/waveshare_s3_touch.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
extern "C" {
#endif

// Capacitive touch version of the 2.4" yellow board
// Waveshare S3 Touch LCD 4.3
extern const HardwareConfig waveshare_s3_touch;

#ifdef __cplusplus
Expand Down
35 changes: 5 additions & 30 deletions boards/waveshare_s3_touch/waveshare_s3_touch_defines.h
Original file line number Diff line number Diff line change
@@ -1,34 +1,9 @@
/**
* The WaveShare S3 Touch uses a panel with the ST7262 display driver.
*/
#pragma once

#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (21 * 1000 * 1000)
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
#define EXAMPLE_PIN_NUM_BK_LIGHT -1
#define EXAMPLE_PIN_NUM_HSYNC 46
#define EXAMPLE_PIN_NUM_VSYNC 3
#define EXAMPLE_PIN_NUM_DE 5
#define EXAMPLE_PIN_NUM_PCLK 7
#define EXAMPLE_PIN_NUM_DATA0 14 // B3
#define EXAMPLE_PIN_NUM_DATA1 38 // B4
#define EXAMPLE_PIN_NUM_DATA2 18 // B5
#define EXAMPLE_PIN_NUM_DATA3 17 // B6
#define EXAMPLE_PIN_NUM_DATA4 10 // B7
#define EXAMPLE_PIN_NUM_DATA5 39 // G2
#define EXAMPLE_PIN_NUM_DATA6 0 // G3
#define EXAMPLE_PIN_NUM_DATA7 45 // G4
#define EXAMPLE_PIN_NUM_DATA8 48 // G5
#define EXAMPLE_PIN_NUM_DATA9 47 // G6
#define EXAMPLE_PIN_NUM_DATA10 21 // G7
#define EXAMPLE_PIN_NUM_DATA11 1 // R3
#define EXAMPLE_PIN_NUM_DATA12 2 // R4
#define EXAMPLE_PIN_NUM_DATA13 42 // R5
#define EXAMPLE_PIN_NUM_DATA14 41 // R6
#define EXAMPLE_PIN_NUM_DATA15 40 // R7
#define EXAMPLE_PIN_NUM_DISP_EN -1

// The pixel number in horizontal and vertical
#define EXAMPLE_LCD_H_RES 800
#define EXAMPLE_LCD_V_RES 480
#define WAVESHARE_LCD_H_RES 800
#define WAVESHARE_LCD_V_RES 480

#define BUFFER_HEIGHT (EXAMPLE_LCD_V_RES / 10)
#define EXAMPLE_LVGL_TICK_PERIOD_MS 5

0 comments on commit cf44ad4

Please sign in to comment.